diff --git a/.gitignore b/.gitignore
index 8528997..75d7d04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,3 +16,5 @@ OUT/
*.bin
*.elf
*.list
+*.scvd
+
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..83849a1
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/printf"]
+ path = src/printf
+ url = https://github.com/mpaland/printf
diff --git a/.vscode/settings.json b/.vscode/settings.json
index a37e70d..3821b7b 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -6,6 +6,19 @@
"stm32f0xx_rcc.h": "c",
"uart.h": "c",
"xshell.h": "c",
- "xprintf.h": "c"
+ "xprintf.h": "c",
+ "ush.h": "c",
+ "printf.h": "c",
+ "sstream": "c",
+ "system_error": "c",
+ "string.h": "c",
+ "*.tcc": "c",
+ "optional": "c",
+ "ratio": "c",
+ "type_traits": "c",
+ "functional": "c",
+ "displed.h": "c",
+ "menu.h": "c",
+ "hmi.h": "c"
},
}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 9cecc1d..dd18aa1 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,674 +1,22 @@
- GNU GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
+The MIT License (MIT)
- 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.
+Copyright (c) 2019 Neo Xu
- Preamble
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
- The GNU General Public License is a free, copyleft license for
-software and other kinds of works.
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
- 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.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
- To protect your rights, we need to prevent others from denying you
-these rights or asking you to surrender the rights. Therefore, you have
-certain responsibilities if you distribute copies of the software, or if
-you modify it: responsibilities to respect the freedom of others.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must pass on to the recipients the same
-freedoms that you received. You must make sure that they, too, receive
-or can get the source code. And you must show them these terms so they
-know their rights.
-
- Developers that use the GNU GPL protect your rights with two steps:
-(1) assert copyright on the software, and (2) offer you this License
-giving you legal permission to copy, distribute and/or modify it.
-
- For the developers' and authors' protection, the GPL clearly explains
-that there is no warranty for this free software. For both users' and
-authors' sake, the GPL requires that modified versions be marked as
-changed, so that their problems will not be attributed erroneously to
-authors of previous versions.
-
- Some devices are designed to deny users access to install or run
-modified versions of the software inside them, although the manufacturer
-can do so. This is fundamentally incompatible with the aim of
-protecting users' freedom to change the software. The systematic
-pattern of such abuse occurs in the area of products for individuals to
-use, which is precisely where it is most unacceptable. Therefore, we
-have designed this version of the GPL to prohibit the practice for those
-products. If such problems arise substantially in other domains, we
-stand ready to extend this provision to those domains in future versions
-of the GPL, as needed to protect the freedom of users.
-
- Finally, every program is threatened constantly by software patents.
-States should not allow patents to restrict development and use of
-software on general-purpose computers, but in those that do, we wish to
-avoid the special danger that patents applied to a free program could
-make it effectively proprietary. To prevent this, the GPL assures that
-patents cannot be used to render the program non-free.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- TERMS AND CONDITIONS
-
- 0. Definitions.
-
- "This License" refers to version 3 of the GNU General Public License.
-
- "Copyright" also means copyright-like laws that apply to other kinds of
-works, such as semiconductor masks.
-
- "The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
- To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of an
-exact copy. The resulting work is called a "modified version" of the
-earlier work or a work "based on" the earlier work.
-
- A "covered work" means either the unmodified Program or a work based
-on the Program.
-
- To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
- To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user through
-a computer network, with no transfer of a copy, is not conveying.
-
- An interactive user interface displays "Appropriate Legal Notices"
-to the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
- 1. Source Code.
-
- The "source code" for a work means the preferred form of the work
-for making modifications to it. "Object code" means any non-source
-form of a work.
-
- A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
- The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
- The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
- The Corresponding Source need not include anything that users
-can regenerate automatically from other parts of the Corresponding
-Source.
-
- The Corresponding Source for a work in source code form is that
-same work.
-
- 2. Basic Permissions.
-
- All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
- You may make, run and propagate covered works that you do not
-convey, without conditions so long as your license otherwise remains
-in force. You may convey covered works to others for the sole purpose
-of having them make modifications exclusively for you, or provide you
-with facilities for running those works, provided that you comply with
-the terms of this License in conveying all material for which you do
-not control copyright. Those thus making or running the covered works
-for you must do so exclusively on your behalf, under your direction
-and control, on terms that prohibit them from making any copies of
-your copyrighted material outside their relationship with you.
-
- Conveying under any other circumstances is permitted solely under
-the conditions stated below. Sublicensing is not allowed; section 10
-makes it unnecessary.
-
- 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
- No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
- When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such circumvention
-is effected by exercising rights under this License with respect to
-the covered work, and you disclaim any intention to limit operation or
-modification of the work as a means of enforcing, against the work's
-users, your or third parties' legal rights to forbid circumvention of
-technological measures.
-
- 4. Conveying Verbatim Copies.
-
- You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
- You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
- 5. Conveying Modified Source Versions.
-
- You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these conditions:
-
- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-
- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under section
- 7. This requirement modifies the requirement in section 4 to
- "keep intact all notices".
-
- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-
- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
- A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
- 6. Conveying Non-Source Forms.
-
- You may convey a covered work in object code form under the terms
-of sections 4 and 5, provided that you also convey the
-machine-readable Corresponding Source under the terms of this License,
-in one of these ways:
-
- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-
- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the
- Corresponding Source from a network server at no charge.
-
- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-
- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-
- e) Convey the object code using peer-to-peer transmission, provided
- you inform other peers where the object code and Corresponding
- Source of the work are being offered to the general public at no
- charge under subsection 6d.
-
- A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
- A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal, family,
-or household purposes, or (2) anything designed or sold for incorporation
-into a dwelling. In determining whether a product is a consumer product,
-doubtful cases shall be resolved in favor of coverage. For a particular
-product received by a particular user, "normally used" refers to a
-typical or common use of that class of product, regardless of the status
-of the particular user or of the way in which the particular user
-actually uses, or expects or is expected to use, the product. A product
-is a consumer product regardless of whether the product has substantial
-commercial, industrial or non-consumer uses, unless such uses represent
-the only significant mode of use of the product.
-
- "Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to install
-and execute modified versions of a covered work in that User Product from
-a modified version of its Corresponding Source. The information must
-suffice to ensure that the continued functioning of the modified object
-code is in no case prevented or interfered with solely because
-modification has been made.
-
- If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
- The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or updates
-for a work that has been modified or installed by the recipient, or for
-the User Product in which it has been modified or installed. Access to a
-network may be denied when the modification itself materially and
-adversely affects the operation of the network or violates the rules and
-protocols for communication across the network.
-
- Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
- 7. Additional Terms.
-
- "Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
- When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
- Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders of
-that material) supplement the terms of this License with terms:
-
- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-
- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-
- c) Prohibiting misrepresentation of the origin of that material, or
- requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-
- d) Limiting the use for publicity purposes of names of licensors or
- authors of the material; or
-
- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-
- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions of
- it) with contractual assumptions of liability to the recipient, for
- any liability that these contractual assumptions directly impose on
- those licensors and authors.
-
- All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
- If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
- Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions;
-the above requirements apply either way.
-
- 8. Termination.
-
- You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
- However, if you cease all violation of this License, then your
-license from a particular copyright holder is reinstated (a)
-provisionally, unless and until the copyright holder explicitly and
-finally terminates your license, and (b) permanently, if the copyright
-holder fails to notify you of the violation by some reasonable means
-prior to 60 days after the cessation.
-
- Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
- Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
- 9. Acceptance Not Required for Having Copies.
-
- You are not required to accept this License in order to receive or
-run a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
- 10. Automatic Licensing of Downstream Recipients.
-
- Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
- An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
- You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
- 11. Patents.
-
- A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
- A contributor's "essential patent claims" are all patent claims
-owned or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
- Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
- In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
- If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
- If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
- A patent license is "discriminatory" if it does not include within
-the scope of its coverage, prohibits the exercise of, or is
-conditioned on the non-exercise of one or more of the rights that are
-specifically granted under this License. You may not convey a covered
-work if you are a party to an arrangement with a third party that is
-in the business of distributing software, under which you make payment
-to the third party based on the extent of your activity of conveying
-the work, and under which the third party grants, to any of the
-parties who would receive the covered work from you, a discriminatory
-patent license (a) in connection with copies of the covered work
-conveyed by you (or copies made from those copies), or (b) primarily
-for and in connection with specific products or compilations that
-contain the covered work, unless you entered into that arrangement,
-or that patent license was granted, prior to 28 March 2007.
-
- Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
- 12. No Surrender of Others' Freedom.
-
- If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you may
-not convey it at all. For example, if you agree to terms that obligate you
-to collect a royalty for further conveying from those to whom you convey
-the Program, the only way you could satisfy both those terms and this
-License would be to refrain entirely from conveying the Program.
-
- 13. Use with the GNU Affero General Public License.
-
- Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU Affero General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the special requirements of the GNU Affero General Public License,
-section 13, concerning interaction through a network will apply to the
-combination as such.
-
- 14. Revised Versions of this License.
-
- The Free Software Foundation may publish revised and/or new versions of
-the GNU General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Program specifies that a certain numbered version of the GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-GNU General Public License, you may choose any version ever published
-by the Free Software Foundation.
-
- If the Program specifies that a proxy can decide which future
-versions of the GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
- Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
- 15. Disclaimer of Warranty.
-
- THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
-IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
- 16. Limitation of Liability.
-
- IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
-SUCH DAMAGES.
-
- 17. Interpretation of Sections 15 and 16.
-
- If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-state the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- {one line to give the program's name and a brief idea of what it does.}
- Copyright (C) {year} {name of author}
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-
-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:
-
- {project} Copyright (C) {year} {fullname}
- 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/src/MDK/AD5791Ref.uvoptx b/src/MDK/AD5791Ref.uvoptx
new file mode 100644
index 0000000..ad15fd9
--- /dev/null
+++ b/src/MDK/AD5791Ref.uvoptx
@@ -0,0 +1,770 @@
+
+
+
+ 1.0
+
+ ### uVision Project, (C) Keil Software
+
+
+ *.c
+ *.s*; *.src; *.a*
+ *.obj; *.o
+ *.lib
+ *.txt; *.h; *.inc
+ *.plm
+ *.cpp
+ 0
+
+
+
+ 0
+ 0
+
+
+
+ AD5791Ref
+ 0x4
+ ARM-ADS
+
+ 12000000
+
+ 1
+ 1
+ 0
+ 1
+ 0
+
+
+ 1
+ 65535
+ 0
+ 0
+ 0
+
+
+ 79
+ 66
+ 8
+ .\LIST\
+
+
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+
+
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+
+
+ 1
+ 0
+ 1
+
+ 18
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 1
+ 0
+ 0
+ 6
+
+
+
+
+
+
+
+
+
+
+ STLink\ST-LINKIII-KEIL_SWO.dll
+
+
+
+ 0
+ UL2CM3
+ -U -O206 -S8 -C0 -P00 -N00("") -D00(00000000) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FN1 -FC1000 -FD20000000 -FF0STM32F0xx_32 -FL08000 -FS08000000 -FP0($$Device:STM32F070F6Px$CMSIS\Flash\STM32F0xx_32.FLM)
+
+
+ 0
+ ST-LINKIII-KEIL_SWO
+ -U49FF6C064971554838362087 -O206 -SF1000 -C0 -A0 -I0 -HNlocalhost -HP7184 -P2 -N00("ARM CoreSight SW-DP") -D00(0BB11477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO15 -FD20000000 -FC1000 -FN1 -FF0STM32F0xx_32.FLM -FS08000000 -FL08000 -FP0($$Device:STM32F070F6Px$CMSIS\Flash\STM32F0xx_32.FLM)
+
+
+ 0
+ DLGUARM
+ (105=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMRTXEVENTFLAGS
+ -L70 -Z18 -C0 -M0 -T1
+
+
+ 0
+ ST-LINKIII-KEIL
+ -U -O206 -S3 -C0 -N00("ARM CoreSight SW-DP") -D00(1BA01477) -L00(0) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO23 -FD20000000 -FC800 -FN1 -FF0STM32F10x_128 -FS08000000 -FL020000
+
+
+ 0
+ DLGTARM
+ (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)
+
+
+ 0
+ ARMDBGFLAGS
+
+
+
+
+
+ 0
+ 0
+ 119
+ 1
+ 134229348
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ ..\app\hmi.c
+
+ \\\../app/hmi.c\119
+
+
+
+
+ 0
+ 1
+ pstr
+
+
+ 1
+ 1
+ buff
+
+
+ 2
+ 1
+ ush
+
+
+ 3
+ 1
+ pline
+
+
+ 4
+ 1
+ line_buff
+
+
+ 5
+ 1
+ argc
+
+
+ 6
+ 1
+ pstr_start
+
+
+ 7
+ 1
+ uvalue,0x0A
+
+
+ 8
+ 1
+ fvalue,0x0A
+
+
+
+
+ 1
+ 2
+ 0x8006000
+ 0
+
+
+
+ 0
+
+
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+ System Viewer\TIM14
+ 35905
+
+
+
+ 1
+ 0
+ 2
+ 10000000
+
+
+
+
+
+ USER
+ 1
+ 0
+ 0
+ 0
+
+ 1
+ 1
+ 1
+ 0
+ 0
+ 0
+ ..\main.c
+ main.c
+ 0
+ 0
+
+
+ 1
+ 2
+ 1
+ 0
+ 0
+ 0
+ ..\stm32f0xx_it.c
+ stm32f0xx_it.c
+ 0
+ 0
+
+
+
+
+ APP
+ 1
+ 0
+ 0
+ 0
+
+ 2
+ 3
+ 1
+ 0
+ 0
+ 0
+ ..\printf\printf.c
+ printf.c
+ 0
+ 0
+
+
+ 2
+ 4
+ 1
+ 0
+ 0
+ 0
+ ..\app\fifo.c
+ fifo.c
+ 0
+ 0
+
+
+ 2
+ 5
+ 1
+ 0
+ 0
+ 0
+ ..\app\serial_frame.c
+ serial_frame.c
+ 0
+ 0
+
+
+ 2
+ 6
+ 1
+ 0
+ 0
+ 0
+ ..\app\ush.c
+ ush.c
+ 0
+ 0
+
+
+ 2
+ 7
+ 1
+ 0
+ 0
+ 0
+ ..\app\displed.c
+ displed.c
+ 0
+ 0
+
+
+ 2
+ 8
+ 1
+ 0
+ 0
+ 0
+ ..\app\voltref.c
+ voltref.c
+ 0
+ 0
+
+
+ 2
+ 9
+ 1
+ 0
+ 0
+ 0
+ ..\app\hmi.c
+ hmi.c
+ 0
+ 0
+
+
+
+
+ LIB
+ 0
+ 0
+ 0
+ 0
+
+ 3
+ 10
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\CMSIS\Device\ST\STM32F0xx\Source\Templates\system_stm32f0xx.c
+ system_stm32f0xx.c
+ 0
+ 0
+
+
+ 3
+ 11
+ 2
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\CMSIS\Device\ST\STM32F0xx\Source\Templates\arm\startup_stm32f030.s
+ startup_stm32f030.s
+ 0
+ 0
+
+
+ 3
+ 12
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_wwdg.c
+ stm32f0xx_wwdg.c
+ 0
+ 0
+
+
+ 3
+ 13
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_adc.c
+ stm32f0xx_adc.c
+ 0
+ 0
+
+
+ 3
+ 14
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_can.c
+ stm32f0xx_can.c
+ 0
+ 0
+
+
+ 3
+ 15
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_cec.c
+ stm32f0xx_cec.c
+ 0
+ 0
+
+
+ 3
+ 16
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_comp.c
+ stm32f0xx_comp.c
+ 0
+ 0
+
+
+ 3
+ 17
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_crc.c
+ stm32f0xx_crc.c
+ 0
+ 0
+
+
+ 3
+ 18
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_crs.c
+ stm32f0xx_crs.c
+ 0
+ 0
+
+
+ 3
+ 19
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dac.c
+ stm32f0xx_dac.c
+ 0
+ 0
+
+
+ 3
+ 20
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dbgmcu.c
+ stm32f0xx_dbgmcu.c
+ 0
+ 0
+
+
+ 3
+ 21
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dma.c
+ stm32f0xx_dma.c
+ 0
+ 0
+
+
+ 3
+ 22
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_exti.c
+ stm32f0xx_exti.c
+ 0
+ 0
+
+
+ 3
+ 23
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_flash.c
+ stm32f0xx_flash.c
+ 0
+ 0
+
+
+ 3
+ 24
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_gpio.c
+ stm32f0xx_gpio.c
+ 0
+ 0
+
+
+ 3
+ 25
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_i2c.c
+ stm32f0xx_i2c.c
+ 0
+ 0
+
+
+ 3
+ 26
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_iwdg.c
+ stm32f0xx_iwdg.c
+ 0
+ 0
+
+
+ 3
+ 27
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_misc.c
+ stm32f0xx_misc.c
+ 0
+ 0
+
+
+ 3
+ 28
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_pwr.c
+ stm32f0xx_pwr.c
+ 0
+ 0
+
+
+ 3
+ 29
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_rcc.c
+ stm32f0xx_rcc.c
+ 0
+ 0
+
+
+ 3
+ 30
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_rtc.c
+ stm32f0xx_rtc.c
+ 0
+ 0
+
+
+ 3
+ 31
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_spi.c
+ stm32f0xx_spi.c
+ 0
+ 0
+
+
+ 3
+ 32
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_syscfg.c
+ stm32f0xx_syscfg.c
+ 0
+ 0
+
+
+ 3
+ 33
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_tim.c
+ stm32f0xx_tim.c
+ 0
+ 0
+
+
+ 3
+ 34
+ 1
+ 0
+ 0
+ 0
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_usart.c
+ stm32f0xx_usart.c
+ 0
+ 0
+
+
+
+
+ BSP
+ 1
+ 0
+ 0
+ 0
+
+ 4
+ 35
+ 1
+ 0
+ 0
+ 0
+ ..\bsp\ad5791.c
+ ad5791.c
+ 0
+ 0
+
+
+ 4
+ 36
+ 1
+ 0
+ 0
+ 0
+ ..\bsp\key.c
+ key.c
+ 0
+ 0
+
+
+ 4
+ 37
+ 1
+ 0
+ 0
+ 0
+ ..\bsp\uart.c
+ uart.c
+ 0
+ 0
+
+
+
+
+ ::CMSIS
+ 0
+ 0
+ 0
+ 1
+
+
+
diff --git a/src/MDK/AD5791Ref.uvprojx b/src/MDK/AD5791Ref.uvprojx
new file mode 100644
index 0000000..31c9fa9
--- /dev/null
+++ b/src/MDK/AD5791Ref.uvprojx
@@ -0,0 +1,606 @@
+
+
+
+ 2.1
+
+ ### uVision Project, (C) Keil Software
+
+
+
+ AD5791Ref
+ 0x4
+ ARM-ADS
+ 5060750::V5.06 update 6 (build 750)::ARMCC
+ 0
+
+
+ STM32F070F6Px
+ STMicroelectronics
+ Keil.STM32F0xx_DFP.2.0.0
+ http://www.keil.com/pack/
+ IRAM(0x20000000,0x00001800) IROM(0x08000000,0x00008000) CPUTYPE("Cortex-M0") CLOCK(12000000) ELITTLE
+
+
+ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F0xx_32 -FS08000000 -FL08000 -FP0($$Device:STM32F070F6Px$CMSIS\Flash\STM32F0xx_32.FLM))
+ 0
+ $$Device:STM32F070F6Px$Drivers\CMSIS\Device\ST\STM32F0xx\Include\stm32f0xx.h
+
+
+
+
+
+
+
+
+
+ $$Device:STM32F070F6Px$CMSIS\SVD\STM32F0x0.svd
+ 0
+ 0
+
+
+
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 1
+
+ .\OUT\
+ PowerV7
+ 1
+ 0
+ 1
+ 1
+ 1
+ .\LIST\
+ 1
+ 0
+ 0
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+
+ 0
+ 0
+
+
+ 0
+ 0
+ 0
+ 0
+
+ 0
+
+
+
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 3
+
+
+ 1
+
+
+ SARMCM3.DLL
+ -REMAP
+ DARMCM1.DLL
+ -pCM0
+ SARMCM3.DLL
+
+ TARMCM1.DLL
+ -pCM0
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 16
+
+
+
+
+ 1
+ 0
+ 0
+ 1
+ 1
+ 4096
+
+ 1
+ BIN\UL2CM3.DLL
+
+
+
+
+
+ 0
+
+
+
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 1
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ "Cortex-M0"
+
+ 0
+ 0
+ 0
+ 1
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 8
+ 0
+ 0
+ 0
+ 0
+ 3
+ 3
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x1800
+
+
+ 1
+ 0x8000000
+ 0x8000
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 1
+ 0x8000000
+ 0x8000
+
+
+ 1
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x0
+ 0x0
+
+
+ 0
+ 0x20000000
+ 0x1800
+
+
+ 0
+ 0x0
+ 0x0
+
+
+
+
+
+ 1
+ 2
+ 0
+ 0
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0
+ 1
+ 1
+ 1
+ 1
+ 0
+ 0
+ 0
+
+ --preinclude ..\stm32f0xx_conf.h
+ STM32F030,USE_STDPERIPH_DRIVER,M_PI=3.14159265358979f
+
+ ..\..\stm32f0xxlib\CMSIS\Device\ST\STM32F0xx\Include;..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\inc;..\..\src;..\..\src\app;..\..\src\bsp;..\printf
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 1
+ 0
+ 0
+ 0
+ 1
+ 0
+ 0x08000000
+ 0x20000000
+
+
+
+
+ --keep *.o(ushtable)
+
+
+
+
+
+
+
+ USER
+
+
+ main.c
+ 1
+ ..\main.c
+
+
+ stm32f0xx_it.c
+ 1
+ ..\stm32f0xx_it.c
+
+
+
+
+ APP
+
+
+ printf.c
+ 1
+ ..\printf\printf.c
+
+
+ fifo.c
+ 1
+ ..\app\fifo.c
+
+
+ serial_frame.c
+ 1
+ ..\app\serial_frame.c
+
+
+ ush.c
+ 1
+ ..\app\ush.c
+
+
+ displed.c
+ 1
+ ..\app\displed.c
+
+
+ voltref.c
+ 1
+ ..\app\voltref.c
+
+
+ hmi.c
+ 1
+ ..\app\hmi.c
+
+
+
+
+ LIB
+
+
+ system_stm32f0xx.c
+ 1
+ ..\..\stm32f0xxlib\CMSIS\Device\ST\STM32F0xx\Source\Templates\system_stm32f0xx.c
+
+
+ startup_stm32f030.s
+ 2
+ ..\..\stm32f0xxlib\CMSIS\Device\ST\STM32F0xx\Source\Templates\arm\startup_stm32f030.s
+
+
+ stm32f0xx_wwdg.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_wwdg.c
+
+
+ stm32f0xx_adc.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_adc.c
+
+
+ stm32f0xx_can.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_can.c
+
+
+ stm32f0xx_cec.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_cec.c
+
+
+ stm32f0xx_comp.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_comp.c
+
+
+ stm32f0xx_crc.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_crc.c
+
+
+ stm32f0xx_crs.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_crs.c
+
+
+ stm32f0xx_dac.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dac.c
+
+
+ stm32f0xx_dbgmcu.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dbgmcu.c
+
+
+ stm32f0xx_dma.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_dma.c
+
+
+ stm32f0xx_exti.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_exti.c
+
+
+ stm32f0xx_flash.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_flash.c
+
+
+ stm32f0xx_gpio.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_gpio.c
+
+
+ stm32f0xx_i2c.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_i2c.c
+
+
+ stm32f0xx_iwdg.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_iwdg.c
+
+
+ stm32f0xx_misc.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_misc.c
+
+
+ stm32f0xx_pwr.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_pwr.c
+
+
+ stm32f0xx_rcc.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_rcc.c
+
+
+ stm32f0xx_rtc.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_rtc.c
+
+
+ stm32f0xx_spi.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_spi.c
+
+
+ stm32f0xx_syscfg.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_syscfg.c
+
+
+ stm32f0xx_tim.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_tim.c
+
+
+ stm32f0xx_usart.c
+ 1
+ ..\..\stm32f0xxlib\STM32F0xx_StdPeriph_Driver\src\stm32f0xx_usart.c
+
+
+
+
+ BSP
+
+
+ ad5791.c
+ 1
+ ..\bsp\ad5791.c
+
+
+ key.c
+ 1
+ ..\bsp\key.c
+
+
+ uart.c
+ 1
+ ..\bsp\uart.c
+
+
+
+
+ ::CMSIS
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Makefile b/src/Makefile
index 6c95e03..d62d08f 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,6 +7,7 @@ LDSCRIPT := ./STM32F030F4.ld
SOURCE := $(wildcard ./*.c)
SOURCE += $(wildcard ./bsp/*.c)
SOURCE += $(wildcard ./app/*.c)
+SOURCE += $(wildcard ./printf/*.c)
SOURCE += $(wildcard ../stm32f0xxlib/STM32F0xx_StdPeriph_Driver/src/*.c)
SOURCE_ASM := ../src/startup_stm32f030.s
@@ -18,6 +19,7 @@ INC_DIR += -I../stm32f0xxlib/CMSIS/Device/ST/STM32F0xx/Include
INC_DIR += -I../stm32f0xxlib/STM32F0xx_StdPeriph_Driver/inc
INC_DIR += -I./app
INC_DIR += -I./bsp
+INC_DIR += -I./printf
INC_DIR += --include ./stm32f0xx_conf.h
CC = arm-none-eabi-gcc
diff --git a/src/app/displed.c b/src/app/displed.c
new file mode 100644
index 0000000..5cf6c28
--- /dev/null
+++ b/src/app/displed.c
@@ -0,0 +1,155 @@
+#include "serial_frame.h"
+#include "string.h"
+#include "uart.h"
+#include "ush.h"
+
+#define CMD_SETBLINK 1 //start which led(s) to blink
+#define CMD_SETBLINK_SPEED 2 //set the blink speed
+#define CMD_SETCONTRASTA 3 //set the contrast level
+#define CMD_SETCONTRASTB 4 //set the contrast level
+#define CMD_PRINT 5 //print string to led.
+#define CMD_SETSCROLL_SPEED 6 //set scroll speed
+#define CMD_SAVE_SETTING 7 //save current settings as default settings.
+#define CMD_ADD_FONT 8 //add temp font.
+
+#define LEDSEGA 0x01
+#define LEDSEGB 0x02
+#define LEDSEGC 0x04
+#define LEDSEGD 0x08
+#define LEDSEGE 0x10
+#define LEDSEGF 0x20
+#define LEDSEGG 0x40
+#define LEDSEGDP 0x80
+
+static uint8_t curr_contrast = 3;
+
+uint8_t displed_getcontr(void){
+ return curr_contrast;
+}
+
+void displed_setcontr(uint8_t contr){
+ uint8_t buff[8]; //maximum number to display is 10.123456
+ if(contr > 100)
+ contr = 100;
+ USH_Print("Set contrast to %d\n", contr);
+ buff[0] = CMD_SETCONTRASTA;
+ buff[1] = 2;
+ buff[2] = 0xff;
+ buff[3] = contr;
+ curr_contrast = contr;
+ usart_for_led();
+ sframe_encode(uart_char, buff, 4);
+ usart_for_ush();
+}
+
+//highlight the seledted led. led: 0 to 3
+void displed_highlight(uint8_t led){
+ uint8_t buff[8];
+ uint8_t contr;
+ if(led>3) return;
+ buff[0] = CMD_SETCONTRASTA;
+ buff[1] = 2;
+ buff[2] = 0;
+ buff[3] = contr;
+ usart_for_led();
+ for(int8_t i=0;i<4;i++){
+ buff[2] = 1<pbuff = pbuff;
+ pfifo->buff_size = len;
+ pfifo->write_index = 0;
+ pfifo->read_index = 0;
+ pfifo->data_count = 0;
+}
+
+/**
+ * @brief get current fifo status(data count in fifo)
+ * @return count of data in fifo.
+*/
+uint32_t fifo_status(fifo_def *pfifo)
+{
+ return pfifo->data_count;
+}
+
+/**
+ * @brief write one byte to fifo.
+ * @param ch: the character to write.
+ * @return fifo_err_ok if succeeded.
+*/
+fifo_err_def fifo_write1B(fifo_def *pfifo, uint8_t ch){
+ if(pfifo->data_count >= pfifo->buff_size)
+ return fifo_err_full; //fifo is already full
+ //write one data to fifo and modify windex and data_count
+ pfifo->pbuff[pfifo->write_index] = ch;
+ //enter critical area
+ FIFO_DIS_INT();
+ pfifo->write_index ++;
+ if(pfifo->write_index == pfifo->buff_size)
+ pfifo->write_index = 0;
+ pfifo->data_count ++;
+ FIFO_EN_INT();
+ //exit critical area
+ return fifo_err_ok;
+}
+
+/**
+ * @brief read one byte from fifo.
+ * @param ch: the pointer to save data read.
+ * @return return fifo_err_ok if succeeded
+*/
+fifo_err_def fifo_read1B(fifo_def *pfifo, uint8_t *ch){
+ if(ch == 0) return fifo_err_nullp;
+ if(pfifo->data_count){ //we have data to read.
+ *ch = pfifo->pbuff[pfifo->read_index];
+ //enter critical area.
+ FIFO_DIS_INT();
+ pfifo->read_index ++;
+ if(pfifo->read_index == pfifo->buff_size)
+ pfifo->read_index = 0; //rewind to zero.
+ pfifo->data_count --;
+ FIFO_EN_INT();
+ //exit critical area.
+ return fifo_err_ok;
+ }
+ return fifo_err_empty;
+}
+
+/**
+ * @brief write a buffer to fifo.
+ * @param pbuff: the pointer to data to be stored to fifo.
+ * @param plen: the pointer to store how many data is in buffer,
+ * and used to store the actual stored data count.
+ * @return fifo_err_ok if succeeded. If not all data are written, also return fifo_err_ok,
+ * read plen to determine the actual written data count.
+*/
+fifo_err_def fifo_write(fifo_def *pfifo, uint8_t *pbuff, uint32_t *plen){
+ uint32_t write_len = *plen;
+ uint32_t temp;
+ if(pfifo->data_count >= pfifo->buff_size)
+ return fifo_err_full;
+ /* step1, how many data we can write? */
+ write_len = write_len > pfifo->buff_size-pfifo->data_count?\
+ pfifo->buff_size-pfifo->data_count : write_len;
+ /* step2, how many data can be written directly to the buffer. */
+ temp = pfifo->buff_size - pfifo->write_index; //we write from 'write_index' to end of buffer.
+ if(write_len < temp){ //good, we can write all data at once.
+ memcpy(pfifo->pbuff+pfifo->write_index, pbuff, write_len);
+ /* !modify critical pointers. */
+ FIFO_DIS_INT();
+ pfifo->write_index += write_len;
+ pfifo->data_count += write_len;
+ FIFO_EN_INT();
+ /* exit critical area. */
+ }
+ else{ //we need two steps to write.
+ //firstly, write data until to end of buffer.
+ memcpy(pfifo->pbuff+pfifo->write_index, pbuff, temp);
+ //then write from start of buffer.
+ if(write_len != temp) //we do need the second write.
+ memcpy(pfifo->pbuff, pbuff+temp, write_len-temp);
+ /* !modify critical pointers. */
+ FIFO_DIS_INT();
+ pfifo->write_index = write_len-temp;
+ pfifo->data_count += write_len;
+ FIFO_EN_INT();
+ /* exit critical area. */
+ }
+ *plen = write_len;
+ return fifo_err_ok;
+}
+
+/**
+ * @brief read from fifo to a buffer.
+ * @param pbuff: the buffer used to store data read.
+ * @param plen: the pointer to say how many data expected to read. It also stores the
+ * actual data count read to buffer.
+ * @return fifo_err_ok if succeeded.
+*/
+fifo_err_def fifo_read(fifo_def *pfifo, uint8_t *pbuff, uint32_t *plen)
+{
+ uint32_t read_len, temp;
+ if(pfifo->data_count == 0)
+ return fifo_err_empty;
+ read_len = pfifo->data_count > *plen?\
+ *plen: pfifo->data_count;
+ /* How many data we can read directly from buffer? */
+ temp = pfifo->buff_size - pfifo->read_index;
+ if(read_len < temp){ //good, we can read directly.
+ memcpy(pbuff, pfifo->pbuff+pfifo->read_index, read_len);
+ //enter critical area.
+ FIFO_DIS_INT();
+ pfifo->read_index += read_len;
+ pfifo->data_count -= read_len;
+ FIFO_EN_INT();
+ //exit critical area.
+ }
+ else{//we need two steps to read all data.
+ memcpy(pbuff, pfifo->pbuff + pfifo->read_index, temp);
+ //then read from buffer start.
+ if(read_len != temp)
+ memcpy(pbuff+temp, pfifo->pbuff, read_len-temp);
+ /* enter critical area */
+ FIFO_DIS_INT();
+ pfifo->read_index = read_len - temp;
+ pfifo->data_count -= read_len;
+ FIFO_EN_INT();
+ //exit critical area.
+ }
+ *plen = read_len;
+ return fifo_err_ok;
+}
diff --git a/src/app/fifo.h b/src/app/fifo.h
new file mode 100644
index 0000000..53a78a5
--- /dev/null
+++ b/src/app/fifo.h
@@ -0,0 +1,32 @@
+#ifndef _FIFO_H_
+#define _FIFO_H_
+#include "stdint.h"
+
+#define FIFO_DIS_INT() NVIC_DisableIRQ(USART1_IRQn)//disableInterrupts() //disable interrupt
+#define FIFO_EN_INT() NVIC_EnableIRQ(USART1_IRQn)//enableInterrupts() //enable interrupt again.
+
+typedef enum
+{
+ fifo_err_ok = 0,
+ fifo_err_full = -1,
+ fifo_err_empty = -2,
+ fifo_err_nullp = -3, //null pointer provided.
+}fifo_err_def;
+
+typedef struct
+{
+ uint8_t *pbuff;
+ uint32_t buff_size;
+ uint32_t write_index;
+ uint32_t read_index;
+ uint32_t data_count;
+}fifo_def;
+
+void fifo_init(fifo_def *pfifo, uint8_t *pbuff, uint32_t len);
+uint32_t fifo_status(fifo_def *pfifo);
+fifo_err_def fifo_write1B(fifo_def *pfifo, uint8_t ch);
+fifo_err_def fifo_read1B(fifo_def *pfifo, uint8_t *ch);
+fifo_err_def fifo_write(fifo_def *pfifo, uint8_t *pbuff, uint32_t *plen);
+fifo_err_def fifo_read(fifo_def *pfifo, uint8_t *pbuff, uint32_t *plen);
+
+#endif
diff --git a/src/app/hmi.c b/src/app/hmi.c
new file mode 100644
index 0000000..60c90f3
--- /dev/null
+++ b/src/app/hmi.c
@@ -0,0 +1,164 @@
+#include "hmi.h"
+#include "key.h"
+#include "displed.h"
+#include "printf.h"
+
+/**
+ * Get input from key/encoder and control display and peripherals.
+*/
+#define MAINMENU_0 0
+#define MAX_MAIN_MENU 2
+
+float voltref_get_value(void);
+static int32_t mainmenu, submenu, menudepth = 1;
+static uint8_t flag_update_disp; //the flag means that display should be updated.
+void hmi_init(void){
+ mainmenu = 0;
+ submenu = 0;
+ key_init();
+ displed_init();
+}
+
+static void disp_update(void){
+ #define MAX_CONTR_INDEX 3
+ char str[8];
+ if(flag_update_disp == 0) return;
+ flag_update_disp = 0;
+ switch (mainmenu){
+ case 0:
+ if(menudepth == 0){ //display current voltage setting.
+ float volt;
+ volt = voltref_get_value();
+ snprintf(str, 8, "%.6f", volt);
+ displed_str(str);
+ }
+ break;
+ case 1:
+ if(menudepth == 0)
+ displed_str("CONt."); //contraset
+ else{
+ snprintf(str, 8, "C%03d", displed_getcontr());
+ displed_str(str);
+ if(menudepth == 1){
+ displed_set_blink(0); //disable all.
+ displed_highlight(3-submenu);
+ }
+ if(menudepth == 2){
+ displed_set_blink(1<<(3-submenu));
+ }
+ }
+ break;
+ case 2:
+ displed_str("HEL.O"); //contraset
+ default:
+ break;
+ }
+}
+
+static inline void _mainmenu_update(int8_t delta){
+ if(delta)
+ flag_update_disp = 1;//if main menu changed, we always need to update screen.
+ mainmenu += delta;
+ if(mainmenu > MAX_MAIN_MENU)
+ mainmenu = MAX_MAIN_MENU;
+ if(mainmenu < 0)
+ mainmenu = 0;
+}
+
+static uint32_t ipow(uint32_t x, uint32_t y){
+ uint32_t res = x;
+ if(y == 0) return 1;
+ if(y == 1) return res;
+ y--;
+ while(y--)
+ res *= x;
+ return res;
+}
+
+static void hmi_process_key(int8_t encoder, uint8_t key){
+ if(menudepth == 0){//going through the main menu
+ _mainmenu_update(encoder);
+ if(key == KEY_OK){ //go to submemue;
+ menudepth = 1;
+ flag_update_disp = 1;
+ submenu = 0;
+ return;
+ }
+ }
+ if(key == (KEY_PRESS_L|KEY_OK)){
+ if(menudepth){
+ menudepth --;
+ flag_update_disp = 1;
+ submenu = 0;
+ }
+ return;
+ }
+ switch (mainmenu){
+ case MAINMENU_0:
+ if(menudepth == 1){ //go through voltage in 1.
+ if(encoder){//adjust submenu position
+ submenu += encoder;
+ if(submenu < 0) submenu = 0;
+ if(submenu > 7) submenu = 7;
+ }
+ }
+ else if(menudepth == 2){//set voltage.
+ if(encoder){//adjusting value
+ float volt = voltref_get_value(); //get current settings.
+ volt = volt + ipow(10, 8-submenu)*encoder;
+ }
+ }
+
+ break;
+ case 1: //set contrast.
+ if(menudepth == 1){//go through value
+ if(encoder){//adjust submenu position
+ submenu += -encoder;
+ if(submenu < 0) submenu = 0;
+ if(submenu > 2) submenu = 2;
+ }
+ if(key == KEY_OK){
+ flag_update_disp = 1;
+ menudepth = 2;
+ }
+ }
+ else if(menudepth == 2){
+ if(encoder){
+ int8_t contr = displed_getcontr();
+ contr += encoder*ipow(10, submenu);
+ if(contr < 100&&contr>0)
+ displed_setcontr(contr);
+ }
+ if(key == KEY_OK)
+ menudepth = 1;
+ }
+ flag_update_disp = 1;
+ break;
+ case 2:
+ break;
+ default:
+ break;
+ }
+}
+
+void hmi_disp_update(void){
+ flag_update_disp = 1;
+ disp_update();
+}
+
+void hmi_poll(void){
+ static uint8_t key_pre;
+ static uint8_t encoder_pre;
+ uint8_t key = get_key();
+ uint8_t encoder = get_encoder();
+
+ if((encoder != encoder_pre) || (key != key_pre)){
+ int8_t temp;
+ temp = (int8_t)(encoder - encoder_pre);
+ encoder_pre = encoder;
+ key_pre = key;
+ hmi_process_key(temp, key);
+ printf("Encode delta:%d\n", temp);
+ disp_update();
+ }
+}
diff --git a/src/app/hmi.h b/src/app/hmi.h
new file mode 100644
index 0000000..cc3374c
--- /dev/null
+++ b/src/app/hmi.h
@@ -0,0 +1,9 @@
+#ifndef _HMI_H_
+#define _HMI_H_
+#include "stdint.h"
+
+void hmi_init(void);
+void hmi_poll(void);
+void hmi_disp_update(void);
+
+#endif
diff --git a/src/app/menu.c b/src/app/menu.c
new file mode 100644
index 0000000..7d4ea1f
--- /dev/null
+++ b/src/app/menu.c
@@ -0,0 +1,17 @@
+#include "menu.h"
+
+menu_error_def menu_init(menu_node_def *head){
+
+ return menu_error_ok;
+}
+
+menu_error_def menu_append_brother(menu_node_def *pbrother){
+
+ return menu_error_ok;
+}
+
+menu_error_def menu_append_submenu(menu_node_def *pfather, menu_node_def *menu_node){
+
+ return menu_error_ok;
+}
+
diff --git a/src/app/menu.h b/src/app/menu.h
new file mode 100644
index 0000000..6227d18
--- /dev/null
+++ b/src/app/menu.h
@@ -0,0 +1,21 @@
+#ifndef _MENU_H_
+#define _MENU_H_
+
+typedef enum{
+ menu_error_ok = 0,
+}menu_error_def;
+
+typedef struct _menu_node{
+ struct _menu_node *parent;
+ struct _menu_node *brother;
+ void (*update)(menu_event_def event, void *para);
+ char *name;
+}menu_node_def;
+
+typedef enum{
+ menu_event_key = 0, /**< key value has changed */
+ menu_event_encoder, /**< encoder value has changed. */
+
+}menu_event_def;
+
+#endif
diff --git a/src/app/serial_frame.c b/src/app/serial_frame.c
new file mode 100644
index 0000000..404f87f
--- /dev/null
+++ b/src/app/serial_frame.c
@@ -0,0 +1,111 @@
+/**
+ * Serial frame uses the similar method in HDLC protocol.
+ * high level data link control protocol
+ * 0x7d as frame start and 0x7c as end marker(not same as HDLC)
+ * 0x7e is the escape character, both data 0x7d and 0x7e should be
+ * escaped with 0x7e + data^0x20.
+ * So, data 0x7e will be encoded to 0x7e+0x5e; data 0x7d will be
+ * encoded to 0x7e+0x5d
+ * */
+#include "serial_frame.h"
+
+/**
+ * @brief init sframe with given buffer(and size) and function pointer.
+ * @param pbuff: the buffer used to store frame received.
+ * @param buffsz: buffer size.
+ * @param callback: the function pointer that will be called when valid frame is received.
+ * @return none.
+*/
+void sframe_init(sframe_def *psframe, uint8_t *pbuff, uint32_t buffsz, sframe_callback callback){
+ if(psframe == 0) return;
+ psframe->pbuff = pbuff;
+ psframe->buffsz = buffsz;
+ psframe->state = sframe_state_start;
+ psframe->frame_len = 0;
+ psframe->windex = 0;
+ psframe->callback = callback;
+}
+
+/**
+ * @brief decode the input data in buffer.
+ * @return return 0.
+*/
+int32_t sframe_decode(sframe_def *psframe, uint8_t *pinput, uint32_t len){
+ while(len--){
+ if(psframe->state != sframe_state_end)
+ if(*pinput == SFRAME_STOP) //if we received unexpected STOP flag, restart the parser.
+ psframe->state = sframe_state_start;
+ switch(psframe->state){
+ case sframe_state_start: //waiting for start flag.
+ if(*pinput == SFRAME_START)
+ psframe->state = sframe_state_framelen; //next byte is frame length
+ break;
+ case sframe_state_framelen: //frame length
+ psframe->frame_len = *pinput;
+ psframe->state = sframe_state_payload;
+ break;
+ case sframe_state_payload:
+ if(*pinput == SFRAME_ESCAPE)
+ psframe->state = sframe_state_escaping; //this is not a data.
+ else
+ psframe->pbuff[psframe->windex++] = *pinput;
+ if(psframe->windex == psframe->frame_len)
+ //we got enough data, check the end flag.
+ psframe->state = sframe_state_end;
+ break;
+ case sframe_state_escaping: //this is an escaping data.
+ psframe->pbuff[psframe->windex++] = *pinput ^ 0x20;
+ psframe->state = sframe_state_payload;
+ if(psframe->windex == psframe->frame_len)
+ //we got enough data, check the end flag.
+ psframe->state = sframe_state_end;
+ break;
+ case sframe_state_end:
+ if(*pinput == SFRAME_STOP){
+ if(psframe->callback)
+ psframe->callback(psframe->pbuff, psframe->frame_len);
+ psframe->state = sframe_state_start;
+ psframe->windex = 0;
+ }
+ break;
+ }
+ pinput ++;
+ }
+ return 0;
+}
+
+/**
+ * @brief encode the data and output it through function pfunc.
+ * @param pfunc: the function used to output one character.
+ * @param pdata: pointer to the data.
+ * @param len: data length.
+ * @return none.
+*/
+int32_t sframe_encode(sframe_outfunc pfunc, uint8_t *pdata, uint32_t len){
+ if(pdata == 0) return 0;
+ if(pfunc == 0) return 0;
+ if(len == 0) return 0;
+ /**
+ * send out frame start and frame length.
+ */
+ pfunc((uint8_t)SFRAME_START);
+ pfunc((uint8_t)len);
+ //sending out data
+ while(len){
+ switch (*pdata){
+ case SFRAME_START:
+ case SFRAME_STOP:
+ case SFRAME_ESCAPE:
+ pfunc((uint8_t)SFRAME_ESCAPE);
+ pfunc(*pdata++ ^ 0x20);
+ len --;
+ continue;
+ }
+ pfunc(*pdata++);
+ len--;
+ }
+ pfunc((uint8_t)SFRAME_STOP);
+ pfunc((uint8_t)SFRAME_STOP);
+ return 0;
+}
+
diff --git a/src/app/serial_frame.h b/src/app/serial_frame.h
new file mode 100644
index 0000000..823ded0
--- /dev/null
+++ b/src/app/serial_frame.h
@@ -0,0 +1,38 @@
+#ifndef _SERIAL_FRAME_H_
+#define _SERIAL_FRAME_H_
+#include "stdint.h"
+
+#define SFRAME_START 0x7d
+#define SFRAME_STOP 0x7c //i don't want to use same mark as start and stop.
+#define SFRAME_ESCAPE 0x7e
+
+typedef enum{
+ sframe_state_start = 0,
+ sframe_state_framelen,
+ sframe_state_payload,
+ sframe_state_escaping,
+ sframe_state_crc,
+ sframe_state_end,
+}sframe_state_def;
+
+typedef void (*sframe_callback)(uint8_t*, uint32_t);
+typedef void (*sframe_outfunc)(uint8_t);
+
+/**
+ * @brief this structure is only used for decoder.
+ * The encoder will send out data when encoding.
+*/
+typedef struct _sframe{
+ uint8_t *pbuff; /**< buffer used to store decoded frame. */
+ uint32_t buffsz; /**< buffer size */
+ uint32_t frame_len; /**< decoded frame length. */
+ uint32_t windex; /**< the index to current buff position */
+ sframe_state_def state; /**< current state. */
+ sframe_callback callback; /**< the function that will be called if a frame is successfully decode. */
+}sframe_def;
+
+void sframe_init(sframe_def *psframe, uint8_t *pbuff, uint32_t buffsz, sframe_callback callback);
+int32_t sframe_decode(sframe_def *psframe, uint8_t *pinput, uint32_t len);
+int32_t sframe_encode(sframe_outfunc pfunc, uint8_t *pdata, uint32_t len);
+
+#endif
diff --git a/src/app/ush.c b/src/app/ush.c
new file mode 100644
index 0000000..bb2af1b
--- /dev/null
+++ b/src/app/ush.c
@@ -0,0 +1,510 @@
+/**
+ * @author Neo Xu (neo.xu1990@gmail.com)
+ * @license The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Neo Xu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * @brief ush - micro-shell is a shell for embedded devices.
+*/
+#include "ush.h"
+
+/**
+ * The commands that defined by macro USH_REGISTER are stored in 'ushsection' section.
+ * The commands that registered by function ush_cmd_append() is listed to list ush_list;
+ * */
+#ifdef __CC_ARM
+extern int ushtable$$Base;
+extern int ushtable$$Limit;
+#define _USH_TABLE_START (ush_cmd_def *)&ushtable$$Base
+#define _USH_TABLE_END (ush_cmd_def *)&ushtable$$Limit
+#elif defined(__GNUC__)
+extern const uint32_t __start_ushsection;
+extern const uint32_t __end_ushsection;
+#define _USH_TABLE_START (ush_cmd_def *)&__start_ushsection
+#define _USH_TABLE_END (ush_cmd_def *)&__end_ushsection
+#endif
+
+static ush_list_def *ush_list = {0}; /**< the ush command list added dynamically */
+
+/**
+ * @brief if the character is mark of end-of-line
+*/
+#define _ush_is_endofline(ch) ((ch == '\r') || (ch =='\n'))
+
+/**
+ * @brief if the character is a seperator
+*/
+#define _ush_is_seperator(ch) ((ch == ' ') || (ch =='\t'))
+
+/**
+ * @brief compare if the cmd is equal to the input string.
+ * @return return 1 if the two string are same.
+*/
+static inline uint8_t _ush_is_str_same(const uint8_t *cmd, const uint8_t *str){
+ while(*cmd && *str){
+ if(*cmd != *str)
+ return 0;
+ cmd++; str++;
+ }
+ if((*cmd == 0) && (*str == 0))
+ return 1; //the string has same length.
+ return 0;
+}
+
+/**
+ * @brief find a command from build-in table and dynamic list.
+ * @param cmd: the command string.
+ * @return return the function pointer if found, otherwise, return 0.
+*/
+static inline ush_func_def ush_find_cmd(uint8_t const *cmd){
+ ush_cmd_def *pcmd;
+ ush_list_def *plist;
+ plist = ush_list; //find it in the list.
+ while(plist){
+ if(_ush_is_str_same(cmd, plist->item->cmd))
+ return (ush_func_def)plist->item->func;
+ plist = plist->next;
+ }
+ for(pcmd = _USH_TABLE_START;pcmd<_USH_TABLE_END;pcmd++){
+ if(_ush_is_str_same(cmd, pcmd->cmd))
+ return (ush_func_def)pcmd->func;
+ }
+ return 0;
+}
+
+/**
+ * @brief Parse the input line buffer and split the input to argv.
+ * @note: character '\r' or '\n' is end mark of valid input command.
+ * character ' ' or '\t' is the sperator of parameters.
+ * '\0' is regarded as a normall input.
+ * If pairs of character '\"' show up in parameter, the content between it them
+ * is regarded as one whole parameter, no matter what's inside of it. Example:
+ * [echo "hello world!""Nice to meet you" \n] is decoded to :
+ * param1: [echo]
+ * param2: [hello world!], note chareter \" is removed.
+ * param3: [Nice to meet you]
+ * All other characters are regarded as valid parameters.
+ * @param pline: pointer to the line input buffer.
+ * @param buff_len: line buffer size, the parser will stop if it reaches end of buffer.
+ * @param pargc: pointer to store how many arguments are found.
+ * @param argv: buffer used to store all pointers to parameters.
+*/
+static inline ush_error_def ush_parser(uint8_t *pline, uint32_t buff_len, uint32_t *pargc, uint8_t *argv[USH_MAX_ARG]){
+ ush_error_def err = ush_error_ok;
+ uint32_t argc;
+ uint8_t flag_found_quotation = 0;
+ uint8_t flag_escaping = 0;
+ if(pline == 0) return ush_error_nullp;
+ if(pargc == 0) return ush_error_nullp;
+ if(argv == 0) return ush_error_nullp;
+ if(buff_len == 0) return ush_error_nocmd;
+ argc = 0; //init it to zero.
+ while(*pline){
+ if(argc == USH_MAX_ARG){
+ err = ush_error_maxarg;
+ break;
+ }
+ //skip existing seperators
+ while(*pline && buff_len){
+ if(!_ush_is_seperator(*pline)) break;
+ *pline = '\0'; //make is invalid.
+ buff_len--;
+ pline++;
+ }
+ //are we reaching to end of input?
+ if(buff_len == 0) break;
+ if(*pline == '\"'){ //we are meeting a possible string.
+ *pline = 0; /* Make it as 0 */
+ uint8_t *pstr_start = ++pline; //start of string.
+ //do we have another valid '\""'? otherwise, the parameter is not completed.
+ while(*pline && buff_len){
+ if(flag_escaping)
+ flag_escaping = 0;
+ else if(*pline == '\"'){//great, we have found one pair of \"
+ flag_found_quotation = 1;
+ *pline = '\0'; //mark it as end of parameter.
+ if(pline == pstr_start);//this is an empty string.
+ else
+ argv[argc++] = pstr_start;
+ pline++; buff_len--; //go to next one before break.
+ break;
+ }
+ else if(*pline == '\\'){ //next string should be escaped.
+ flag_escaping = 1;
+ }
+ pline++; buff_len--;
+ }
+ if(flag_found_quotation == 0){
+ err = ush_error_str;
+ break; //return and report founded arguements till now.
+ }
+ else{
+ flag_found_quotation = 0;
+ continue; /* We have found a string and pointer has been moved to end of string. */
+ }
+ }
+ else
+ argv[argc++] = pline;
+ //skip this parameter
+ while(*pline && buff_len){
+ if(_ush_is_seperator(*pline)) break;
+ if(_ush_is_endofline(*pline)) break;
+ if(*pline == '\"') break; /* This is the case [hello"123 4"], so here " acts like a seperator */
+ buff_len--;
+ pline++;
+ }
+ }
+ *pargc = argc;
+ return err;
+}
+/**
+ * @brief process a line buffer ended with \r or \n
+*/
+static inline ush_error_def ush_process_line(ush_def *ush){
+ ush_func_def pfunc;
+ int32_t ret;
+ ush_error_def error = ush_error_ok;
+
+ error = ush_parser(ush->linebuff, ush->w_pos, &ush->argc, ush->argv);
+ if(error != ush_error_ok) return error;
+ if(ush->argc < 1) return ush_error_nocmd;
+ pfunc = ush_find_cmd(ush->argv[0]);
+ if(pfunc){
+ ret = pfunc(ush->argc, ush->argv);
+ USH_Print("ret \t0x%08x\n", ret);
+ }
+ else{
+ error = ush_error_nocmd;
+ USH_Print("error command not found\n");
+ }
+ USH_Print(USH_ECHO);
+ return error;
+}
+
+/**
+ * @brief process the input data, execute the command if found.
+ * @param pline: the buffer for input data.
+ * @param len: length of the linebuffer.
+ * @return return ush_error_ok if succeeded.
+*/
+ush_error_def ush_process_input(ush_def *ush, const uint8_t *pbuff, uint32_t len){
+ ush_error_def err = ush_error_ok;
+ uint8_t ch;
+ if(ush == 0) return ush_error_nullp;
+ if(pbuff == 0) return ush_error_nullp;
+ while(len--){ /* copy all input to line buffer, and check if there is end-of-line */
+ ch = *pbuff++;
+ ush->linebuff[ush->w_pos] = ch;
+ if(ush->state == ush_state_in_str){
+ ush->w_pos ++; //store it and move on.
+ if(ch == '\\'){
+ ush->state = ush_state_escaping; //next input should be escaped, no matter what it is.
+ }
+ else if(ch == '\"'){ //end of string.
+ ush->state = ush_state_normal;
+ }
+ }
+ else if(ush->state == ush_state_escaping){
+ /**
+ * No matter what charecter this one is, it's regarded as normal input.
+ * Specially for string \", this " is not regarded as end of string.
+ */
+ ush->w_pos++;//move on to next one.
+ ush->state = ush_state_in_str; //go back to string input mode.
+ }
+ else{//this is a normal input
+ if(_ush_is_endofline(ch)){//input is completed
+ ush->linebuff[ush->w_pos] = '\0';
+ err = ush_process_line(ush);
+ //we don't check the return value, as we cannot do anything to it.
+ ush->w_pos = 0; //rewind to start of line buffer.
+ continue;
+ }
+ else if(ch == '\"'){ //the input is a string.
+ ush->state = ush_state_in_str;
+ }
+ ush->w_pos++; //this is just a normal input.
+ }
+ if(ush->w_pos == ush->buffsz){//the input is too long. we reset and return error.
+ ush->w_pos = 0;
+ ush->state = ush_state_normal;
+ }
+ }
+ return err;
+}
+
+/**
+ * @brief add a new command to list dynamically.
+ * @param pitem: the list element
+ * @return return ush_erro_ok.
+*/
+ush_error_def ush_cmdlist_append(ush_list_def *pitem){
+ if(ush_list) //there is item in the list.
+ pitem->next = ush_list;
+ ush_list = pitem;
+ return ush_error_ok;
+}
+/**
+ * @brief init ush with provided buffer to store line input
+ * @param pbuff: the line buffer.
+ * @param len: length of the buffer.
+ * @return return ush_erro_ok.
+*/
+ush_error_def ush_init(ush_def *ush, uint8_t *pbuff, uint32_t len){
+ if(ush == 0) return ush_error_nullp;
+ if(pbuff == 0) return ush_error_nullp;
+ if(len == 0) return ush_error_buffsz;
+ ush->argc = 0;
+ ush->buffsz = len;
+ ush->linebuff = pbuff;
+ ush->state = ush_state_normal;
+ ush->w_pos = 0;
+ return ush_error_ok;
+}
+
+/**
+ * @brief try to tanslate a string to number. double is not supported.
+ * @param pstr: the input string.
+ * @param len: length of the input string.
+ * @param value: pointer to a 32bit address to store data.
+ * @return return ush_error_ok if no erros in string.
+*/
+ush_error_def ush_str2num(const uint8_t *pstr, uint32_t len, ush_num_def* num_type, void *value){
+ uint32_t num_base; /* base is either binary[0b] or oct[0] or hex[0x] or dec. */
+ double fvalue;
+ uint8_t point_pos;
+ uint8_t flag_negative_sign = 0;
+ uint8_t flag_point = 0;
+ //firstly get over the seperator
+ while(*pstr && len){
+ if(_ush_is_seperator(*pstr)){
+ pstr++;
+ len --;
+ }
+ else
+ break;
+ }
+ //detect sign
+ if(len){
+ if(*pstr == '-'){
+ flag_negative_sign = 1;
+ pstr ++;
+ len --;
+ }
+ }
+ else
+ return ush_error_nullstr;
+
+ //detect number base
+ if(len){
+ if(pstr[0] == '0'){// we need at least 2 characters for binary and hex based number.
+ if(len>1){// started with 0 but has more number.
+ pstr++;
+ if((pstr[0] == 'b') || (pstr[0] == 'B')){//binary
+ num_base = 2;
+ pstr++; //goto number
+ }
+ else if((pstr[0] == 'x') || (pstr[0] == 'X')){//hex
+ num_base = 16;
+ pstr++; //goto number
+ }
+ else if(pstr[0] != '.') //except 0.123
+ num_base = 8; //next character is number
+ else
+ num_base = 10;
+ }
+ else{
+ *(uint32_t*)value = 0;
+ *num_type = ush_num_uint32;
+ return ush_error_ok;
+ }
+ }
+ else
+ num_base = 10;
+ }
+ else
+ return ush_error_strillegal; //null or illegal
+ //decode string to number
+ fvalue = 0;//init value to zero;
+ point_pos = 0;
+ while(*pstr && len){
+ if(*pstr == '.'){
+ if(flag_point){//already got a point
+ return ush_error_strillegal; //illegal string.
+ }
+ else
+ flag_point = 1;
+ pstr ++;
+ len --;
+ continue;
+ }
+ if(flag_point)
+ point_pos++; //got a input after point. eg: 9.1
+ if(num_base == 2){
+ fvalue *= 2;
+ if(*pstr == '0')
+ ;//pass
+ else if(*pstr == '1')
+ fvalue += 1;
+ else
+ return ush_error_strillegal;//illegal value
+ }
+ else if(num_base == 8){
+ fvalue *= 8;
+ if((*pstr >= '0') && (*pstr<='7'))
+ fvalue += *pstr - '0';
+ else
+ return ush_error_strillegal;//illegal value
+ }
+ else if(num_base == 10){
+ fvalue *= 10;
+ if((*pstr >= '0') && (*pstr<='9'))
+ fvalue += *pstr - '0';
+ else
+ return ush_error_strillegal;//illegal value
+ }
+ else{//base 16
+ fvalue *= 16;
+ if((*pstr >= '0') && (*pstr<='9'))
+ fvalue += *pstr - '0';
+ else if((*pstr >= 'a') && (*pstr<='f'))
+ fvalue += *pstr - 'a' + 10;
+ else if((*pstr >= 'A') && (*pstr<='F'))
+ fvalue += *pstr - 'A' + 10;
+ else
+ return ush_error_strillegal;//illegal value
+ }
+ pstr ++;
+ len --;
+ }
+ while(point_pos--)
+ fvalue /= num_base;
+ if(flag_point){
+ if(flag_negative_sign)
+ fvalue = -fvalue;
+ *(float*)value = fvalue;
+ *num_type = ush_num_float;
+ }
+ else{
+ uint32_t uvalue = fvalue+0.5f;
+ *num_type = ush_num_uint32;
+ if(flag_negative_sign){
+ *(int32_t*)value = -uvalue;
+ *num_type = ush_num_int32;
+ }
+ else{
+ *(uint32_t*)value = uvalue;
+ *num_type = ush_num_int32;
+ }
+ }
+ return ush_error_ok;
+}
+
+/**
+ * @brief build-in function to say hello
+*/
+static int32_t ush_hello(uint32_t argc, uint8_t **argv){
+ USH_Print("hello from ush \n");
+ USH_Print("found argc:%d\n",argc);
+ for(int i=0;i>8)&0xf,\
+ (USH_VER_NUMBER>>4)&0xf,\
+ USH_VER_NUMBER&0xf);
+ for(pcmd = _USH_TABLE_START;pcmd<_USH_TABLE_END;pcmd++){
+ USH_Print("%-8s --\t%s\n", pcmd->cmd, pcmd->desc);
+ }
+ if(ush_list)
+ while(plist){
+ USH_Print("%-8s --\t%s\n", plist->item->cmd, plist->item->desc);
+ plist = plist->next;
+ }
+ return 0x87654321;
+}
+USH_REGISTER(ush_help, help, list the supported functions);
+USH_REGISTER(ush_help, ?, list the supported functions); /** example of registering one function with different command. */
+
+/**
+ * @brief convert the parameters to number and print it out.
+*/
+static int32_t ush_print_num(uint32_t argc, uint8_t **argv){
+ ush_num_def num_type;
+ uint32_t value;
+ argc--;
+ argv++;
+ if(argc == 0){
+ USH_Print("error need to input a number.\n");
+ }
+ while(argc--){
+ uint32_t str_len = 0;
+ for(int i=0;;i++){
+ if((*argv)[i] == '\0')
+ break;
+ str_len ++;
+ }
+ if(ush_str2num(*argv, str_len, &num_type, &value) == ush_error_ok){
+ USH_Print("value type is ");
+ switch(num_type){
+ case ush_num_uint32: USH_Print("uint32_t:%u\n",value); break;
+ case ush_num_int32 : USH_Print("int32_t:%d\n",(int32_t)value); break;
+ case ush_num_float : USH_Print("float:%f\n",*(float *)(&value)); break;
+ default:USH_Print("unknown\n"); break;
+ }
+ }
+ else
+ {
+ USH_Print("String[%s] is illegal\n", *argv);
+ }
+ argv ++;
+ }
+ return 0;
+}
+USH_REGISTER(ush_print_num, num, convert string to number);
+//ush_error_def ush_str2num(const uint8_t *pstr, uint32_t len, ush_num_def* num_type, void *value){
+
+/**
+ * @brief example to add a new command to list dynamically.
+*/
+static int32_t ush_debug(uint32_t argc, uint8_t **argv){
+ static const ush_cmd_def cmd_hello = {
+ .func = ush_hello,
+ .cmd = "h",
+ .desc = "say hello"
+ };
+ static ush_list_def list_hello={
+ .next = 0,
+ .item = &cmd_hello,
+ };
+
+ ush_cmdlist_append(&list_hello);
+ return 0;
+}
+USH_REGISTER(ush_debug, debug, Enable the build-in commands);
diff --git a/src/app/ush.h b/src/app/ush.h
new file mode 100644
index 0000000..cc7b39a
--- /dev/null
+++ b/src/app/ush.h
@@ -0,0 +1,102 @@
+/**
+ * @author Neo Xu (neo.xu1990@gmail.com)
+ * @license The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Neo Xu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * @brief ush - micro-shell is a shell for embedded devices.
+*/
+
+#ifndef _USH_H_
+#define _USH_H_
+#include "stdint.h"
+
+#define USH_MAX_ARG 128
+#define USH_ECHO "ush>>"
+
+#include "printf.h"
+#define USH_Print printf /**< define the method to output message. */
+
+#define USH_VER_NUMBER 0x010 //0.1.0
+
+typedef enum{
+ ush_error_ok = 0, /**< all ok */
+ ush_error_nullp = -1, /**< null pointer */
+ ush_error_nocmd = -2, /**< no valid command found */
+ ush_error_maxarg = -3, /**< reached to maximum arguments allowed */
+ ush_error_buffsz = -4, /**< line buffer size is limted. */
+ ush_error_str = -5, /**< the string parameter is incompleted. */
+ ush_error_nullstr = -6, /**< input string is null. */
+ ush_error_strillegal = -7,/**=0;i--)
- {
- xPrintf_PutChar(result[i]);
- }
-}
-
-unsigned char Isdigit(char c)
-{
- if((c >= 0x30) && (c <= 0x39))
- return 1;
- else
- return 0;
-}
-
-int atoi(char *str)
-{
- int num = 0;;
-
- while(Isdigit(*str))
- {
- num *= 10;
- num += (*str++) - 0x30;
- }
- return num;
-}
-static unsigned char buf[128];
-
-
-// does a more powerful printf (supports %d, %u, %o, %x, %c, %s)
-// Supports:
-// %d - decimal
-// %u - unsigned decimal
-// %o - octal
-// %x - hex
-// %c - character
-// %s - strings
-// and the width,precision,padding modifiers
-// **this printf does not support floating point numbers
-
-int xPrintf(const char *sfmt, ...)
-{
- register unsigned char *f, *bp;
- register long l;
- register unsigned long u;
- register int i;
- register int fmt;
- register unsigned char pad = ' ';
- int flush_left = 0, f_width = 0, prec = 2^32-1, hash = 0, do_long = 0;
- int sign = 0;
-
- va_list ap;
- va_start(ap, sfmt);
-
- f = (unsigned char *) sfmt;
-
- for (; *f; f++)
- {
- if (*f != '%')
- { // not a format character
- // then just output the char
- xPrintf_PutChar(*f);
- }
- else
- {
- f++; // if we have a "%" then skip it
- if (*f == '-')
- {
- flush_left = 1; // minus: flush left
- f++;
- }
- if (*f == '0'
- || *f == '.')
- {
- // padding with 0 rather than blank
- pad = '0';
- f++;
- }
- if (*f == '*')
- { // field width
- f_width = va_arg(ap, int);
- f++;
- }
- else if (Isdigit(*f))
- {
- f_width = atoi((char *) f);
- while (Isdigit(*f))
- f++; // skip the digits
- }
- if (*f == '.')
- { // precision
- f++;
- if (*f == '*')
- {
- prec = va_arg(ap, int);
- f++;
- }
- else if (Isdigit(*f))
- {
- prec = atoi((char *) f);
- while (Isdigit(*f))
- f++; // skip the digits
- }
- }
- if (*f == '#')
- { // alternate form
- hash = 1;
- f++;
- }
- if (*f == 'l')
- { // long format
- do_long = 1;
- f++;
- }
-
- fmt = *f;
- bp = buf;
- switch (fmt) { // do the formatting
- case 'd': // 'd' signed decimal
- if (do_long)
- l = va_arg(ap, long);
- else
- l = (long) (va_arg(ap, int));
- if (l < 0)
- {
- sign = 1;
- l = -l;
- }
- do {
- *bp++ = l % 10 + '0';
- } while ((l /= 10) > 0);
- if (sign)
- *bp++ = '-';
- f_width = f_width - (bp - buf);
- if (!flush_left)
- while (f_width-- > 0)
- xPrintf_PutChar(pad);
- for (bp--; bp >= buf; bp--)
- xPrintf_PutChar(*bp);
- if (flush_left)
- while (f_width-- > 0)
- xPrintf_PutChar(' ');
- break;
- case 'o': // 'o' octal number
- case 'x': // 'x' hex number
- case 'u': // 'u' unsigned decimal
- if (do_long)
- u = va_arg(ap, unsigned long);
- else
- u = (unsigned long) (va_arg(ap, unsigned));
- if (fmt == 'u')
- { // unsigned decimal
- do {
- *bp++ = u % 10 + '0';
- } while ((u /= 10) > 0);
- }
- else if (fmt == 'o')
- { // octal
- do {
- *bp++ = u % 8 + '0';
- } while ((u /= 8) > 0);
- if (hash)
- *bp++ = '0';
- }
- else if (fmt == 'x')
- { // hex
- do {
- i = u % 16;
- if (i < 10)
- *bp++ = i + '0';
- else
- *bp++ = i - 10 + 'a';
- } while ((u /= 16) > 0);
- if (hash)
- {
- *bp++ = 'x';
- *bp++ = '0';
- }
- }
- i = f_width - (bp - buf);
- if (!flush_left)
- while (i-- > 0)
- xPrintf_PutChar(pad);
- for (bp--; bp >= buf; bp--)
- xPrintf_PutChar((int) (*bp));
- if (flush_left)
- while (i-- > 0)
- xPrintf_PutChar(' ');
- break;
- case 'c': // 'c' character
- i = va_arg(ap, int);
- xPrintf_PutChar((int) (i));
- break;
- case 's': // 's' string
- bp = va_arg(ap, unsigned char *);
- if (!bp)
- bp = (unsigned char *) "(nil)";
- f_width = f_width - strlen((char *) bp);
- if (!flush_left)
- while (f_width-- > 0)
- xPrintf_PutChar(pad);
- for (i = 0; *bp && i < prec; i++)
- {
- xPrintf_PutChar(*bp);
- bp++;
- }
- if (flush_left)
- while (f_width-- > 0)
- xPrintf_PutChar(' ');
- break;
- case '%': // '%' character
- xPrintf_PutChar('%');
- break;
- }
- flush_left = 0, f_width = 0, prec = 2^32-1, hash = 0, do_long = 0;
- sign = 0;
- pad = ' ';
- }
- }
-
- va_end(ap);
- return 0;
-}
diff --git a/src/app/xprintf.h b/src/app/xprintf.h
deleted file mode 100644
index 5b41d75..0000000
--- a/src/app/xprintf.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XPRINTF_H_
-#define _XPRINTF_H_
-
-void xPrintf(const char *fmt, ...);
-
-#endif
diff --git a/src/app/xshell.c b/src/app/xshell.c
deleted file mode 100644
index 9a32d51..0000000
--- a/src/app/xshell.c
+++ /dev/null
@@ -1,601 +0,0 @@
-#include "string.h"
-#include "stdint.h"
-#include "xshell.h"
-#include "xprintf.h"
-
-#if ENABLE_XSHELL_PRINTF
-/*compelte function xShell_printf(const char*str,...)*/
-#include "stdio.h"
-#define xShell_printf xPrintf
-#else
-void xShell_printf(const char*str,...){};
-#endif
-
-#if USE_XSHELL
-
-//extern int xShellTab$$Base;
-//extern int xShellTab$$Limit;
-
-static unsigned long xShell_Parameter[MAX_PARAMETER];
-
-#ifdef __CC_ARM
-#define _xShell_Record_Base (xShell_Recorde_st *)&xShellTab$$Base
-#define _xShell_Record_Limit (xShell_Recorde_st *)&xShellTab$$Limit
-#elif defined(__GNUC__)
-extern const uint32_t __start_xShellTab;
-extern const uint32_t __end_xShellTab;
-#define _xShell_Record_Base (xShell_Recorde_st *)&__start_xShellTab
-#define _xShell_Record_Limit (xShell_Recorde_st *)&__end_xShellTab
-#endif
-static xShell_Recorde_st* xShell_SearchFunc(char*pFuncName)
-{
- xShell_Recorde_st *pRecord = _xShell_Record_Base;
-
- for(;pRecord<_xShell_Record_Limit;pRecord++)
- {
- if(pRecord->nByteOfValue!=0)//function ,this field must be zero
- {
- continue;
- }
- else
- {
- if(strcmp(pFuncName,pRecord->name)==0)
- return pRecord;
- }
- }
-
- return (xShell_Recorde_st*)0;
-}
-
-static xShell_Recorde_st* xShell_SearchVar(char*pVarName)
-{
- xShell_Recorde_st *pRecord = (xShell_Recorde_st *)_xShell_Record_Base;
-
- for(;pRecord<_xShell_Record_Limit;pRecord++)
- {
- if(pRecord->nByteOfValue ==0)//variable ,this field must not be zero
- {
- continue;
- }
- else
- {
- if(strcmp(pVarName,pRecord->name)==0)
- return pRecord;
- }
- }
-
- return (xShell_Recorde_st*)0;
-}
-
-static xShell_Recorde_st*xShell_Search(char*pVarName)
-{
- xShell_Recorde_st *pRecord = (xShell_Recorde_st *)_xShell_Record_Base;
-
- for(;pRecord<_xShell_Record_Limit;pRecord++)
- {
- if(strcmp(pVarName,pRecord->name)==0)
- return pRecord;
- }
-
- return (xShell_Recorde_st*)0;
-}
-
-static unsigned long xShell_CallFunc(xShell_Recorde_st*pRecord,unsigned int parameters)
-{
- xShell_Func f = NULL;
- unsigned long r=0;
-
- if(pRecord == NULL)
- return (unsigned long)-1l;
-
- f = (xShell_Func)(pRecord->addr);
- switch (parameters)
- {
- case 0:
- r = f(0);
- break;
-
- case 1:
- r = f(xShell_Parameter[0]);
- break;
-
- case 2:
- r = f(xShell_Parameter[0], xShell_Parameter[1]);
- break;
-
- case 3:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2]);
- break;
-
- case 4:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3]);
- break;
-
- case 5:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4]);
- break;
-
- case 6:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4], xShell_Parameter[5]);
- break;
-
- case 7:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4], xShell_Parameter[5], xShell_Parameter[6]);
- break;
-
- case 8:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4], xShell_Parameter[5], xShell_Parameter[6], xShell_Parameter[7]);
- break;
-
- case 9:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4], xShell_Parameter[5], xShell_Parameter[6], xShell_Parameter[7],
- xShell_Parameter[8]);
- break;
-
- case 10:
- r = f(xShell_Parameter[0], xShell_Parameter[1], xShell_Parameter[2], xShell_Parameter[3],
- xShell_Parameter[4], xShell_Parameter[5], xShell_Parameter[6], xShell_Parameter[7],
- xShell_Parameter[8], xShell_Parameter[9]);
- break;
- }
- return r;
-}
-static unsigned long xShell_CallVar(xShell_Recorde_st*pRecord)
-{
- unsigned long temp = 0;
- char *pData = NULL;
- int i ;
-
- if(pRecord == NULL)
- return (unsigned long)-1;
-
- pData = (char*)pRecord->addr;
- i = pRecord->nByteOfValue;
- switch(i)
- {
- case 1: temp = (unsigned long)(*pData);break;
- case 2: temp = (unsigned long)(*((unsigned short*)pData));break;
- case 4:
- default:temp = *((unsigned int*)pData);break;
- }
- return temp;
-}
-
-static unsigned int xShell_Pow(unsigned int m,unsigned int n)
-{
- unsigned int Result=1;
- while(n--)
- Result*=m;
- return Result;
-}
-
-static unsigned int xShell_Str2Num(char*Str,unsigned long *Res)
-{
- unsigned int Temp;
- unsigned int Num=0;
- unsigned int HexDec=10;
- char *p;
- p=Str;
- *Res=0;
- while(1)
- {//convert BIG chars to small chars "ABCDEF"//16??
- if((*p>='A'&&*p<='F')||(*p=='X'))
- *p=*p+0x20;
- else if(*p=='\0')break;
- p++;
- }
- p=Str;
- while(1)
- {
- if((*p<='9'&&*p>='0')||(*p<='f'&&*p>='a')||(*p=='x'&&Num==1))
- {//
- if(*p>='a')HexDec=16;
- Num++;
- }else if(*p=='\0')break;
- else return 1;
- p++;
- }
- p=Str;
- if(HexDec==16)
- {
- if(Num<3)return 2;
- if(*p=='0' && (*(p+1)=='x'))//
- {
- p+=2;
- Num-=2;
- }else return 3;
- }else if(Num==0)return 4;
- while(1)
- {
- if(Num)Num--;
- if(*p<='9'&&*p>='0')Temp=*p-'0';
- else Temp=*p-'a'+10;
- *Res+=Temp*xShell_Pow(HexDec,Num);
- p++;
- if(*p=='\0')break;
- }
- return 0;
-}
-
-static char *xShell_delete_space(char * pStr)
-{
- //delete space at begin of pStr and end of pStr
- char *p = pStr;
- char *pStart = NULL;
-
- while(*p == ' ')p++;
- pStart = p;
-
- p = pStr;
- p += strlen(pStr)-1;
- while(*p == ' ') *p-- = '\0';
-
- return pStart;
-}
-
-static char xShell_IslegalChar(char c)
-{
- if(c>=32&&c<=126)
- return 1;
- else
- return 0;
-}
-static char xShell_IslegalID(char c)
-{
- if((c>='a'&&c<='z') || (c>='A'&&c<='Z') || c=='_')
- return 1;
- else
- return 0;
-}
-
-static xShell_err_t xShell_ParameterToNum(char *pStr,unsigned long *out)
-{
- xShell_Recorde_st* pRecord = NULL;
- int len;
-
- if(*pStr == 0)
- return xShell_EPARA;
-
- if(xShell_IslegalID(*pStr))
- {//it is must be a varible
- pRecord = xShell_SearchVar(pStr);
- if( pRecord == NULL)
- return xShell_EPARA;
- else
- {
- *out = xShell_CallVar(pRecord);
- }
- }
- else if(*pStr == '\"')
- {
- len = strlen(pStr)-1;
- if(pStr[len] != '\"' || len==0)
- return xShell_ESTR;
- pStr[len] = '\0';
- *out = (unsigned long)(pStr+1);
- }
- else
- {
- if(xShell_Str2Num(pStr,out)!=0)
- return xShell_EPARA;
- }
- return xShell_EOK;
-}
-
-static xShell_err_t xShell_token(xShell_st *xShell)
-{
-// xShell_err_t err_code = xShell_EOK;
- char *pIstr;
- unsigned int Index,tempIndex;
- unsigned int len;
-//1. delete all ' 'before any string
- pIstr = xShell_delete_space(xShell->line);
- xShell->pLine = pIstr;
- Index = 0;
- if(*pIstr == '\0')
- return xShell_EOK;
-//2. the first character should be "a-z","A-z",'_'
- if(!(
- (pIstr[Index]>='a'&&pIstr[Index]<='z') \
- || (pIstr[Index]>='A'&&pIstr[Index]<='Z') \
- || pIstr[Index]=='_')
- )
- return xShell_ESTR;
-//3.seperate all token
- Index = 0;
- tempIndex = 0;
- xShell->token_count = 0;
- while(1)
- {
- if(pIstr[Index] == '\0')
- {
- //it is not a funtion or string or const,it must be a varible
- if(xShell->token_count == 0)
- {
- xShell->token[xShell->token_count].token_type = xShell_TokenVar;
- xShell->token[xShell->token_count].token_index = 0;
- xShell->token[xShell->token_count].token_end = Index-1;
- xShell->token_count++;
- }
- break;
- }
- if(xShell_IslegalChar(pIstr[Index]) == 0)
- return xShell_ESTR;
- if(pIstr[Index] == '(')
- {
- if(xShell->token_count != 1)//there must "be" "one" function name before,
- {
- xShell->token[xShell->token_count].token_type = xShell_TokenFunc;
- xShell->token[xShell->token_count].token_index = 0;
- xShell->token[xShell->token_count].token_end = Index-1;
- xShell->token_count++;
- tempIndex = Index+1;
- //check if it is really a function call
- //check ')'
- len = strlen(pIstr);
- if(pIstr[len-1] != ')')
- return xShell_EFUNC;//function not complte
- //check if parameter is enough
- //xShell->call_type = xShell_CallFunction;
- }
- else
- return xShell_EFUNC;
- }
- if(pIstr[Index] == ')')
- {
- //')' only can be showed up in funciton call
- //the first token must be TokenFunc
- if(xShell->token[0].token_type != xShell_TokenFunc)
- return xShell_ESTR;
- if(tempIndex!=Index)//there maybe some parameter,regard ' 'as parameter too
- {
- xShell->token[xShell->token_count].token_type = xShell_TokenPara;
- xShell->token[xShell->token_count].token_index = tempIndex;
- xShell->token[xShell->token_count].token_end = Index-1;
- xShell->token_count++;
- }
- //else "()",function has no parameter
- else
- {
- if(pIstr[tempIndex-1]!='(')
- return xShell_EPARA;
- }
- }
- if(pIstr[Index] == ',')
- {
- //',' only can be showed up in funciton call
- //the first token must be TokenFunc
- if(xShell->token[0].token_type != xShell_TokenFunc)
- return xShell_ESTR;
- if(xShell->token_count > MAX_TOKEN_NUM-1)
- return xShell_ETOKEN_FULL;
- if(tempIndex!=Index)//there maybe some parameter,regard ' 'as parameter too
- {
- xShell->token[xShell->token_count].token_type = xShell_TokenPara;
- xShell->token[xShell->token_count].token_index = tempIndex;
- xShell->token[xShell->token_count].token_end = Index-1;
- xShell->token_count++;
- tempIndex = Index+1;
- }
- else
- return xShell_EPARA;
- }
- Index++;
- }
- return xShell_EOK;
-}
-
-static xShell_err_t xShell_paser(xShell_st* xShell)
-{
- xShell_err_t err_code;
- int i;
- char *pToken = NULL;
- xShell_Recorde_st *pRecord=NULL;
-#ifdef xShell_EN_ECHO
- unsigned long oValue;
- xShell_printf("\n");
-#endif
- err_code = xShell_token(xShell);
- if(err_code!=xShell_EOK)
- return err_code;
- if(*xShell->pLine == '\0')
- return xShell_EOK;//input is only " "
-//delete all space not needed
- for(i=0;itoken_count;i++)
- {
- xShell->pLine[xShell->token[i].token_end+1] = '\0';//cut the string
- pToken = xShell->pLine+xShell->token[i].token_index;
- xShell->token[i].token_index = xShell_delete_space(pToken)\
- -xShell->pLine;
- pToken = xShell->pLine+xShell->token[i].token_index;
- xShell->token[i].token_end = xShell->token[i].token_index + strlen(pToken) - 1;
-
- if(xShell->token[i].token_indextoken[i].token_end)
- xShell->token[i].token_end = xShell->token[i].token_index;
- }
-//check function or variable or equition,equation has not completed
- if(xShell->token[0].token_type == xShell_TokenFunc)
- {
- pToken = xShell->pLine+xShell->token[0].token_index;
- pRecord = xShell_SearchFunc(pToken);
- if(pRecord == 0)
- return xShell_ENULLNODE;
- for(i=1;itoken_count;i++)
- {
- if(xShell_ParameterToNum(xShell->pLine+xShell->token[i].token_index,xShell_Parameter+i-1) != xShell_EOK)
- return xShell_EPARA;
- }
- //call function
-#ifdef xShell_EN_ECHO
- oValue = xShell_CallFunc(pRecord,xShell->token_count-1);
- xShell_printf("\nr:%8ld,a:0x%08x",oValue,(unsigned int)pRecord->addr);
-#else
- xShell_CallFunc(pRecord,xShell->token_count-1);
-#endif
- }
- else if(xShell->token[0].token_type == xShell_TokenVar)
- {
- pToken = xShell->pLine+xShell->token[0].token_index;
- pRecord = xShell_Search(pToken);
- if(pRecord == NULL)
- return xShell_EUNKOWNSYMBOL;
-#ifdef xShell_EN_ECHO
- oValue = xShell_CallVar(pRecord) ;
- xShell_printf("\nr:%8ld,a:0x%08x",oValue,(unsigned int)pRecord->addr);
-#else
- xShell_CallVar(pRecord) ;
-#endif
- }
- return xShell_EOK;
-}
-static void xShell_PrintErro(xShell_err_t err_code)
-{
- switch(err_code)
- {
- case xShell_ESTR:
- xShell_printf("String Erro");
- break;
- case xShell_EFUNC:
- xShell_printf("Function Erro");
- break;
- case xShell_EPARA:
- xShell_printf("Parameter erro");
- break;
- case xShell_ETOKEN_FULL:
- xShell_printf("Token Full");
- break;
- case xShell_ENULLNODE:
- xShell_printf("Null Node");
- break;
- case xShell_EUNKOWNSYMBOL:
- xShell_printf("Unkown Symbol");
- break;
- default:;
- }
-}
-
-void xShell_InputChar(xShell_st *xShell,char c)
-{
- xShell_err_t err_code = xShell_EOK;
- /* handle CR key */
- if (c == '\r')
- {
- c = '\r';
- }
- /* handle tab key */
- else if (c == '\t')
- {
- /* auto complete */
- // finsh_auto_complete(&shell->line[0]);
- /* re-calculate position */
- // shell->line_position = strlen(shell->line);
-// continue;
- return;
- }
- /* handle backspace key */
- else if (c == 0x7f || c == 0x08)
- {
- if (xShell->line_position != 0)
- {
- xShell_printf("%c %c", c, c);
- }
- if (xShell->line_position <= 0) xShell->line_position = 0;
- else xShell->line_position --;
- xShell->line[xShell->line_position] = 0;
- return;
- }
-
- /* handle end of line, break */
- if (c == '\r' || c == '\n')
- {
- if (xShell->line_position != 0)
- {
- xShell->line[xShell->line_position] = '\0';
- err_code = xShell_paser(xShell);
- xShell_PrintErro(err_code);
-
- memset(xShell, 0, sizeof(xShell_st));
- }
-#ifdef xShell_EN_ECHO
- xShell_printf(xShell_PROMT);
-#endif
- return;
- }
- /* normal character */
- xShell->line[xShell->line_position] = c; c = 0;
-#ifdef xShell_EN_ECHO
- xShell_printf("%c", xShell->line[xShell->line_position]);
-#endif
- xShell->line_position ++;
-
- return;
-}
-
-void list(void)
-{
- char flag = 0;
- xShell_Recorde_st *pRecord = _xShell_Record_Base;
-
- for(;pRecord<_xShell_Record_Limit;pRecord++)
- {
- if(pRecord->nByteOfValue!=0)//function ,this field must be zero
- {
- continue;
- }
- else
- {
- if(flag == 0)
- {
- flag = 1;
- xShell_printf("functions:\n");
- }
- xShell_printf(pRecord->name);
- xShell_printf("()\t--");
- xShell_printf(pRecord->description);
- xShell_printf("\n");
- }
- }
-
- flag = 0;
- pRecord = _xShell_Record_Base;
- for(;pRecord<_xShell_Record_Limit;pRecord++)
- {
- if(pRecord->nByteOfValue!=0)//function ,this field must be zero
- {
- if(flag == 0)
- {
- flag = 1;
- xShell_printf("variables:\n");
- }
- xShell_printf(pRecord->name);
- xShell_printf("\t--");
- xShell_printf(pRecord->description);
- xShell_printf("\n");
- }
- else
- {
- continue;
- }
- }
-}
-xShell_FUN_REG(list,list the functions and variables);
-void hello(void)
-{
- #ifdef ENABLE_XSHELL_PRINTF
- xShell_printf("\nHello from xshell\n");
- xShell_printf("version 0.2 2015.3.25@XJTU,Xi'an,Shannxi\n");
- xShell_printf("type \"list()\"to list all functions\n");
- #endif
-}
-xShell_FUN_REG(hello,say hello);
-#else
-void xShell_InputChar(xShell_st *xShell,char c)
-{
-
-}
-#endif
diff --git a/src/app/xshell.h b/src/app/xshell.h
deleted file mode 100644
index c400449..0000000
--- a/src/app/xshell.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/************xShell*******************************************************
-* used on stm32f103ze,compiler:arm_cc;not support IAR
-*
-* ver 0.1,2013-12-22,by ������ in xjtu,xi'an,shanxi,CHINA
-**************************************************************************
-* ver 0.2,2015-3-25,by ������ in xjtu,xi'an,shanxi,CHINA,
-* made it more easier to use
-**************************************************************************
-* how to use it:
-* 1. set flag USE_XSHELL to 1,
-* you can simple turn it off by set it to 0
-* 2. add "--keep *.o(xShellTab)" to misc control in linker page(without "")
-* 3. complete function xShell_printf(const char*str,...),
-* if you dont want any output, just write a empty function
-* you can use this to simply it
-* #define xShell_print printf
-* this is much easier to realize the printf function
-* 4. register your function use the macro xShell_FUN_REG(name, desc)
-* 5. register your variable use the macro xShell_VAR_REG(name, desc)
-* the variable can be list to the terminal
-* 6. when you received a character, execute
-* xShell_InputChar(xShell_st *xShell,char c);
-* fistly, you should first define the struct (xShell),this is
-* the workspace of xshell, pass its pointer to this function,
-* parameter 'c' is the charater you received
-* 7. enjoy it.
-*
-****************************************************************************/
-#ifndef _XSHELL_H_
-#define _XSHELL_H_
-
-/*user can modify this*/
-#define USE_XSHELL 1
-#define ENABLE_XSHELL_PRINTF 1
-#define xShell_EN_ECHO
-
-
-/*user should not modify below this line*/
-/****************************************/
-#define MAX_TOKEN_NUM 10
-#define MAX_PARAMETER 10
-#define xSHELL_MAX_CHARS 128
-#ifdef xShell_EN_ECHO
-#define xShell_PROMT "\nxShell>>"
-#endif
-typedef enum
-{
- xShell_EOK = 0,
- xShell_ESTR = 1,
- xShell_EFUNC,
- xShell_EPARA,
- xShell_ETOKEN_FULL,
- xShell_EUNKOWNSYMBOL,
- xShell_ENULLNODE,
-}xShell_err_t;
-
-typedef enum
-{
- xShell_TokenUnknown = 0,
- xShell_TokenFunc ,
- xShell_TokenPara,//function's parameter
- xShell_TokenVar,
- xShell_TokenStr,
- xShell_TokenConst,
-}xShell_token_type;
-
-typedef struct
-{
- xShell_token_type token_type;
- unsigned char token_index;
- unsigned char token_end;
-}xShell_token_st;
-
-typedef struct
-{
- const char *name;
- const char *description;
- void *addr;//the address of item;
- unsigned int nByteOfValue;//how much byte the value is;as for function ,this field must be zero
-}xShell_Recorde_st;
-
-typedef struct
-{
- char *pLine;
- char line[xSHELL_MAX_CHARS];
- int line_position;
- xShell_token_st token[MAX_TOKEN_NUM];
- unsigned char token_count;
-}xShell_st;
-
-typedef unsigned long (*xShell_Func)();
-
-
-#define xShell_FUN_REG(name, desc) \
-static const char xShell_fun_##name##_name[] = #name; \
-static const char xShell_fun_##name##_desc[] = #desc; \
-xShell_Recorde_st qsh_fun_##name##_record __attribute__((section(".xShellTab"))) = \
-{ \
- xShell_fun_##name##_name, \
- xShell_fun_##name##_desc, \
- (void *)&name, \
- 0 \
-}
-
-#define xShell_VAR_REG(name, desc) \
-static const char xShell_var_##name##_name[] = #name; \
-static const char xShell_var_##name##_desc[] = #desc; \
-xShell_Recorde_st xShell_var_##name##_record __attribute__((section(".xShellTab"))) = \
-{ \
- xShell_var_##name##_name, \
- xShell_var_##name##_desc, \
- (void *)&name, \
- sizeof(name) \
-}
-
-//use it in RTT
-void xShell_InputChar(xShell_st *xShell,char c);
-#endif
diff --git a/src/bsp/ad5791.c b/src/bsp/ad5791.c
index c32cb74..50fcf4f 100644
--- a/src/bsp/ad5791.c
+++ b/src/bsp/ad5791.c
@@ -1,3 +1,29 @@
+/**
+ * @author Neo Xu (neo.xu1990@gmail.com)
+ * @license The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Neo Xu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * @brief ad5791 driver.
+*/
#include "ad5791.h"
#define AD5791_SYNC_L() GPIOA->BRR = GPIO_Pin_4
@@ -53,8 +79,7 @@ static float vref_volt = 10.002838f; /* 10V by default. */
* @brief A simple delay function used to meet AD5791 timing.
* @return none.
*/
-static void ad5791_delay(void)
-{
+static void ad5791_delay(void){
volatile uint32_t i = 100;
while(i--);
}
@@ -62,13 +87,11 @@ static void ad5791_delay(void)
* @brief send out 24bits though serial port
* @return none.
*/
-static void ad5791_send24b(uint32_t data)
-{
+static void ad5791_send24b(uint32_t data){
uint8_t count = 0;
uint32_t mask = 1<<23; /* start from MSB */
AD5791_SYNC_L();
- for(;count<24;count++)
- {
+ for(;count<24;count++){
AD5791_SCLK_H();
if(mask&data)
AD5791_DIN_H();
@@ -88,8 +111,7 @@ static void ad5791_send24b(uint32_t data)
* @brief Write 24bit data to AD5791
* @return none.
*/
-static void ad5791_write_data(uint32_t data)
-{
+static void ad5791_write_data(uint32_t data){
ad5791_send24b(AD5791_CMD(AD5791REG_WDATA, data));
dac_code20b = data;
}
@@ -98,8 +120,7 @@ static void ad5791_write_data(uint32_t data)
* @brief ad5791 control registers setting.
* @return none.
*/
-static void ad5791_ctrl(uint32_t ctrl_set)
-{
+static void ad5791_ctrl(uint32_t ctrl_set){
ad5791_send24b(AD5791_CMD(AD5791REG_CTRL, ctrl_set));
}
@@ -107,8 +128,7 @@ static void ad5791_ctrl(uint32_t ctrl_set)
* @brief set AD5791 clear code, the dac output data when CLR command is valid.
* @return none.
*/
-static void ad5791_set_clrcode(uint32_t data)
-{
+static void ad5791_set_clrcode(uint32_t data){
ad5791_send24b(AD5791_CMD(AD5791REG_CLRCODE, data));
}
@@ -116,19 +136,16 @@ static void ad5791_set_clrcode(uint32_t data)
* @brief Software control of AD5791 like LDAC and RESET.
* @return none.
*/
-static void ad5791_sctrl(uint32_t ctrl_set)
-{
+static void ad5791_sctrl(uint32_t ctrl_set){
ad5791_send24b(AD5791_CMD(AD5791REG_SCTRL, ctrl_set));
}
-void ad5791_set_volt(float volt);
/**
* @brief Init AD5791 related GPIO peripheral etc.
* @return none.
* SYNC-->PA4, SCLK-->PA5 DIN-->PA3
*/
-void ad5791_init(void)
-{
+void ad5791_init(void){
GPIO_InitTypeDef gpio_init;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
gpio_init.GPIO_Mode = GPIO_Mode_OUT;
@@ -147,20 +164,21 @@ void ad5791_init(void)
ad5791_ctrl(AD5791CTRL_A1_OFF|AD5791CTRL_CODE_BIN|AD5791CTRL_COMP10V|AD5791CTRL_OPGND_NORMAL|\
AD5791CTRL_OUT_NORMAL|AD5791CTRL_SDO_DIS);
ad5791_set_clrcode(0);
- ad5791_write_data(0x80000);
- ad5791_set_volt(10.0f);
+ ad5791_write_data(0x00000);
}
/**
- * @brief set ad5791 output voltage. This will include calibration correction.
- * @return none.
+ * @brief set the volatage. unit is V
+ * @param volt: the desired voltage in V
+ * @return the real voltage in V.
*/
-void ad5791_set_volt(float volt)
-{
+float ad5791_set_volt(float volt){
uint32_t code;
- code = volt/vref_volt*0xfffff;
+ code = (uint32_t)(volt/vref_volt*0xfffff + 0.5f);
if(code > 0xfffff) code = 0xfffff;
+ code &= 0xffffc;
ad5791_write_data(code);
+ return code*vref_volt/0xfffff;
}
/**
@@ -184,14 +202,9 @@ void ad5791_cal(uint32_t volt)
vref_volt = 0xfffff/vref_volt*10.0f;
}
-#include "xshell.h"
-xShell_FUN_REG(ad5791_set_code,Set the AD5791 code directly);
-xShell_FUN_REG(ad5791_cal, mark that current output voltage is 10V.);
-
void ad5791_volt_debug(uint32_t volt_mv)
{
float voltage = volt_mv;
voltage /= 1000; //volt
ad5791_set_volt(voltage);
}
-xShell_FUN_REG(ad5791_volt_debug,Set the AD5791 voltage in mV unit);
diff --git a/src/bsp/ad5791.h b/src/bsp/ad5791.h
index 54c6c7f..35c9522 100644
--- a/src/bsp/ad5791.h
+++ b/src/bsp/ad5791.h
@@ -3,6 +3,6 @@
#include "stm32f0xx.h"
void ad5791_init(void);
void ad5791_set_code(uint32_t code);
-void ad5791_set_volt(float volt);
+float ad5791_set_volt(float volt);
#endif
diff --git a/src/bsp/key.c b/src/bsp/key.c
index 90c260a..e0f28f0 100644
--- a/src/bsp/key.c
+++ b/src/bsp/key.c
@@ -1,10 +1,9 @@
#include "key.h"
#include "stm32f0xx.h"
-void key_init(void)
-{
+void key_init(void){
GPIO_InitTypeDef gpio_init;
- TIM_TimeBaseInitTypeDef timerbase_init;
+ TIM_ICInitTypeDef TIM_ICInitStruct;
/* Button-->PB1 */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
gpio_init.GPIO_Mode = GPIO_Mode_IN;
@@ -13,6 +12,108 @@ void key_init(void)
gpio_init.GPIO_PuPd = GPIO_PuPd_UP;
gpio_init.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &gpio_init);
+
+ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ /* TIM3 clock enable */
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
+
+ /* GPIOA clock enable */
+ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
+
+ /* TIM1 channel 2 pin (PE.11) configuration */
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+ /* Connect TIM pins to AF1 */
+ GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
+ GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);
+
+ /* Time base configuration */
+ TIM_TimeBaseStructure.TIM_Period = 511;
+ TIM_TimeBaseStructure.TIM_Prescaler = 0;
+ TIM_TimeBaseStructure.TIM_ClockDivision = 0;
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+
+ TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
+
+ /* Prescaler configuration */
+ TIM_PrescalerConfig(TIM3, 0, TIM_PSCReloadMode_Immediate);
+ TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
+ TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
+ TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
+ TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
+ TIM_ICInitStruct.TIM_ICFilter = 0x0f;
+ TIM_ICInit(TIM3, &TIM_ICInitStruct);
+ TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
+ TIM_ICInit(TIM3, &TIM_ICInitStruct);
+
+ TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI1, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
+
+ /* TIM3 enable counter */
+ TIM_Cmd(TIM3, ENABLE);
- timerbase_init.TIM_ClockDivision = TIM_CKD_DIV1;
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
+ /* Time base configuration */
+ TIM_TimeBaseStructure.TIM_Period = 10-1; //10ms interrupt period.
+ TIM_TimeBaseStructure.TIM_Prescaler = 64000-1; //64MHz clock input. 1kHz clock.
+ TIM_TimeBaseStructure.TIM_ClockDivision = 0;
+ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
+ TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
+ TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE);
+ NVIC_InitTypeDef nvic;
+ nvic.NVIC_IRQChannel = TIM14_IRQn;
+ nvic.NVIC_IRQChannelCmd = ENABLE;
+ nvic.NVIC_IRQChannelPriority = 2;
+ NVIC_Init(&nvic);
+ TIM_Cmd(TIM14, ENABLE);
+}
+
+uint8_t get_encoder(void){
+ return TIM3->CNT>>1;
+}
+
+static char Flag_KeyCheck = 0;
+uint8_t get_key(void){
+ uint16_t keystat = (~GPIOB->IDR)&GPIO_Pin_1; //if key is pressed, the bit is set.
+ uint16_t key_value = 0;
+ static uint16_t keystat_pre;
+ static uint16_t counter;
+ static uint8_t flag_key_cont;
+ if(Flag_KeyCheck == 0) return 0;
+ Flag_KeyCheck = 0;
+ if((keystat_pre == keystat)&&(keystat)){// status not changed. and key is pressed.
+ counter++;
+ if(counter == 60){//0.6second
+ counter = 0;
+ key_value = KEY_PRESS_L|keystat_pre;
+ flag_key_cont = 1;
+ }
+ }
+ else{
+ counter = 0;
+ if((keystat^keystat_pre)&~keystat){//key value changed and edge is loosing the key.
+ if(flag_key_cont){
+ flag_key_cont = 0;
+ }
+ else
+ key_value = keystat_pre; //the key is from ON to off, so we use _pre to get which key is pressed.
+ }
+ }
+ keystat_pre = keystat; //do not include the
+ return key_value;
+}
+
+void TIM14_IRQHandler(void)//10ms
+{
+ if(TIM14->SR & TIM_IT_Update)
+ {
+ TIM14->SR = ~TIM_FLAG_Update;
+ Flag_KeyCheck = 1;
+ }
}
diff --git a/src/bsp/key.h b/src/bsp/key.h
index 70a7f3f..d79ceee 100644
--- a/src/bsp/key.h
+++ b/src/bsp/key.h
@@ -1,6 +1,11 @@
#ifndef _KEY_H_
#define _KEY_H_
+#define KEY_PRESS_L 0x80 //the key is pressed for a long time.
+#define KEY_OK 0x02
+
void key_init(void);
+uint8_t get_encoder(void);
+uint8_t get_key(void);
#endif
diff --git a/src/bsp/uart.c b/src/bsp/uart.c
index d0c1fa8..f1d5213 100644
--- a/src/bsp/uart.c
+++ b/src/bsp/uart.c
@@ -1,27 +1,31 @@
#include "uart.h"
-static uint8_t buart_init_done = 0;
-void uart_init(void)
+static void (*uart_callback)(uint8_t);
+
+void uart_init(uint32_t baudrate, void(*pfunc)(uint8_t))
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
+ uart_callback = pfunc;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_1);
+ GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10;
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_2;
GPIO_Init(GPIOA,&GPIO_InitStructure);
+ GPIOA->ODR |= GPIO_Pin_2|GPIO_Pin_9;
//USART
- USART_InitStructure.USART_BaudRate = 115200;
+ USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
USART_InitStructure.USART_Parity = USART_Parity_No;
@@ -40,18 +44,48 @@ void uart_init(void)
NVIC_Init(&NVIC_InitStructure);// USART_String("at\r\n");
}
-void uart_char(char data)
+void usart_for_led(void){
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
+ GPIO_Init(GPIOA,&GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
+ GPIO_Init(GPIOA,&GPIO_InitStructure);
+}
+
+void usart_for_ush(void){
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+ GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//50MHz
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
+ GPIO_Init(GPIOA,&GPIO_InitStructure);
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
+ GPIO_Init(GPIOA,&GPIO_InitStructure);
+}
+
+void uart_char(uint8_t data)
{
- if(!buart_init_done){
- buart_init_done = 1;
- uart_init();
- }
- USART_SendData(USART1, (unsigned char) data);// USART1 ???? USART2 ?
- while (!(USART1->ISR & USART_FLAG_TXE));
+ USART_SendData(USART1, (unsigned char) data);
+ while (!(USART1->ISR & USART_FLAG_TC));
+}
+
+/**
+ * output function from printf.c
+*/
+void _putchar(char data){
+ USART_SendData(USART1, (unsigned char) data);
+ while (!(USART1->ISR & USART_FLAG_TC));
}
-#include "xshell.h"
-xShell_st xShell;
void USART1_IRQHandler(void)
{
@@ -59,8 +93,8 @@ void USART1_IRQHandler(void)
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
- xShell_InputChar(&xShell,USART1->RDR);
- //CBuff_Write(&cbuff,USART1->RDR);
+ if(uart_callback)
+ uart_callback((uint8_t)(USART1->RDR));
}
}
diff --git a/src/bsp/uart.h b/src/bsp/uart.h
index d362138..c4a4357 100644
--- a/src/bsp/uart.h
+++ b/src/bsp/uart.h
@@ -1,7 +1,11 @@
#ifndef _USART_H_
#define _USART_H_
#include "stm32f0xx.h"
-void uart_init(void);
-void uart_char(char data);
+
+void uart_init(uint32_t baudrate, void(*pfunc)(uint8_t));
+void uart_char(uint8_t data);
+
+void usart_for_led(void);
+void usart_for_ush(void);
#endif
diff --git a/src/main.c b/src/main.c
index ee9f57f..294a3ef 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,19 +1,16 @@
#include "stm32f0xx.h"
-#include "uart.h"
-#include "xprintf.h"
-#include "ad5791.h"
+#include "hmi.h"
+void voltref_init(void);
+void voltref_loop(void);
int main(void)
-{
- RCC_ClocksTypeDef RCC_Clocks;
- uart_init();
- xPrintf("Hello from STM32F030 xPrint.\n");
- RCC_GetClocksFreq(&RCC_Clocks);
- xPrintf("Clock Frequency:\nSysClk:%d\nHCLK:%d\nPCLK:%d\n", RCC_Clocks.SYSCLK_Frequency,\
- RCC_Clocks.HCLK_Frequency, RCC_Clocks.PCLK_Frequency);
- ad5791_init();
+{
+ voltref_init();
+ hmi_init();
while(1)
{
+ voltref_loop();
+ hmi_poll();
}
}
diff --git a/src/printf b/src/printf
new file mode 160000
index 0000000..c013a0e
--- /dev/null
+++ b/src/printf
@@ -0,0 +1 @@
+Subproject commit c013a0e8d6bb57247074c748a05bbe7f43bdec6f