diff --git a/luci-app-ouad/LICENSE b/luci-app-ouad/LICENSE new file mode 100644 index 000000000..e963df829 --- /dev/null +++ b/luci-app-ouad/LICENSE @@ -0,0 +1,622 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + diff --git a/luci-app-ouad/Makefile b/luci-app-ouad/Makefile new file mode 100644 index 000000000..7f855b068 --- /dev/null +++ b/luci-app-ouad/Makefile @@ -0,0 +1,20 @@ +# +# Copyright (C) 2020 Nate Ding +# +# This is free software, licensed under the GUN General Public License v3. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk + +LUCI_Title:=LuCI support for ssd1306 0.91\' 138x32 display +LUCI_DEPENDS:=+i2c-tools +coreutils-nohup +libuci +LUCI_PKGARCH:=all + +PKG_LICENSE:=GPLv3 +PKG_LINCESE_FILES:=LICENSE +PKF_MAINTAINER:=natelol + +include $(TOPDIR)/feeds/luci/luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/luci-app-ouad/README.md b/luci-app-ouad/README.md new file mode 100644 index 000000000..8f78c1d2b --- /dev/null +++ b/luci-app-ouad/README.md @@ -0,0 +1,80 @@ +# luci-app-oled + +This is the LuCI app written for openwrt (**tested ~~only~~ on NanoPi R2S**) which supports ssd 1306 0.91' oled display. + +**Raspberry Pi CM4** + +This has been tested on Raspberry Pi CM4 as described in issue [#10](https://github.com/NateLol/luci-app-oled/issues/10#issuecomment-922245476). +You can find what revisions you need to make to have it work on your device. +Enjoy! + +## Features|功能 +--- +### Dispaly Info|显示信息 + +**0. Enable|开启** + +开启oled显示。 + +**1. Autoswitch|定时开关** + +由于夜间oled的显示屏太亮,并且也几乎不会看它,所以应邀提供定时开关的功能,选中autoswitch之后,可以设置**显示**的起始和结束时间。 + +**2. Time|时间** + +显示时间。 + +**3. IP|IP地址** + +显示LAN口的IP地址,记得LAN口不可以去除**桥接**选项,否则失效。由于使用的是`br-lan`,因为不同固件可能会交换`eth0`和`eth1`。 + +**4. CPU Temp|CPU温度** + +显示CPU温度。 + +**5. CPU Freq|CPU频率** + +显示实时CPU频率 + +**6. Network Speed|网速** + +提供不同接口的选择,`eth0`和`eth1`,个人可以按需修改。网速单位基准为字节(Byte)而不是一般的位(bit),[MB/s, KB/s, B/s]这样显示的数字能够比较小,不至于过长。 + +**7. Display Interval|显示间隔** + +为了延缓oled的光衰,提供屏保服务,每隔设定的时间运行一次屏保程序。 + +--- +### Screensavers|屏保 + +屏保提供不同的选择,默认推荐的是`Scroll Text|文字滚动`,其他的选择自行探索。 + +## Q&A + +Q0. 如何使用该程序?|在那里找到luci界面? + +A0. 该程序安装位置在luci界面的`services|服务`下的`OLED`,点击即可找到。 + +--- + +Q1. 是否会支持其他oled屏幕,例如同系列的0.96'的? + +A1. 由于开发者身边并没有相应的屏幕去调试,所以是暂时不考虑吧。如果你想贡献代码,非常欢迎,请开PR。 + +--- + + +Q2. 为什么我的IP地址显示错误? + +A2. 很大原因是你修改了LAN接口的属性,例如去除了该接口的**桥接**属性。 + +--- + + +Q3. 为什么我的oled不显示? + +A3. 很有可能是您的固件内核驱动不完整,该程序的运行需要在内核驱动中加上**kmod-i2c-xxx**,见issue [#10](https://github.com/NateLol/luci-app-oled/issues/10)。 + +--- + +如果你在使用过程中还遇到问题,请开issue。 diff --git a/luci-app-ouad/luasrc/controller/oled.lua b/luci-app-ouad/luasrc/controller/oled.lua new file mode 100644 index 000000000..554ceadd8 --- /dev/null +++ b/luci-app-ouad/luasrc/controller/oled.lua @@ -0,0 +1,17 @@ +module("luci.controller.oled", package.seeall) + +function index() + if not nixio.fs.access("/etc/config/oled") then + return + end + entry({"admin", "services", "oled"}, alias("admin", "services", "oled", "setting"),_("OLED"), 90).dependent = true + entry({"admin", "services", "oled", "status"}, call("act_status")) + entry({"admin", "services", "oled", "setting"}, cbi("oled/setting"),_("Setting"),30).leaf = true +end + +function act_status() + local e={} + e.running = luci.sys.call("pgrep -f /usr/bin/oled > /dev/null")==0 + luci.http.prepare_content("application/json") + luci.http.write_json(e) +end diff --git a/luci-app-ouad/luasrc/model/cbi/oled/setting.lua b/luci-app-ouad/luasrc/model/cbi/oled/setting.lua new file mode 100644 index 000000000..7204bc017 --- /dev/null +++ b/luci-app-ouad/luasrc/model/cbi/oled/setting.lua @@ -0,0 +1,84 @@ +m = Map("oled", translate("OLED"), translate("A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) with screensavers!

Any issues, please go to: ")..[[luci-app-oled]]) + +--m.chain("luci") + +m:section(SimpleSection).template="oled/status" + +s = m:section(TypedSection, "oled", translate("")) +s.anonymous=true +s.addremove=false + +--OPTIONS +s:tab("info", translate("Info Display")) +s:tab("screensaver", translate("screensaver")) + +o = s:taboption("info", Flag, "enable", translate("Enable")) +o.default=0 +o = s:taboption("info", Value, "path", translate("I2C PATH")) +o.default='/dev/i2c-0' +o = s:taboption("info", Flag, "rotate", translate("180 degree rotation")) +o.default=0 +o = s:taboption("info", Flag, "autoswitch", translate("Enable Auto switch")) +o.default=0 +from = s:taboption("info", ListValue, "from", translate("From")) +to = s:taboption("info", ListValue, "to", translate("To")) +for i=0,23 do + for j=0,30,30 do + from:value(i*60+j,string.format("%02d:%02d",i,j)) + to:value(i*60+j,string.format("%02d:%02d",i,j)) + end +end +from:value(1440,"24:00") +to:value(1440,"24:00") +from:depends("autoswitch",'1') +to:depends("autoswitch",'1') +from.default=0 +to.default=1440 + +--informtion options---- +o = s:taboption("info", Flag, "date", translate("Date"), translate('Format YYYY-MM-DD HH:MM:SS')) +o.default=0 +o = s:taboption("info", Flag, "lanip", translate("IP"), translate("LAN IP address")) +o.default=0 +o = s:taboption("info", Flag, "cputemp", translate("CPU temperature")) +o.default=0 +o = s:taboption("info", Flag, "cpufreq", translate("CPU frequency")) +o.default=0 +o = s:taboption("info", Flag, "netspeed", translate("Network speed"), translate("1Mbps(m/s)=1,000Kbps(k/s)=1,000,000bps(b/s)")) +o.default=0 +o = s:taboption("info", Value, "netsource", translate("which eth to monitor")) +o:depends("netspeed",'1') +o.default='eth0' +o = s:taboption("info", Value, "time", translate("Display interval(s)"), translate('Screensaver will activate in set seconds')) +o.default=0 + +--screensaver options-- +o = s:taboption("screensaver", Flag, "scroll", translate("Scroll Text")) +o.default=1 +o = s:taboption("screensaver", Value, "text", translate("Text you want to scroll")) +o:depends("scroll",'1') +o.default='OPENWRT' +o = s:taboption("screensaver", Flag, "drawline", translate("Draw Many Lines")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawrect", translate("Draw Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "fillrect", translate("Draw Multiple Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawcircle", translate("Draw Multiple Circles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawroundrect", translate("Draw a white circle, 10 pixel radius")) +o.default=0 +o = s:taboption("screensaver", Flag, "fillroundrect", translate("Fill the Round Rectangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawtriangle", translate("Draw Triangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "filltriangle", translate("Fill Triangles")) +o.default=0 +o = s:taboption("screensaver", Flag, "displaybitmap", translate("Display miniature bitmap")) +o.default=0 +o = s:taboption("screensaver", Flag, "displayinvertnormal", translate("Invert Display Normalize it")) +o.default=0 +o = s:taboption("screensaver", Flag, "drawbitmapeg", translate("Draw a bitmap and animate")) +o.default=0 + +return m diff --git a/luci-app-ouad/luasrc/view/oled/status.htm b/luci-app-ouad/luasrc/view/oled/status.htm new file mode 100644 index 000000000..0da0c6426 --- /dev/null +++ b/luci-app-ouad/luasrc/view/oled/status.htm @@ -0,0 +1,22 @@ + + +
+

+ <%:Collecting data...%> +

+
diff --git a/luci-app-ouad/po/zh_Hans/oled.po b/luci-app-ouad/po/zh_Hans/oled.po new file mode 100644 index 000000000..ae01eab33 --- /dev/null +++ b/luci-app-ouad/po/zh_Hans/oled.po @@ -0,0 +1,154 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +msgid "" +"A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) " +"with screensavers!

Any issues, please go to:" +msgstr "" +"这是一款支持在ssd1306,0.91寸,128x32像素的oled显示屏上显示你要的信息,包含屏" +"保的程序。

