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