任何问题请到:" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:24 +msgid "CPU frequency" +msgstr "CPU 频率" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:22 +msgid "CPU temperature" +msgstr "CPU 温度" + +msgid "Scroll Text" +msgstr "文字滚动" + +msgid "Enable Auto switch" +msgstr "启用定时开关" + +msgid "From" +msgstr "起始时间" + +msgid "To" +msgstr "结束时间" + +msgid "Text you want to scroll" +msgstr "你想要显示的文字" + +msgid "which eth to monitor" +msgstr "选择监控哪个网口" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:20 +msgid "Collecting data..." +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Date" +msgstr "时间" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:48 +msgid "Display miniature bitmap" +msgstr "小图案" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Display interval(s)" +msgstr "信息显示间隔(秒)" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Screensaver will activate in set seconds" +msgstr "屏保每间隔设置的时间运行一次" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:32 +msgid "Draw Many Lines" +msgstr "直线" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:38 +msgid "Draw Multiple Circles" +msgstr "多圆" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:36 +msgid "Draw Multiple Rectangles" +msgstr "多方块" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:34 +msgid "Draw Rectangles" +msgstr "方块" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:44 +msgid "Draw Triangles" +msgstr "三角形" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:54 +msgid "Draw a bitmap and animate" +msgstr "动图" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:52 +msgid "Draw a bitmap and animate movement" +msgstr "变化图" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:40 +msgid "Draw a white circle, 10 pixel radius" +msgstr "实心圆" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:15 +msgid "Enable" +msgstr "启用" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:46 +msgid "Fill Triangles" +msgstr "三角填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:42 +msgid "Fill the Round Rectangles" +msgstr "方形填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Format YYYY-MM-DD HH:MM:SS" +msgstr "日期格式 YYYY-MM-DD HH:MM:SS" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:17 +msgid "I2C PATH" +msgstr "I2C 路径" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "IP" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:12 +msgid "Info Display" +msgstr "显示信息" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:50 +msgid "Invert Display Normalize it" +msgstr "反转" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "LAN IP address" +msgstr "LAN 地址" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:10 +msgid "NOT RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:26 +msgid "Network speed" +msgstr "网速" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:7 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:7 +msgid "OLED" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:7 +msgid "RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:9 +msgid "Setting" +msgstr "设置" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:13 +msgid "screensaver" +msgstr "屏保" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:19 +msgid "180 degree rotation" +msgstr "180 度旋转" diff --git a/luci-app-ouad/po/zh_Hant/oled.po b/luci-app-ouad/po/zh_Hant/oled.po new file mode 100644 index 000000000..4a24e35fb --- /dev/null +++ b/luci-app-ouad/po/zh_Hant/oled.po @@ -0,0 +1,135 @@ +msgid "" +msgstr "Content-Type: text/plain; charset=UTF-8" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +msgid "" +"A LuCI app that helps you config your oled display (SSD1306, 0.91', 128X32) " +"with screensavers!

Any issues, please go to:" +msgstr "這是壹款支持在ssd1306,0.91寸,128x32像素的oled顯示屏上顯示妳要的信息,包含屏保的程序。

任何問題請到:" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:24 +msgid "CPU frequency" +msgstr "CPU頻率" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:22 +msgid "CPU temperature" +msgstr "CPU溫度" + +msgid "Scroll Text" +msgstr "文字滾動" + +msgid "Text you want to scroll" +msgstr "妳想要顯示的文字" + +msgid "which eth to monitor" +msgstr "選擇監控哪個網口" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:20 +msgid "Collecting data..." +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Date" +msgstr "時間" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:48 +msgid "Display miniature bitmap" +msgstr "小圖案" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Display interval(s)" +msgstr "信息顯示間隔(秒)" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:28 +msgid "Screensaver will activate in set seconds" +msgstr "屏保每間隔設置的時間運行壹次" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:32 +msgid "Draw Many Lines" +msgstr "直線" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:38 +msgid "Draw Multiple Circles" +msgstr "多圓" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:36 +msgid "Draw Multiple Rectangles" +msgstr "多方塊" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:34 +msgid "Draw Rectangles" +msgstr "方塊" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:44 +msgid "Draw Triangles" +msgstr "三角形" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:54 +msgid "Draw a bitmap and animate" +msgstr "動圖" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:52 +msgid "Draw a bitmap and animate movement" +msgstr "變化圖" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:40 +msgid "Draw a white circle, 10 pixel radius" +msgstr "實心圓" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:15 +msgid "Enable" +msgstr "啟用" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:46 +msgid "Fill Triangles" +msgstr "三角填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:42 +msgid "Fill the Round Rectangles" +msgstr "方形填充" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:18 +msgid "Format YYYY-MM-DD HH:MM:SS" +msgstr "日期格式 YYYY-MM-DD HH:MM:SS" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "IP" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:12 +msgid "Info Display" +msgstr "顯示信息" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:50 +msgid "Invert Display Normalize it" +msgstr "反轉" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:20 +msgid "LAN IP address" +msgstr "LAN地址" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:10 +msgid "NOT RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:26 +msgid "Network speed" +msgstr "網速" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:7 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:1 +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:7 +msgid "OLED" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/view/oled/status.htm:7 +msgid "RUNNING" +msgstr "" + +#: ../../package/new/luci-app-oled/luasrc/controller/oled.lua:9 +msgid "Setting" +msgstr "設置" + +#: ../../package/new/luci-app-oled/luasrc/model/cbi/oled/setting.lua:13 +msgid "screensaver" +msgstr "屏保" diff --git a/luci-app-ouad/root/etc/config/oled b/luci-app-ouad/root/etc/config/oled new file mode 100644 index 000000000..e89ab41aa --- /dev/null +++ b/luci-app-ouad/root/etc/config/oled @@ -0,0 +1,27 @@ +config oled + option enable '0' + option drawline '0' + option drawrect '0' + option fillrect '0' + option drawcircle '0' + option drawroundrect '0' + option fillroundrect '0' + option drawtriangle '0' + option filltriangle '0' + option displaybitmap '0' + option displayinvertnormal '0' + option drawbitmapeg '0' + option date '1' + option netspeed '0' + option lanip '1' + option cpufreq '1' + option cputemp '1' + option time '60' + option from '0' + option to '1440' + option autoswitch '0' + option rotate '0' + option scroll '0' + option text 'OPENWRT' + option netsource 'eth0' + option path '/dev/i2c-0' diff --git a/luci-app-ouad/root/etc/init.d/oled b/luci-app-ouad/root/etc/init.d/oled new file mode 100755 index 000000000..6f61278f8 --- /dev/null +++ b/luci-app-ouad/root/etc/init.d/oled @@ -0,0 +1,138 @@ +#!/bin/sh /etc/rc.common +START=88 + +PROG=/usr/bin/oled + +stop() { + kill -2 $(pgrep /usr/bin/oled) + kill -9 $(pgrep -f /usr/sbin/netspeed) + echo "oled exit..." +} + +start() { + enabled=$(uci get oled.@oled[0].enable) + if [ $enabled -eq 0 ]; then + exit 0 + fi + + autoswitch=$(uci get oled.@oled[0].autoswitch) + from=$(uci get oled.@oled[0].from) + to=$(uci get oled.@oled[0].to) + + if [ ${autoswitch} -eq 1 ]; then + hour=$(date +"%H") + min=$(date +"%M") + ihour=`expr $hour + 0` + imin=`expr $min + 0` + now=$(($ihour*60+$imin)) + if [[ $now -lt $from || $now -gt $to ]]; then + stop + exit 0 + fi + fi + + #crontab daemon + if ! grep "/etc/init.d/oled \+restart" /etc/crontabs/root >/dev/null 2>&1; then + echo "*/5 * * * * /etc/init.d/oled restart >/dev/null 2>&1" >> /etc/crontabs/root + fi + + date=$(uci get oled.@oled[0].date) + lanip=$(uci get oled.@oled[0].lanip) + cputemp=$(uci get oled.@oled[0].cputemp) + cpufreq=$(uci get oled.@oled[0].cpufreq) + netspeed=$(uci get oled.@oled[0].netspeed) + time=$(uci get oled.@oled[0].time) + drawline=$(uci get oled.@oled[0].drawline) + drawrect=$(uci get oled.@oled[0].drawrect) + fillrect=$(uci get oled.@oled[0].fillrect) + drawcircle=$(uci get oled.@oled[0].drawcircle) + drawroundrect=$(uci get oled.@oled[0].drawroundrect) + fillroundrect=$(uci get oled.@oled[0].fillroundrect) + drawtriangle=$(uci get oled.@oled[0].drawtriangle) + filltriangle=$(uci get oled.@oled[0].filltriangle) + displaybitmap=$(uci get oled.@oled[0].displaybitmap) + displayinvertnormal=$(uci get oled.@oled[0].displayinvertnormal) + drawbitmapeg=$(uci get oled.@oled[0].drawbitmapeg) + rotate=$(uci get oled.@oled[0].rotate) + scroll=$(uci get oled.@oled[0].scroll) + text=$(uci get oled.@oled[0].text) + netsource=$(uci get oled.@oled[0].netsource) + path=$(uci get oled.@oled[0].path) + + if [ ${netspeed} -eq 1 ]; then + nohup /usr/sbin/netspeed ${netsource} >/dev/null 2>&1 & + else + kill -9 $(pgrep -f /usr/sbin/netspeed) + rm -f /tmp/netspeed + fi + nohup ${PROG} ${date} ${lanip} ${cputemp} ${cpufreq} ${netspeed} ${time} ${drawline} ${drawrect} ${fillrect} ${drawcircle} ${drawroundrect} ${fillroundrect} ${drawtriangle} ${filltriangle} ${displaybitmap} ${displayinvertnormal} ${drawbitmapeg} ${scroll} "${text}" "${netsource}" "${path}" ${rotate} 1 > /dev/null 2>&1 & +} + +restart() { + enabled=$(uci get oled.@oled[0].enable) + pgrep -f ${PROG} >/dev/null + if [ $? -eq 0 ]; then + if [ $enabled -eq 1 ]; then + autoswitch=$(uci get oled.@oled[0].autoswitch) + from=$(uci get oled.@oled[0].from) + to=$(uci get oled.@oled[0].to) + if [ ${autoswitch} -eq 1 ]; then + hour=$(date +"%H") + min=$(date +"%M") + ihour=`expr $hour + 0` + imin=`expr $min + 0` + now=$(($ihour*60+$imin)) + if [[ $now -lt $from || $now -gt $to ]]; then + stop + exit 0 + fi + fi + + date=$(uci get oled.@oled[0].date) + lanip=$(uci get oled.@oled[0].lanip) + cputemp=$(uci get oled.@oled[0].cputemp) + cpufreq=$(uci get oled.@oled[0].cpufreq) + netspeed=$(uci get oled.@oled[0].netspeed) + time=$(uci get oled.@oled[0].time) + drawline=$(uci get oled.@oled[0].drawline) + drawrect=$(uci get oled.@oled[0].drawrect) + fillrect=$(uci get oled.@oled[0].fillrect) + drawcircle=$(uci get oled.@oled[0].drawcircle) + drawroundrect=$(uci get oled.@oled[0].drawroundrect) + fillroundrect=$(uci get oled.@oled[0].fillroundrect) + drawtriangle=$(uci get oled.@oled[0].drawtriangle) + filltriangle=$(uci get oled.@oled[0].filltriangle) + displaybitmap=$(uci get oled.@oled[0].displaybitmap) + displayinvertnormal=$(uci get oled.@oled[0].displayinvertnormal) + drawbitmapeg=$(uci get oled.@oled[0].drawbitmapeg) + rotate=$(uci get oled.@oled[0].rotate) + scroll=$(uci get oled.@oled[0].scroll) + text=$(uci get oled.@oled[0].text) + netsource=$(uci get oled.@oled[0].netsource) + path=$(uci get oled.@oled[0].path) + + kill -9 $(pgrep /usr/bin/oled) + kill -9 $(pgrep -f /usr/sbin/netspeed) + + if [ ${netspeed} -eq 1 ]; then + nohup /usr/sbin/netspeed ${netsource} >/dev/null 2>&1 & + else + kill -9 $(pgrep -f /usr/sbin/netspeed) + rm -f /tmp/netspeed + fi + nohup ${PROG} ${date} ${lanip} ${cputemp} ${cpufreq} ${netspeed} ${time} ${drawline} ${drawrect} ${fillrect} ${drawcircle} ${drawroundrect} ${fillroundrect} ${drawtriangle} ${filltriangle} ${displaybitmap} ${displayinvertnormal} ${drawbitmapeg} ${scroll} "${text}" "${netsource}" "${path}" ${rotate} 0 > /dev/null 2>&1 & + else + stop + fi + else + if [ $enabled -eq 1 ]; then + start + else + exit 0 + fi + fi +} + +boot() { + start +} diff --git a/luci-app-ouad/root/etc/uci-defaults/oled b/luci-app-ouad/root/etc/uci-defaults/oled new file mode 100644 index 000000000..2e6ae5c01 --- /dev/null +++ b/luci-app-ouad/root/etc/uci-defaults/oled @@ -0,0 +1,25 @@ +#!/bin/sh + +uci_write_config() { + uci -q set oled.@oled[0].path="$1" + uci -q set oled.@oled[0].rotate="$2" + uci -q commit oled +} + +. /lib/functions/system.sh + +case "$(board_name)" in +hinlink,opc-h69k) + uci_write_config '/dev/i2c-5' 1 + ;; +esac + +uci -q batch <<-EOF >/dev/null + delete ucitrack.@oled[-1] + add ucitrack oled + set ucitrack.@oled[-1].init=oled + commit ucitrack +EOF + +rm -rf /tmp/luci-* +exit 0 diff --git a/luci-app-ouad/root/usr/sbin/netspeed b/luci-app-ouad/root/usr/sbin/netspeed new file mode 100755 index 000000000..6be8ca48d --- /dev/null +++ b/luci-app-ouad/root/usr/sbin/netspeed @@ -0,0 +1,20 @@ +#!/bin/ash +IF=$1 +if [ -z "$IF" ]; then + IF=`ls -1 /sys/class/net/ | head -1` +fi +RXPREV=-1 +TXPREV=-1 +echo "Listening $IF..." +while [ 1 == 1 ] ; do + RX=`cat /sys/class/net/${IF}/statistics/rx_bytes` + TX=`cat /sys/class/net/${IF}/statistics/tx_bytes` + if [ $RXPREV -ne -1 ] ; then + let BWRX=$RX-$RXPREV + let BWTX=$TX-$TXPREV + echo "$BWRX $BWTX">/tmp/netspeed + fi + RXPREV=$RX + TXPREV=$TX + sleep 1 +done diff --git a/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json b/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json new file mode 100644 index 000000000..7c436b871 --- /dev/null +++ b/luci-app-ouad/root/usr/share/rpcd/acl.d/luci-app-oled.json @@ -0,0 +1,11 @@ +{ + "luci-app-oled": { + "description": "Grant UCI access for luci-app-oled", + "read": { + "uci": [ "oled" ] + }, + "write": { + "uci": [ "oled" ] + } + } +} diff --git a/luci-app-ouad/src/Example_Code/Main.c b/luci-app-ouad/src/Example_Code/Main.c new file mode 100644 index 000000000..2ec3e610e --- /dev/null +++ b/luci-app-ouad/src/Example_Code/Main.c @@ -0,0 +1,238 @@ +/* + * Main.c + * + * Created on : Sep 6, 2017 + * Author : Vinay Divakar + * Description : Example usage of the SSD1306 Driver API's + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include + +/* Header Files */ +#include "I2C.h" +#include "SSD1306_OLED.h" +#include "example_app.h" + +/* Oh Compiler-Please leave me as is */ +volatile unsigned char flag = 0; + +/* Alarm Signal Handler */ +void ALARMhandler(int sig) +{ + /* Set flag */ + flag = 5; +} + +void BreakDeal(int sig) +{ + clearDisplay(); + usleep(1000000); + Display(); + exit(0); +} + +int main(int argc, char* argv[]) +{ + int date=atoi(argv[1]); + int lanip=atoi(argv[2]); + int cputemp=atoi(argv[3]); + int cpufreq=atoi(argv[4]); + int netspeed=atoi(argv[5]); + int time=atoi(argv[6]); + int drawline=atoi(argv[7]); + int drawrect=atoi(argv[8]); + int fillrect=atoi(argv[9]); + int drawcircle=atoi(argv[10]); + int drawroundcircle=atoi(argv[11]); + int fillroundcircle=atoi(argv[12]); + int drawtriangle=atoi(argv[13]); + int filltriangle=atoi(argv[14]); + int displaybitmap=atoi(argv[15]); + int displayinvertnormal=atoi(argv[16]); + int drawbitmapeg=atoi(argv[17]); + int scroll=atoi(argv[18]); + char *text=argv[19]; + char *eth=argv[20]; + char *path=argv[21]; + int rotate=atoi(argv[22]); + int needinit=atoi(argv[23]); + + if(path == NULL) + path = I2C_DEV0_PATH; + + /* Initialize I2C bus and connect to the I2C Device */ + if(init_i2c_dev(path, SSD1306_OLED_ADDR) == 0) + { + printf("I2C: Bus Connected to SSD1306\r\n"); + } + else + { + printf("I2C: OOPS! Something Went Wrong\r\n"); + exit(1); + } + + /* Register the Alarm Handler */ + signal(SIGALRM, ALARMhandler); + signal(SIGINT, BreakDeal); + //signal(SIGTERM, BreakDeal); + + /* Run SDD1306 Initialization Sequence */ + if (needinit==1) + display_Init_seq(); + + if (rotate==1) + display_rotate(); + else + display_normal(); + + /* Clear display */ + clearDisplay(); + + // draw a single pixel +// drawPixel(0, 1, WHITE); +// Display(); +// usleep(1000000); +// clearDisplay(); + + // draw many lines + while(1){ + if(scroll){ + testscrolltext(text); + usleep(1000000); + clearDisplay(); + } + + if(drawline){ + testdrawline(); + usleep(1000000); + clearDisplay(); + } + + // draw rectangles + if(drawrect){ + testdrawrect(); + usleep(1000000); + clearDisplay(); + } + + // draw multiple rectangles + if(fillrect){ + testfillrect(); + usleep(1000000); + clearDisplay(); + } + + // draw mulitple circles + if(drawcircle){ + testdrawcircle(); + usleep(1000000); + clearDisplay(); + } + + // draw a white circle, 10 pixel radius + if(drawroundcircle){ + testdrawroundrect(); + usleep(1000000); + clearDisplay(); + } + + // Fill the round rectangle + if(fillroundcircle){ + testfillroundrect(); + usleep(1000000); + clearDisplay(); + } + + // Draw triangles + if(drawtriangle){ + testdrawtriangle(); + usleep(1000000); + clearDisplay(); + } + // Fill triangles + if(filltriangle){ + testfilltriangle(); + usleep(1000000); + clearDisplay(); + } + + // Display miniature bitmap + if(displaybitmap){ + display_bitmap(); + Display(); + usleep(1000000); + }; + + // Display Inverted image and normalize it back + if(displayinvertnormal){ + display_invert_normal(); + clearDisplay(); + usleep(1000000); + Display(); + } + + // Generate Signal after 20 Seconds + + // draw a bitmap icon and 'animate' movement + if(drawbitmapeg){ + alarm(10); + flag=0; + testdrawbitmap_eg(); + clearDisplay(); + usleep(1000000); + Display(); + } + + //setCursor(0,0); + setTextColor(WHITE); + + // info display + int sum = date+lanip+cpufreq+cputemp+netspeed; + if (sum == 0) { + clearDisplay(); + return 0; + } + + for(int i = 1; i < time; i++){ + if (sum == 1){//only one item for display + if (date) testdate(CENTER, 8); + if (lanip) testlanip(CENTER, 8); + if (cpufreq) testcpufreq(CENTER, 8); + if (cputemp) testcputemp(CENTER, 8); + if (netspeed) testnetspeed(SPLIT,0); + Display(); + usleep(1000000); + clearDisplay(); + }else if (sum == 2){//two items for display + if(date) {testdate(CENTER, 16*(date-1));} + if(lanip) {testlanip(CENTER, 16*(date+lanip-1));} + if(cpufreq) {testcpufreq(CENTER, 16*(date+lanip+cpufreq-1));} + if(cputemp) {testcputemp(CENTER, 16*(date+lanip+cpufreq+cputemp-1));} + if(netspeed) {testnetspeed(MERGE, 16*(date+lanip+cpufreq+cputemp+netspeed-1));} + Display(); + usleep(1000000); + clearDisplay(); + }else{//more than two items for display + if(date) {testdate(FULL, 8*(date-1));} + if(lanip) {testlanip(FULL, 8*(date+lanip-1));} + if(cpufreq && cputemp) { + testcpu(8*(date+lanip)); + if(netspeed) {testnetspeed(FULL, 8*(date+lanip+1+netspeed-1));} + }else{ + if(cpufreq) {testcpufreq(FULL, 8*(date+lanip+cpufreq-1));} + if(cputemp) {testcputemp(FULL, 8*(date+lanip+cpufreq+cputemp-1));} + if(netspeed) {testnetspeed(FULL, 8*(date+lanip+cpufreq+cputemp+netspeed-1));} + } + Display(); + usleep(1000000); + clearDisplay(); + } + } + } +} diff --git a/luci-app-ouad/src/Example_Code/example_app.c b/luci-app-ouad/src/Example_Code/example_app.c new file mode 100644 index 000000000..9ce62d025 --- /dev/null +++ b/luci-app-ouad/src/Example_Code/example_app.c @@ -0,0 +1,650 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. + + * example_app.c + * + * Created on : Sep 6, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "SSD1306_OLED.h" +#include "example_app.h" + +#define BUFMAX SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT + +/* MACRO's */ +#define LOGO16_GLCD_HEIGHT 16 +#define LOGO16_GLCD_WIDTH 16 +#define NUMFLAKES 10 +#define XPOS 0 +#define YPOS 1 +#define DELTAY 2 + + + +#define TIMESIZE 64 +//temperature +#define TEMPPATH "/sys/class/thermal/thermal_zone0/temp" +#define TEMPSIZE 5 +//cpu +#define FREQSIZE 8 +#define FREQPATH "cat /sys/devices/system/cpu/cpu[04]/cpufreq/cpuinfo_cur_freq" +//ip +#define IPPATH "ifconfig br-lan|grep 'inet addr:'|cut -d: -f2|awk '{print $1}'" +#define IPSIZE 20 +//netspeed +#define NETPATH "cat /tmp/netspeed" + +/* Extern volatile */ +extern volatile unsigned char flag; + +/* Bit Map - Taken from Adafruit SSD1306 OLED Library */ +static const unsigned char logo16_glcd_bmp[] = +{ + 0b00000000, 0b11000000, + 0b00000001, 0b11000000, + 0b00000001, 0b11000000, + 0b00000011, 0b11100000, + 0b11110011, 0b11100000, + 0b11111110, 0b11111000, + 0b01111110, 0b11111111, + 0b00110011, 0b10011111, + 0b00011111, 0b11111100, + 0b00001101, 0b01110000, + 0b00011011, 0b10100000, + 0b00111111, 0b11100000, + 0b00111111, 0b11110000, + 0b01111100, 0b11110000, + 0b01110000, 0b01110000, + 0b00000000, 0b00110000 +}; + +FILE *fp; +char content_buff[BUFMAX]; +char buf[BUFMAX]; +int display_offset =7; +/* draw many lines */ +void testdrawline() +{ + short i = 0; + for (i=0; i=0; i-=4) + { + drawLine(0, SSD1306_LCDHEIGHT-1, SSD1306_LCDWIDTH-1, i, WHITE); + Display(); + usleep(1000); + } + usleep(250000); + + clearDisplay(); + for (i=SSD1306_LCDWIDTH-1; i>=0; i-=4) + { + drawLine(SSD1306_LCDWIDTH-1, SSD1306_LCDHEIGHT-1, i, 0, WHITE); + Display(); + usleep(1000); + } + for (i=SSD1306_LCDHEIGHT-1; i>=0; i-=4) + { + drawLine(SSD1306_LCDWIDTH-1, SSD1306_LCDHEIGHT-1, 0, i, WHITE); + Display(); + usleep(1000); + } + usleep(250000); + + clearDisplay(); + for (i=0; i0; i-=5) + { + fillTriangle(SSD1306_LCDWIDTH/2, SSD1306_LCDHEIGHT/2-i, + SSD1306_LCDWIDTH/2-i, SSD1306_LCDHEIGHT/2+i, + SSD1306_LCDWIDTH/2+i, SSD1306_LCDHEIGHT/2+i, WHITE); + if (color == WHITE) + color = BLACK; + else + color = WHITE; + Display(); + usleep(1000); + } +} + +/* Display a bunch of characters and emoticons */ +void testdrawchar() +{ + unsigned char i = 0; + setTextSize(1); + setTextColor(WHITE); + setCursor(0,0); + + for (i=0; i < 168; i++) + { + if (i == '\n') + continue; + oled_write(i); + if ((i > 0) && (i % 21 == 0)) + println(); + } + Display(); + usleep(1000); +} + +/* Display "scroll" and scroll around */ +void testscrolltext(char* str) +{ + setTextSize(2); + setTextColor(WHITE); + setCursor(10,8); + sprintf(buf,"%s",str); + print_strln(buf); + Display(); + usleep(1000); + startscrollright(0x00, 0x0F); + usleep(5000000); + stopscroll(); + usleep(1000000); + startscrollleft(0x00, 0x0F); + usleep(5000000); + stopscroll(); + usleep(1000000); + startscrolldiagright(0x00, 0x07); + usleep(5000000); + startscrolldiagleft(0x00, 0x07); + usleep(5000000); + stopscroll(); +} + + + +/* Display Texts */ +void display_texts() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(10,0); + print_str("HELLO FELLAS!"); + println(); + printFloat_ln(3.141592, 4); //Print 4 No's after the decimal Pt. + printNumber_L_ln(-1234, DEC); + printNumber_UC_ln(170, BIN); + setTextSize(2); + setTextColor(WHITE); + print_str("0x"); + printNumber_UL_ln(0xDEADBEEF, HEX); +} + +/* Display miniature bitmap */ +void display_bitmap() +{ + drawBitmap(30, 16, logo16_glcd_bmp, 16, 16, 1); +} + +/* Invert Display and Normalize it */ +void display_invert_normal() +{ + invertDisplay(SSD1306_INVERT_DISPLAY); + usleep(1000000); + invertDisplay(SSD1306_NORMALIZE_DISPLAY); + usleep(1000000); +} + +/* Draw a bitmap and 'animate' movement */ +void testdrawbitmap(const unsigned char *bitmap, unsigned char w, unsigned char h) +{ + unsigned char icons[NUMFLAKES][3], f = 0; + + // initialize + for (f=0; f< NUMFLAKES; f++) + { + icons[f][XPOS] = rand() % SSD1306_LCDWIDTH; + icons[f][YPOS] = 0; + icons[f][DELTAY] = (rand() % 5) + 1; + + /* Looks kinna ugly to me - Un-Comment if you need it */ + //print_str("x: "); + //printNumber_UC(icons[f][XPOS], DEC); + //print_str("y: "); + //printNumber_UC(icons[f][YPOS], DEC); + //print_str("dy: "); + //printNumber_UC(icons[f][DELTAY], DEC); + } + + while (flag != 5) + { + // draw each icon + for (f=0; f< NUMFLAKES; f++) + { + drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE); + } + Display(); + usleep(200000); + + // then erase it + move it + for (f=0; f< NUMFLAKES; f++) + { + drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, BLACK); + + // move it + icons[f][YPOS] += icons[f][DELTAY]; + + // if its gone, reinit + if (icons[f][YPOS] > SSD1306_LCDHEIGHT) + { + icons[f][XPOS] = rand() % SSD1306_LCDWIDTH; + icons[f][YPOS] = 0; + icons[f][DELTAY] = (rand() % 5) + 1; + } + } + } +} + +/* Draw bitmap and animate */ +void testdrawbitmap_eg() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(10,0); + testdrawbitmap(logo16_glcd_bmp, LOGO16_GLCD_HEIGHT, LOGO16_GLCD_WIDTH); +} + +/* Intro */ +void deeplyembedded_credits() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(1,0); + print_strln("deeplyembedded.org"); + println(); + print_strln("Author:Vinay Divakar"); + println(); + println(); + print_strln("THANK YOU"); +} + + +void testdate(int mode, int y) +{ + time_t rawtime; + time_t curtime; + uint8_t timebuff[TIMESIZE]; + curtime = time(NULL); + time(&rawtime); + switch (mode) + { + case CENTER: + setTextSize(2); + strftime(timebuff,80,"%H:%M",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + setCursor((127-strlen(buf)*11)/2-4, y); + break; + case FULL: + setTextSize(1); + strftime(timebuff,80,"%Y-%m-%d %H:%M:%S",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + setCursor(display_offset, y); + } + print_strln(buf); +} + + +void testlanip(int mode, int y) +{ + setTextSize(1); + if((fp=popen(IPPATH,"r"))!=NULL) + { + fscanf(fp,"%s",content_buff); + fclose(fp); + //ipbuff[strlen(ipbuff)-1]=32; + switch(mode) + { + case CENTER: + setTextSize(1); + sprintf(buf,"%s",content_buff); + setCursor((127-strlen(buf)*6)/2, y+4); + break; + + case FULL: + setTextSize(1); + sprintf(buf,"IP:%s",content_buff); + setCursor(display_offset, y); + } + print_strln(buf); + } + +} + + +void testcputemp(int mode, int y) +{ + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + switch (mode) + { + case CENTER: + setTextSize(2); + sprintf(buf, "%.2f",atoi(content_buff)/100.0); + setCursor((127-(strlen(buf)+2)*11)/2-4, y); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-16, getCursorY()+3, 2, WHITE); + break; + case FULL: + setTextSize(1); + sprintf(buf,"CPU TEMP:%.2f",atoi(content_buff)/100.0); + setCursor(display_offset, y); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-8, getCursorY()+1, 1, WHITE); + } + + } + +} + + +void testcpufreq(int mode, int y) +{ + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + switch(mode) + { + case CENTER: + setTextSize(2); + sprintf(buf,"%4dMHz",atoi(content_buff)/1000); + setCursor((127-strlen(buf)*11)/2-4, y); + break; + case FULL: + setTextSize(1); + sprintf(buf,"CPU FREQ:%4dMHz",atoi(content_buff)/1000); + setCursor(display_offset, y); + } + print_strln(buf); + } + +} + +void testnetspeed(int mode, int y) +{ + int rx,tx; + if((fp=popen(NETPATH,"r")) != NULL) + { + fscanf(fp,"%d %d", &rx, &tx); + fclose(fp); + rx = rx; + tx = tx; + switch(mode) + { + case SPLIT: + setTextSize(2); + if (tx < 1000) sprintf(buf, "%03dB", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK", tx/1000); + setCursor((127-(strlen(buf)+1)*11)/2,0); + oled_write(24); + print_str(buf); + + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + setCursor((127-(strlen(buf)+1)*11)/2,16); + oled_write(25); + print_str(buf); + break; + case MERGE: + setTextSize(1); + if (tx < 1000) sprintf(buf, "%03dB ", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK ", tx/1000); + setCursor((127-(2*strlen(buf)-1)*6)/2-4, y+4); + oled_write(24); + print_str(buf); + + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + oled_write(25); + print_str(buf); + break; + case FULL: + setTextSize(1); + setCursor(display_offset, y); + oled_write(24); + if (tx < 1000) sprintf(buf, "%03dB ", tx); + else if (tx > 1000000) sprintf(buf, "%03dM", tx/1000000); + else sprintf(buf, "%03dK ", tx/1000); + print_str(buf); + + oled_write(25); + if (rx < 1000) sprintf(buf, "%03dB", rx); + else if (rx > 1000000) sprintf(buf, "%03dM", rx/1000000); + else sprintf(buf, "%03dK", rx/1000); + print_str(buf); + } + } +} +void testcpu(int y) +{ +//freq + setTextSize(1); + setCursor(display_offset, y); + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + sprintf(buf,"CPU:%4dMHz ", atoi(content_buff)/1000); + print_str(buf); + } + + +//temp + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + sprintf(buf, "%.2f",atoi(content_buff)/100.0); + print_str(buf); + oled_write(0); + oled_write(67); + drawCircle(getCursorX()-8, getCursorY()+1, 1, WHITE); + } +} + +void testprintinfo() +{ + setTextSize(1); + setTextColor(WHITE); + setCursor(0,0); +//DATE + + time_t rawtime; + time_t curtime; + uint8_t timebuff[TIMESIZE]; + curtime = time(NULL); + time(&rawtime); + strftime(timebuff,80,"%Y-%m-%d_%w %H:%M:%S",localtime(&rawtime)); + sprintf(buf,"%s",timebuff); + print_strln(buf); + + //br-lan ip + if((fp=popen(IPPATH,"r"))!=NULL) + { + fscanf(fp,"%s",content_buff); + fclose(fp); + //ipbuff[strlen(ipbuff)-1]=32; + sprintf(buf,"IP:%s",content_buff); + print_strln(buf); + } + + //CPU temp + if((fp=popen(FREQPATH,"r")) != NULL) + { + fgets(content_buff,FREQSIZE,fp); + fclose(fp); + sprintf(buf,"CPU freq:%d MHz ",atoi(content_buff)/1000); + print_strln(buf); + } + + //cpu freq + if((fp=fopen(TEMPPATH,"r"))!=NULL) + { + fgets(content_buff,TEMPSIZE,fp); + fclose(fp); + sprintf(buf,"CPU temp:%.2f C",atoi(content_buff)/100.0); + print_strln(buf); + } + + + +} + diff --git a/luci-app-ouad/src/Example_Code/example_app.h b/luci-app-ouad/src/Example_Code/example_app.h new file mode 100644 index 000000000..eb0435826 --- /dev/null +++ b/luci-app-ouad/src/Example_Code/example_app.h @@ -0,0 +1,30 @@ +#define CENTER 0 //single item display +#define SPLIT 1 //two items +#define MERGE 2 +#define FULL 3 + +void testdrawline(); +void testdrawrect(); +void testfillrect(); +void testdrawcircle(); +void testdrawroundrect(); +void testfillroundrect(); +void testdrawtriangle(); +void testfilltriangle(); +void testdrawchar(); +void testscrolltext(char *str); +void display_texts(); +void display_bitmap(); +void display_invert_normal(); +void testdrawbitmap(const unsigned char *bitmap, unsigned char w, unsigned char h); +void testdrawbitmap_eg(); +void deeplyembedded_credits(); +void testprintinfo(); +void testdate(int mode, int y); +void testlanip(int mode, int y); +void testcpufreq(int mode, int y); +void testcputemp(int mode, int y); +void testnetspeed(int mode, int y); +void testcpu(int y); + + diff --git a/luci-app-ouad/src/I2C_Library/I2C.c b/luci-app-ouad/src/I2C_Library/I2C.c new file mode 100644 index 000000000..7177f8424 --- /dev/null +++ b/luci-app-ouad/src/I2C_Library/I2C.c @@ -0,0 +1,281 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. + + * I2C.c + * + * Created on : September 19, 2017 + * Author : Vinay Divakar + * Description : This is an I2C Library for the BeagleBone that consists of the API's to support the standard + * I2C operations. + * Website : www.deeplyembedded.org + */ + +/*Libs Includes*/ +#include +#include +#include +#include +#include +// heuristic to guess what version of i2c-dev.h we have: +// the one installed with `apt-get install libi2c-dev` +// would conflict with linux/i2c.h, while the stock +// one requires linus/i2c.h +#ifndef I2C_SMBUS_BLOCK_MAX +// If this is not defined, we have the "stock" i2c-dev.h +// so we include linux/i2c.h +#include +typedef unsigned char i2c_char_t; +#else +typedef char i2c_char_t; +#endif + +/* Header Files */ +#include "I2C.h" + + +/* Exposed objects for i2c-x */ +I2C_DeviceT I2C_DEV_2; + +/**************************************************************** + * Function Name : Open_device + * Description : Opens the I2C device to use + * Returns : 0 on success, -1 on failure + * Params @i2c_dev_path: Path to the I2C device + * @fd: Variable to store the file handler + ****************************************************************/ +int Open_device(char *i2c_dev_path, int *fd) +{ + if((*fd = open(i2c_dev_path, O_RDWR))<0) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : Close_device + * Description : Closes the I2C device in use + * Returns : 0 on success, -1 on failure + * Params : @fd: file descriptor + ****************************************************************/ +int Close_device(int fd) +{ + if(close(fd) == -1) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : Set_slave_addr + * Description : Connect to the Slave device + * Returns : 0 on success, -1 on failure + * Params @fd: File descriptor + * @slave_addr: Address of the slave device to + * talk to. + ****************************************************************/ +int Set_slave_addr(int fd, unsigned char slave_addr) +{ + if(ioctl(fd, I2C_SLAVE, slave_addr) < 0) + return -1; + else + return 0; +} + + +/**************************************************************** + * Function Name : i2c_write + * Description : Write a byte on SDA + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: File descriptor + * @data: data to write on SDA + ****************************************************************/ +int i2c_write(int fd, unsigned char data) +{ + int ret = 0; + ret = write(fd, &data, I2C_ONE_BYTE); + if((ret == -1) || (ret != 1)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read + * Description : Read a byte on SDA + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @read_data: Points to the variable that stores + * the read data byte + ****************************************************************/ +int i2c_read(int fd, unsigned char *read_data) +{ + int ret = 0; + ret = read(fd, &read_data, I2C_ONE_BYTE); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read_register + * Description : Read a single register of the slave device + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @read_addr: Register address to be read + * @read_data: Points to the variable that stores + * the read data byte + ****************************************************************/ +int i2c_read_register(int fd, unsigned char read_addr, unsigned char *read_data) +{ + int ret = 0; + if(i2c_write(fd, read_addr) == -1) + { + perror("I2C: Failed to write |"); + return -1; + } + ret = read(fd, &read_data, I2C_ONE_BYTE); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_read_registers + * Description : Read a multiple registers on the slave device + * from starting address + * Returns : No. of bytes read on success, -1 on failure + * Params @fd: File descriptor + * @num: Number of registers/bytes to read from. + * @starting_addr: Starting address to read from + * @buff_Ptr: Buffer to store the read bytes + ****************************************************************/ +int i2c_read_registers(int fd, int num, unsigned char starting_addr, + unsigned char *buff_Ptr) +{ + int ret = 0; + if(i2c_write(fd, starting_addr) == -1) + { + perror("I2C: Failed to write |"); + return -1; + } + ret = read(fd, buff_Ptr, num); + if(ret == -1) + perror("I2C: Failed to read |"); + if(ret == 0) + perror("I2C: End of FILE |"); + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_multiple_writes + * Description : Write multiple bytes on SDA + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: file descriptor + * @num: No. of bytes to write + * @Ptr_buff: Pointer to the buffer containing the + * bytes to be written on the SDA + ****************************************************************/ +int i2c_multiple_writes(int fd, int num, unsigned char *Ptr_buff) +{ + int ret = 0; + ret = write(fd, Ptr_buff, num); + if((ret == -1) || (ret != num)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : i2c_write_register + * Description : Write a control byte or byte to a register + * Returns : No. of bytes written on success, -1 on failure + * Params @fd: file descriptor + * @reg_addr_or_cntrl: Control byte or Register + * address to be written + * @val: Command or value to be written in the + * addressed register + ****************************************************************/ +int i2c_write_register(int fd, unsigned char reg_addr_or_cntrl, unsigned char val) +{ + unsigned char buff[2]; + int ret = 0; + buff[0] = reg_addr_or_cntrl; + buff[1] = val; + ret = write(fd, buff, I2C_TWO_BYTES); + if((ret == -1) || (ret != I2C_TWO_BYTES)) + return -1; + else + return(ret); +} + + +/**************************************************************** + * Function Name : config_i2c_struct + * Description : Initialize the I2C device structure + * Returns : NONE + * Params @i2c_dev_path: Device path + * @slave_addr: Slave device address + * @i2c_dev: Pointer to the device structure + ****************************************************************/ +void config_i2c_struct(char *i2c_dev_path, unsigned char slave_addr, I2C_DevicePtr i2c_dev) +{ + i2c_dev->i2c_dev_path = i2c_dev_path; + i2c_dev->fd_i2c = 0; + i2c_dev->i2c_slave_addr = slave_addr; +} + + +/**************************************************************** + * Function Name : init_i2c_dev + * Description : Connect the i2c bus to the slave device + * Returns : 0 on success, -1 on failure + * Params @i2c_path: the path to the device + * @slave_addr: Slave device address + ****************************************************************/ +int init_i2c_dev(const char* i2c_path, unsigned char slave_address) +{ + config_i2c_struct((char*)i2c_path, slave_address, &I2C_DEV_2); + if(Open_device(I2C_DEV_2.i2c_dev_path, &I2C_DEV_2.fd_i2c) == -1) + { + perror("I2C: Failed to open device |"); + return -1; + } + if(Set_slave_addr(I2C_DEV_2.fd_i2c, I2C_DEV_2.i2c_slave_addr) == -1) + { + perror("I2C: Failed to connect to slave device |"); + return -1; + } + + return 0; +} diff --git a/luci-app-ouad/src/I2C_Library/I2C.h b/luci-app-ouad/src/I2C_Library/I2C.h new file mode 100644 index 000000000..ffcc45933 --- /dev/null +++ b/luci-app-ouad/src/I2C_Library/I2C.h @@ -0,0 +1,69 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. + + * I2C.h + * + * Created on : Sep 4, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +#ifndef I2C_H_ +#define I2C_H_ + +#include + +/* No. of bytes per transaction */ +#define I2C_ONE_BYTE 1 +#define I2C_TWO_BYTES 2 +#define I2C_THREE_BYTES 3 + +/*Definitions specific to i2c-x */ +#define I2C_DEV0_PATH "/dev/i2c-0" +#define I2C_DEV1_PATH "/dev/i2c-1" +#define I2C_DEV2_PATH "/dev/i2c-2" + +/*I2C device configuration structure*/ +typedef struct{ + char* i2c_dev_path; + int fd_i2c; + unsigned char i2c_slave_addr; +}I2C_DeviceT, *I2C_DevicePtr; + +/* Exposed Generic I2C Functions */ +extern int Open_device(char *i2c_dev_path, int *fd); +extern int Close_device(int fd); +extern int Set_slave_addr(int fd, unsigned char slave_addr); +extern int i2c_write(int fd, unsigned char data); +extern int i2c_read(int fd, unsigned char *read_data); +extern int i2c_read_register(int fd, unsigned char read_addr, unsigned char *read_data); +extern int i2c_read_registers(int fd, int num, unsigned char starting_addr, + unsigned char *buff_Ptr); +extern void config_i2c_struct(char *i2c_dev_path, unsigned char slave_addr, I2C_DevicePtr i2c_dev); +extern int i2c_multiple_writes(int fd, int num, unsigned char *Ptr_buff); +extern int i2c_write_register(int fd, unsigned char reg_addr_or_cntrl, unsigned char val); + +/* Exposed I2C-x Specific Functions */ +extern int init_i2c_dev(const char* i2c_path, unsigned char slave_address); + +#endif /* I2C_H_ */ diff --git a/luci-app-ouad/src/LICENSE b/luci-app-ouad/src/LICENSE new file mode 100644 index 000000000..e99e91b40 --- /dev/null +++ b/luci-app-ouad/src/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. diff --git a/luci-app-ouad/src/Makefile b/luci-app-ouad/src/Makefile new file mode 100644 index 000000000..0f1b25559 --- /dev/null +++ b/luci-app-ouad/src/Makefile @@ -0,0 +1,19 @@ +CC = gcc +LD = gcc + +SOURCES = SSD1306_OLED_Library/SSD1306_OLED.c Example_Code/Main.c Example_Code/example_app.c I2C_Library/I2C.c +OBJS := $(SOURCES:.c=.o) +CPPFLAGS := -I SSD1306_OLED_Library -I I2C_Library +CFLAGS := -g + +oled: $(OBJS) + $(CC) $^ -o $@ + +clean: + rm -rf oled $(OBJS) + +compile: oled + +install: compile + mkdir -p $(DESTDIR)/usr/bin + cp oled $(DESTDIR)/usr/bin/oled diff --git a/luci-app-ouad/src/README.md b/luci-app-ouad/src/README.md new file mode 100644 index 000000000..080474f06 --- /dev/null +++ b/luci-app-ouad/src/README.md @@ -0,0 +1,21 @@ +# SSD1306-OLED-display-driver-for-BeagleBone +This is a SSD1306 OLED Display Library fully compatible with the BeagleBone. + +The Library has 3 components: +1. I2C component for enabling communication between the BeagleBone and display. +2. Control component for sending I2C commands to configure and control the display. +3. Graphics component for drawing geometrical figures, bitmaps, texts, characters, emoticons and numbers. + +Author: Vinay Divakar + +References: +1. https://github.com/adafruit/Adafruit_SSD1306 +2. https://github.com/adafruit/Adafruit-GFX-Library + +Youtube demo: https://youtu.be/sDKf6zW6Pyg + +MIT license, check LICENSE file for more information + +This Library is written in C. To use it, just include the I2C and SSD1306 Libraries in your project. + +Enjoy :) diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c new file mode 100644 index 000000000..b15660356 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.c @@ -0,0 +1,2761 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. + + * SSD1306_OLED.c + * + * Created on : Sep 26, 2017 + * Author : Vinay Divakar + * Description : SSD1306 OLED Driver, Graphics API's. + * Website : www.deeplyembedded.org + */ + +/* Lib Includes */ +#include +#include +#include +#include +#include +#include "I2C.h" +#include "SSD1306_OLED.h" +#include "gfxfont.h" + +/* Enable or Disable DEBUG Prints */ +//#define SSD1306_DBG + +/* MACROS */ +#define SWAP(x,y) {short temp; temp = x; x = y; y = temp;} +#define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#define pgm_read_word(addr) (*(const unsigned long *)(addr)) +#define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) + +/* static Variables */ +static unsigned char _rotation = 0,textsize = 0; +static short _width = SSD1306_LCDWIDTH; +static short _height = SSD1306_LCDHEIGHT; +static short cursor_x = 0, cursor_y = 0, textcolor = 0, textbgcolor = 0; +static bool _cp437 = false, wrap = true; + +/* static struct objects */ +static GFXfontPtr gfxFont; + +/* Externs - I2C.c */ +extern I2C_DeviceT I2C_DEV_2; + +/* Chunk Buffer */ +static unsigned char chunk[17] = {0}; + +/* Memory buffer for displaying data on LCD - This is an Apple - Fruit */ +static unsigned char screen[DISPLAY_BUFF_SIZE] ={0}; + +/* Static Functions */ +static void transfer(); +static void drawFastVLine(short x, short y,short h, short color); +static void writeFastVLine(short x, short y, short h, short color); +static void drawFastHLine(short x, short y,short w, short color); +static void writeFastHLine(short x, short y, short w, short color); +static short print(const unsigned char *buffer, short size); + +// Standard ASCII 5x7 font +static const unsigned char ssd1306_font5x7[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, //space + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08,//up INDEX 24 + 0x10, 0x20, 0x7E, 0x20, 0x10,//down INDEX 25 + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22,//C + 0x7F, 0x41, 0x41, 0x41, 0x3E,//D + 0x7F, 0x49, 0x49, 0x49, 0x41,//E + 0x7F, 0x09, 0x09, 0x09, 0x01,//F + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; + +/**************************************************************** + * Function Name : clearDisplay + * Description : Clear the display memory buffer + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void clearDisplay() +{ + memset(screen, 0x00, DISPLAY_BUFF_SIZE); +} + +/**************************************************************** + * Function Name : display_Init_seq + * Description : Performs SSD1306 OLED Initialization Sequence + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_Init_seq() +{ + /* Add the reset code, If needed */ + + /* Send display OFF command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAY_OFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFF Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFF Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display clock frequency */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_CLK) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CLK Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CLK Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CLK command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPCLK_DIV) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CLK Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CLK Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display multiplex */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MULTIPLEX) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MULT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MULT Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display MULT command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_MULT_DAT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MULT Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MULT Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display OFFSET */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_OFFSET) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display OFFSET command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISP_OFFSET_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display OFFSET Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display START LINE - Check this command if something weird happens */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_START_LINE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display START LINE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display START LINE Command Failed\r\n"); +#endif + exit(1); + } + + /* Enable CHARGEPUMP*/ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONFIG_CHARGE_PUMP) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CHARGEPUMP command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CHARGE_PUMP_EN) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CHARGEPUMP Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display MEMORYMODE */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MEM_ADDR_MODE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display MEMORYMODE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display MEMORYMODE Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display HORIZONTAL MEMORY ADDR MODE command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_HOR_MM) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL MEMORY ADDR MODE Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL MEMORY ADDR MODE Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display COM */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMPINS) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COM Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COM Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display COM command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONFIG_COM_PINS) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COM Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COM Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display CONTRAST */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_CONTRAST) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display CONTRAST command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONTRAST_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display CONTRAST Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display PRECHARGE */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_PRECHARGE) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display PRECHARGE command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PRECHARGE_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PRECHARGE Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display VCOMH */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VCOMDETECT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Failed\r\n"); +#endif + exit(1); + } + + /* Send display VCOMH command parameter */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VCOMH_VAL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Parameter Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display VCOMH Command Parameter Failed\r\n"); +#endif + exit(1); + } + + /* Set display ALL-ON */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYALLON_RESUME) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display ALL-ON Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display ALL-ON Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to NORMAL-DISPLAY */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display NORMAL-DISPLAY Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display NORMAL-DISPLAY Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to DEACTIVATE_SCROLL */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DEACTIVATE_SCROLL Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DEACTIVATE_SCROLL Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display to TURN-ON */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYON) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display TURN-ON Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display TURN-ON Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : display_normal + * Description : Normal display + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_normal() +{ + /* Set display SEG_REMAP */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display COMSCANDEC */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIR Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIR Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : display_rotate + * Description : 180 degree rotation + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void display_rotate() +{ + /* Set display SEG_REMAP1 */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP1) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display SEG_REMAP Command Failed\r\n"); +#endif + exit(1); + } + + /* Set display COMSCANDEC1 */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC1) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIR Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIR Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : transfer + * Description : Transfer the frame buffer onto the display + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void transfer() +{ + short loop_1 = 0, loop_2 = 0; + short index = 0x00; + for (loop_1 = 0; loop_1 < 1024; loop_1++) + { + chunk[0] = 0x40; + for(loop_2 = 1; loop_2 < 17; loop_2++) + chunk[loop_2] = screen[index++]; + if(i2c_multiple_writes(I2C_DEV_2.fd_i2c, 17, chunk) == 17) + { +#ifdef SSD1306_DBG + printf("Chunk written to RAM - Completed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Chunk written to RAM - Failed\r\n"); +#endif + exit(1); + } + + memset(chunk,0x00,17); + if(index == 1024) + break; + } +} + + +/**************************************************************** + * Function Name : Display + * Description : 1. Resets the column and page addresses. + * 2. Displays the contents of the memory buffer. + * Returns : NONE. + * Params : NONE. + * Note : Each new form can be preceded by a clearDisplay. + ****************************************************************/ +void Display() +{ + Init_Col_PG_addrs(SSD1306_COL_START_ADDR,SSD1306_COL_END_ADDR, + SSD1306_PG_START_ADDR,SSD1306_PG_END_ADDR); + transfer(); +} + +/**************************************************************** + * Function Name : Init_Col_PG_addrs + * Description : Sets the column and page, start and + * end addresses. + * Returns : NONE. + * Params : @col_start_addr: Column start address + * @col_end_addr: Column end address + * @pg_start_addr: Page start address + * @pg_end_addr: Page end address + ****************************************************************/ +void Init_Col_PG_addrs(unsigned char col_start_addr, unsigned char col_end_addr, + unsigned char pg_start_addr, unsigned char pg_end_addr) +{ + /* Send COLMN address setting command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COL_ADDR) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN Command Failed\r\n"); +#endif + exit(1); + } + + /* Set COLMN start address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_start_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN Start Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN Start Address param Failed\r\n"); +#endif + exit(1); + } + + /* Set COLMN end address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_end_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display COLMN End Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display COLMN End Address param Failed\r\n"); +#endif + exit(1); + } + + /* Send PAGE address setting command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PAGEADDR) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE Command Failed\r\n"); +#endif + exit(1); + } + + /* Set PAGE start address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_start_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE Start Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE Start Address param Failed\r\n"); +#endif + exit(1); + } + + /* Set PAGE end address */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_end_addr) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display PAGE End Address param Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display PAGE End Address param Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : setRotation + * Description : Set the display rotation + * Returns : NONE. + * Params : @x: Display rotation parameter + ****************************************************************/ +void setRotation(unsigned char x) +{ + _rotation = x & 3; + switch(_rotation) + { + case 0: + case 2: + _width = SSD1306_LCDWIDTH; + _height = SSD1306_LCDHEIGHT; + break; + case 1: + case 3: + _width = SSD1306_LCDHEIGHT; + _height = SSD1306_LCDWIDTH; + break; + } +} + +/**************************************************************** + * Function Name : startscrollright + * Description : Activate a right handed scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrollright(unsigned char start, unsigned char stop) +{ + /* Send SCROLL horizontal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + exit(1); + } + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrollleft + * Description : Activate a left handed scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrollleft(unsigned char start, unsigned char stop) +{ + /* Send SCROLL horizontal left command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL LEFT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display HORIZONTAL SCROLL LEFT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_2 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_4 Passed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("HORI_SR Param_6 Passed\r\n"); +#endif + exit(1); + } + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrolldiagright + * Description : Activate a diagonal scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrolldiagright(unsigned char start, unsigned char stop) +{ + /* Send SCROLL diagonal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LCDHEIGHT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Cmd Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Cmd Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : startscrolldiagleft + * Description : Activate a diagonal scroll for rows start + * through stop + * Returns : NONE. + * Params : @start: Start location + * @stop: Stop location + * HINT. : the display is 16 rows tall. To scroll the whole + * display, run: display.scrollright(0x00, 0x0F) + ****************************************************************/ +void startscrolldiagleft(unsigned char start, unsigned char stop) +{ + /* Send SCROLL diagonal right command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n"); +#endif + exit(1); + } + + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_1 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LCDHEIGHT) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_2 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("Cmd Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("Cmd Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_3 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_4 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_6 Failed\r\n"); +#endif + exit(1); + } + + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("DIAG_SR Param_5 Failed\r\n"); +#endif + exit(1); + } + + /* Send SCROLL Activate command */ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES) + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Passed\r\n"); +#endif + } + else + { +#ifdef SSD1306_DBG + printf("SCROLL Activate Command Failed\r\n"); +#endif + exit(1); + } +} + +/**************************************************************** + * Function Name : stopscroll + * Description : Stop scrolling + * Returns : NONE. + * Params : NONE. + ****************************************************************/ +void stopscroll() +{ + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) == I2C_TWO_BYTES) + { + printf("De-activate SCROLL Command Passed\r\n"); + } + else + { + printf("De-activate SCROLL Command Passed Failed\r\n"); + exit(1); + } +} + +/**************************************************************** + * Function Name : invertDisplay + * Description : Invert or Normalize the display + * Returns : NONE. + * Params : @i: 0x00 to Normal and 0x01 for Inverting + ****************************************************************/ +void invertDisplay(unsigned char i) +{ + if (i) + { + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_INVERTDISPLAY) == I2C_TWO_BYTES) + { + printf("Display Inverted - Passed\r\n"); + } + else + { + printf("Display Inverted - Failed\r\n"); + exit(1); + } + } + else + { + if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) == I2C_TWO_BYTES) + { + printf("Display Normal - Passed\r\n"); + } + else + { + printf("Display Normal - Failed\r\n"); + exit(1); + } + } +} + +/**************************************************************** + * Function Name : drawPixel + * Description : Draw a pixel + * Returns : -1 on error and 0 on success + * Params : @x: X - Co-ordinate + * @y: Y - Co-ordinate + * @color: Color + ****************************************************************/ +signed char drawPixel(short x, short y, short color) +{ + /* Return if co-ordinates are out of display dimension's range */ + if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height)) + return -1; + switch(_rotation) + { + case 1: + SWAP(x,y); + x = _width - x - 1; + break; + case 2: + x = _width - x - 1; + y = _height - y - 1; + break; + case 3: + SWAP(x,y); + y = _height - y - 1; + break; + } + + /* x is the column */ + switch(color) + { + case WHITE: screen[x+ (y/8)*SSD1306_LCDWIDTH] |= (1 << (y&7)); break; + case BLACK: screen[x+ (y/8)*SSD1306_LCDWIDTH] &= ~(1 << (y&7)); break; + case INVERSE: screen[x+ (y/8)*SSD1306_LCDWIDTH] ^= (1 << (y&7)); break; + } + return 0; +} + +/**************************************************************** + * Function Name : writeLine + * Description : Bresenham's algorithm + * Returns : NONE + * Params : @x0: X0 Co-ordinate + * @y0: Y0 Co-ordinate + * @x1: X1 Co-ordinate + * @y1: Y1 Co-ordinate + * @color: Pixel color + ****************************************************************/ +void writeLine(short x0, short y0, short x1, short y1, short color) +{ + short steep = 0, dx = 0, dy = 0, err = 0, ystep = 0; + steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) + { + SWAP(x0, y0); + SWAP(x1, y1); + } + + if (x0 > x1) + { + SWAP(x0, x1); + SWAP(y0, y1); + } + dx = x1 - x0; + dy = abs(y1 - y0); + + err = dx / 2; + + if (y0 < y1) + { + ystep = 1; + } else + { + ystep = -1; + } + + for (; x0<=x1; x0++) + { + if (steep) + { + drawPixel(y0, x0, color); + } else + { + drawPixel(x0, y0, color); + } + err -= dy; + if (err < 0) + { + y0 += ystep; + err += dx; + } + } +} + +/* (x,y) is topmost point; if unsure, calling function +should sort endpoints or call writeLine() instead */ +void drawFastVLine(short x, short y,short h, short color) +{ + //startWrite(); + writeLine(x, y, x, y+h-1, color); + //endWrite(); +} + +/* (x,y) is topmost point; if unsure, calling function +should sort endpoints or call writeLine() instead */ +void writeFastVLine(short x, short y, short h, short color) +{ + drawFastVLine(x, y, h, color); +} + +/* (x,y) is leftmost point; if unsure, calling function + should sort endpoints or call writeLine() instead */ +void drawFastHLine(short x, short y,short w, short color) +{ + //startWrite(); + writeLine(x, y, x+w-1, y, color); + //endWrite(); +} + +// (x,y) is leftmost point; if unsure, calling function +// should sort endpoints or call writeLine() instead +void writeFastHLine(short x, short y, short w, short color) +{ + drawFastHLine(x, y, w, color); +} + +/**************************************************************** + * Function Name : drawCircleHelper + * Description : Draw a.... + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void drawCircleHelper( short x0, short y0, short r, unsigned char cornername, short color) +{ + short f = 1 - r; + short ddF_x = 1; + short ddF_y = -2 * r; + short x = 0; + short y = r; + + while (x= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) + { + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 + y, y0 + x, color); + } + if (cornername & 0x2) + { + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 + y, y0 - x, color); + } + if (cornername & 0x8) + { + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 - x, y0 + y, color); + } + if (cornername & 0x1) + { + drawPixel(x0 - y, y0 - x, color); + drawPixel(x0 - x, y0 - y, color); + } + } +} + +/**************************************************************** + * Function Name : drawLine + * Description : Draw line between two points + * Returns : NONE + * Params : @x0: X0 Starting X Co-ordinate + * @y0: Y0 Starting Y Co-ordinate + * @x1: X1 Ending X Co-ordinate + * @y1: Y1 Ending Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void drawLine(short x0, short y0, short x1, short y1, short color) +{ + if(x0 == x1) + { + if(y0 > y1) + SWAP(y0, y1); + drawFastVLine(x0, y0, y1 - y0 + 1, color); + } + else if(y0 == y1) + { + if(x0 > x1) SWAP(x0, x1); + drawFastHLine(x0, y0, x1 - x0 + 1, color); + } + else + { + //startWrite(); + writeLine(x0, y0, x1, y1, color); + //endWrite(); + } +} + +/**************************************************************** + * Function Name : drawRect + * Description : Draw a rectangle + * Returns : NONE + * Params : @x: Corner X Co-ordinate + * @y: Corner Y Co-ordinate + * @w: Width in pixels + * @h: Height in pixels + * @color: Pixel color + ****************************************************************/ +void drawRect(short x, short y, short w, short h, short color) +{ + //startWrite(); + writeFastHLine(x, y, w, color); + writeFastHLine(x, y+h-1, w, color); + writeFastVLine(x, y, h, color); + writeFastVLine(x+w-1, y, h, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : fillRect + * Description : Fill the rectangle + * Returns : NONE + * Params : @x: Starting X Co-ordinate + * @y: Starting Y Co-ordinate + * @w: Width in pixels + * @h: Height in pixels + * @color: Pixel color + ****************************************************************/ +void fillRect(short x, short y, short w, short h, short color) +{ + short i = 0; + //startWrite(); + for (i=x; i= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + drawPixel(x0 + x, y0 + y, color); + drawPixel(x0 - x, y0 + y, color); + drawPixel(x0 + x, y0 - y, color); + drawPixel(x0 - x, y0 - y, color); + drawPixel(x0 + y, y0 + x, color); + drawPixel(x0 - y, y0 + x, color); + drawPixel(x0 + y, y0 - x, color); + drawPixel(x0 - y, y0 - x, color); + } + //endWrite(); +} + +/**************************************************************** + * Function Name : fillCircleHelper + * Description : Used to do circles and roundrects + * Returns : NONE + * Params : @x: Center X Co-ordinate + * @y: Center Y Co-ordinate + * @r: Radius in pixels + * @cornername: Corner radius in pixels + * @color: Pixel color + ****************************************************************/ +void fillCircleHelper(short x0, short y0, short r, unsigned char cornername, short delta, short color) +{ + + short f = 1 - r; + short ddF_x = 1; + short ddF_y = -2 * r; + short x = 0; + short y = r; + + while (x= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) + { + writeFastVLine(x0+x, y0-y, 2*y+1+delta, color); + writeFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) + { + writeFastVLine(x0-x, y0-y, 2*y+1+delta, color); + writeFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +/**************************************************************** + * Function Name : fillCircle + * Description : Fill the circle + * Returns : NONE + * Params : @x0: Center X Co-ordinate + * @y0: Center Y Co-ordinate + * @r: Radius in pixels + * @color: Pixel color + ****************************************************************/ +void fillCircle(short x0, short y0, short r, short color) +{ + //startWrite(); + writeFastVLine(x0, y0-r, 2*r+1, color); + fillCircleHelper(x0, y0, r, 3, 0, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : drawTriangle + * Description : Draw a triangle + * Returns : NONE + * Params : @x0: Corner-1 X Co-ordinate + * @y0: Corner-1 Y Co-ordinate + * @x1: Corner-2 X Co-ordinate + * @y1: Corner-2 Y Co-ordinate + * @x2: Corner-3 X Co-ordinate + * @y2: Corner-3 Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void drawTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color) +{ + drawLine(x0, y0, x1, y1, color); + drawLine(x1, y1, x2, y2, color); + drawLine(x2, y2, x0, y0, color); +} + +/**************************************************************** + * Function Name : fillTriangle + * Description : Fill a triangle + * Returns : NONE + * Params : @x0: Corner-1 X Co-ordinate + * @y0: Corner-1 Y Co-ordinate + * @x1: Corner-2 X Co-ordinate + * @y1: Corner-2 Y Co-ordinate + * @x2: Corner-3 X Co-ordinate + * @y2: Corner-3 Y Co-ordinate + * @color: Pixel color + ****************************************************************/ +void fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color) +{ + short a, b, y, last, dx01, dy01, dx02, dy02, dx12, dy12; + int sa, sb; + + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) + { + SWAP(y0, y1); + SWAP(x0, x1); + } + if (y1 > y2) + { + SWAP(y2, y1); + SWAP(x2, x1); + } + if (y0 > y1) + { + SWAP(y0, y1); + SWAP(x0, x1); + } + + //startWrite(); + if(y0 == y2) + { // Handle awkward all-on-same-line case as its own thing + a = b = x0; + if(x1 < a) + a = x1; + else if(x1 > b) + b = x1; + if(x2 < a) + a = x2; + else if(x2 > b) + b = x2; + writeFastHLine(a, y0, b-a+1, color); + // endWrite(); + return; + } + + dx01 = x1 - x0; + dy01 = y1 - y0; + dx02 = x2 - x0; + dy02 = y2 - y0; + dx12 = x2 - x1; + dy12 = y2 - y1; + sa = 0; + sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if(y1 == y2) + last = y1; // Include y1 scanline + else + last = y1-1; // Skip it + + for(y=y0; y<=last; y++) + { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + SWAP(a,b); + writeFastHLine(a, y, b-a+1, color); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for(; y<=y2; y++) + { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if(a > b) + SWAP(a,b); + writeFastHLine(a, y, b-a+1, color); + } + //endWrite(); +} + +/**************************************************************** + * Function Name : drawRoundRect + * Description : Draw a rounded rectangle + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void drawRoundRect(short x, short y, short w, short h, short r, short color) +{ + // smarter version + //startWrite(); + writeFastHLine(x+r , y , w-2*r, color); // Top + writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom + writeFastVLine(x , y+r , h-2*r, color); // Left + writeFastVLine(x+w-1, y+r , h-2*r, color); // Right + // draw four corners + drawCircleHelper(x+r , y+r , r, 1, color); + drawCircleHelper(x+w-r-1, y+r , r, 2, color); + drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); + drawCircleHelper(x+r , y+h-r-1, r, 8, color); + //endWrite(); +} + +/**************************************************************** + * Function Name : fillRoundRect + * Description : Fill a rounded rectangle + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @w: Width + * @h: height + * @r: Corner radius + * @color: Pixel color + ****************************************************************/ +void fillRoundRect(short x, short y, short w, short h, short r, short color) +{ + // smarter version + //startWrite(); + fillRect(x+r, y, w-2*r, h, color); + + // draw four corners + fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); + //endWrite(); +} + +/*---------------------------------------------------------------------------- + * BITMAP API's + ----------------------------------------------------------------------------*/ + +/**************************************************************** + * Function Name : drawBitmap + * Description : Draw a bitmap + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @bitmap: bitmap to display + * @w: Width + * @h: height + * @color: Pixel color + ****************************************************************/ +void drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, short color) +{ + short byteWidth = 0, j = 0, i = 0; + unsigned char byte = 0; + byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte + + for(j=0; j 0) ? s : 1; +} + +/**************************************************************** + * Function Name : setTextColor + * Description : Set text color + * Returns : @c - Color + ****************************************************************/ +void setTextColor(short c) +{ + // For 'transparent' background, we'll set the bg + // to the same as fg instead of using a flag + textcolor = textbgcolor = c; +} + +/**************************************************************** + * Function Name : setTextWrap + * Description : Wraps the text + * Returns : @w - enable or disbale wrap + ****************************************************************/ +void setTextWrap(bool w) +{ + wrap = w; +} + +/**************************************************************** + * Function Name : getRotation + * Description : Get the rotation value + * Returns : NONE. + ****************************************************************/ +unsigned char getRotation() +{ + return _rotation; +} + +/**************************************************************** + * Function Name : drawBitmap + * Description : Draw a character + * Returns : NONE + * Params : @x: X Co-ordinate + * @y: Y Co-ordinate + * @c: Character + * @size: Scaling factor + * @bg: Background color + * @color: Pixel color + ****************************************************************/ +void drawChar(short x, short y, unsigned char c, short color, short bg, unsigned char size) +{ + unsigned char line = 0, *bitmap = NULL, w = 0, h = 0, xx = 0, yy = 0, bits = 0, bit = 0; + char i = 0, j = 0, xo = 0, yo = 0; + short bo = 0, xo16 = 0, yo16 = 0; + GFXglyphPtr glyph; + if(!gfxFont) + { + // 'Classic' built-in font + if((x >= _width) || (y >= _height) || ((x + 6 * size - 1) < 0) || ((y + 8 * size - 1) < 0)) + return; + + // Handle 'classic' charset behavior + if(!_cp437 && (c >= 176)) + c++; + + // Char bitmap = 5 columns + for(i=0; i<5; i++ ) + { + line = pgm_read_byte(&ssd1306_font5x7[c * 5 + i]); + for(j=0; j<8; j++, line >>= 1) + { + if(line & 1) + { + if(size == 1) + drawPixel(x+i, y+j, color); + else + fillRect(x+i*size, y+j*size, size, size, color); + } + else if(bg != color) + { + if(size == 1) + drawPixel(x+i, y+j, bg); + else + fillRect(x+i*size, y+j*size, size, size, bg); + } + } + } + + // If opaque, draw vertical line for last column + if(bg != color) + { + if(size == 1) + writeFastVLine(x+5, y, 8, bg); + else + fillRect(x+5*size, y, size, 8*size, bg); + } + + } + // Custom font + else + { + // Character is assumed previously filtered by write() to eliminate + // newlines, returns, non-printable characters, etc. Calling + // drawChar() directly with 'bad' characters of font may cause mayhem! + + c -= (unsigned char)pgm_read_byte(&gfxFont->first); + glyph = &(((GFXglyphT *)pgm_read_pointer(&gfxFont->glyph))[c]); + bitmap = (unsigned char *)pgm_read_pointer(&gfxFont->bitmap); + bo = pgm_read_word(&glyph->bitmapOffset); + w = pgm_read_byte(&glyph->width); + h = pgm_read_byte(&glyph->height); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + + if(size > 1) + { + xo16 = xo; + yo16 = yo; + } + + // Todo: Add character clipping here + + // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. + // THIS IS ON PURPOSE AND BY DESIGN. The background color feature + // has typically been used with the 'classic' font to overwrite old + // screen contents with new data. This ONLY works because the + // characters are a uniform size; it's not a sensible thing to do with + // proportionally-spaced fonts with glyphs of varying sizes (and that + // may overlap). To replace previously-drawn text when using a custom + // font, use the getTextBounds() function to determine the smallest + // rectangle encompassing a string, erase the area with fillRect(), + // then draw new text. This WILL unfortunately 'blink' the text, but + // is unavoidable. Drawing 'background' pixels will NOT fix this, + // only creates a new set of problems. Have an idea to work around + // this (a canvas object type for MCUs that can afford the RAM and + // displays supporting setAddrWindow() and pushColors()), but haven't + // implemented this yet. + for(yy=0; yy _width)) + { + // Off right? + cursor_x = 0; // Reset x to zero, + cursor_y += textsize * 8; // advance y one line + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + cursor_x += textsize * 6; // Advance x one char + } + + } + else + { + // Custom font + if(c == '\n') + { + cursor_x = 0; + cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance); + } + else if(c != '\r') + { + first = pgm_read_byte(&gfxFont->first); + if((c >= first) && (c <= (unsigned char)pgm_read_byte(&gfxFont->last))) + { + glyph = &(((GFXglyphT*)pgm_read_pointer(&gfxFont->glyph))[c - first]); + w = pgm_read_byte(&glyph->width); + h = pgm_read_byte(&glyph->height); + if((w > 0) && (h > 0)) + { + // Is there an associated bitmap? + xo = (char)pgm_read_byte(&glyph->xOffset); // sic + if(wrap && ((cursor_x + textsize * (xo + w)) > _width)) + { + cursor_x = 0; + cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance); + } + drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + } + cursor_x += (unsigned char)pgm_read_byte(&glyph->xAdvance) * (short)textsize; + } + } + } + return 1; +} + +/**************************************************************** + * Function Name : print + * Description : Base function for printing strings + * Returns : No. of characters printed + * Params : @buffer: Ptr to buffer containing the string + * @size: Length of the string. + ****************************************************************/ +short print(const unsigned char *buffer, short size) +{ + short n = 0; + while(size--) + { + if(oled_write(*buffer++)) + n++; + else + break; + } + return (n); +} + +/**************************************************************** + * Function Name : print_str + * Description : Print strings + * Returns : No. of characters printed + * Params : @strPtr: Ptr to buffer containing the string + ****************************************************************/ +short print_str(const unsigned char *strPtr) +{ + return print(strPtr, strlen(strPtr)); +} + +/**************************************************************** + * Function Name : println + * Description : Move to next line + * Returns : No. of characters printed + * Params : NONE. + ****************************************************************/ +short println() +{ + return print_str("\r\n"); +} + +/**************************************************************** + * Function Name : print_strln + * Description : Print strings and move to next line + * Returns : No. of characters printed + * Params : @strPtr: Ptr to buffer containing the string + ****************************************************************/ +short print_strln(const unsigned char *strPtr) +{ + short n = 0; + n = print(strPtr, strlen(strPtr)); + n += print_str("\r\n"); + return (n); +} + +/*---------------------------------------------------------------------------- + * NUMBERS HANDLING API's + ----------------------------------------------------------------------------*/ + +/**************************************************************** + * Function Name : printNumber + * Description : Base function to print unsigned numbers + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber(unsigned long n, unsigned char base) +{ + unsigned long m = 0; + char c = 0; + char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte. + char *str = &buf[sizeof(buf) - 1]; + + *str = '\0'; + + // prevent crash if called with base == 1 + if(base < 2) + base = 10; + do + { + m = n; + n /= base; + c = m - base * n; + *--str = c < 10 ? c + '0' : c + 'A' - 10; + } + while(n); + //return oled_write((unsigned char)str); + return print_str(str); +} + +/**************************************************************** + * Function Name : printNumber_UL + * Description : Print unsigned long data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UL(unsigned long n, int base) +{ + if(base == 0) + return oled_write(n); + else + return printNumber(n, base); +} + +/**************************************************************** + * Function Name : printNumber_UL_ln + * Description : Print unsigned long & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UL_ln(unsigned long num, int base) +{ + short n = 0; + n = printNumber(num, base); + n += println(); + return (n); +} + +/**************************************************************** + * Function Name : printNumber_UI + * Description : Print unsigned int data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UI(unsigned int n, int base) +{ + return printNumber((unsigned long) n, base); +} + +/**************************************************************** + * Function Name : printNumber_UI_ln + * Description : Print unsigned int & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UI_ln(unsigned int n, int base) +{ + short a = 0; + a = printNumber((unsigned long) n, base); + a += println(); + return (a); +} + +/**************************************************************** + * Function Name : printNumber_UC + * Description : Print unsigned char data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UC(unsigned char b, int base) +{ + return printNumber((unsigned long) b, base); +} + +/**************************************************************** + * Function Name : printNumber_UC_ln + * Description : Print unsigned char & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_UC_ln(unsigned char b, int base) +{ + short n = 0; + n = printNumber((unsigned long) b, base); + n += println(); + return (n); +} + +/**************************************************************** + * Function Name : printNumber_L + * Description : Print Long data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_L(long n, int base) +{ + int t = 0; + if(base == 0) + { + return oled_write(n); + } + else if(base == 10) + { + if(n < 0) + { + t = oled_write('-'); + n = -n; + return printNumber(n, 10) + t; + } + return printNumber(n, 10); + } + else + { + return printNumber(n, base); + } +} + +/**************************************************************** + * Function Name : printNumber_UC_ln + * Description : Print long & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_L_ln(long num, int base) +{ + short n = 0; + n = printNumber_L(num, base); + n += println(); + return n; +} + +/**************************************************************** + * Function Name : printNumber_I + * Description : Print int data types + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_I(int n, int base) +{ + return printNumber_L((long) n, base); +} + +/**************************************************************** + * Function Name : printNumber_I_ln + * Description : Print int & advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @base: Base e.g. HEX, BIN... + ****************************************************************/ +short printNumber_I_ln(int n, int base) +{ + short a = 0; + a = printNumber_L((long) n, base); + a += println(); + return a; +} + +/**************************************************************** + * Function Name : printFloat + * Description : Print floating Pt. No's. + * Returns : No. of characters printed + * Params : @n: Number + * @digits: Resolution + ****************************************************************/ +short printFloat(double number, unsigned char digits) +{ + unsigned char i = 0; + short n = 0; + unsigned long int_part = 0; + double remainder = 0.0; + int toPrint = 0; + + // Round correctly so that print(1.999, 2) prints as "2.00" + double rounding = 0.5; + + if(isnan(number)) + return print_str("nan"); + if(isinf(number)) + return print_str("inf"); + if(number > 4294967040.0) + return print_str("ovf"); // constant determined empirically + if(number < -4294967040.0) + return print_str("ovf"); // constant determined empirically + + // Handle negative numbers + if(number < 0.0) + { + n += oled_write('-'); + number = -number; + } + + + for(i = 0; i < digits; ++i) + rounding /= 10.0; + + number += rounding; + + // Extract the integer part of the number and print it + int_part = (unsigned long) number; + remainder = number - (double) int_part; + n += printNumber_UL(int_part,DEC); + + // Print the decimal point, but only if there are digits beyond + if(digits > 0) + { + n += print_str("."); + } + + // Extract digits from the remainder one at a time + while(digits-- > 0) + { + remainder *= 10.0; + toPrint = (int)remainder; + n += printNumber_I(toPrint,DEC); + remainder -= toPrint; + } + return n; +} + +/**************************************************************** + * Function Name : printFloat_ln + * Description : Print floating Pt. No and advance to next line + * Returns : No. of characters printed + * Params : @n: Number + * @digits: Resolution + ****************************************************************/ +short printFloat_ln(double num, int digits) +{ + short n = 0; + n = printFloat(num, digits); + n += println(); + return n; +} diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h new file mode 100644 index 000000000..b7fcf39a1 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/SSD1306_OLED.h @@ -0,0 +1,204 @@ +/* + * MIT License + +Copyright (c) 2017 DeeplyEmbedded + +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. + + * SSD1306_OLED.h + * + * Created on : Sep 21, 2017 + * Author : Vinay Divakar + * Website : www.deeplyembedded.org + */ + +#ifndef SSD1306_OLED_H_ +#define SSD1306_OLED_H_ + +/* Lib's */ +#include + +/* Find Min and Max - MACROS */ +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define MAX(a,b) (((a)>(b))?(a):(b)) + +/* I2C Address of SSD1306 */ +#define SSD1306_OLED_ADDR 0x3C +#define DISPLAY_BUFF_SIZE (SSD1306_LCDWIDTH*SSD1306_LCDHEIGHT/8) + +/* COLOR MACROS */ +#define WHITE 1 +#define BLACK 0 +#define INVERSE 2 + +/* Number output format */ +#define DEC 10 +#define HEX 16 +#define OCT 8 +#define BIN 2 +#define DEFAULT 0 + +/*D/C# bit is '0' indicating that following + * byte is a command. '1' is for data + */ +#define SSD1306_CNTRL_CMD 0x00 +#define SSD1306_CNTRL_DATA 0x40 + + +/*-----------------------Enable the WxL of the Display ---------------------------*/ +//#define SSD1306_128_64 +#define SSD1306_128_32 +//#define SSD1306_96_16 +/*--------------------------------------------------------------------------------*/ + +/* LCD HxW i.e. 64x128 || WxL i.e. 128x64 */ +#if defined SSD1306_128_64 +#define SSD1306_LCDWIDTH 128 +#define SSD1306_LCDHEIGHT 64 +#endif +#if defined SSD1306_128_32 + #define SSD1306_LCDWIDTH 128 + #define SSD1306_LCDHEIGHT 32 +#endif +#if defined SSD1306_96_16 + #define SSD1306_LCDWIDTH 96 + #define SSD1306_LCDHEIGHT 16 +#endif + +/* SSD1306 Commands */ +#define SSD1306_DISPLAY_OFF 0xAE +#define SSD1306_SET_DISP_CLK 0xD5 +#define SSD1306_SET_MULTIPLEX 0xA8 +#define SSD1306_SET_DISP_OFFSET 0xD3 +#define SSD1306_SET_DISP_START_LINE 0x40 +#define SSD1306_CONFIG_CHARGE_PUMP 0x8D +#define SSD1306_SET_MEM_ADDR_MODE 0x20 +#define SSD1306_SEG_REMAP (0xA0 | 0x01) +#define SSD1306_SEG_REMAP1 0xA0 +#define SSD1306_SET_COMSCANDEC 0xC8 +#define SSD1306_SET_COMSCANDEC1 0xC0 +#define SSD1306_SET_COMPINS 0xDA +#define SSD1306_SET_CONTRAST 0x81 +#define SSD1306_SET_PRECHARGE 0xD9 +#define SSD1306_SET_VCOMDETECT 0xDB +#define SSD1306_DISPLAYALLON_RESUME 0xA4 +#define SSD1306_NORMAL_DISPLAY 0xA6 +#define SSD1306_DISPLAYON 0xAF +#define SSD1306_SET_COL_ADDR 0x21 +#define SSD1306_PAGEADDR 0x22 +#define SSD1306_INVERT_DISPLAY 0x01 +#define SSD1306_NORMALIZE_DISPLAY 0x00 + +/* SDD1306 Scroll Commands */ +#define SSD1306_SET_VERTICAL_SCROLL_AREA 0xA3 +#define SSD1306_ACTIVATE_SCROLL 0x2F +#define SSD1306_DEACTIVATE_SCROLL 0x2E +#define SSD1306_RIGHT_HORIZONTAL_SCROLL 0x26 +#define SSD1306_LEFT_HORIZONTAL_SCROLL 0x27 +#define SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL 0x29 +#define SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL 0x2A +#define SSD1306_INVERTDISPLAY 0xA7 + +/* SSD1306 Configuration Commands */ +#define SSD1306_DISPCLK_DIV 0x80 +#if defined SSD1306_128_64 +#define SSD1306_MULT_64 0x3F +#endif +#if defined SSD1306_128_32 + #define SSD1306_MULT_64 0x1F +#endif +#define SSD1306_MULT_64 0x1F +#define SSD1306_DISP_OFFSET_VAL 0x00 +#define SSD1306_COL_START_ADDR 0x00 //Reset to = 0 +#define SSD1306_COL_END_ADDR (SSD1306_LCDWIDTH - 1) //Reset to = 127 +#define SSD1306_PG_START_ADDR 0x00 +#define SSD1306_PG_END_ADDR 7 +#define SSD1306_CHARGE_PUMP_EN 0x14 +#if defined SSD1306_128_64 +#define SSD1306_CONFIG_COM_PINS 0x12 +#endif +#if defined SSD1306_128_32 + #define SSD1306_CONFIG_COM_PINS 0x02 +#endif +#define SSD1306_CONTRAST_VAL 0xCF //207 +#define SSD1306_PRECHARGE_VAL 0xF1 +#define SSD1306_VCOMH_VAL 0x40 +#define SSD1306_MULT_DAT (SSD1306_LCDHEIGHT - 1) +#define SSD1306_HOR_MM 0x00 + +/*SSD1306 Display API's */ +extern void clearDisplay(); +extern void display_Init_seq(); +extern void Display(); +extern void Init_Col_PG_addrs(unsigned char col_start_addr, unsigned char col_end_addr, + unsigned char pg_start_addr, unsigned char pg_end_addr); +extern void setRotation(unsigned char x); +extern void startscrollright(unsigned char start, unsigned char stop); +extern void startscrollleft(unsigned char start, unsigned char stop); +extern void startscrolldiagright(unsigned char start, unsigned char stop); +extern void startscrolldiagleft(unsigned char start, unsigned char stop); +extern void stopscroll(); +extern void setCursor(short x, short y); +extern short getCursorX(); +extern short getCursorY(); +extern unsigned char getRotation(); +extern void invertDisplay(unsigned char i); + +/*SSD1306 Graphics Handling API's */ +extern signed char drawPixel(short x, short y, short color); +extern void writeLine(short x0, short y0, short x1, short y1, short color); +extern void drawCircleHelper( short x0, short y0, short r, unsigned char cornername, short color); +extern void drawLine(short x0, short y0, short x1, short y1, short color); +extern void drawRect(short x, short y, short w, short h, short color); +extern void fillRect(short x, short y, short w, short h, short color); +extern void drawCircle(short x0, short y0, short r, short color); +extern void fillCircleHelper(short x0, short y0, short r, unsigned char cornername, short delta, short color); +extern void fillCircle(short x0, short y0, short r, short color); +extern void drawTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color); +extern void fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color); +extern void drawRoundRect(short x, short y, short w, short h, short r, short color); +extern void fillRoundRect(short x, short y, short w, short h, short r, short color); +extern void drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, short color); +extern short oled_write(unsigned char c); + +/*SSD1306 Text and Character Handling API's */ +extern void setTextSize(unsigned char s); +extern void setTextColor(short c); +extern void setTextWrap(bool w); +extern void drawChar(short x, short y, unsigned char c, short color, short bg, unsigned char size); +extern short print_str(const unsigned char *strPtr); +extern short println(); +extern short print_strln(const unsigned char *strPtr); + +/*SSD1306 Number Handling API's */ +extern short printNumber(unsigned long n, unsigned char base); +extern short printNumber_UL(unsigned long n, int base); +extern short printNumber_UL_ln(unsigned long num, int base); +extern short printNumber_UI(unsigned int n, int base); +extern short printNumber_UI_ln(unsigned int n, int base); +extern short printNumber_UC(unsigned char b, int base); +extern short printNumber_UC_ln(unsigned char b, int base); +extern short printNumber_L(long n, int base); +extern short printNumber_L_ln(long num, int base); +extern short printNumber_I(int n, int base); +extern short printNumber_I_ln(int n, int base); +extern short printFloat(double number, unsigned char digits); +extern short printFloat_ln(double num, int digits); +#endif /* SSD1306_OLED_H_ */ + diff --git a/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h b/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h new file mode 100644 index 000000000..e66128a88 --- /dev/null +++ b/luci-app-ouad/src/SSD1306_OLED_Library/gfxfont.h @@ -0,0 +1,18 @@ +#ifndef _GFXFONT_H_ +#define _GFXFONT_H_ + +typedef struct { // Data stored PER GLYPH + unsigned short bitmapOffset; // Pointer into GFXfont->bitmap + unsigned char width, height; // Bitmap dimensions in pixels + unsigned char xAdvance; // Distance to advance cursor (x axis) + char xOffset, yOffset; // Dist from cursor pos to UL corner +} GFXglyphT, *GFXglyphPtr; + +typedef struct { // Data stored for FONT AS A WHOLE: + unsigned char *bitmap; // Glyph bitmaps, concatenated + GFXglyphPtr glyph; // Glyph array + unsigned char first, last; // ASCII extents + unsigned char yAdvance; // Newline distance (y axis) +} GFXfontT, *GFXfontPtr; + +#endif // _GFXFONT_H_