diff --git "a/OpenHarmony\347\241\254\344\273\266\345\274\200\345\217\221\345\237\272\347\241\200/README.md" "b/OpenHarmony\347\241\254\344\273\266\345\274\200\345\217\221\345\237\272\347\241\200/README.md" index 2d27be08409cc8329c19261f9d2bacdd16249f54..974bdf37949e16af9fcb7dac35cd5716ec636fc4 100644 --- "a/OpenHarmony\347\241\254\344\273\266\345\274\200\345\217\221\345\237\272\347\241\200/README.md" +++ "b/OpenHarmony\347\241\254\344\273\266\345\274\200\345\217\221\345\237\272\347\241\200/README.md" @@ -11,11 +11,14 @@ XC-HM-01201 OpenHarmony硬件应用 #### 提升能力 -快速认知并初步掌握基于中软国际Hi3861开发板的OpenHarmony系统软件应用开发基本知识及操作能力。 +快速认知并初步掌握基于中软国际Hi3861教学开发板套件的OpenHarmony系统软件应用开发基本知识及操作能力。 #### 课程作者 北京中软国际教育科技股份有限公司(卓越研究院) +#### 教学开发板套件 +中软国际《Wi-Fi AIoT智能开发套件(海思Hi3861)》 + #### 课程发布日期 2020年09月 @@ -33,7 +36,7 @@ Online在线课程 * 有一定的物联网开发经验的OH初学者 #### 学习基础 -C编程语言 / Java编程语言 +C编程语言 #### 课程大纲 | 序号 | 章名称 | @@ -44,8 +47,8 @@ C编程语言 / Java编程语言 | 第4讲 | Hi3861外设——环境监测板开发 | | 第5讲 | Hi3861上交互命令AT分析及实现 | | 第6讲 | Hi3861上WiFi开发 | -| 第6讲 | Hi3861上网络编程开发 | -| 第7讲 | Hi3861上物联网应用开发 | +| 第7讲 | Hi3861上网络编程开发 | +| 第8讲 | Hi3861上物联网应用开发 | #### 相关资源素材 diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/LICENSE" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/LICENSE" new file mode 100644 index 0000000000000000000000000000000000000000..ee5839968a2bf86c93283efc09d40fd050b7cfa2 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/LICENSE" @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..3ee16206de783d6a867cf0d84eb52965a040cb34 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/README.md" @@ -0,0 +1,154 @@ +## 一、HiSpark WiFi-IoT 鸿蒙开发套件概述 + +##### [HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +* 基于海思 Pagasus芯片,支持OpenHarmony。 +* 主控为WiFi SOC Hi3861,160MHz主频,SRAM 352KB,ROM 288KB,2M Flash。 +* 1个主板、6个扩展版,支持多功能、多应用开发。 +* 通用底板,降低开发难度,提升开发自主性。 +* 板载NFC,实现OpenHarmony”碰一碰“。 + +## 二、润和工程师与您面对面 |HiHope一站式教程 + +初入“鸿蒙”深似海?NO!NO!NO!润和HiHope伴您走江湖~ + +有HiSpark WiFi-IoT鸿蒙套件在手,再加上此套件的官方开发团队亲自为您传道授业,无论是开箱、开发环境搭建,还是应用开发、样例开发,在这里全部一站搞定,轻松上手。 + +如果您还有个性化问题,也可以第一时间连线我们的[开发工程师](https://bbs.elecfans.com/group_1429),为您解惑,获得权威支持和帮助。 + +#### (一)手把手教您快速完成开箱 + +Step by Step带您顺畅开箱,省去自行摸索的时间,助您快速完成HiSpark WiFi-IoT鸿蒙开发套件的组装。 + +1、套件开箱视频 + +[手把手教您快速开箱HiSpark WiFi-IoT鸿蒙开发套件](https://www.bilibili.com/video/BV1Sa4y1L78o?from=search&seid=15781732748881430523) + +#### (二)鸿蒙开发环境搭建 + +开发者可以自行选择开发环境的搭建方式。 + +1、**一键式环境搭建** + +使用docker镜像,可以简单快捷地完成鸿蒙开发环境搭建 + +(1)、文档 + +​ [一键式环境搭建](https://gitee.com/hihopeorg/hispark-hm-pegasus/blob/master/docs/QuickStart/hos_docker_environment.md) + +2、**快速环境搭建** + +便于windows环境使用,开发者不需要一步步安装各种依赖包。 + +(1)、文档 + +​ [快速环境搭建](https://gitee.com/hihopeorg/hispark-hm-pegasus/blob/master/docs/QuickStart/hos_vmware_environment.md) + +3、**手把手教您完成OpenHarmony开发环境搭建** + +下载源码、配置环境、编译源码,只需三步,即可完成OpenHarmony开发环境搭建。 + +(1)、视频教程 + +​ [手把手教您完成鸿蒙开发环境搭建](https://developer.huaweiuniversity.com/portal/courses/HuaweiX+CBGHWDCN134/about?source=hwdev) + +(2)、文档 + +​ [手把手教您完成鸿蒙开发环境搭建](https://gitee.com/hihopeorg/hispark-hm-pegasus/blob/master/docs/QuickStart/hos_source_code_download_and_compile.md) + +#### (三)应用开发教程 + +1、视频系列(鸿蒙官方社区平台) + +* [课程整体简介](https://edu.51cto.com/center/course/lesson/index?id=657752) +* [WiFi-IoT 套件简介](https://edu.51cto.com/center/course/lesson/index?id=657754) +* [海思Pegasus芯片简介](https://edu.51cto.com/center/course/lesson/index?id=657753) +* [OpenHarmony 开发环境搭建](https://edu.51cto.com/center/course/lesson/index?id=657751) +* [Hi3861开发板第一个示例程序演示](https://edu.51cto.com/center/course/lesson/index?id=657750) +* [核心板LED控制程序讲解及演示](https://edu.51cto.com/center/course/lesson/index?id=657749) +* [交通灯板编程演示](https://edu.51cto.com/center/course/lesson/index?id=657748) +* [炫彩灯板编程演示](https://edu.51cto.com/center/course/lesson/index?id=657747) +* [OLED板编程演示](https://edu.51cto.com/center/course/lesson/index?id=657746) +* [环境监测板编程演示](https://edu.51cto.com/center/course/lesson/index?id=657745) +* [WiFi-IoT 硬件 WiFi STA模式编程](https://edu.51cto.com/center/course/lesson/index?id=689780) +* [WiFi-IoT 硬件 WiFi AP模式编程](https://edu.51cto.com/center/course/lesson/index?id=689972) +* [TCP/IP协议和LWIP开源项目简介](https://edu.51cto.com/center/course/lesson/index?id=689971) +* [TCP协议简介以及编程套路](https://edu.51cto.com/center/course/lesson/index?id=690493) +* [TCP程序实验](https://edu.51cto.com/center/course/lesson/index?id=690492) + +* [[更多: 陆续上传中...]](https://edu.51cto.com/course/25739.html) + +2、文档系列(Gitee) + +- [OpenHarmony开发教程简介](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/tree/master) +- [从零开始搭建OpenHarmony开发环境](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/01_envsetup/README.md) +- [OpenHarmony 开发指南——源码下载和编译](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/01_envsetup/hos_source_code_download_and_compile.md) +- [OpenHarmony 开发指南——DevEco Device Tool 安装配置](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/01_envsetup/hos_deveco_device_tool_install.md) +- [OpenHarmony 开发指南——使用HiBurn烧录固件到开发板](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/01_envsetup/hos_use_hiburn_download_firmware.md) +- [使用OpenHarmony控制外设——输入输出](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/02_device_control/README.md) +- [使用OpenHarmony控制外设——读取传感器](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/03_sensing/README.md) +- [OpenHarmony WiFi编程——连接热点、创建热点](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/04_wifi/README.md) +- [OpenHarmony 网络编程——使用TCP/IP协议](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/05_network/README.md) + + +#### (四)样例开发教程 + +HiSpark WiFi-IoT鸿蒙开发套件提供多样化样例,易于您掌握OpenHarmony开发流程,并在此基础上进行扩展。 + +例程列表如下所示: + +| 编号 | 例程名 | 说明 | +| ---- | ------ | ---------------- | +| 1 | thread | [多线程](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/00_thread) | +| 2 | timer | [软定时器](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/01_timer) | +| 3 | delay | [等待](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/02_delay) | +| 4 | mutex | [互斥锁](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/03_mutex) | +| 5 | semp | [信号量](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/04_semaphore) | +| 6 | message | [消息队列](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/05_message) | +| 7 | gpio_led | [gpio控制主板led闪烁](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/06_gpioled) | +| 8 | gpio_button | [通过usr按键控制led亮灭](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/07_gpiobutton) | +| 9 | pwm_led | [pwm控制led亮暗程度](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/08_pwmled) | +| 10 | adc | [ADC采集电压值从而感知环境的光照强度](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/09_adc) | +| 11 | i2c_aht20 | [I2C读取温湿度](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/10_i2caht20) | +| 12 | uart | [UART](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/11_uart) | +| 13 | ssd1306 | [SSD1306 OLED屏驱动库](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/12_ssd1306) | +| 14 | oled_player | [在0.96寸OLED屏上播放视频](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/13_oledplayer) | +| 15 | pwm_beer | [pwm控制蜂鸣器](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/14_pwmbeer) | +| 16 | pwm_beer_music | [pwm控制蜂鸣器播放音乐](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/15_pwmbeermusic) | +| 17 | traffic_light_demo | [交通灯样例](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/16_trafficlight) | +| 18 | colorful_light_demo | [炫彩灯样例](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/17_colorfullight) | +| 19 | environment_demo | [环境监测样例](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/18_environment) | +| 20 | wifi_connect_demo | [WiFi联网](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/19_wificonnect) | +| 21 | wifi_hotspot_demo.c | [创建热点](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/20_wifihotspot) | +| 22 | tcp_client_test | [TCP客户端](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/21_tcpclient) | +| 23 | tcp_server_test | [TCP服务端](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/22_tcpserver) | +| 24 | udp_client_test | [UDP客户端](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/23_udpclient) | +|25|udp_server_test|[UDP服务端](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/24_udpserver)| +|||| + + + +## 三、[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 官方购买渠道 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +- [HiSpark WiFi-IoT鸿蒙开发套件介绍](http://www.hihope.org/pro/pro1.aspx?mtt=8) + +- [HiSpark WiFi-IoT鸿蒙开发套件官方购买渠道](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341861125.3.383b4a82wiKJEK&id=622343426064&scene=taobao_shop) + +## 四、联系我们 + +#### (一)技术资料支持 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** +- HiHope官网-资源中心(SDK包、技术文档下载)**www.hihope.org** + + ![hihope](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/hihope.png) + +#### (二)开发者互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛**https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.png" new file mode 100755 index 0000000000000000000000000000000000000000..063271e1371998523cdbe82add752a32404c296c Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.xmind" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.xmind" new file mode 100755 index 0000000000000000000000000000000000000000..20396bd62924af9601774fa70120b06a57fd6c60 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.xmind" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..8164d2735c4046a05eb13b59cedc0125dd183564 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/HardwareDocs/README.md" @@ -0,0 +1,5 @@ +# HiSpark WiFi IoT 开发套件编程速查 + + + +![](./HiSpark_WiFi_IoT_DevKits_Hardware_Quick_Reference.png) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..5a3e2d5a3acdb76d981c3cf81f39db926be446ee --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/README.md" @@ -0,0 +1,43 @@ +# 从零开始搭建OpenHarmony开发环境 + + + +本节课程中向大家演示——如何从零搭建Hamony OS开发环境,具体包括: + +* Linux系统——源码下载和编译环境 + + * [OpenHarmony 开发指南——源码下载和编译](hos_source_code_download_and_compile.md) + +* Windows系统——源码编辑和烧录环境 + + * [OpenHarmony 开发指南——DevEco Device Tool 安装配置](hos_deveco_device_tool_install.md) + * [OpenHarmony 开发指南——使用HiBurn烧录固件到开发板](hos_use_hiburn_download_firmware.md) + +* Windows主机访问Linux主机 + + * 支持远程终端访问 + + * 安装openssh-server:`sudo apt install openssh-server`,完成后可以使用远程终端登录MobaXterm(或者Putty) + + * 支持Windows系统“映射网络驱动器” + + * 安装samba:`sudo apt install samba`, + * 添加samba账号并设置密码:`sudo smbpasswd -a $USER`(其中$USER为用户名), + * 修改配置(修改完需要重启服务`sudo service smbd restart`): + + ```ini + [home] + comment = User Homes + path = /home + browsable = yes + writable = yes + guest ok = no + read only = no + create mask = 0755 + ``` + + * 如果是VirtualBox里面安装的Linux + + * 添加一个HostOnly的虚拟网卡,混杂模式:全部允许 + * 虚拟网卡设置成功后,Windows主机上应该可以ping通虚拟机 + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_deveco_device_tool_install.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_deveco_device_tool_install.md" new file mode 100755 index 0000000000000000000000000000000000000000..ed211b1ffbdd89eb447927a22639989fb1f64b8b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_deveco_device_tool_install.md" @@ -0,0 +1,138 @@ +# OpenHarmony 开发指南——DevEco Device Tool 安装配置 + +本文介绍如何在Windows主机上安装DevEco Device Tool工具。 + +**坑点总结**: + +1. 国内部分网络环境下,安装npm包可能会很慢或者超时,推荐使用国内npm源(如淘宝源、华为源等); +2. serialport这个npm包安装的过程中需要编译源码,需要先安装windows-build-tools再安装这个包才会成功; +3. DevEco Device Tool中打包了预编译的.exe文件,只能在Windows版的VSCode中使用(暂不支持Linux和Mac OS); + +## 准备环境 + +本节介绍下载、编译鸿蒙源码需要的软硬件环境。 + +### 硬件环境 + +![开发环境](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200910235406.07666083971622121425650879377172:50510911011517:2800:A260456A9C92CDA9B13E2E3A942A5A015A20E4EC9CAEF0760A683198DDAB5578.png?needInitFileName=true?needInitFileName=true) + +其中,Linux主机用于源码下载和编译,Windows主机用于烧写程序到单板以及源码编辑。 + + + +### 软件环境 + +| 硬件 | 说明 | +| ----------------- | ------------------------------------------------------------ | +| Linux主机 | 推荐实际物理机器,Ubuntu16.04及以上64位系统,Shell使用bash,安装有samba、vim等常用软件,需要做适当适配以支持linux文件共享,(Samba配置需要注意,除了修改配置文件,还需要使用 `smbpasswd` 命令创建密码);使用虚拟机也可以,但需要配置正确虚拟网络,这里不做详细介绍。 | +| Windows主机 | Windows XP/Windows7/Windows10 系统 | +| USB转UART芯片驱动 | 对单板进行烧录和调试需要安装串口驱动程序,AI Camera和DIY IPC套件附赠的USB串口线内置PL2302芯片,需要安装USB转UART驱动,下载链接: http://www.hihope.org/download 页面,USB-to-Serial Comm Port.exe 文件。WiFi IoT主控芯片上集成的是CH340G芯片,可以选择联网自动安装驱动程序。 | +| 远程终端 | 推荐MobaXterm(PuTTY、SecureCRT等其他远程终端也可以),用于在Windows主机上登录Linux主机,进行源码下载、编译等工作 | + + + +DevEco Device Tool以Visual Studio Code插件方式提供,安装分为如下几步: + +1. 安装Visual Studio Code +2. 安装Node.js +3. 安装JDK +4. 安装hpm和**其他npm包** +5. 安装DevEco Device Tool插件 +6. 安装C/C++插件 + +其中,下载nodejs、和JDK包可能较慢,安装hpm包 + + +## 安装VSCode + +DevEco Device Tool(简称DevEco插件)是一个Visual Studio Code(简称VSCode)的插件,需要先安装VSCode; + +VSCode下载页面:https://code.visualstudio.com/Download,例如选择 System Installer 64 bit 下载 + +安装过程中,请勾选“添加到PATH(重启后生效)”,其他按照默认选项进行即可; + + + +## 安装Node.js + +DevEco插件的烧录功能依赖nodejs和相关插件,需要先安装nodejs和相关插件; + +Node.js下载页面:https://nodejs.org/en/download/ 例如选择 64 bit Windows Installer (.msi) 下载 + +安装完成后,设置环境变量 `NODE_PATH` 为 `C:\Users\%USERNAME%\AppData\Roaming\npm\node_modules` 其中`%USERNAME%`为实际用户名; + +Node.js 安装过程中提示,“Tools for Native Modules” 界面的复选框可以不用勾选(勾选该选项后需要从npm官网下载安装vs编译工具包和Python,耗时较长,后续安装serial插件之前,使用国内镜像单独安装速度较快); + + + +## 安装JDK + +**说明** 需要安装JDK 1.8,如果已安装JDK,打开命令行工具,输入**java -version**命令,检查版本号是否1.8版本。 + +请自行下载并安装JDK,版本要求为:1.8版本。 + +Windows版的OpenJDK可以在JetBrains下载:https://confluence.jetbrains.com/display/JBR/JetBrains+Runtime + +或者从红帽下载(有CDN加速,下载速度较快): https://developers.redhat.com/products/openjdk/download + +下载压缩包版本可以免安装,解压后配置bin目录到PATH 即可使用(CLASSPATH 可以不配置); + + + +## 安装hpm和其他npm包 + +1. 使用国内镜像源,加速模块下载速度:`npm config set registry https://registry.npm.taobao.org` + +2. 安装hpm 鸿蒙组件管理器:`npm install -g @ohos/hpm-cli` + +3. 安装Windows编译工具包,serialport 包需要编译本地模块,必须先安装此包才能安装 serialport 包: + + `npm install -g windows-build-tools` + +4. 安装 tftp 包,用于启动tftp服务器,通过网络方式向单板烧录映像: + + `npm install -g tftp` + +5. 安装 serialport 包,用于通过串口烧写映像:`npm install -g serialport` + `npm install -g @serialport/parser-readline` + +```sh +npm config set registry https://registry.npm.taobao.org +npm install -g @ohos/hpm-cli +npm install -g windows-build-tools +npm install -g tftp +npm install -g serialport +npm install -g @serialport/parser-readline +``` + + + +## 下载DevEco插件 + +1. 登录[HarmonysOS设备开发门户](https://device.harmonyos.com/cn/home),点击右上角**注册**按钮,注册开发者帐号,注册指导参考[注册华为帐号](https://developer.huawei.com/consumer/cn/doc/20300)。如果已有华为开发者帐号,请直接点击**登录**按钮。 + +2. 进入[HUAWEI DevEco Device Tool产品页](https://device.harmonyos.com/cn/ide),下载DevEco Device Tool安装包。 + +3. 打开Visual Studio Code软件。 + +4. 采用从本地磁盘安装方式,安装DevEco Device Tool。 + + ![点击放大](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200914093622.93560046166375321457328824276949:50510914020140:2800:6D71CB138B0590368E613ED5A7B302262DE31733629047F66500DF27757F2853.gif?needInitFileName=true?needInitFileName=true) + + 安装成功后,界面如下图所示。 + + ![点击放大](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200914093622.37832007141604464627097125460649:50510914020140:2800:F6288E3BA1FDA293B52D1BA2F6FFBF4F6DDB53DD792FB42E66F234A75AA1BB85.png?needInitFileName=true?needInitFileName=true) + + + +## 安装C/C++插件 + +HarmonysOS设备开发采用C/C++语言,Visual Studio Code工具对C/C++语言的支持插件非常丰富,可以安装“C/C++”插件来实现C/C++代码智能提示、代码高亮、格式化等功能,帮助您更高效、便利的开发更规范和优美的代码。 + +在Visual Studio Code的插件市场,输入“C/C++”,然后点击“Install”。 + +![点击放大](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200914093623.01024343525247339263582244765607:50510914020140:2800:8CECD4F3E002EEED38F29A6832DBA7A98F78ACCA9AA2FD36341147DA52300C96.png?needInitFileName=true?needInitFileName=true) + +如果在线安装失败,可点击右下角弹框的“Go to Download Page”,下载离线插件(选择“cpptools-win32.vsix”版本,Windows下,64位和32位系统均为同一个安装包)。然后再参考[安装DevEco Device Tool插件的方式](https://device.harmonyos.com/cn/docs/ide/user-guides/tool_install-0000001050164976#ZH-CN_TOPIC_0000001050164976__section4336315185716),离线安装C/C++插件。 + +![img](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200914093623.16985116067731605372818769568785:50510914020140:2800:0B1E3CA592229336927B6953172125E21AE192B930A3BE4A977382875E06BAD2.png?needInitFileName=true?needInitFileName=true) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_docker_environment.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_docker_environment.md" new file mode 100644 index 0000000000000000000000000000000000000000..3bbd3a516456e99c51cb3dba89cadaf524a1f37a --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_docker_environment.md" @@ -0,0 +1,175 @@ +## 1. 使用存储库安装 + +在新主机上首次安装Docker Engine之前,需要设置Docker存储库。之后,您可以从存储库安装和更新Docker。 + +#### 1.1 设置存储库 + +1. 更新`apt`软件包索引并安装软件包以允许`apt`通过HTTPS使用存储库: + +``` +sudo apt-get update + +sudo apt-get install \ + apt-transport-https \ + ca-certificates \ + curl \ + gnupg-agent \ + software-properties-common +``` + +2. 添加Docker的官方GPG密钥: + +``` +$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - +``` + +`9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88`通过搜索指纹的后8个字符,验证您现在是否拥有带有指纹的密钥。 + +``` +$ sudo apt-key fingerprint 0EBFCD88 + +pub rsa4096 2017-02-22 [SCEA] + 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 +uid [ unknown] Docker Release (CE deb) +sub rsa4096 2017-02-22 [S] +``` + +3. 使用以下命令来设置**稳定的**存储库。要添加 **每晚**或**测试**存储库,请在以下命令中的单词后面添加`nightly`或`test`(或两者)`stable`。[了解**每晚**和**测试**频道](https://docs.docker.com/engine/install/)。 + +> **注意**:下面的`lsb_release -cs`子命令返回Ubuntu发行版的名称,例如`xenial`。有时,在Linux Mint等发行版中,您可能需要更改`$(lsb_release -cs)` 为父Ubuntu发行版。例如,如果您使用 `Linux Mint Tessa`,则可以使用`bionic`。Docker对未经测试和不受支持的Ubuntu发行版不提供任何保证。 + +> + +``` +$ sudo add-apt-repository \ + "deb [arch=amd64] https://download.docker.com/linux/ubuntu \ + $(lsb_release -cs) \ + stable" +``` + +#### 1.2 安装DOCKER引擎 + +1. 更新`apt`程序包索引,并安装*最新版本*的Docker Engine和容器,或转到下一步以安装特定版本: + + ```sh + sudo apt-get update + sudo apt-get install docker-ce docker-ce-cli containerd.io + ``` + + > 有多个Docker存储库吗? + > + > 如果启用了多个Docker存储库,则在未在`apt-get install`or `apt-get update`命令中指定版本的情况下进行安装或更新将始终安装可能的最高版本,这可能不适合您的稳定性需求。 + +2. 要安装*特定版本*的Docker Engine,请在存储库中列出可用版本,然后选择并安装: + + 一种。列出您的仓库中可用的版本: + + ``` + $ apt-cache madison docker-ce + + docker-ce | 5:20.10.2~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:20.10.1~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:20.10.0~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.14~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.13~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.12~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.11~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.10~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + docker-ce | 5:19.03.9~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages + ... + ``` + + b。使用第二列中的版本字符串安装特定版本,例如`5:18.09.1~3-0~ubuntu-xenial`。 + + ```sh + 例: sudo apt-get install docker-ce= docker-ce-cli= containerd.io + + $ sudo apt-get install docker-ce=<5:20.10.0~3-0~ubuntu-focal> docker-ce-cli=<5:20.10.0~3-0~ubuntu-focal> containerd.io + ``` + +3. 通过运行`hello-world` 映像来验证是否正确安装了Docker Engine 。 + + ``` + $ sudo docker run hello-world + ``` + + 此命令下载测试图像并在容器中运行它。容器运行时,它会打印参考消息并退出。 + +**docker 安装完成后测试hello-world出现问题(Unable to find image 'hello-world:latest' locally)** + +新建/etc/docker/daemon.json + +```sh +vim /etc/docker/daemon.json +chmod 777 /etc/docker/daemon.json +#添加下面内容 +#docker在本地没有找到hello-world镜像,也没有从docker仓库中拉取镜像,出项这个问题的原因:是应为#docker服务器再国外,我们在国内无法正常拉取镜像,所以就需要我们为docker设置国内阿里云的镜像加速器; +{ +"registry-mirrors": ["https://alzgoonw.mirror.aliyuncs.com"] +} + +sudo systemctl restart docker +sudo systemctl status docker +``` + +Docker Engine已安装并正在运行。该`docker`组已创建,但未添加任何用户。您需要使用`sudo`来运行Docker命令。继续进行[Linux后安装,](https://docs.docker.com/engine/install/linux-postinstall/)以允许非特权用户运行Docker命令以及其他可选配置步骤。 + +``` +# 创建docker组 +$ sudo groupadd docker + +# 将您的用户添加到该docker组 +$ sudo usermod -aG docker lxy + +# 注销并重新登录,以便重新评估您的组成员身份。 +$ newgrp docker + +# 验证您是否可以运行docker不带命令的命令sudo +$ docker run hello-world + +``` + + + +## 2. 配置Docker以在启动时启动 + +当前大多数Linux发行版(RHEL,CentOS,Fedora,Debian,Ubuntu 16.04及更高版本)都[`systemd`](https://docs.docker.com/engine/install/linux-postinstall/#systemd)用于管理系统启动时启动的服务。在Debian和Ubuntu上,默认情况下,将Docker服务配置为在引导时启动。要在启动时自动启动其他发行版的Docker和Containerd,请使用以下命令: + +``` +$ sudo systemctl enable docker.service +$ sudo systemctl enable containerd.service +``` + +若要禁用此行为,请`disable`改用。 + +``` +$ sudo systemctl disable docker.service +$ sudo systemctl disable containerd.service +``` + +如果需要添加HTTP代理,为Docker运行时文件设置不同的目录或分区,或进行其他自定义,请参阅 [自定义系统的Docker守护程序选项](https://docs.docker.com/config/daemon/systemd/)。 + + + +## 3. 镜像压缩包获取 + +云盘资料链接: https://pan.baidu.com/s/1uiiCpbJqViGb7Qs6HdCb8g +提取码: ddab +“Pegasus物联网套件开发环境-docker镜像” 目录下面的 “wifiiot.tar” + +## 4. Docker使用 + +```sh + +# 接收到 tar 包之后,怎么使用 tar 包 +sudo docker load < /(下载的tar包所在ubuntu服务器中的路径)/wifiiot.tar + +sudo docker images #查看镜像 +sudo docker run -dit --name=xxx --net=host 镜像的ID /bin/bash + +sudo docker ps -a #查看容器的ID +# 启动容器 +sudo docker start 容器ID +sudo docker attach 容器ID +``` + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_source_code_download_and_compile.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_source_code_download_and_compile.md" new file mode 100755 index 0000000000000000000000000000000000000000..120ae7b111662ad57bb9432cd43b21a478750f79 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_source_code_download_and_compile.md" @@ -0,0 +1,249 @@ +# 手把手教您完成鸿蒙开发环境搭建 + +本文介绍了如何下载鸿蒙系统源码,如何一次性配置可以编译三个目标平台(`Hi3516`,`Hi3518`和`Hi3861`)的编译环境,以及如何将源码编译为三个目标平台的二进制文件。 + +**坑点总结**: + +1. 下载源码基本上没有太多坑,可以很顺利的进行 +2. 编译源码主要的一个大坑是,默认版本的`scons`依赖python 3.7+,鸿蒙基础编译代码依赖`python3`,需要安装python 3.7+,并和当前系统上的python2.7/python3.6和谐共处!解决方法一般有两种: + * 使用`virtualenv`管理多个版本的python环境,这种方式好处是只在当前shell会话生效不影响系统环境、其他用户和其他shell会话,缺点是使用前需要source active脚本稍微有点麻烦; + * 使用`update-alternatives`管理系统的多个版本python命令,这种方式需要切换系统的链接`/usr/bin/python`和`/usr/bin/python3`,可能会影响依赖python的应用程序(例如`apt`)的正常使用、其他用户和其他shell会话; + +## 准备环境 + +本节介绍下载、编译和烧写鸿蒙系统所需的软硬件环境。 + +### 硬件环境 + +![开发环境](https://communityfile-drcn.op.hicloud.com/FileServer/getFile/cmtyPub/011/111/111/0000000000011111111.20200910235406.07666083971622121425650879377172:50510911011517:2800:A260456A9C92CDA9B13E2E3A942A5A015A20E4EC9CAEF0760A683198DDAB5578.png?needInitFileName=true?needInitFileName=true) + +其中,Linux主机用于源码下载和编译,Windows主机用于烧写程序到单板以及源码编辑。 + + + +### 软件环境 + +| 硬件 | 说明 | +| ----------------- | ------------------------------------------------------------ | +| Linux主机 | 推荐实际物理机器,Ubuntu16.04及以上64位系统,Shell使用bash,使用虚拟机也可以,如何安装这里不做详细介绍。 | +| Windows主机 | Windows XP/Windows7/Windows10 系统 | +| 远程终端 | 推荐MobaXterm(PuTTY、SecureCRT等其他远程终端也可以),用于在Windows主机上登录Linux主机,进行源码下载、编译等工作 | +| USB转串口芯片驱动 | 下载链接: http://www.hihope.org/download 页面,USB-to-Serial Comm Port.exe 文件(AI Camera和DIY IPC套件附赠的USB串口线中集成了PL2302芯片,需要安装此驱动才能识别)。WiFi IoT主控芯片上集成的是CH340G芯片,可以选择联网自动安装驱动程序。 | + + + +**本文所有操作均基于Ubuntu 18.04进行,其他发行版和Ubuntu版本上的命令操作可能不完全一致,但说明的原理可以互通。** + + + +## 下载源码 + +本节介绍如何在Linux主机上下载鸿蒙源码,所有命令均通过远程终端在Linux主机上执行。 + +这里使用的是“从代码仓库获取”的方式,这种方式方便后续更新代码;你也可以从官网下载源码压缩包(这里不再介绍)。 + +### 配置 repo 工具 + +如果你的Linux系统上还没有配置repo命令,需要先下载并配置repo命令行工具: + +```sh +mkdir ~/bin/ +# sudo apt install curl # 如果没有curl命令需要先下载 +curl https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > ~/bin/repo +chmod +x ~/bin/repo +echo 'export PATH=~/bin:$PATH' >> ~/.bashrc +source ~/.bashrc +``` + +### 下载OpenHarmony源码 + +```sh +mkdir -p ~/harmonyos/openharmony && cd ~/harmonyos/openharmony +sudo apt install --no-install-recommends git python # repo工具本身是python脚本,它会调用git命令下载单个代码仓 +# 开始前需要配置`user.name`和`user.email`,如果没有配置,使用如下命令进行配置: +# git config --global user.name "yourname" +# git config --global user.email "your-email-address" +repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify +repo sync -c # 以后每天同步远程仓的修改,只需要执行这一条命令即可 +``` + + + +## 配置环境 + +本节介绍如何在Linux主机上配置鸿蒙源码的编译构建环境,所有命令均通过远程终端在Linux主机上执行。 + +### 安装文件系统打包工具 + +1. 运行"mkfs.vfat",如果未找到该命令,需要安装 + +2. 运行"mcopy ",如果未找到该命令,需要安装 + + +```sh +sudo apt-get install dosfstools mtools # 官方文档说明的两个文件系统打包工具 +sudo apt-get install zip # 官方文档虽然没有写,但是打包rootfs过程中需要使用 +sudo apt install mtd-utils # 3518需要打包 jffs2 镜像的mkfs.jffs2 命令,需要安装这个包 +sudo apt install build-essential # 安装gcc/g++/make等工具,ffmpeg的测试过程中需要使用链接器ld,需要这个包 +``` + +### 下载、配置编译工具链 + +使用如下命令,分别下载 gn、ninja、LLVM、hc-gen包,根据官方文档修改,一步到位,不用反复复制粘贴! + +```sh +# 下载gn/ninja/LLVM/hc-gen包 +URL_PREFIX=https://repo.huaweicloud.com/harmonyos/compiler +DOWNLOAD_DIR=~/Downloads # 下载目录,可自行修改 +TOOLCHAIN_DIR=~/harmonyos/toolchain # 工具链存放目录,可自行修改 + +[ -e $DOWNLOAD_DIR ] || mkdir $DOWNLOAD_DIR +[ -e $TOOLCHAIN_DIR ] || mkdir -p $TOOLCHAIN_DIR + +wget -P $DOWNLOAD_DIR $URL_PREFIX/gn/1523/linux/gn.1523.tar +wget -P $DOWNLOAD_DIR $URL_PREFIX/ninja/1.9.0/linux/ninja.1.9.0.tar +wget -P $DOWNLOAD_DIR $URL_PREFIX/clang/9.0.0-34042/linux/llvm-linux-9.0.0-34042.tar +wget -P $DOWNLOAD_DIR $URL_PREFIX/hc-gen/0.65/linux/hc-gen-0.65-linux.tar + +# 编译 hi3861 需要 riscv 编译工具链 +wget -P $DOWNLOAD_DIR $URL_PREFIX/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz + +# 解压gn/ninja/LLVM/hc-gen包: +tar -C $TOOLCHAIN_DIR/ -xvf $DOWNLOAD_DIR/gn.1523.tar +tar -C $TOOLCHAIN_DIR/ -xvf $DOWNLOAD_DIR/ninja.1.9.0.tar +tar -C $TOOLCHAIN_DIR/ -xvf $DOWNLOAD_DIR/llvm-linux-9.0.0-34042.tar +tar -C $TOOLCHAIN_DIR/ -xvf $DOWNLOAD_DIR/hc-gen-0.65-linux.tar +tar -C $TOOLCHAIN_DIR/ -xvf $DOWNLOAD_DIR/gcc_riscv32-linux-7.3.0.tar.gz + +# 向 ~/.bashrc 中追加gn/ninja/LLVM/hc-gen路径配置: +cat <> ~/.bashrc +TOOLCHAIN_DIR=$TOOLCHAIN_DIR +export PATH=\$TOOLCHAIN_DIR/gn:\$PATH +export PATH=\$TOOLCHAIN_DIR/ninja:\$PATH +export PATH=\$TOOLCHAIN_DIR/llvm/bin:\$PATH +export PATH=\$TOOLCHAIN_DIR/hc-gen:\$PATH +export PATH=\$TOOLCHAIN_DIR/gcc_riscv32/bin:\$PATH +export PATH=~/.local/bin:\$PATH # 用户pip二进制工具目录 +EOF + +# 生效环境变量 +source ~/.bashrc +``` + +### 安装python3.8和pip包管理器 + +* 安装python3.8和pip(编译鸿蒙源码`hi3861`目标平台需要使用scons,默认安装的scons版本需要python版本>=3.7): + + * `sudo apt-get install --no-install-recommends python3.8 python3-pip` + +* 将默认python切换为3.8(因为18.04 上默认Python3版本是 3.6),通常有两种方式切换: + + * 使用`virtualenv`管理,单独source相应的active脚本切换当前shell会话的默认python版本(推荐,下面均已这种方式进行操作); + * 使用 `update-alternatives`管理,并切换全局Python脚本配置(不推荐,用完需要切换回去,否则会影响apt等依赖python3的软件包使用); + +* 配置pip包下载源,加速国内安装pip包: + + ```sh + mkdir ~/.pip/ + cat < ~/.pip/pip.conf + [global] + index-url = https://mirrors.huaweicloud.com/repository/pypi/simple + trusted-host = mirrors.huaweicloud.com + timeout = 120 + EOF + ``` + +### 准备virtualenv + +```sh +# 安装virtualenv +pip3 install virtualenv + +# 创建使用python3.8为默认python解释器的virtualenv +mkdir ~/harmonyos/venv && virtualenv -p python3.8 ~/harmonyos/venv + +# 激活 virtualenv,激活后的pip3 install会将包文件缓存到相应的子目录中 +source ~/harmonyos/venv/bin/activate + +# 安装 setuptools 和 kconfiglib +pip3 install setuptools kconfiglib + +# 安装编译hi3861需要的pip包 +pip3 install scons ecdsa pycryptodome +# pip3 install --upgrade --ignore-installed six + +# 可选:将激活脚本添加到 bashrc 中,下次登录默认自动激活此python虚拟环境,可以使用 deactivate 使虚拟环境无效 +cat <> ~/.bashrc +source ~/harmonyos/venv/bin/activate +EOF +``` + + + +## 编译源码 + +激活刚刚建立的python虚拟环境后,在源码根目录下(`openharmony`目录)执行: + +```sh +$ source ~/harmonyos/venv/bin/activate # 激活虚拟环境,激活后 deactivate 命令可使当前虚拟环境无效 +$ python build.py -h # 查看支持哪些目标平台 +usage: + python build.py ipcamera_hi3516dv300 + python build.py ipcamera_hi3518ev300 + python build.py wifiiot + + Quickstart: https://device.harmonyos.com/cn/docs/start/introduce/oem_start_guide-0000001054913231 + +positional arguments: + product Name of the product + +optional arguments: + -h, --help show this help message and exit + -b BUILD_TYPE, --build_type BUILD_TYPE + release or debug version. + -t [TEST [TEST ...]], --test [TEST [TEST ...]] + Compile test suit + -n, --ndk Compile ndk +``` + +可以查看支持哪些目标平台,目前可选的有三个。 + +### 切换默认shell为bash + +`vendor`目录下的部分Makefile里面使用了bash特有的`pushd`/`popd`命令,需要使用bash环境才能编译通过,有两种方法切换默认shell: + +1. `sudo dpkg-reconfigure dash`弹出对话框之后选择No; +2. `sudo rm /bin/sh && sudo ln -s /bin/bash /bin/sh`; + +### 编译3516目标平台的命令 + +```sh +python build.py ipcamera_hi3516dv300 -b debug +``` + +编译生成的kernel、rootfs、userfs映像文件会生成到`out/ipcamera_hi3516dv300`目录下,u-boot二进制会生成在`vendor`目录(可以通过`find vendor -name u-boot*.bin`命令进行查找)。 + +### 编译3518目标平台的命令 + +```sh +python build.py ipcamera_hi3516dv300 -b debug +``` + +编译生成的kernel、rootfs、userfs映像文件会生成到`out/ipcamera_hi3518ev300`目录下,u-boot二进制会生成在`vendor`目录(可以通过`find vendor -name u-boot*.bin`命令进行查找)。 + +### 编译3861目标平台的命令 + +```sh +python build.py wifiiot +``` + +编译生成的二进制文件位于`out/wifiiot/`子目录下,刷机需要使用`Hi3861_wifiiot_app_allinone.bin`文件。 + + + +### ffmpeg相关编译失败问题定位 + +编译过程中可能会遇到ffmpeg相关的编译失败,可能是因为`configure`过程中出现了问题,可以通过`vendor/hisi/hi35xx/middleware/source/third_party/ffmpeg/ffmpeg-y/ffbuild/config.log`文件查看。 + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_use_hiburn_download_firmware.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_use_hiburn_download_firmware.md" new file mode 100755 index 0000000000000000000000000000000000000000..4fc5103e0d2dad32680b3c3ede96ee595a4ba8d5 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_use_hiburn_download_firmware.md" @@ -0,0 +1,91 @@ +# 使用HiBurn烧录鸿蒙.bin文件到Hi3861开发板 + + + +鸿蒙官方文档的“Hi3861开发板第一个示例程序”中描述了——如何使用DevEco Device Tool工具烧录二进制文件到Hi3861开发板; + +本文将介绍如何使用HiBurn工具烧录鸿蒙的.bin文件到Hi3861开发板。 + + + +**获取HiBurn工具** +通过鸿蒙官方文档我们知道DevEco Device Tool是一个VSCode插件,它以.vsix文件的形式向开发者提供。事实上,这个文件.vsix文件是一个zip格式的压缩文件。你可以在git bash或Linux环境中,使用file命令将它识别出来: + +```sh +$ file DevEcoDeviceTool-1.0.0.vsix +DevEcoDeviceTool-1.0.0.vsix: Zip archive data, at least v2.0 to extract +``` + + + +在Windows上,你可以使用一般的压缩解压软件将它打开,并将它解压开。 + +解压之后,可以在extension\deveco\tools子目录中看到一个文件名为 HiBurn.exe 的文件,它就是我们今天要介绍的HiBurn工具(你也可以从本文的附件中直接下载 HiBurn.zip 解压)。 + + + +## 使用HiBurn烧写.bin文件到Hi3861 +Win10系统执行前需要右键“属性”->解除锁定,否则会系统默认会报安全警告,不允许执行。 + +双击单开后,界面如下: + +![img](https://dl-harmonyos.51cto.com/images/202010/62e2d14388024bc25ea071e678acc6db7e4af6.png) + + + +### 操作步骤 + +1. 点界面左上角的Setting->Com settings进入串口参数设置界面,串口参数设置界面上,Baud为波特率,默认115200,可以选择921600,2000000,或者 3000000(实测最快支持的值),其他参数保持默认,点“确定”保存; + + ![img](https://dl-harmonyos.51cto.com/images/202010/3529fa7845bbfe985c05740eaa26b7ae5b4fa3.png) + +2. 根据设备管理器,选择正确的COM口,例如我的开发板是COM8,如果是打开程序之后才插串口线的,可以点一下“Refresh”刷新串口下拉框的可选项; + + ![img](https://dl-harmonyos.51cto.com/images/202010/a8cd10f109e13ce9fee494013d969f27d908e4.png)![img](https://dl-harmonyos.51cto.com/images/202010/e563b8e72b63f37a2b86119887702351b7fd24.png) + +3. 点“Select file”弹出文件选择对话框,选择编译生成的allinone.bin文件,这个bin其实是多个bin合并的文件,从命名上也能看得出来,例如,我选择的Z:\harmonyos\openharmony\out\wifiiot\Hi3861_wifiiot_app_allinone.bin + 勾选“Auto burn”,自动下载多个bin文件,到这里,配置完毕,应如下图; + + ![img](https://dl-harmonyos.51cto.com/images/202010/618209d31a6fdd6375550620829aa19585f646.png) + +4. 点击Connect,连接串口设备,这时HiBurn会打开串口设备,并尝试开始烧写,需要确保没有其他程序占用串口设备(烧写之前可能正在用超级终端或串口助手查看串口日志,需要确保其他软件已经关闭了当前使用的串口); + 复位设备,按开发板的RESET按键; + 等待输出框出现三个"=========================================="以及上方均出现successful,即说明烧录成功; + +5. 烧录成功后,需要手动点“Disconnect”断开串口连接,否则会提示“Wait connect success flag (hisilicon) overtime.”; + + + +### 和 DevEco Device Tool方式对比 +使用HiBurn烧录相对于使用DevEco Device Tool烧录而言,好处主要有以下几点: + +1. 不依赖VSCode,你可以不用安装VSCode、nodejs、JDK、以及一些npm包; +2. 下载速度更快,HiBurn.exe最大波特率可以设置到3000000,而DevEco Device Tool最大只能为921600,是它的三倍; + + + +HiBurn方式烧录目前的缺点主要是: + +1. 需要手动点Disconnect主动断开连接,否则默认会重复下载;烧录成功后,如果你不断开串口,并且再次按了一下RESET按键,你会发现,它又烧录了一遍。 +2. HiBurn的串口参数无法保存,你关闭之后下次打开还需要重新设置,而DevEco则会可以保存串口参数; +3. HiBurn相对DevEco来说,操作步骤更多一些,也稍微复杂一点; + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_vmware_environment.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_vmware_environment.md" new file mode 100644 index 0000000000000000000000000000000000000000..3ab90e0eff2569fa1088da28e0f06d4789c195ff --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/QuickStart/hos_vmware_environment.md" @@ -0,0 +1,115 @@ +# 快速环境搭建 + +本文介绍如何使用VMware镜像文件快速完成鸿蒙开发环境搭建 + +## 一、硬件环境 + +- 一台windows电脑: + + - 安装好VMware + + VMware版本:[VMware-workstation-full-16.1.0-17198959](https://www.vmware.com/products/workstation-pro/workstation-pro-evaluation.html) + +## 二、资料下载 + +- VMware镜像下载 + - https://pan.baidu.com/s/1uiiCpbJqViGb7Qs6HdCb8g 提取码: ddab + +## 三、环境搭建 + +1、将下载好的`Ubuntu20.4`镜像`Pegasus_ubuntu20.4.rar`文件解压到某个目录下。 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_pegasus_ubuntu20.4.png) + +2、打开VMware Workstation工具,将ovf文件导入到工程中,然后开启此虚拟机 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm.png) + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/import_vm_ovf.png) + + + +3、进入登录页面后,登录用户为:`Pegasus`;密码为:`pegasus` + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_login.png) + +4、登录之后,打开终端界面,进入代码目录`cd harmony/openharmony`;开始编译:`./build.py wifiiot` + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_compile.png) + +5、查看编译结果 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_compile_success.png) + +6、windows主机访问linux主机 + +该环境安装了该环境安装了samba,配置内容可以查看`/etc/samba/smb.conf`。账号与密码均为pegasus; + +(1). 查询虚拟机的地址:打开终端界面`ifconfig` + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_ifconfig.png) + +(2). 确保windows主机可以ping通虚拟机 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_ping.png) + +(3). ping通主机后,可以将虚拟机的指定目录映射到网络驱动器 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_map_network_drive.png) + +用户与密码均为:`pegasus` + +映射成功后,打开网络驱动器,既可以直接获取虚拟机指定目录下的内容 + +![hihope_illustration](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/vm_file.png) + +6、镜像烧录 + +请参考[使用HiBurn烧录固件到开发板](https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development/blob/master/01_envsetup/hos_use_hiburn_download_firmware.md) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..97539aad4875814644facc21fef0c0e090ce8f9c Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..7db58279bc8b23b3604987372619019399bb5c3a Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/HiSpark_WiFi-IoT_Hi3861_CH340G_VER.B.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_DCL_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_DCL_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..9677ead450d10fb7e4b9821772df577af843aa5c Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_DCL_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EM_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EM_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..13caad16575400d18ad2fb8724a0b2d804bbeb2c Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EM_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EXB_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EXB_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..1303fa615cee79abd33776f041f2e8b00f473c5f Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_EXB_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_JTAG_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_JTAG_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..609b5329d6ed40c82c664c28535514a03fe30499 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_JTAG_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_NFC_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_NFC_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..e3f830600c9fdd33f7e0a996f8125b43906449d8 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_NFC_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_OLED_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_OLED_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..c9388c47e0dbcee597567d88ffe077e47cc75088 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_OLED_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_SSL_VER.A.pdf" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_SSL_VER.A.pdf" new file mode 100755 index 0000000000000000000000000000000000000000..6337bee586d5ce8dfe5d296a7daed66e24f446a5 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/bord/SchematicDiagram/HiSpark_WiFi_IoT_SSL_VER.A.pdf" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/hihope.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/hihope.png" new file mode 100755 index 0000000000000000000000000000000000000000..588833d756c44695a0de564d68df8483255c9aaf Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/hihope.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/import_vm_ovf.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/import_vm_ovf.png" new file mode 100755 index 0000000000000000000000000000000000000000..c189c9e8b92f4379213e0f88ab7fcae50b20666e Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/import_vm_ovf.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/uart.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/uart.png" new file mode 100644 index 0000000000000000000000000000000000000000..f107573a4f48cc13ae347ebf27957220394df1c5 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/uart.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm.png" new file mode 100755 index 0000000000000000000000000000000000000000..c364dc38610849d93914d4cf78e6d25fa610c705 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile.png" new file mode 100755 index 0000000000000000000000000000000000000000..0bfccef82859a367ab47b0617380eb8b30a8f360 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile_success.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile_success.png" new file mode 100755 index 0000000000000000000000000000000000000000..0ebc8453a6705f728ddc48eb17762e8e266503b4 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_compile_success.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_file.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_file.png" new file mode 100755 index 0000000000000000000000000000000000000000..b3ede80e67ce61251effcdaccbe8c7352644bc62 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_file.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ifconfig.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ifconfig.png" new file mode 100755 index 0000000000000000000000000000000000000000..5b1d10837f249d58e773da30329ebf367ed91d51 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ifconfig.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_login.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_login.png" new file mode 100755 index 0000000000000000000000000000000000000000..5f3fd2463fb9f67905922e023c208430c497c390 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_login.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_map_network_drive.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_map_network_drive.png" new file mode 100755 index 0000000000000000000000000000000000000000..5af92068cbe1394c0989d08a8cbce985091f58d2 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_map_network_drive.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ovf.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ovf.png" new file mode 100755 index 0000000000000000000000000000000000000000..5132f050516017d60683c4acfd86110b9c21bd09 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ovf.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_pegasus_ubuntu20.4.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_pegasus_ubuntu20.4.png" new file mode 100755 index 0000000000000000000000000000000000000000..82a03bc8dcf3d105e005884295821d93ff1505fa Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_pegasus_ubuntu20.4.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ping.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ping.png" new file mode 100755 index 0000000000000000000000000000000000000000..abc930f5e903df3a8845d73c5f57d98ba564a6ae Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/vm_ping.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/wifi_iot.png" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/wifi_iot.png" new file mode 100755 index 0000000000000000000000000000000000000000..29cd8b3dd48244d10e52da1fc98c8ed54aec0861 Binary files /dev/null and "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/docs/figures/wifi_iot.png" differ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/BUILD.gn" new file mode 100644 index 0000000000000000000000000000000000000000..6adb2ac4612eddc21b85e6cca929fd943818d0e9 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("thread_demo") { + sources = [ + "thread.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..c001a1c915b8fb6e0a4ad4bc2bdb848eeefd7d85 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/README.md" @@ -0,0 +1,185 @@ +# HiSpark WiFi-IoT 鸿蒙开发套件样例开发--线程(Thread) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Thread API + +| API名称 | 说明 | +| --------------------- | ------------------------------------------------------ | +| osThreadNew | 创建一个线程并将其加入活跃线程组中 | +| osThreadGetName | 返回指定线程的名字 | +| osThreadGetId | 返回当前运行线程的线程ID | +| osThreadGetState | 返回当前线程的状态 | +| osThreadSetPriority | 设置指定线程的优先级 | +| osThreadGetPriority | 获取当前线程的优先级 | +| osThreadYield | 将运行控制转交给下一个处于READY状态的线程 | +| osThreadSuspend | 挂起指定线程的运行 | +| osThreadResume | 恢复指定线程的运行 | +| osThreadDetach | 分离指定的线程(当线程终止运行时,线程存储可以被回收) | +| osThreadJoin | 等待指定线程终止运行 | +| osThreadExit | 终止当前线程的运行 | +| osThreadTerminate | 终止指定线程的运行 | +| osThreadGetStackSize | 获取指定线程的栈空间大小 | +| osThreadGetStackSpace | 获取指定线程的未使用的栈空间大小 | +| osThreadGetCount | 获取活跃线程数 | +| osThreadEnumerate | 获取线程组中的活跃线程数 | + +### osThreadNew() + +```c +osThreadId_t osThreadNew(osThreadFunc_t func, void *argument,const osThreadAttr_t *attr ) +``` + +> **注意** :不能在中断服务调用该函数 + +**参数:** + +| 名字 | 描述 | +| :------- | :------------------------------- | +| func | 线程函数. | +| argument | 作为启动参数传递给线程函数的指针 | +| attr | 线程属性 | + +### osThreadTerminate() + +```c +osStatus_t osThreadTerminate (osThreadId_t thread_id) +``` + +| 名字 | 描述 | +| --------- | ---------------------------------------------------- | +| thread_id | 指定线程id,该id是由osThreadNew或者osThreadGetId获得 | + +## 二、代码分析 + +创建线程,创建成功则打印线程名字和线程ID + +``` +osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg) { + osThreadAttr_t attr = { + name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0 + }; + osThreadId_t tid = osThreadNew(func, arg, &attr); + if (tid == NULL) { + printf("osThreadNew(%s) failed.\r\n", name); + } else { + printf("osThreadNew(%s) success, thread id: %d.\r\n", name, tid); + } + return tid; +} +``` + +该函数首先会打印自己的参数,然后对全局变量count进行循环+1操作,之后会打印count的值 + +``` +void threadTest(void *arg) { + static int count = 0; + printf("%s\r\n",(char *)arg); + osThreadId_t tid = osThreadGetId(); + printf("threadTest osThreadGetId, thread id:%p\r\n", tid); + while (1) { + count++; + printf("threadTest, count: %d.\r\n", count); + osDelay(20); + } +} +``` + +主程序rtosv2_thread_main创建线程并运行,并使用上述API进行相关操作,最后终止所创建的线程。 + +``` +void rtosv2_thread_main(void *arg) { + (void)arg; + osThreadId_t tid=newThread("test_thread", threadTest, "This is a test thread."); + + const char *t_name = osThreadGetName(tid); + printf("[Thread Test]osThreadGetName, thread name: %s.\r\n", t_name); + + osThreadState_t state = osThreadGetState(tid); + printf("[Thread Test]osThreadGetState, state :%d.\r\n", state); + + osStatus_t status = osThreadSetPriority(tid, osPriorityNormal4); + printf("[Thread Test]osThreadSetPriority, status: %d.\r\n", status); + + osPriority_t pri = osThreadGetPriority (tid); + printf("[Thread Test]osThreadGetPriority, priority: %d.\r\n", pri); + + status = osThreadSuspend(tid); + printf("[Thread Test]osThreadSuspend, status: %d.\r\n", status); + + status = osThreadResume(tid); + printf("[Thread Test]osThreadResume, status: %d.\r\n", status); + + uint32_t stacksize = osThreadGetStackSize(tid); + printf("[Thread Test]osThreadGetStackSize, stacksize: %d.\r\n", stacksize); + + uint32_t stackspace = osThreadGetStackSpace(tid); + printf("[Thread Test]osThreadGetStackSpace, stackspace: %d.\r\n", stackspace); + + uint32_t t_count = osThreadGetCount(); + printf("[Thread Test]osThreadGetCount, count: %d.\r\n", t_count); + + osDelay(100); + status = osThreadTerminate(tid); + printf("[Thread Test]osThreadTerminate, status: %d.\r\n", status); +} +``` + +## 三、如何编译 + +1. 将此目录下的 `thread.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:thread_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` +[Thread Test] osThreadNew(test_thread) success. +[Thread Test] osThreadGetName, thread name: test_thread. +[Thread Test] osThreadGetState, state :1. +[Thread Test] This is a test thread. <-testThread log +[Thread Test] threadTest osThreadGetId, thread id:0xe8544 +[Thread Test] threadTest, count: 1. <-testThread log +[Thread Test] osThreadSetPriority, status: 0. +[Thread Test] osThreadGetPriority, priority: 28. +[Thread Test] osThreadSuspend, status: 0. +[Thread Test] osThreadResume, status: 0. +[Thread Test] osThreadGetStackSize, stacksize: 2048. +[Thread Test] osThreadGetStackSpace, stackspace: 1144. +[Thread Test] osThreadGetCount, count: 12. +[Thread Test] threadTest, count: 2. <-testThread log +[Thread Test] threadTest, count: 3. <-testThread log +[Thread Test] threadTest, count: 4. <-testThread log +[Thread Test] threadTest, count: 5. <-testThread log +[Thread Test] threadTest, count: 6. <-testThread log +[Thread Test] osThreadTerminate, status: 0. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/thread.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/thread.c" new file mode 100644 index 0000000000000000000000000000000000000000..2d19a0cf765754a5b3f03c9f30a21ef9d3efaedf --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/00_thread/thread.c" @@ -0,0 +1,85 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg) { + osThreadAttr_t attr = { + name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0 + }; + osThreadId_t tid = osThreadNew(func, arg, &attr); + if (tid == NULL) { + printf("[Thread Test] osThreadNew(%s) failed.\r\n", name); + } else { + printf("[Thread Test] osThreadNew(%s) success, thread id: %d.\r\n", name, tid); + } + return tid; +} + +void threadTest(void *arg) { + static int count = 0; + printf("%s\r\n",(char *)arg); + osThreadId_t tid = osThreadGetId(); + printf("[Thread Test] threadTest osThreadGetId, thread id:%p\r\n", tid); + while (1) { + count++; + printf("[Thread Test] threadTest, count: %d.\r\n", count); + osDelay(20); + } +} + +void rtosv2_thread_main(void *arg) { + (void)arg; + osThreadId_t tid=newThread("test_thread", threadTest, "This is a test thread."); + + const char *t_name = osThreadGetName(tid); + printf("[Thread Test] osThreadGetName, thread name: %s.\r\n", t_name); + + osThreadState_t state = osThreadGetState(tid); + printf("[Thread Test] osThreadGetState, state :%d.\r\n", state); + + osStatus_t status = osThreadSetPriority(tid, osPriorityNormal4); + printf("[Thread Test] osThreadSetPriority, status: %d.\r\n", status); + + osPriority_t pri = osThreadGetPriority (tid); + printf("[Thread Test] osThreadGetPriority, priority: %d.\r\n", pri); + + status = osThreadSuspend(tid); + printf("[Thread Test] osThreadSuspend, status: %d.\r\n", status); + + status = osThreadResume(tid); + printf("[Thread Test] osThreadResume, status: %d.\r\n", status); + + uint32_t stacksize = osThreadGetStackSize(tid); + printf("[Thread Test] osThreadGetStackSize, stacksize: %d.\r\n", stacksize); + + uint32_t stackspace = osThreadGetStackSpace(tid); + printf("[Thread Test] osThreadGetStackSpace, stackspace: %d.\r\n", stackspace); + + uint32_t t_count = osThreadGetCount(); + printf("[Thread Test] osThreadGetCount, count: %d.\r\n", t_count); + + osDelay(100); + status = osThreadTerminate(tid); + printf("[Thread Test] osThreadTerminate, status: %d.\r\n", status); +} + +static void ThreadTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "rtosv2_thread_main"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)rtosv2_thread_main, NULL, &attr) == NULL) { + printf("[ThreadTestTask] Falied to create rtosv2_thread_main!\n"); + } +} + +APP_FEATURE_INIT(ThreadTestTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..23303946dd249abdeb6b4a6aef8094f60e665541 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("timer_demo") { + sources = [ + "timer.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..41aacff92be6c55645c3af7d3863979b1583e46a --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/README.md" @@ -0,0 +1,121 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--软定时器(Timer) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Timer API + +| API名称 | 说明 | +| ---------------- | ------------------------ | +| osTimerNew | 创建和初始化定时器 | +| osTimerGetName | 获取指定的定时器名字 | +| osTimerStart | 启动或者重启指定的定时器 | +| osTimerStop | 停止指定的定时器 | +| osTimerIsRunning | 检查一个定时器是否在运行 | +| osTimerDelete | 删除定时器 | + +### osTimerNew() + +```c +osTimerId_t osTimerNew (osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) +``` + +**参数:** + +| 名字 | 描述 | +| :------- | :----------------------------------------------------------- | +| func | 定时器回调函数. | +| type | 定时器类型,osTimerOnce表示单次定时器,ostimer周期表示周期性定时器. | +| argument | 定时器回调函数的参数 | +| attr | 定时器属性 | + +## 二、代码分析 + +定时器的回调函数 + +```c +void cb_timeout_periodic(void *arg) { + (void)arg; + times++; +} +``` + +使用osTimerNew创建一个100个时钟周期调用一次回调函数cb_timeout_periodic定时器,每隔100个时钟周期检查一下全局变量times是否小于3,若不小于3则停止时钟周期 + +```c +void timer_periodic(void) { + osTimerId_t periodic_tid = osTimerNew(cb_timeout_periodic, osTimerPeriodic, NULL, NULL); + if (periodic_tid == NULL) { + printf("[Timer Test] osTimerNew(periodic timer) failed.\r\n"); + return; + } else { + printf("[Timer Test] osTimerNew(periodic timer) success, tid: %p.\r\n",periodic_tid); + } + osStatus_t status = osTimerStart(periodic_tid, 100); + if (status != osOK) { + printf("[Timer Test] osTimerStart(periodic timer) failed.\r\n"); + return; + } else { + printf("[Timer Test] osTimerStart(periodic timer) success, wait a while and stop.\r\n"); + } + + while(times < 3) { + printf("[Timer Test] times:%d.\r\n",times); + osDelay(100); + } + + status = osTimerStop(periodic_tid); + printf("[Timer Test] stop periodic timer, status :%d.\r\n", status); + status = osTimerDelete(periodic_tid); + printf("[Timer Test] kill periodic timer, status :%d.\r\n", status); +} + +``` + + + +## 三、如何编译 + +1. 将此目录下的 `timer.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:timer_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` +[Timer Test] osTimerNew(periodic timer) success, tid: 0xe9b4c. +[Timer Test] osTimerStart(periodic timer) success, wait a while and stop. +[Timer Test] times:0. +[Timer Test] times:1. +[Timer Test] times:2. +[Timer Test] stop periodic timer, status :0. +[Timer Test] kill periodic timer, status :0. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/timer.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/timer.c" new file mode 100755 index 0000000000000000000000000000000000000000..9d8bfc61cfed4503ac32ba83995c24462b5a40b5 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/01_timer/timer.c" @@ -0,0 +1,58 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +static int times = 0; + +void cb_timeout_periodic(void *arg) { + (void)arg; + times++; +} + +void timer_periodic(void) { + osTimerId_t periodic_tid = osTimerNew(cb_timeout_periodic, osTimerPeriodic, NULL, NULL); + if (periodic_tid == NULL) { + printf("[Timer Test] osTimerNew(periodic timer) failed.\r\n"); + return; + } else { + printf("[Timer Test] osTimerNew(periodic timer) success, tid: %p.\r\n",periodic_tid); + } + osStatus_t status = osTimerStart(periodic_tid, 100); + if (status != osOK) { + printf("[Timer Test] osTimerStart(periodic timer) failed.\r\n"); + return; + } else { + printf("[Timer Test] osTimerStart(periodic timer) success, wait a while and stop.\r\n"); + } + + while(times < 3) { + printf("[Timer Test] times:%d.\r\n",times); + osDelay(100); + } + + status = osTimerStop(periodic_tid); + printf("[Timer Test] stop periodic timer, status :%d.\r\n", status); + status = osTimerDelete(periodic_tid); + printf("[Timer Test] kill periodic timer, status :%d.\r\n", status); +} + +static void TimerTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "timer_periodic"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)timer_periodic, NULL, &attr) == NULL) { + printf("[TimerTestTask] Falied to create timer_periodic!\n"); + } +} + +APP_FEATURE_INIT(TimerTestTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..e8c0b0114b2bd8623fe3d3eca248c8021d97b289 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("delay_demo") { + sources = [ + "delay.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..58a0cc478ee4dac0ffece8f0ff6dc02a4174782c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/README.md" @@ -0,0 +1,78 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--等待(Delay) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Delay API + +| API名称 | 说明 | +| ------------ | -------------------- | +| osDelay | 等待指定的ticks | +| osDelayUntil | 等待到指定的时钟周期 | + +## 二、代码分析 + +使用`osDelay`让线程等待100个时钟周期,然后通过`osKernelGetTickCount`获取当前的时钟周期tick, 在此基础上增加100个时钟周期,之后调用`osDelayUntil`让线程等待tick + 100个时钟周期后恢复运行 + +```c +void rtosv2_delay_main(void *arg) { + (void)arg; + + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); + osStatus_t status = osDelay(100); + printf("[Delay Test] osDelay, status: %d.\r\n", status); + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); + + uint32_t tick = osKernelGetTickCount(); + tick += 100; + status = osDelayUntil(tick); + printf("[Delay Test] osDelayUntil, status: %d.\r\n", status); + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); +} +``` + + + +## 三、如何编译 + +1. 将此目录下的 `delay.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:delay_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` +[Delay Test] Current system tick: 248. +[Delay Test] osDelay, status: 0. +[Delay Test] Current system tick: 348. +[Delay Test] osDelayUntil, status: 0. +[Delay Test] Current system tick: 448. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/delay.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/delay.c" new file mode 100644 index 0000000000000000000000000000000000000000..0d8a7a022657974a27cd75a0490f5295aa6e75a6 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/02_delay/delay.c" @@ -0,0 +1,39 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +void rtosv2_delay_main(void *arg) { + (void)arg; + + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); + osStatus_t status = osDelay(100); + printf("[Delay Test] osDelay, status: %d.\r\n", status); + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); + + uint32_t tick = osKernelGetTickCount(); + tick += 100; + status = osDelayUntil(tick); + printf("[Delay Test] osDelayUntil, status: %d.\r\n", status); + printf("[Delay Test] Current system tick: %d.\r\n", osKernelGetTickCount()); +} + +static void DelayTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "rtosv2_delay_main"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)rtosv2_delay_main, NULL, &attr) == NULL) { + printf("[DelayTestTask] Falied to create rtosv2_delay_main!\n"); + } +} + +APP_FEATURE_INIT(DelayTestTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..43bf422c3a7d1542caae5d9f7376f4d6fc6c209e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("mutex_demo") { + sources = [ + "mutex.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..15ce77b4e16545a8086d99ae5de75e039e0760df --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/README.md" @@ -0,0 +1,127 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--互斥锁(Mutex) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Mutex API + +| API名称 | 说明 | +| --------------- | -------------------------------------------------------- | +| osMutexNew | 创建并初始化一个互斥锁 | +| osMutexGetName | 获得指定互斥锁的名字 | +| osMutexAcquire | 获得指定的互斥锁的访问权限,若互斥锁已经被锁,则返回超时 | +| osMutexRelease | 释放指定的互斥锁 | +| osMutexGetOwner | 获得指定互斥锁的所有者线程 | +| osMutexDelete | 删除指定的互斥锁 | + +## 二、代码分析 + +全局变量`g_test_value`若同时被多个线程访问,会将其加1,然后判断其奇偶性,并输出日志,如果没有互斥锁保护,线程会被中断导致错误,所以需要创建互斥锁来保护多线程共享区域 + +```c +void number_thread(void *arg) { + osMutexId_t *mid = (osMutexId_t *)arg; + while(1) { + if (osMutexAcquire(*mid, 100) == osOK) { + g_test_value++; + if (g_test_value % 2 == 0) { + printf("[Mutex Test] %s gets an even value %d.\r\n", osThreadGetName(osThreadGetId()), g_test_value); + } else { + printf("[Mutex Test] %s gets an odd value %d.\r\n", osThreadGetName(osThreadGetId()), g_test_value); + } + osMutexRelease(*mid); + osDelay(5); + } + } +} +``` + +创建三个线程访问全局变量`g_test_value` ,同时创建一个互斥锁共所有线程使用 + +```c +void rtosv2_mutex_main(void *arg) { + (void)arg; + osMutexAttr_t attr = {0}; + + osMutexId_t mid = osMutexNew(&attr); + if (mid == NULL) { + printf("[Mutex Test] osMutexNew, create mutex failed.\r\n"); + } else { + printf("[Mutex Test] osMutexNew, create mutex success.\r\n"); + } + + osThreadId_t tid1 = newThread("Thread_1", number_thread, &mid); + osThreadId_t tid2 = newThread("Thread_2", number_thread, &mid); + osThreadId_t tid3 = newThread("Thread_3", number_thread, &mid); + + osDelay(13); + osThreadId_t tid = osMutexGetOwner(mid); + printf("[Mutex Test] osMutexGetOwner, thread id: %p, thread name: %s.\r\n", tid, osThreadGetName(tid)); + osDelay(17); + + osThreadTerminate(tid1); + osThreadTerminate(tid2); + osThreadTerminate(tid3); + osMutexDelete(mid); +} +``` + + + +## 三、如何编译 + +1. 将此目录下的 `mutex.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:mutex_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +截取部分运行结果 + +``` +[Mutex Test] osMutexNew, create mutex success. +[Mutex Test] osThreadNew(Thread_1) success, thread id: 0xe84c4. +RTOSV2.0_TES[Mutex Test] Thread_1 gets an odd value 1. +[Mutex Test] Thread_2 gets an even value 2. +T: osThreadNew(Thread_2) success, thread id: 0xe871c. +[Mutex Test] osThreadNew(Thread_3) success, thread id: 0xe8910. +[Mutex Test] Thread_3 gets an odd value 3. +[Mutex Test] Thread_1 gets an even value 4. +[Mutex Test] Thread_2 gets an odd value 5. +[Mutex Test] Thread_3 gets an even value 6. +[Mutex Test] Thread_1 gets an odd value 7. +[Mutex Test] Thread_2 gets an even value 8. +[Mutex Test] Thread_3 gets an odd value 9. +[Mutex Test] osMutexGetOwner, thread id: 0xe8910, thread name: Thread_3. +[Mutex Test] Thread_1 gets an even value 10. +[Mutex Test] Thread_2 gets an odd value 11. +[Mutex Test] Thread_3 gets an even value 12. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/mutex.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/mutex.c" new file mode 100755 index 0000000000000000000000000000000000000000..73b9a8266b7749bf1070a6688431b669b805e84e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/03_mutex/mutex.c" @@ -0,0 +1,81 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +static int g_test_value = 0; + +void number_thread(void *arg) { + osMutexId_t *mid = (osMutexId_t *)arg; + while(1) { + if (osMutexAcquire(*mid, 100) == osOK) { + g_test_value++; + if (g_test_value % 2 == 0) { + printf("[Mutex Test]%s gets an even value %d.\r\n", osThreadGetName(osThreadGetId()), g_test_value); + } else { + printf("[Mutex Test]%s gets an odd value %d.\r\n", osThreadGetName(osThreadGetId()), g_test_value); + } + osMutexRelease(*mid); + osDelay(5); + } + } +} + +osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg) { + osThreadAttr_t attr = { + name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0 + }; + osThreadId_t tid = osThreadNew(func, arg, &attr); + if (tid == NULL) { + printf("[Mutex Test]osThreadNew(%s) failed.\r\n", name); + } else { + printf("[Mutex Test]osThreadNew(%s) success, thread id: %d.\r\n", name, tid); + } + return tid; +} + +void rtosv2_mutex_main(void *arg) { + (void)arg; + osMutexAttr_t attr = {0}; + + osMutexId_t mid = osMutexNew(&attr); + if (mid == NULL) { + printf("[Mutex Test]osMutexNew, create mutex failed.\r\n"); + } else { + printf("[Mutex Test]osMutexNew, create mutex success.\r\n"); + } + + osThreadId_t tid1 = newThread("Thread_1", number_thread, &mid); + osThreadId_t tid2 = newThread("Thread_2", number_thread, &mid); + osThreadId_t tid3 = newThread("Thread_3", number_thread, &mid); + + osDelay(13); + osThreadId_t tid = osMutexGetOwner(mid); + printf("[Mutex Test]osMutexGetOwner, thread id: %p, thread name: %s.\r\n", tid, osThreadGetName(tid)); + osDelay(17); + + osThreadTerminate(tid1); + osThreadTerminate(tid2); + osThreadTerminate(tid3); + osMutexDelete(mid); +} + +static void MutexTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "rtosv2_mutex_main"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)rtosv2_mutex_main, NULL, &attr) == NULL) { + printf("[MutexTestTask] Falied to create rtosv2_mutex_main!\n"); + } +} + +APP_FEATURE_INIT(MutexTestTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..bf3196421453d233d757090c3ced017d6dbb663e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("semp_demo") { + sources = [ + "semp.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..86ddf3901edbd5dee96a330f8ccfd768c96c31cd --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/README.md" @@ -0,0 +1,133 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--信号量(Semaphore) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Semaphore API + +| API名称 | 说明 | +| ------------------- | ------------------------------------------------------------ | +| osSemaphoreNew | 创建并初始化一个信号量 | +| osSemaphoreGetName | 获取一个信号量的名字 | +| osSemaphoreAcquire | 获取一个信号量的令牌,若获取不到,则会超时返回 | +| osSemaphoreRelease | 释放一个信号量的令牌,但是令牌的数量不超过初始定义的的令牌数 | +| osSemaphoreGetCount | 获取当前的信号量令牌数 | +| osSemaphoreDelete | 删除一个信号量 | + +## 二、代码分析 + +`osSemaphoreAcquire`获取共享资源的访问权限,若获取失败,则等待;访问成功后,可以通过`osSemaphoreRelease`释放对共享资源的访问 + +本样例为经典的消费者与生产者问题,需要确保仓库满时,生产者需要进入等待状态,产品消费完时,消费者需要进入等待状态 + +```c +void producer_thread(void *arg) { + (void)arg; + empty_id = osSemaphoreNew(BUFFER_SIZE, BUFFER_SIZE, NULL); + filled_id = osSemaphoreNew(BUFFER_SIZE, 0U, NULL); + while(1) { + osSemaphoreAcquire(empty_id, osWaitForever); + product_number++; + printf("[Semp Test]%s produces a product, now product number: %d.\r\n", osThreadGetName(osThreadGetId()), product_number); + osDelay(4); + osSemaphoreRelease(filled_id); + } +} + +void consumer_thread(void *arg) { + (void)arg; + while(1){ + osSemaphoreAcquire(filled_id, osWaitForever); + product_number--; + printf("[Semp Test]%s consumes a product, now product number: %d.\r\n", osThreadGetName(osThreadGetId()), product_number); + osDelay(3); + osSemaphoreRelease(empty_id); + } +} +``` + +由于消费产品的速度大于生产速度,所以定义了三个生产者,两个消费者 + +```c +void rtosv2_semp_main(void *arg) { + (void)arg; + empty_id = osSemaphoreNew(BUFFER_SIZE, BUFFER_SIZE, NULL); + filled_id = osSemaphoreNew(BUFFER_SIZE, 0U, NULL); + + osThreadId_t ptid1 = newThread("producer1", producer_thread, NULL); + osThreadId_t ptid2 = newThread("producer2", producer_thread, NULL); + osThreadId_t ptid3 = newThread("producer3", producer_thread, NULL); + osThreadId_t ctid1 = newThread("consumer1", consumer_thread, NULL); + osThreadId_t ctid2 = newThread("consumer2", consumer_thread, NULL); + + osDelay(50); + + osThreadTerminate(ptid1); + osThreadTerminate(ptid2); + osThreadTerminate(ptid3); + osThreadTerminate(ctid1); + osThreadTerminate(ctid2); + + osSemaphoreDelete(empty_id); + osSemaphoreDelete(filled_id); +} +``` + + + +## 三、如何编译 + +1. 将此目录下的 `semp.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:semp_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +截取部分运行结果 + +``` +[Semp Test] osThreadNew(consumer1) success, thread id: 0xe8910. +[Semp Test] osThreadNew(consumer2) success, thread id: 0xe871c. +[Semp Test] osThreadNew(producer1) success, thread id: 0xe84c4. +[Semp Test] [Semp Test] producer1 produces a product, now product number: 1. +[Semp Test] producer2 produces a product, now product number: 2. +osThreadNew(producer2) success, thread id: 0xe8974. +[Semp Test] osThreadNew(producer3) success, thread id: 0xe89d8. +[Semp Test] producer3 produces a product, now product number: 3. +[Semp Test] producer1 produces a product, now product number: 4. +[Semp Test] consumer1 consumes a product, now product number: 3. +[Semp Test] producer2 produces a product, now product number: 4. +[Semp Test] consumer2 consumes a product, now product number: 3. +[Semp Test] consumer1 consumes a product, now product number: 2. +[Semp Test] producer3 produces a product, now product number: 3. +[Semp Test] consumer2 consumes a product, now product number: 2. +[Semp Test] producer1 produces a product, now product number: 3. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/semp.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/semp.c" new file mode 100644 index 0000000000000000000000000000000000000000..eed303258766db8301cf86d99ef5cb7e2e3df21e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/04_semaphore/semp.c" @@ -0,0 +1,89 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#define BUFFER_SIZE 5U +static int product_number = 0; +osSemaphoreId_t empty_id; +osSemaphoreId_t filled_id; + +void producer_thread(void *arg) { + (void)arg; + empty_id = osSemaphoreNew(BUFFER_SIZE, BUFFER_SIZE, NULL); + filled_id = osSemaphoreNew(BUFFER_SIZE, 0U, NULL); + while(1) { + osSemaphoreAcquire(empty_id, osWaitForever); + product_number++; + printf("[Semp Test]%s produces a product, now product number: %d.\r\n", osThreadGetName(osThreadGetId()), product_number); + osDelay(4); + osSemaphoreRelease(filled_id); + } +} + +void consumer_thread(void *arg) { + (void)arg; + while(1){ + osSemaphoreAcquire(filled_id, osWaitForever); + product_number--; + printf("[Semp Test]%s consumes a product, now product number: %d.\r\n", osThreadGetName(osThreadGetId()), product_number); + osDelay(3); + osSemaphoreRelease(empty_id); + } +} + +osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg) { + osThreadAttr_t attr = { + name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0 + }; + osThreadId_t tid = osThreadNew(func, arg, &attr); + if (tid == NULL) { + printf("[Semp Test]osThreadNew(%s) failed.\r\n", name); + } else { + printf("[Semp Test]osThreadNew(%s) success, thread id: %d.\r\n", name, tid); + } + return tid; +} + +void rtosv2_semp_main(void *arg) { + (void)arg; + empty_id = osSemaphoreNew(BUFFER_SIZE, BUFFER_SIZE, NULL); + filled_id = osSemaphoreNew(BUFFER_SIZE, 0U, NULL); + + osThreadId_t ptid1 = newThread("producer1", producer_thread, NULL); + osThreadId_t ptid2 = newThread("producer2", producer_thread, NULL); + osThreadId_t ptid3 = newThread("producer3", producer_thread, NULL); + osThreadId_t ctid1 = newThread("consumer1", consumer_thread, NULL); + osThreadId_t ctid2 = newThread("consumer2", consumer_thread, NULL); + + osDelay(50); + + osThreadTerminate(ptid1); + osThreadTerminate(ptid2); + osThreadTerminate(ptid3); + osThreadTerminate(ctid1); + osThreadTerminate(ctid2); + + osSemaphoreDelete(empty_id); + osSemaphoreDelete(filled_id); +} + +static void SempTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "rtosv2_semp_main"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)rtosv2_semp_main, NULL, &attr) == NULL) { + printf("[SempTestTask] Falied to create rtosv2_semp_main!\n"); + } +} + +APP_FEATURE_INIT(SempTestTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..030d9c63b99eb4d3517da465556a01b3d2d1eaec --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/BUILD.gn" @@ -0,0 +1,37 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("message_demo") { + sources = [ + "message.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..0f8a4e7a2bac02c6d79ae7b0cf2b3083584d0d48 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/README.md" @@ -0,0 +1,152 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--消息队列(MessageQueue) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、MessageQueue API + +| API名称 | 说明 | +| ------------------------- | ------------------------------------------------------------ | +| osMessageQueueNew | 创建和初始化一个消息队列 | +| osMessageQueueGetName | 返回指定的消息队列的名字 | +| osMessageQueuePut | 向指定的消息队列存放1条消息,如果消息队列满了,那么返回超时 | +| osMessageQueueGet | 从指定的消息队列中取得1条消息,如果消息队列为空,那么返回超时 | +| osMessageQueueGetCapacity | 获得指定的消息队列的消息容量 | +| osMessageQueueGetMsgSize | 获得指定的消息队列中可以存放的最大消息的大小 | +| osMessageQueueGetCount | 获得指定的消息队列中当前的消息数 | +| osMessageQueueGetSpace | 获得指定的消息队列中还可以存放的消息数 | +| osMessageQueueReset | 将指定的消息队列重置为初始状态 | +| osMessageQueueDelete | 删除指定的消息队列 | + +## 二、代码分析 + +`osMessageQueueNew`创建一个消息队列 + +发送者每次将自己`count`的值与线程ID发送,并将`count`加1; + +接受者从消息队列中获取一条信息,然后将其打印输出 + +```c +void sender_thread(void *arg) { + static int count=0; + message_entry sentry; + (void)arg; + while(1) { + sentry.tid = osThreadGetId(); + sentry.count = count; + printf("[Message Test] %s send %d to message queue.\r\n", osThreadGetName(osThreadGetId()), count); + osMessageQueuePut(qid, (const void *)&sentry, 0, osWaitForever); + count++; + osDelay(5); + } +} + +void receiver_thread(void *arg) { + (void)arg; + message_entry rentry; + while(1) { + osMessageQueueGet(qid, (void *)&rentry, NULL, osWaitForever); + printf("[Message Test] %s get %d from %s by message queue.\r\n", osThreadGetName(osThreadGetId()), rentry.count, osThreadGetName(rentry.tid)); + osDelay(3); + } +} +``` + +主程序创建了三个消息发送者和两个消息接收者,然后调用相关的API确认消息队列的装填 + +```c +void rtosv2_msgq_main(void *arg) { + (void)arg; + + qid = osMessageQueueNew(QUEUE_SIZE, sizeof(message_entry), NULL); + + osThreadId_t ctid1 = newThread("recevier1", receiver_thread, NULL); + osThreadId_t ctid2 = newThread("recevier2", receiver_thread, NULL); + osThreadId_t ptid1 = newThread("sender1", sender_thread, NULL); + osThreadId_t ptid2 = newThread("sender2", sender_thread, NULL); + osThreadId_t ptid3 = newThread("sender3", sender_thread, NULL); + + osDelay(20); + uint32_t cap = osMessageQueueGetCapacity(qid); + printf("[Message Test] osMessageQueueGetCapacity, capacity: %d.\r\n",cap); + uint32_t msg_size = osMessageQueueGetMsgSize(qid); + printf("[Message Test] osMessageQueueGetMsgSize, size: %d.\r\n",msg_size); + uint32_t count = osMessageQueueGetCount(qid); + printf("[Message Test] osMessageQueueGetCount, count: %d.\r\n",count); + uint32_t space = osMessageQueueGetSpace(qid); + printf("[Message Test] osMessageQueueGetSpace, space: %d.\r\n",space); + + osDelay(80); + osThreadTerminate(ctid1); + osThreadTerminate(ctid2); + osThreadTerminate(ptid1); + osThreadTerminate(ptid2); + osThreadTerminate(ptid3); + osMessageQueueDelete(qid); +} +``` + + + +## 三、如何编译 + +1. 将此目录下的 `message.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:message_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +截取部分运行结果 + +``` +[Message Test] osThreadNew(recevier1) success, thread id: 0xe89d8. +[Message Test] osThreadNew(recevier2) success, thread id: 0xe8974. +[Message Test] osThreadNew(sender1) success, thread id: 0xe84c4. +[Message Test] os[Message Test] sender1 send 0 to message queue. +[Message Test] sender2 send 1 to message queue. +ThreadNew(sender2) success, thread id: 0xe871c. +[Message Test] osThreadNew(sender3) success, thread id: 0xe8910. +[Message Test] recevier1 get 0 from sender1 by message queue. +[Message Test] recevier2 get 1 from sender2 by message queue. +[Message Test] sender3 send 2 to message queue. +[Message Test] sender1 send 3 to message queue. +[Message Test] sender2 send 4 to message queue. +.... +[Message Test] sender3 send 11 to message queue. +[Message Test] recevier2 get 11 from sender3 by message queue. +[Message Test] sender1 send 12 to message queue. +[Message Test] sender2 send 13 to message queue. +[Message Test] recevier1 get 12 from sender1 by message queue. +[Message Test] osMessageQueueGetCapacity, capacity: 3. +[Message Test] osMessageQueueGetMsgSize, size: 8. +[Message Test] osMessageQueueGetCount, count: 1. +[Message Test] osMessageQueueGetSpace, space: 2. +``` + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/message.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/message.c" new file mode 100755 index 0000000000000000000000000000000000000000..6afa2063bdad81e3352e345ddc336d3f0b268351 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/05_message/message.c" @@ -0,0 +1,98 @@ +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#define QUEUE_SIZE 3 +typedef struct { + osThreadId_t tid; + int count; +} message_entry; +osMessageQueueId_t qid; + +void sender_thread(void *arg) { + static int count=0; + message_entry sentry; + (void)arg; + while(1) { + sentry.tid = osThreadGetId(); + sentry.count = count; + printf("[Message Test] %s send %d to message queue.\r\n", osThreadGetName(osThreadGetId()), count); + osMessageQueuePut(qid, (const void *)&sentry, 0, osWaitForever); + count++; + osDelay(5); + } +} + +void receiver_thread(void *arg) { + (void)arg; + message_entry rentry; + while(1) { + osMessageQueueGet(qid, (void *)&rentry, NULL, osWaitForever); + printf("[Message Test] %s get %d from %s by message queue.\r\n", osThreadGetName(osThreadGetId()), rentry.count, osThreadGetName(rentry.tid)); + osDelay(3); + } +} + +osThreadId_t newThread(char *name, osThreadFunc_t func, void *arg) { + osThreadAttr_t attr = { + name, 0, NULL, 0, NULL, 1024*2, osPriorityNormal, 0, 0 + }; + osThreadId_t tid = osThreadNew(func, arg, &attr); + if (tid == NULL) { + printf("[Message Test] osThreadNew(%s) failed.\r\n", name); + } else { + printf("[Message Test] osThreadNew(%s) success, thread id: %d.\r\n", name, tid); + } + return tid; +} + +void rtosv2_msgq_main(void *arg) { + (void)arg; + + qid = osMessageQueueNew(QUEUE_SIZE, sizeof(message_entry), NULL); + + osThreadId_t ctid1 = newThread("recevier1", receiver_thread, NULL); + osThreadId_t ctid2 = newThread("recevier2", receiver_thread, NULL); + osThreadId_t ptid1 = newThread("sender1", sender_thread, NULL); + osThreadId_t ptid2 = newThread("sender2", sender_thread, NULL); + osThreadId_t ptid3 = newThread("sender3", sender_thread, NULL); + + osDelay(20); + uint32_t cap = osMessageQueueGetCapacity(qid); + printf("[Message Test] osMessageQueueGetCapacity, capacity: %d.\r\n",cap); + uint32_t msg_size = osMessageQueueGetMsgSize(qid); + printf("[Message Test] osMessageQueueGetMsgSize, size: %d.\r\n",msg_size); + uint32_t count = osMessageQueueGetCount(qid); + printf("[Message Test] osMessageQueueGetCount, count: %d.\r\n",count); + uint32_t space = osMessageQueueGetSpace(qid); + printf("[Message Test] osMessageQueueGetSpace, space: %d.\r\n",space); + + osDelay(80); + osThreadTerminate(ctid1); + osThreadTerminate(ctid2); + osThreadTerminate(ptid1); + osThreadTerminate(ptid2); + osThreadTerminate(ptid3); + osMessageQueueDelete(qid); +} + +static void MessageTestTask(void) +{ + osThreadAttr_t attr; + + attr.name = "rtosv2_msgq_main"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)rtosv2_msgq_main, NULL, &attr) == NULL) { + printf("[MessageTestTask] Falied to create rtosv2_msgq_main!\n"); + } +} + +APP_FEATURE_INIT(MessageTestTask); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..3111d08ce1971b9c4fc01f59ab8087b810f74c60 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/BUILD.gn" @@ -0,0 +1,24 @@ +# Copyright (c) 2020 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("led_example") { + sources = [ + "led_example.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/kal", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..ec56b6b0931779592640532d8544d4826647dd8b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/README.md" @@ -0,0 +1,59 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--IO控制(gpio_led) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、GPIO API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| unsigned int GpioInit(void); | GPIO模块初始化 | +| unsigned int GpioSetDir(WifiIotGpioIdx id, WifiIotGpioDir dir); | 设置GPIO引脚方向,id参数用于指定引脚,dir参数用于指定输入或输出 | +| unsigned int GpioSetOutputVal(WifiIotGpioIdx id, WifiIotGpioValue val); | 设置GPIO引脚的输出状态,id参数用于指定引脚,val参数用于指定高电平或低电平 | +| unsigned int IoSetFunc(WifiIotIoName id, unsigned char val); | 设置引脚功能,id参数用于指定引脚,val用于指定引脚功能 | +| unsigned int GpioDeinit(void); | 解除GPIO模块初始化 | + +## 二、核心板LED与主控芯片(Pegasus)引脚的对应关系 + +- **LED:**GPIO9/输出低电平点亮LED灯 + + +## 三、如何编译 + +1. 将此目录下的 `led_example.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:led_example", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,会发现核心板上的led等一闪一闪的 + +串口工具也会打印:LED_SPARK + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/led_example.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/led_example.c" new file mode 100755 index 0000000000000000000000000000000000000000..bbb8d377b0be87462f6e6a6566b53a091c4e1d63 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/06_gpioled/led_example.c" @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include + +#include "cmsis_os2.h" +#include "ohos_init.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" + +#define LED_TASK_STACK_SIZE 1024 +#define LED_TASK_PRIO 25 + +static void* GpioTask(const char* arg) +{ + (void)arg; + + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT); + + while (1) { + printf(" LED_SPARK! \n"); + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE0); + osDelay(50); + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE1); + osDelay(50); + } + return NULL; +} + +static void GpioExampleEntry(void) +{ + osThreadAttr_t attr; + + attr.name = "GpioTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = LED_TASK_STACK_SIZE; + attr.priority = LED_TASK_PRIO; + + if (osThreadNew((osThreadFunc_t)GpioTask, NULL, &attr) == NULL) { + printf("[GpioExample] Falied to create GpioTask!\n"); + } +} + +SYS_RUN(GpioExampleEntry); // if test add it diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..8bfa4495b233f4f0fa372b9c4b41efc9bf5f6299 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/BUILD.gn" @@ -0,0 +1,24 @@ +# Copyright (c) 2020 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +static_library("button_example") { + sources = [ + "button_example.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/kal", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..45a554b0bd84983b201ed674a642b1b58b1ede99 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/README.md" @@ -0,0 +1,59 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--IO控制(gpio_button) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、GPIO API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| unsigned int GpioGetInputVal(WifiIotGpioIdx id, WifiIotGpioValue *val); | 获取GPIO引脚状态,id参数用于指定引脚,val参数用于接收GPIO引脚状态 | +| unsigned int IoSetPull(WifiIotIoName id, WifiIotIoPull val); | 设置引脚上拉或下拉状态,id参数用于指定引脚,val参数用于指定上拉或下拉状态 | +| unsigned int GpioRegisterIsrFunc(WifiIotGpioIdx id, WifiIotGpioIntType intType, WifiIotGpioIntPolarity intPolarity, GpioIsrCallbackFunc func, char *arg); | 注册GPIO引脚中断,id参数用于指定引脚,intType参数用于指定中断触发类型(边缘触发或水平触发),intPolarity参数用于指定具体的边缘类型(下降沿或上升沿)或水平类型(高电平或低电平),func参数用于指定中断处理函数,arg参数用于指定中断处理函数的附加参数 | +| typedef void (*GpioIsrCallbackFunc) (char *arg); | 中断处理函数原型,arg参数为附加参数,可以不适用(填NULL),或传入指向用户自定义类型的参数 | +| unsigned int GpioUnregisterIsrFunc(WifiIotGpioIdx id); | 解除GPIO引脚中断注册,id参数用于指定引脚 | + +## 二、核心板USER按键与主控芯片(Pegasus)引脚的对应关系 + +- **USER按键:**GPIO5/按键中断控制LED灯状态反转 + + +## 三、如何编译 + +1. 将此目录下的 `button_example.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:button_example", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,程序开始运行,led灯会先闪烁,在按下USER按键时,led会熄灭,再次按下USER按键,led会亮 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/button_example.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/button_example.c" new file mode 100755 index 0000000000000000000000000000000000000000..f4ca444b9b51dbe3e63faf8cafbd51de4a7a2f86 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/07_gpiobutton/button_example.c" @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" + +#define LED_INTERVAL_TIME 30 +#define LED_TASK_STACK_SIZE 512 +#define LED_TASK_PRIO 25 + +enum LedState { + LED_ON = 0, + LED_OFF, + LED_SPARK, +}; + +enum LedState g_ledState = LED_SPARK; + +static void *LedTask(const char *arg) +{ + (void)arg; + while (1) { + switch (g_ledState) { + case LED_ON: + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE0); + osDelay(LED_INTERVAL_TIME); + break; + case LED_OFF: + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE1); + osDelay(LED_INTERVAL_TIME); + break; + case LED_SPARK: + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE0); + osDelay(LED_INTERVAL_TIME); + GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_VALUE1); + osDelay(LED_INTERVAL_TIME); + break; + default: + osDelay(LED_INTERVAL_TIME); + break; + } + } + + return NULL; +} + +static void OnButtonPressed(char *arg) +{ + (void) arg; + + enum LedState nextState = LED_SPARK; + switch (g_ledState) { + case LED_ON: + nextState = LED_OFF; + break; + case LED_OFF: + nextState = LED_ON; + break; + case LED_SPARK: + nextState = LED_OFF; + break; + default: + break; + } + + g_ledState = nextState; +} + +static void LedExampleEntry(void) +{ + osThreadAttr_t attr; + + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_IO_FUNC_GPIO_5_GPIO); + GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_5, WIFI_IOT_INT_TYPE_EDGE, WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW, + OnButtonPressed, NULL); + + attr.name = "LedTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = LED_TASK_STACK_SIZE; + attr.priority = LED_TASK_PRIO; + + if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { + printf("[LedExample] Falied to create LedTask!\n"); + } +} + +SYS_RUN(LedExampleEntry); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..0361e253a93ab2b3f89c294468ee022b2e9a202a --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("pwm_led_demo") { + sources = [ + "pwm_led_demo.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..e9c786434d9a2d02f2b25211b31b5b7e0a4fbb44 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/README.md" @@ -0,0 +1,64 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--PWM(pwm_led) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、PWM API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ----------------- | +| unsigned int PwmInit(WifiIotPwmPort port); | PWM模块初始化 | +| unsigned int PwmStart(WifiIotPwmPort port, unsigned short duty, unsigned short freq); | 开始输出PWM信号 | +| unsigned int PwmStop(WifiIotPwmPort port); | 停止输出PWM信号 | +| unsigned int PwmDeinit(WifiIotPwmPort port); | 解除PWM模块初始化 | +| unsigned int PwmSetClock(WifiIotPwmClkSource clkSource); | 设置PWM模块时钟源 | + +## 二、炫彩灯板三色灯与主控芯片(Pegasus)引脚的对应关系 + +- **红色:**GPIO10/PWM1/低电平点亮 +- **绿色:**GPIO11/PWM2/低电平点亮 +- **蓝色:**GPIO12/PWM3/低电平点亮 + +## 三、如何编译 + +1. 将此目录下的 `pwm_led_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:pwm_led_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,程序开始运行,炫彩灯板的三色灯会呈现红色,并且亮度会逐渐变化:暗--亮 + +## 五、报错解决 + +编译过程中报错:undefined reference to hi_pwm_init 等几个 hi_pwm_开头的函数 + 原因: 因为默认情况下,hi3861_sdk中,PWM的CONFIG选项没有打开 + 解决: 修改vendor\hisi\hi3861\hi3861\build\config\usr_config.mk文件中的CONFIG_PWM_SUPPORT行: # CONFIG_PWM_SUPPORT is not set修改为CONFIG_PWM_SUPPORT=y + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/pwm_led_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/pwm_led_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..90b43ca3aa22dbd4db1034014b984e226db83b80 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/08_pwmled/pwm_led_demo.c" @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_errno.h" + +#define RED_LED_PIN_NAME WIFI_IOT_IO_NAME_GPIO_10 +#define RED_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_10_GPIO + +#define RESOLUTION 4096 +#define PWM_FREQ_DIVITION 64000 + +static void PWMLedDemoTask(void *arg) +{ + (void)arg; + + // GpioDeinit(); + IoSetFunc(RED_LED_PIN_NAME, WIFI_IOT_IO_FUNC_GPIO_10_PWM1_OUT); + + PwmInit(WIFI_IOT_PWM_PORT_PWM1); // R + + + while (1) { + // use PWM control RED LED brightness + for (int i = 1; i <= RESOLUTION; i *= 2) { + PwmStart(WIFI_IOT_PWM_PORT_PWM1, i, PWM_FREQ_DIVITION); + usleep(250000); + PwmStop(WIFI_IOT_PWM_PORT_PWM1); + } + } +} + +static void PWMLedDemo(void) +{ + osThreadAttr_t attr; + + GpioInit(); + // set Red/Green/Blue LED pin to GPIO function + IoSetFunc(RED_LED_PIN_NAME, RED_LED_PIN_FUNCTION); + + + attr.name = "PWMLedDemoTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 4096; + attr.priority = osPriorityNormal; + + if (osThreadNew(PWMLedDemoTask, NULL, &attr) == NULL) { + printf("[ColorfulLightDemo] Falied to create PWMLedDemoTask!\n"); + } +} + +APP_FEATURE_INIT(PWMLedDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..088e50727bdbd12a9611cae771a6a98d2c621eb4 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("adc_demo") { + sources = [ + "adc_demo.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..b96d3914591c4407ee39dd3b64180fe332985a25 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/README.md" @@ -0,0 +1,58 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--ADC(光敏电阻) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、ADC API + +| API名称 | 说明 | +| ------------------------------------------------------------ | --------------- | +| unsigned int AdcRead(WifiIotAdcChannelIndex channel, unsigned short *data, WifiIotAdcEquModelSel equModel, WifiIotAdcCurBais curBais, unsigned short rstCnt); | 读取ADC通道的值 | + +## 二、炫彩灯板光敏电阻与主控芯片(Pegasus)引脚的对应关系 + +- **光敏电阻:**GPIO9/ADC4/感应范围小,响应快 + +## 三、如何编译 + +1. 将此目录下的 `adc_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +```c + features = [ + "iothardware:adc_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,程序开始运行,改变炫彩灯板光敏电阻周围环境的光,会发现串口打印的`ADCvalue`会发生变化; + +有光时,串口输出的ADC的值为120左右;无光时,串口输出的ADC的值为1800左右。 + +由ADC值计算对应引脚电压的公式为Value=voltage/4/1.8×4096。 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/adc_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/adc_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..a79a6f801ae03a5ce004a8f487f2b1d91f831426 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/09_adc/adc_demo.c" @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_adc.h" +#include "wifiiot_errno.h" + +#define LIGHT_SENSOR_CHAN_NAME WIFI_IOT_ADC_CHANNEL_4 + +#define BLUE_LED_PIN_NAME WIFI_IOT_IO_NAME_GPIO_12 +#define BLUE_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_12_GPIO + +static void ADCLightTask(void *arg) +{ + (void)arg; + + while (1) { + unsigned short data = 0; + + if (AdcRead(LIGHT_SENSOR_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0) + == WIFI_IOT_SUCCESS) { + printf("ADC_VALUE = %d\n", (unsigned int)data); + osDelay(10); + } + + } +} + +static void ADCLightDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "ADCLightTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 4096; + attr.priority = osPriorityNormal; + + if (osThreadNew(ADCLightTask, NULL, &attr) == NULL) { + printf("[ADCLightDemo] Falied to create ADCLightTask!\n"); + } +} + +APP_FEATURE_INIT(ADCLightDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..c92116838e2a8e83bb1e2963a90ebe5e7d135d25 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/BUILD.gn" @@ -0,0 +1,35 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") + +lite_component("app") { + features = [ + "src:aht20", + "test:aht20_test", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..4c4ae30eb89aad2c16ece5e7e1c77216420ca572 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/README.md" @@ -0,0 +1,86 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--I2C(i2c_aht20) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、I2C API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ------------------------------- | +| I2cInit (WifiIotI2cIdx id, unsigned int baudrate) | 用指定的波特速率初始化I2C设备 | +| I2cDeinit (WifiIotI2cIdx id) | 取消初始化I2C设备 | +| I2cWrite (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 将数据写入I2C设备 | +| I2cRead (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 从I2C设备中读取数据 | +| I2cWriteread (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 向I2C设备发送数据并接收数据响应 | +| I2cRegisterResetBusFunc (WifiIotI2cIdx id, WifiIotI2cFunc pfn) | 注册I2C设备回调 | +| I2cSetBaudrate (WifiIotI2cIdx id, unsigned int baudrate) | 设置I2C设备的波特率 | + +## 二、Aht20 API + +本样例提供了一个鸿蒙AHT20数字温湿度传感器驱动库,其功能如下: + +* 使用OpenHarmony的IoT硬件接口; +* 接口简洁易于使用、易于移植; +* 内置了测试程序,可直接进行测试; + +| API名称 | 说明 | +| --------------------------------------------------------- | ----------------------- | +| uint32_t AHT20_Calibrate(void) | 校准,成功返回0 | +| uint32_t AHT20_StartMeasure(void) | 触发测量,成功返回0 | +| uint32_t AHT20_GetMeasureResult(float* temp, float* humi) | 读取测量结果,成功返回0 | + +## 三、如何编译 + +1. 将此目录复制到openharmony源码的根目录下 + +2. 修改openharmony源码的`build/lite/product/wifiiot.json`文件: + + 将`//applications/sample/wifi-iot/app`替换为`//10_i2caht20:app`保存; + +3. 在openharmony源码目录下执行:`python build.py wifiiot` + +## 四、编译错误解决 + +本项目代码使用了鸿蒙IoT硬件子系统的I2C API接口,需要连接到hi3861的I2C相关接口;默认情况下,Hi3861的I2C编译配置没有打开,编译时会有如下错误: + +```txt +riscv32-unknown-elf-ld: ohos/libs/libhal_iothardware.a(hal_wifiiot_i2c.o): in function `.L0 ': +hal_wifiiot_i2c.c:(.text.HalI2cWrite+0x12): undefined reference to `hi_i2c_write' +riscv32-unknown-elf-ld: hal_wifiiot_i2c.c:(.text.HalI2cInit+0x12): undefined reference to `hi_i2c_init' +scons: *** [output/bin/Hi3861_wifiiot_app.out] Error 1 +BUILD FAILED!!!! +``` + +**解决方法** + +需要修改vendor\hisi\hi3861\hi3861\build\config\usr_config.mk文件: +`# CONFIG_I2C_SUPPORT is not set`行,修改为:`CONFIG_I2C_SUPPORT=y` + +## 五、运行结果 + +烧录文件后,按下reset按键,程序开始运行,串口工具会输出测量后的温湿度数据 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..e950a65ab0a547776050dc5dcad833a5c08398f9 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("aht20") { + sources = [ + "aht20.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.c" new file mode 100755 index 0000000000000000000000000000000000000000..a562746d6be829df9cf616403cd3ba332eb7c107 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.c" @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aht20.h" + +#include +#include +#include + +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" + +#define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define AHT20_STARTUP_TIME 20*1000 // 上电启动时间 +#define AHT20_CALIBRATION_TIME 40*1000 // 初始化(校准)时间 +#define AHT20_MEASURE_TIME 75*1000 // 测量时间 + +#define AHT20_DEVICE_ADDR 0x38 +#define AHT20_READ_ADDR ((0x38<<1)|0x1) +#define AHT20_WRITE_ADDR ((0x38<<1)|0x0) + +#define AHT20_CMD_CALIBRATION 0xBE // 初始化(校准)命令 +#define AHT20_CMD_CALIBRATION_ARG0 0x08 +#define AHT20_CMD_CALIBRATION_ARG1 0x00 + +/** + * 传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。 + * 若状态比特位[Bit7]为0代表数据可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。 + **/ +#define AHT20_CMD_TRIGGER 0xAC // 触发测量命令 +#define AHT20_CMD_TRIGGER_ARG0 0x33 +#define AHT20_CMD_TRIGGER_ARG1 0x00 + +// 用于在无需关闭和再次打开电源的情况下,重新启动传感器系统,软复位所需时间不超过20 毫秒 +#define AHT20_CMD_RESET 0xBA // 软复位命令 + +#define AHT20_CMD_STATUS 0x71 // 获取状态命令 + +/** + * STATUS 命令回复: + * 1. 初始化后触发测量之前,STATUS 只回复 1B 状态值; + * 2. 触发测量之后,STATUS 回复6B: 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度 + * RH = Srh / 2^20 * 100% + * T = St / 2^20 * 200 - 50 + **/ +#define AHT20_STATUS_BUSY_SHIFT 7 // bit[7] Busy indication +#define AHT20_STATUS_BUSY_MASK (0x1<> AHT20_STATUS_BUSY_SHIFT) + +#define AHT20_STATUS_MODE_SHIFT 5 // bit[6:5] Mode Status +#define AHT20_STATUS_MODE_MASK (0x3<> AHT20_STATUS_MODE_SHIFT) + + // bit[4] Reserved +#define AHT20_STATUS_CALI_SHIFT 3 // bit[3] CAL Enable +#define AHT20_STATUS_CALI_MASK (0x1<> AHT20_STATUS_CALI_SHIFT) + // bit[2:0] Reserved + +#define AHT20_STATUS_RESPONSE_MAX 6 + +#define AHT20_RESOLUTION (1<<20) // 2^20 + +#define AHT20_MAX_RETRY 10 + +static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen) +{ + WifiIotI2cData data = { 0 }; + data.receiveBuf = buffer; + data.receiveLen = buffLen; + uint32_t retval = I2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, &data); + if (retval != WIFI_IOT_SUCCESS) { + printf("I2cRead() failed, %0X!\n", retval); + return retval; + } + return WIFI_IOT_SUCCESS; +} + +static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen) +{ + WifiIotI2cData data = { 0 }; + data.sendBuf = buffer; + data.sendLen = buffLen; + uint32_t retval = I2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data); + if (retval != WIFI_IOT_SUCCESS) { + printf("I2cWrite(%02X) failed, %0X!\n", buffer[0], retval); + return retval; + } + return WIFI_IOT_SUCCESS; +} + +// 发送获取状态命令 +static uint32_t AHT20_StatusCommand(void) +{ + uint8_t statusCmd[] = { AHT20_CMD_STATUS }; + return AHT20_Write(statusCmd, sizeof(statusCmd)); +} + +// 发送软复位命令 +static uint32_t AHT20_ResetCommand(void) +{ + uint8_t resetCmd[] = {AHT20_CMD_RESET}; + return AHT20_Write(resetCmd, sizeof(resetCmd)); +} + +// 发送初始化校准命令 +static uint32_t AHT20_CalibrateCommand(void) +{ + uint8_t clibrateCmd[] = {AHT20_CMD_CALIBRATION, AHT20_CMD_CALIBRATION_ARG0, AHT20_CMD_CALIBRATION_ARG1}; + return AHT20_Write(clibrateCmd, sizeof(clibrateCmd)); +} + +// 读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字), +// 如果不为1,要发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。 +uint32_t AHT20_Calibrate(void) +{ + uint32_t retval = 0; + uint8_t buffer[AHT20_STATUS_RESPONSE_MAX]; + memset(&buffer, 0x0, sizeof(buffer)); + + retval = AHT20_StatusCommand(); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + retval = AHT20_Read(buffer, sizeof(buffer)); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) { + retval = AHT20_ResetCommand(); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + usleep(AHT20_STARTUP_TIME); + retval = AHT20_CalibrateCommand(); + usleep(AHT20_CALIBRATION_TIME); + return retval; + } + + return WIFI_IOT_SUCCESS; +} + +// 发送 触发测量 命令,开始测量 +uint32_t AHT20_StartMeasure(void) +{ + uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1}; + return AHT20_Write(triggerCmd, sizeof(triggerCmd)); +} + +// 接收测量结果,拼接转换为标准值 +uint32_t AHT20_GetMeasureResult(float* temp, float* humi) +{ + uint32_t retval = 0, i = 0; + if (temp == NULL || humi == NULL) { + return WIFI_IOT_FAILURE; + } + + uint8_t buffer[AHT20_STATUS_RESPONSE_MAX]; + memset(&buffer, 0x0, sizeof(buffer)); + retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) { + // printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY); + usleep(AHT20_MEASURE_TIME); + retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + } + if (i >= AHT20_MAX_RETRY) { + printf("AHT20 device always busy!\r\n"); + return WIFI_IOT_FAILURE; + } + + uint32_t humiRaw = buffer[1]; + humiRaw = (humiRaw << 8) | buffer[2]; + humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4); + *humi = humiRaw / (float)AHT20_RESOLUTION * 100; + + uint32_t tempRaw = buffer[3] & 0x0F; + tempRaw = (tempRaw << 8) | buffer[4]; + tempRaw = (tempRaw << 8) | buffer[5]; + *temp = tempRaw / (float)AHT20_RESOLUTION * 200 - 50; + // printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp); + return WIFI_IOT_SUCCESS; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.h" new file mode 100755 index 0000000000000000000000000000000000000000..d07615c5bf1da4b18328538b15f53fa82e3041e3 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/src/aht20.h" @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AHT20_H +#define AHT20_H + +#include + +uint32_t AHT20_Calibrate(void); + +uint32_t AHT20_StartMeasure(void); + +uint32_t AHT20_GetMeasureResult(float* temp, float* humi); + +#endif // AHT20_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..cee82bac503a0a59ac9f9755c3ab18d85f4da5eb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/BUILD.gn" @@ -0,0 +1,39 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("aht20_test") { + sources = [ + "aht20_test.c", + ] + + include_dirs = [ + "../src", + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/aht20_test.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/aht20_test.c" new file mode 100755 index 0000000000000000000000000000000000000000..57b0793838917eab16693d39f5257bc25d822065 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/10_i2caht20/test/aht20_test.c" @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aht20.h" + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_i2c.h" + +void Aht20TestTask(void* arg) +{ + (void) arg; + uint32_t retval = 0; + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); + + I2cInit(WIFI_IOT_I2C_IDX_0, 400*1000); + + retval = AHT20_Calibrate(); + printf("AHT20_Calibrate: %d\r\n", retval); + + while (1) { + float temp = 0.0, humi = 0.0; + + retval = AHT20_StartMeasure(); + printf("AHT20_StartMeasure: %d\r\n", retval); + + retval = AHT20_GetMeasureResult(&temp, &humi); + printf("AHT20_GetMeasureResult: %d, temp = %.2f, humi = %.2f\r\n", retval, temp, humi); + + sleep(1); + } +} + +void Aht20Test(void) +{ + osThreadAttr_t attr; + + attr.name = "Aht20Task"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 4096; + attr.priority = osPriorityNormal; + + if (osThreadNew(Aht20TestTask, NULL, &attr) == NULL) { + printf("[Aht20Test] Failed to create Aht20TestTask!\n"); + } +} +APP_FEATURE_INIT(Aht20Test); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..7e83bf4379a3e25654d56f4459e7501b5ae0dbba --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("uart_demo") { + sources = [ + "uart_demo.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..f11aeb914d264edaa35e26fb245a97689630742c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/README.md" @@ -0,0 +1,147 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--UART + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、UART API + +使用下面的API实现UART读写 + +#### 鸿蒙UART相关的API接口文件路径 + +**base/iot_hardware/interfaces/kits/wifiiot_lite/wifiiot_uart.h** + +所使用的API接口有: + +| API | 接口说明 | +| ------------------------------------------------------------ | ------------------------ | +| unsigned int UartInit(WifiIotUartIdx id, const WifiIotUartAttribute *param, const WifiIotUartExtraAttr *extraAttr); | 初始化,配置一个UART设备 | +| int UartRead(WifiIotUartIdx id, unsigned char *data, unsigned int dataLen) | 从UART设备中读取数据 | +| int UartWrite(WifiIotUartIdx id, const unsigned char *data, unsigned int dataLen) | 将数据写入UART设备 | + +#### + +## 二、代码分析 + +首先需要使能UART2 + +vendor\hisi\hi3861\hi3861\build\config\usr_config.mk + +配置CONFIG_UART2_SUPPORT=y + +或者调用GPIO相关的API将串口所在的GPIO口设置为UART功能 + +```c +static void* UartDemo_Task(const char* arg) + +{ + unsigned int len = 0; + + (void)arg; + printf("[UartDemo] UartDemo_Task()\n"); + + GpioInit();//使用GPIO,都需要调用该接口 + + printf("UART init...\r\n"); + //UART参数配置 + usr_uart_config(); + + UartWrite(WIFI_IOT_UART_IDX_2, (unsigned char *)uartWriteBuff, sizeof(uartWriteBuff)); + while(1) + { + //读取UART2的数据 + len = UartRead(WIFI_IOT_UART_IDX_2, uartReadBuff, sizeof(uartReadBuff)); + if (len > 0) { + printf("Uart read data:%s", uartReadBuff); + } + usleep(100000); + } + + return NULL; +} + +``` + + + +## 三、如何编译 + +1. 将此目录下的 `uart_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:uart_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` +##### 串口0 +RX:ready to OS start + +sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00 + +FileSystem mount ok. +wifi init success! +[UartDemo] UartDemo_Entry() + +[UartDemo] UartDemo_Task() +UART init... + +00 00:00:00 0 132 D 0/HIVIEW: hilog init success. +00 00:00:00 0 132 D 0/HIVIEW: log limit init success. +00 00:00:00 0 132 I 1/SAMGR: Bootstrap core services(count:3). +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4ae958 TaskPool:0xe5238 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4ae964 TaskPool:0xe5258 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4aea8c TaskPool:0xe5278 +00 00:00:00 0 8 I 1/SAMGR: Init service 0x4ae964 success! +00 00:00:00 0 164 I 1/SAMGR: Init service 0x4ae958 success! +00 00:00:00 0 108 D 0/HIVIEW: hiview init success. +00 00:00:00 0 108 I 1/SAMGR: Init service 0x4aea8c success! +00 00:00:00 0 108 I 1/SAMGR: Initialized all core system services! +00 00:00:00 0 164 I 1/SAMGR: Bootstrap system and application services(count:0). +00 00:00:00 0 164 I 1/SAMGR: Initialized all system and application services! +00 00:00:00 0 164 I 1/SAMGR: Bootstrap dynamic registered services(count:0). + +RX:Uart read data:hello + +RX:Uart read data:12345678 + + + +##### 串口2 + +RX:hello uart! + +TX:hello + +TX:12345678 +``` + +![img](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABXwAAAMWCAYAAABCzk5dAAAgAElEQVR4nOzd%0AT2yc13no/+cVaNwbizHINOsyYHamkA2JuL4tFBtSfBF04QsjVJbdadMiCe4i%0AiwY2SQMBLlI0N7WbLrQr5E3FwEmWESnYAXrhOCU3spid2SruqnV/ZBMBuReW%0A5/0tqDM8c3j+z3nn/TPfDzDQzPue95zzvjOiHj563jNVXde1AAAAAD2hwte6%0Ari88RqPRhT8//fRT+eSTT+RP//RP5aOPPpLLly/Lhx9+2PJZAAAAAM241PYE%0AAAAAgBJsiWD9td4GAAAAGCoSvgAAAOgdM3HrSujaqoABAACAISPhCwAAgF6L%0ASfJmV/hWlciLL158XVUi//W/nj/f2Tnfr54DAAAALfAnfAlwAQAA0CF6wtas%0A2LUlc6eu7H3hBZF33z17/u67InV9tk1E5P/+3/PnW1tnsfA775w9BwAAAFri%0AT/gS4AIAAKBHXMs3ZCV8X3zxPN59993z5zoV+1aVyH/5LxQ/AAAAtKCqqqhH%0A11RVJYeHh879h4eHWfN2J3wJcAEAAHrh1q1bUY+uuXXrlnz88cfO/R9//HH0%0AvF0J3anW73333bN494UXJu96sw90VhChiiVsdm9IVV2RnaOJjXKjqqS6sXtx%0Am3pM7BORox25MvHLi9nnkexcsW03+r+yI7bduzcsY4rI0c6V82N2b3jGt523%0AantDLvYMAAAwPdeyXl3+HoeDgwN5/o//xJr0PTw8lOf/+E/k4OAgud8F5553%0A3z2r2H333bMA13dh1D5fxvl4X27tn8j65qasL483yv6tfTlevS43r69OblNN%0AJvaJyMmh7O4eysl4w7LR54kc7u7K4Ym53RhzeV02N9fF3H28f0v2xRhTRE4O%0Ad2X3ePXsmON9ubWvZugaRz9v1XZVrt+8LquOpgAAALlu3rzp3d/FhO8rr7wi%0AP/3Zz+R/vPyyfP7zn5/Y9/HHH8tPf/YzeeWVV7L7nyqw1+NalcTd2TlLAG9v%0An+/TlzbTY2Lb2Jt35M5mJTe+sSNff7AlayJytLMju2vb8uDO5lmb3RtS3diV%0AzTu11E82ye4NubLzrDzYWnuy/9ey/aCWB2tP9h/tyJUrlRzdqUV1IyKytiay%0A++Mj2VpbE93Rzo436bq5uSlyY1d2ZVPOuzuSH+8eyebWA1mTXbmxsyYP6juy%0ApuZ85YY8W9/R2p/PvdLbAgAAYGx9fV3e+z//KM//8Z/Ie//nH2V9fV1EzpO9%0A+rYUVW2LhFWAW9fnz7e3z5duUPt2ds4DXr2tI7g+3r8l+yfnidaJJOpZA7m1%0Afyyr12/Kef53X3ZP1mVzfdmeNH6SAF4eH3OW8D2WZZHV62fHaU4Od2X38ETE%0AkfA9G0OMxOxZnyfrN+X66rHs757I+sSczfZaX4fL9nEAAAAKuXXrVlTCN9Sm%0ADSqxqyd9bdsU/cvX9MdoNLrwqOtaPv30U3n8+LF88skn8vLLL8tvfvMbeeaZ%0AZ+TDDz/0zutb35ruvP7mb1x7duVGdUPkTi13nt2RK1d2ZfPBA9laM/ZdyJwG%0A9u/ekLNdd2RTjmTnyhU52tyWX28fydZEIvZIdq58Q2TzWdneXZMHTxLPwXGO%0AduTKFbMvvf2OrI3PwxjrH8ztAAAAZVVVFfzP/pg2bdETvCIyVbJXxFHh+61v%0APjn5b4mIev7/Ga+/JSKyJfLNrQttXfHt6vXrsnprXw6P1+X68qHsH8p54lSO%0AZd9M9p4d9CSoPN8/kcNdXpfN6ydya39fjrWk6/LqqpwcHsrx+mTi9vhYZH19%0AVQ6PxW51VVZlX46PRVbVgSfHcnyyKuurIiKrcn3TbH8oJycik1ndEzk8PJH1%0A69dJ9gIAADh8/vOfl//x8svjBK+IOJO9s/TXf91Uz5ty586mVDeuyJW1I5Ft%0ALRm6u3tW7WtN9gb2b27KpuzIr49ExhncZ7dka7OSnZ0j2VSD7O7ItmzKg2eP%0AZNvSjZrjWZHvrsjm2WBHP96Vo80tS7L3ybzkWdk0k7pHPz6rEt6ppHpSUry2%0A/eCsUhkAAABjeqWviEyV7BVxJHybC3BX5fr1Vbm1vyu7yyci61ql7vHx2TIL%0ArvUOfPttSdfldVlfvSWHhyeyqgY5PpRDWZXN5RNxL4e8KqurIvtaxvfk+FhO%0AVtftSzEcH8uxLMt1M6t7cizHsiqrh7fk1rGa0uaFimMAAIB5pyd9RaT1ZK+I%0AyMI/vivyi1+c3c2mHorttVoO7b33RP7bf/Mvh6aWdvj1dsHk57OytnYkR78W%0A0Ut2Nzc35caNHdndelL5u7Mrm1t3ZE1ueHvb3NqWtStqWQe1nIMl3Xu0I1ee%0ALEFxYe+vj+ToaFee3aqlvvOk7ZVvyM7XqfgFAKDLYr8krKvVsnB8advCP74r%0AC9/bkYWnqvM/1cP2+qsvysKCyMI/vScLTwU+FKvX5frqiZzIulwvlvxcluXl%0Ak7OErz6UqvIVkbOK22NZXQ8vr7C6vi7Lx8fj446PT2R11ZLuPTmU3f3js8rl%0AC/tO5OTkUE5Wb8rNmzfl5ua6yOG+HJ5c7AYAAHRHX78ADYW98MLFpK7+S435%0AWl/nN2T3htz49aZsyrZ8w/ttZ6nWZO1ZY9Pmlmyv7crOztGT6t5tseVtL3b1%0Addlc25XdXTmr1D3aVMW+Y2df4rYrmw9cS1CIyJo23tqWbG0eye6PS54zAAAo%0ALfTlZ13+ErS+0pd0UJW+ti9yi2X/0jbzm4jN9XvN1ykB7vG+7J+cVeTuH64W%0ArHhdlmWzq9V1WV/ePavyXT6UQ3lSIexazmHc1aqsLu+eLeuwrC/ncO5sLWCR%0A9c2b7i9sW14/P255XdZXD+Xw+ETWqfIFAKCzurjO7dDpa/aKdGNJh7FtY+ED%0A9T0WLj//eaDDXblx49ey/eCBbIlR8bq5KZs3duTHR1uyZquA3dyUzRs3ZGd3%0Ay7KG745sHz0rdy4ctyZbW5uyvfNj2Xl2V9Y2bWv22qzJ1zfXZHt3V47WLi7n%0AsHujkhtyR+rakz1+do0vagMAAAiwfUGb7YvcUlgrfMdsAa5PMMA9lv39s3Vt%0Ar183Kl5XV2X15FiOXRWwq6uyenJoX3v3+FAOTywJX1mW9fVVOTk+lsPjY1le%0AXY1cT3dZVleX5fj4+MlyDqsTFbzH+7dk92Rdbt7c9CR7l1m7FwAAIMD8gjZ9%0AeYePP/643cm98ILISy/Ftd3envxCY6sj2blyQ3Y3t84SvGtb8g/bItvf2JGz%0AmtdN2doW2b5yRSYKf3dvyJWdoyf712T3hrF/vKyC7QvV5CxRfLQt27ubspWw%0AlsLa1zdlbXdHvrErsq2XBR/tyM7u2VrEF09xR65UT+a39vXJKuajHdnZXZPN%0Ar5MGBgAAELEne0Um1/TNqfR1J3yLB7gncri7L8er62dJ0uV1Ocv5HspZjndV%0A1tdFDnd3J5c9ON6X3cOTJ/uX5Xjf2O9bVkFESxSvJlXWLq+uyvLxoew/+ZI3%0AfbzD47O1iC+e4qHs3noyv2VVxXyiHXeWSAYAAMDFZK/SmaTvu+9erOb9X//L%0A3V7dBeewe+OKbB9NJkrXtv5BtmVbrtzYffL6gdR3npXtK5VU1ZPH7uZ4rd+1%0A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%0Annz3u9+Vp59+erqJ2yp7VcVvgX+nzP/AD20v1b+vne0Yc5uvvf6fsiXOAQAA%0ATE+/w8qWcEz5z3izrZ4YtVUJpyx9EFq6zDW2yRw3l2/u5j7fubnmb7s+se/F%0A4uKibG1tyc7OjoiIvPTSSyJyluzd29uTra0tWVxcHLdfEHGvD2bbp4sJ7EoG%0AlL6xXFWFrmNsFbNmlWhsXy5NJrG6HlS73j9l2vnbqoDNvmP69/VTov00Cf5Q%0ANXZKH9NcZ9/1bOs/BADAxxfgNj2uSJkA0ddP7Hq+bXIF3Oa5xf7CoQe4dV2P%0AA9y9vT3Z39+XV199VZ5++mkZjUbTTVwld1PaJ3V/Hu+GnqdK6ceM02x3tunP%0AVRvff/TybzkAAPOli0seiJSZV0qcOktm0ldErMleEW1Jh9Dt9C4pCTLztW2p%0ABFuAGcPWNjTv2FvFXUs6tKkPQbXvmqW8tz6uXzxS36/UX1Ri2+tzsf0ds7W3%0A/UKV2o953DQJY5ZQAIA0pZKvoS/dmGZc83azNsXeeqcC3P39/XElg0r2mgHu%0AVMykr6rubfDfQPVvfxfosYhtX2pfAACgrC7Eb12We336cl1VTLy3t+dM9oo8%0AqfANVWPalPqffFdw26UAMSe4nUXQ3peKiqbm6Ur2luinZPtUXX8/AaBNXfyf%0AdpGy6+rO4lt/Y255Sxkj1Na13/ZNyD6Li4vy2muvyeuvvy51Xcurr74qly9f%0AjppjI2xLQGTo0r/9ZoUvAABol/mf+vqX7ZrbfctqheI6s41eIBCz3ZyDLd50%0A7fONEdM+tCyaydXedp1dc4lhHpM6TxeV9FXPbcZr+KbeSpaSxPO1nXWAO8sE%0AaZeC91y512va6xw63rW/6eRt05+fJm7rBIA+Kxng5gStsYGs3o++PSdAjOnH%0AN3dXG9+aZ7bnPq73xbemmq196rgi50nfuq7l8uXLZf69U4lNfa1eW7Izcy1f%0A844y/blt+STbsk6+7eb+lPhc7891p5vZxneOtrv5AADAdGK/fNhMgobaxPYV%0Asz21n5wxcvqKbZ97vqnzKVW8ErrDzbqGr+IL+PT9uYGcL8CNTei51u519WUb%0AM2e7PnbsNSgxH98vDCXm38T1Cc2/RP9qn6+9S2o/JcaNOd+cX9ZirptLyudB%0AP8a2bdp+Sp4XgP4rFeCWDBybChCnDXpLBuAhoYpd83XJAH1xcXH8728RZj+2%0A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%0A0lX/U+1r+zz0ql3bkhSl1hN1jZF6/r65xm5X28x9rqScrb3ruWvc3IRfaFkQ%0AV0V1qH3smLnj+ubjm0vs+YbmGXNu05yXrw/bXF1zS3lfAAAAAAAAbFqv8J03%0AdV1bE0VduuXcNUeX0O3mVVWNH/oxJdjmquYSu11PvruuhS1Zp283l5awJfJt%0Ayc6Ua23rO9R/7HxCbNchZVxfYt/3uYk9X988XXKup+t56ufKJfV9AQAAAAAA%0AMJHw7YAuVPbauBLT+p+x/eh/+vrvEjW/nHOdtp+ccVLapczHN3/X9tKfZ1tS%0A1pbszb3OXfz7BwAAAAAAkIOE74y4klBtJnttY4eSZbHVil1P5sYqUXHpqiSd%0AxrTXNqUSVm8/TUVtqBLcJ3Zc3zx916ztz2po/K7+pxAAAAAAAOieBd9tyCm3%0A4Of24/o2+rb6iT0vH70KNmbclLVHzSUKYuZkm09Me71vV3Wn63jfrf7mXFzP%0AY89J7189T9lu9uk7Z1d73zU233vzfF3zMaWcV8p8Yj8/vvmYr1MSlK5jYs5X%0A35eatE39nNjeR/256zNs6yv255UPSWAAAAAAAGCzIOJOLqQmE3L6cd0C31Y/%0ATbZPmWOpubiOcSWLYufueh3bLva1S0yiftrtKZ+30vOZtp/c+aS2LTFu6t/r%0AnH7UfluiddpxfftLzD/17yoAAAAAAJhvLOkwp0gWtStnLWRMr4+f+z7OGQAA%0AAAAAtGeh7QkA84gkHgAAAAAAAJpAhS8AAAAAAAAADAQJXwAAAAAAAAAYCJZ0%0AAAAAAAAAAFp07969tqfQedeuXRs/53r5kfAFAACtI2ALI8A9o6+DX9f1+PVo%0ANBq/Ho1GcvXq1bamCAAAkGVjY6PtKXTWwcHBhW1cLzcSvhirqmrwXybWl3Ps%0AyzyHpqoqEWnuS/VU/02OAfQZAZsbAe459fNTJXf1hK9K+tquFwAAADAvFkTc%0ASYjU5MS89RM6xmxbYj5625Q5hRKI+n5zDHOutnZ1XVvPw9cmdu6u+ZpIoMXJ%0ATTpOm4QOfT58+5r6e2E7xtZXqc+t77xdSiSJc65zqZ+fAAAAAABgti6pJI56%0AqF/mXdtd5q2f0DFNzUevZNGfp87H19asmPHNxbdd78vcl3I9XWOkXgffnHPn%0A0ZQmK0xTP8/quKbG1bfbPjux89Q/D6WV+tymyn2/bFKuc6mfVwAAAACA5q2s%0A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%0AXGcAAAAAADDvFkQmkyR1XY+fu7a7zFs/JdrbElSxY/ja6fvNMcxrYWtX17X1%0APHxtYufumq8pt695k/r51I+b5hr7xlX7bP3njDvtXJuUe/1t/XT1HKc15HMD%0AAAAAgJKuXbuWfMy9e/camEm/NHndlpaW5PT0NLn/0HE5/cYes2D+Iq5eu7a7%0AzFs/pdrridTYhEhKFaNtPr65+BKvtuSweU1zEzu5x7vadi3B1NRcUj9verum%0AxvV9HnLGtZ2T6zxn/Z7nXn8b288nYB4R4OaZpwD35OQkeS4AAAB9cnBwEN12%0AY2OjwZn0SxPXLSZmXVpaGj/PjZtNOf3oFqY6uoBSCY55SpS4ErOK71rkVlya%0AbVKS0/PyviD/cxLb36y0NS5JX+AMAW4eAlwAAAAoZoyl4itf7OU6Zt6Y1yEU%0Ar5YojtCf6+PZxrZtM/toPeFbKrHRlQSJaymEtujzcVVJllj31DVGiYSfqz/f%0Aefn2TzOGWdkceh6aR2jZkWmXyHDNx/W+h65p6Bx87VM/b67Ep+v9dY2piz2v%0AWXxuXWPFJn1t/fjed/OYlO0x8y+1vAtQCgFuvq4HuMvLy9Y+/+3f/i15HgAA%0AAEN1eno6EXPpz/V9Kt4y4zNXUnFehO5UC9Gva0yfMfNIuUOu9YTv0JS8xbvE%0A+CLpyyXoCSdfMk/vu1Ti2DcXNXZozJwqyVDls3qu+rZVsrqSZr7raEuWlVoi%0AwzYfX38xyzKY18E2lq19yb8Hrv5iPg+xS0+UnmfpymdXPynvS+r2mPmT5EWX%0AEOBOp8sBrh4HmA8AAAD4mTGZK0ab1+KHVK7iCNvvI75jQjG2qy99TB0J3zli%0ASzzp1ZKxvyiFEm59+4UrVAXtOqb0HGLGTe3Ttf6t/jwmae9KpLrGDfUR8zmZ%0Axeepif+kCPF93kTS/2PG1U/o2JjtvgS62d43n779TMCwEeCW1UaAa6vw/fd/%0A//ekeQMAAMwLFWeF4lu9GIJYOL4AxFZgEupXv9Y5fcRU/ZLwHRBXcs+XbHHd%0Ajm1r18dkbqzUSkZXH7nXqIkKUFt1qa/63FXpaZtPanVsbtV705+7tj7PrmuX%0AW5meepxvuYyUSl5X+yH/rED/EODm6XKAq760ra5r+dznPicff/wxP3MAAAAc%0AzNgr1FYk/0t7hyTljreU62W28y2n5qvoDY274Lr123eLuk1uP7G3xs+qn9jz%0AKtXerHpMOSY2qeK6td/XztyubpU052ibS86t8q7r4Os/dB1Sr6fJ9l7mVES7%0AjomplAzN39XWPKeYym6zL9v7rtrlzr1kRXnMZzGmX9tcS/ThEvp7Fiv2c+v7%0A+2u2j3kvU6rAzTkAbSDAzdOHAPdzn/uc/Md//Ac/XwAAAALMu69Kt8eZnGsW%0Aqta1LUVn7rf1tSBSbj3GnH5s+9rsZ9btc35JianMC/Vvbne9jm0X+9olZ56p%0An4ectqnnk/Ie+PZNO//QdUodt8m/pzFi3gffttjPc848U8edxc+lEu+va/ss%0A33egFALc2WgjwP2DP/iD8XO+tA0AACAf8e+k2KIR13eF5I7n+3Jj87W3wjd5%0ABugkEioAAOQjwJ3U5QBXxTzLy8vjCl/1AAAAwBlbfJXyxcXzHhun3vFmaxN7%0ADfX3pVTxCQlfAAAwOAS40+l7gAsAADDvfJWhtliL+CvPtNfNFvuWiIlJ+AIA%0AgMEhwJ2Nrga4AAAAwDRi73hzHWt+H4Urtk3dHjs/Er4AAACY0PUAd3l5OXt+%0AAAAAXbexsdH2FHqp1HWbtvAgVGzi2u4b11fQYkPCFwAAdAoBbp55CnBPTk5Y%0AtxcAAAzSvXv32p5CL3HdJpHwBQAAnUGglofrBgAAAEC51PYE0B1VVbU9hcb1%0A5Rz7Ms++4zoDAAAAAIChWRCZTHrot8a5trvMWz+hY2xtVV+ufaH+bQmq2HPw%0AtdP3m2OY187Wrq5r63XytYmdu2u+Jm7rjJPzeVbHTXONQ58P377Ucaeda5Om%0AOS+zn66e47SGfG4AAAAAADRtwfzFWr12bXeZt358XFWDZrLUlYT2cR2fM5/Q%0AHEPH2hK4rjnqiW7fdYiVe7yrbdcSTE3NJefzrNo1NW7Mf36kft7Ntq7jZ/2e%0AT3NeJtvPMwAAAAAAgNaXdCh1S3WXbs2OSWDNMkkTk6B2tfFVKaf02URyGjC1%0AlQBt63Pr+k8XAAAAAAAwv1r/0rZSyZm+VLnZlnTQq4/bps/DVSVZYp6uMaZ9%0AH0PLUdjGUNt9y23kjmFWNoeeh+YRWqZk2iUyXPNxve+haxrzHwa2c3ItERI6%0AB994Mdc5tORIm59b11ixlb62fnzvu3lMyvaY+Zda3gUAAAAAgO9///ttTyHK%0Ad77znZmM03rCd57YljJo+5Zs2/ipyyXo5+FLCup9N5Xg9i0Z4VuCosTSELZx%0AVd+2imdX0sx3HW3JslJLZNjm4+vPNa7vOvjG0tvPYumDmM9DzDmW4hpX7Ss1%0Ahm1M87lI/OfNtT1m/iR5gXIIcAEAADDvvve977U9Ba/vfve7MxuLhO8M+RJn%0A+vOuJEFciTf1Z+w8Qwm3rpxvrFAVtOuY0nOIGTe1T9f6t/rzmKS9K5Easy3X%0ALD5PbVTh+z5vIun/MePqJ3RszHZfAt1s75tP334mAF1BgAsAAABAhIRv60pV%0AMeZwJfd8c3Ddjm1r18dkbqzUSkZXH7nXqIkKUFt1qe/z6ar0tM1nVpWyTX/u%0A2vo8u65XbmV66nG+5TJSKnld7Yf8swIAAAAAUly7di35mHv37mWNtbS0JKen%0Ap9bXS0tLzuNOT08n9rte631jthZct1f7bru2ye0n9lb3WfUTe14+tirYmPnb%0AzsPVt/48NKfUqlzXrf2+duZ22238rrnkJABd18HXf+g6pF5Pk+09zqmIdh0T%0AUykZmr+rrXlOMZXdriUAbGOkzj3n753Zp+vvmO+zGNOvbU4l+nAJ/T2LFfu5%0A9f39NdvHvJcpVeDmHDCfCHABAAAw7w4ODqLbbmxsWLeb8WxMbKrHsa72MXGw%0A2Z64ePYWRMqtr5jTj21fm/002T51/iXm4jrGlVCJnbvrdWy72NcuOfMscf1T%0A+4n5D4Vp+o8dJ2XMEn+XmuojVsz74NsW+3kObY9t6xt3Fj/HSr03Tf48x3wh%0AwAUAAACmF1PM4Dompl0oFk7prwmhZStthW6x27vuUtsTQDv69CEFACCHL3Hr%0AOya2XR8CXNs29ZhmOwAAANrz0Ucfyde+9jX5+c9/nnTc0tLSxENt0/fb2unt%0A9bauu+XM8drgioXVHa22u7Jjt/cBa/gCAIBe+eijj+TmzZvy7W9/O+k4W7Bp%0ALuPgStyKiDWg1YNi81j1vI2kry/ANV+nbgcAAEB7VCz8xS9+Ua5evZp0rC0h%0A64pVbW3N/frx+us242Clbwna0kj4AgCA3iDAjTPvAS4AAMAQ6bHwX/3VX8ln%0APvMZb/smq2ttFcLqta0wArPFkg4AAKAXcgLcpoJc2+1u6rVZCQwAAACk+PnP%0Afy5f+9rX5KOPPhpvS42FRexLnMXGp77lHFTf5hg5S6qhGSR8AQD4/9m7gxBZ%0AsjNRzKf6VT+mB4/6ijGIMTP0QliUxwZ7xs30bS8aQa/MbAq8mtVcMDQ2hodm%0A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%0AFwAAAABgJSR8AQAAAABWQsIXgEXqfozvkBxizAAAAKyLhC+3JCqY08nJyd7O%0AwW5bue3tOo5Df63tI/6Tk5OD/DG+zWZz8M8vAAAAh+00hLsf3vsfsHPLc46t%0An6F1Um27vnKPDfWfSiTU7kOpXf/xeBvxsUu1i5McNW1qY8/FO0U/LMc+E2W5%0Acx1qjfl/AQAAAPbhNE4Edvdzy3OOrZ+SUtVgP9GUS0KX5NYfE89QjEPr5hJ0%0AqRj7ie7Scag1VT+d1vUPtfqwc+jx79pUxyZ3nA/92O86/rnOz9rtDv2/kPq/%0ABgAAAPZl9ikdpqqwW1KlXk317j4TATUJ6lybUpVyS5+7SE4D7IP3JQAAAA7J%0A6dwBTJX4PJRKqtSUDv3q47n144iP6ZRx5rbR+jyWYq1d3i2LH8tNG5Fqn7ud%0A2+6YKSlS6+T6LU2fkdvfqeIc00/rOdX6XOW2W9N3Ls7ScesvKz1HQ9ue6jwZ%0A6r90Do+Jf2i7U+zbNvtV6iMV66H8/wIAAAAhLKDC95h0CdN+4mHuy35T249j%0AHDJ0+fLJyf0fyJoy0R/HmjrOpeVdLN1jqf5TyZ/+8nhqiVRCP5U8G3OsU9uN%0A27TGX3t8Wqq7a/c3dcym6n/McS6dx6k4W8+rmv6nPk+G+o/3LfU6aIl/aL9K%0Acea09J+Lt3Q8S+8DAAAAcEhmr/A9JqVESf/2UpINqUTumER1LiE8lCieWy6B%0ANLROqZ99xjMm/qnj3IVd918bQ//23PH0lZ73XJxTvwZrtjvm/Mz1DwAAALwg%0A4TuzVAXevqS2NxRDvyKwZOnJ3FpxBeQY/XW3TQym4iklzlrjn+L5mnJ/5+h/%0ATAxzxxPLPe8tz+82r+Ha7ZbiHLpqYMnvLUuPDwAAgHU7rb18e+jD69h+ch/0%0A5+qndr9KUlWwNfGn9iPXd//2UEytVbmpOFOJrFxya+jS8TiW3O3afer3391u%0AWR73WZu8S80NWqpk7q8Xb6P1eYmlqkxb4k/1MTZhldrf/u34uS4dn9r+h45n%0A6bmtOUfj7Zbea3JV8WP6H3q9pJSqeOPnd0zF/rbHZ2xyvPV13Xoexu1KX8aN%0A/X9BEhgAAIB9OA1huPqq1ph+Uo/N2c8u27fGP0UsuXVyyYfa2HP3a9vV3s+p%0ASdRvu7zl+Zo6nta2uUTztvHEz+uunp9dv8amODZTbLe1/zHHadfn7VTHp2bb%0A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%0A+4naOHGbS+J2idfNZnP7191vkWofLxvbd40HDx7spG1qndT68bKh+2O09lkT%0A57bbGbuNFtv2N3U8AMCyKYAAAODQDFb4xonb/v24bfdvf2BbGgznksq5gXGp%0A3dRVDQ8ePLjzl2uTatuS5Ly5ubn3eLysf//Bgwfh5uZm1D5toybOqXX7OkWS%0Atv+8pG7Hz1vN8w8ArJsCiOnbptZRALH9NloogACA9Rucw7d0P9c+nl83XtY6%0A/26/j13P3RsnVHMJ1n4ysqZ9Sap9vKy7P0eyN44hJ3cscoPcrm084I+Pa+o4%0Aj4071U8qjtJyAOB4DP2ORKptqho3pXasnfp9i5p4t5UbG6XapMZLtWPk1Fiv%0ANB6cuwCiFOfUptrn0ni8dgw85+cQAKBNMeFbO8DNJXr7CdpUm1qpy9p2oSV5%0AGw8+4+Wpvkv3c+sPVQdvK1ddUeo7HnwP6Q8ac8nt/mOpRPG2A93UfrYm6lMf%0AaAx8AWDdFEAogEjFkKMAAgBYgkkqfGsGmaU2qX5T7Wt+wGLMgDf+hjuXgCyt%0AV1o2NrF4c3Oz9eC51H9uH0vJ6drtt14G2D/mucH8NvvemnTu2pbaGPgCwPop%0AgFAAkVtHAcSLuACAZckmfFOXjrUmbYeSsV2fQ5fHjY2pVumyrNTApzRAipOB%0AYwZAqSqAKbUOFlP7VPow0B+gDg3s475Ll46NHeAOVVTkSOwCAAogFEDE9xVA%0AKIAAgKVLJnxzA9nSQHSbZGw/6Vu7Xmv7GrlLq+IBXsu3+KXtDLVPtdvFXFq5%0A7UxxydjQwDLVJq5o2HZgP+aDCgCAAggFEP32ISiAAAAOQzLhm6smqJlbrHbd%0AeNmYZG/rejk1lzQNfdudWpYaGNd8cz60/pRSl4t12x5K0ub2p7StuI9cm6kH%0AlaXns/ayQwDgeCiAUAChAAIAOFTFOXxblAaa8UA0V8HQn5us9GvG8WPbDnRz%0Al6CVEprbJGPHJktbKxFqY2nVr96ojSdXFRLfTg1wt5VLIsfLc8+xxC8AHB8F%0AEAogFEAYBwPAoZok4VtzCVp/IFr64YrUY/3qhVz/qTjGaBlUlr4hH+pnTLK3%0Adb1apXm8Sm1bBrily99SidUpB5dDl9yVtjeUFAYA6CiAUADRsh0FEADArlQn%0AfEuDx9SAc5t28WO5y+R2pSa5V/ttf6ptPIgubSs3uN5FdUON1D7VxNM6WKw5%0A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%0AuK1CmKhNv/z8/DycX1+GR/1XdSIJcdUb7V5fPgqX3WDq+fr91+9VzXw0pfXu%0APXb/zfz84uJZnFfhxaA9sV8vVrsKl5fX1fu7F9epSeafvwnd2ZeLcBGib6eC%0AS9Xm82yeoKvL52/iO5jD9+rRo3DdfZERnSfXl5fh6myG83WRzsPFRQiXD6Pj%0AX3PpUOn1Fyq+ad/2dXn1KDx4dP3iw/RAPHdF5+Ac8Y459vf62EPcW2kb4N67%0AhK1lS40VDS3H5d77yYOH4fK6mwvubkL77OJJuHnyODzOPnYRzu7MMZ97fyr1%0Ar/Kuxi9+8Yvwi1/8YrL+FEAogKjciWUXQAy4uryc6DgwZJsCiKtHD8LD64vE%0AF62MMncBxLb2XQAxZbz7LICYiAKIOysrgFioSaZ0OP3Pz8Iv//BB+A/+5//h%0AzvJ//R/9Z1N03+zs+eTO3bf3z+6HO1UIU7V54Tw8vnkczvpvMo/C3cn0Qwjn%0A4ar3xnMWHt9OGP5s4v3r3ofVq/Oay3JK6/Uv5Xh+uUb8Vf3ZeTgPzysfMgmR%0Au/1fhbOLs+r93Yuzi/D47PLO3GnhcWrg86zC4nZf5oqXW2cXj8NFaP1V2JJ+%0Adc+DcHn25MWHveg8eXh55vnvObt48vwXWf//9s6mtXEjjON/LSlbSiz7A/TY%0AZae0sLAnU0pvPYQEZyj0lEP8AXLJTR9BHyAfQB9Beb30XtQeTA+FetmFHnIs%0AGDmHhSW21IPeXy3Jkh1v/j8wycjSzKPRzGj0+D+PYhMkU65+WK7c/wozqN0v%0AE049XWR+Fa5jT/022LK9qFb3q/Lowu6Ck1mhZshTNORPcIVm5bavzBK2GqRf%0AihHlX+R8KauXkvGkbTg+tcLV1RWur6/D9O3tLW5ublotgwIICiD83HdXALES%0AE6aZo94mHdFQADHVoZvesx5piy0KINZl0wKItu3dlABiq1AAQQHE5tmre0Cd%0A+GOv/v4dzuIRL/a+qFvMeggNlq0Vp9vaJ3OM91BbijRgGxXtTuQb720CmmVV%0AOM4vL2WSltjV6zzJTRXqJrSr6HzTNq9Kr4fQLOSaWPlcSPd4bS1vW3BF8q6N%0ANOziN8pmvstpz/Fvi9oJ8cgZL1I75Pbbteu1cr8sv76r7VndBivRsr0ASuq+%0AgX2F5rQw/q1sI4DnKNWzm82xP+mUMAx4k7rgV3lpwPD/hnc3aSBobtELLfzz%0AyF0RZiFxew3LQ1RmHoX1UlL3JXVZecxK5VG1H5XlTzxUVQ2do4qiQFVVzGaz%0AzsvdOxD4CODb1Pb33/+AN52XnkVICeg6pBYTLuhmVtzQwj4RniBgPBhioMe3%0A5Qkgxolj4gKI4XCA4IlDGjaKum+i3MLjPKfYYBx854dUiD8DCwmJIXRhwC4R%0AQET5ezYDotL5bgShwRDDWL16daAJoJb8aTrFFIIroDaI0Axo5hDDsag+n5pO%0AMfUdSHGkwdAO6yA0C7YYYzAcIOrSBmyjigCioP91hDmOxjtvTmFE405NexJt%0AsKMGVGovVtX9tFIeGyMxxyxDxu5f8XudF492Cl8AASA9UIfCCHOMQU2fb/E4%0AUC6ASN7j4gKIyBFfJNhohUy73dL9dMcJflSXUkKxbdutc3Dc4ev89gEvfv4m%0As8/712/x6t0EAPDv16/x3dUf69hbimmayThcTxavo0w13oSbcHFxgfPzczw+%0APm7bFFICr9NuwOtEymD7IE8d13XDv+nP/v4+HMeBbdtwHAe9Xg/L5RKz2QyL%0AxQInJye4v7+HqqqYTCaNbaj7ArYv//yvUwEE58PPA47PuwGv027A60TKWL99%0AeAIIYRmQMDEemJB+aI1QAGEbkCkBRJnDPSOAsGKKbl3kh3tICyBsvtzxcydw%0A+J6entZX+H41sfHx7QD7f83hOC7gp+PfvwGw+PQJ7379qVNnLyGEEEIIIQEP%0ADw9wHCeRXi6XnZZZRQDxzy8/ck5MCCGEPBsENCvQ98ZWSaZXy9VYgVe6qrlo%0AKUyl1Xnkc0JKiX6/D6BBSAfAc+o6TrkweO/lS05sE+QtJSaEEEIIIU24vLyE%0A67oYjUYAvBi+ruvi6OgIiqLg7u4OjuPg4OAAihK9VC3+f1MogCCEEEIIIU+R%0A+XwOoKHDN826L6EghBBCCCGkCf1+P/FCs3gM3yDdRQxfCiCaQAEEIYQQQkhb%0AxGP2ptOtOHy3yW7EKyOEEEIIIW1yfHwMVVXDmL6j0Qi9Xi8M6XB4eBimFUUJ%0AP11BAQQhhBBCCNkG/X4/VPYG6Z13+JLnwdnZGQPq7wC8TrsBrxMpg+2D7BLz%0A+Tx0+AJezF7XdUPnbhDTt2tn77ahAIIQQggh5PkRj9mbTv8PvEGRTDRKy7UA%0AAAAASUVORK5CYII=) + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)**http://www.hihope.org/** + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/uart_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/uart_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..deeec88f31fc553617caa73fa230ba5d4e2ebddc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/11_uart/uart_demo.c" @@ -0,0 +1,78 @@ +#include +#include +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_uart.h" +#include "wifiiot_uart_ex.h" + + +unsigned char uartWriteBuff[] = "hello uart!"; +unsigned char uartReadBuff[2048] = {0}; +int usr_uart_config(void) +{ + int ret; + + //初始化UART配置,115200,数据bit为8,停止位1,奇偶校验为NONE,流控为NONE + WifiIotUartAttribute g_uart_cfg = {115200, 8, 1, WIFI_IOT_UART_PARITY_NONE, 0}; + ret = UartInit(WIFI_IOT_UART_IDX_2, &g_uart_cfg,NULL); + + if (ret != 0) + { + printf("uart init fail\r\n"); + } + return ret; +} + + +//1.任务处理函数 +static void* UartDemo_Task(const char* arg) +{ + unsigned int len = 0; + + (void)arg; + printf("[UartDemo] UartDemo_Task()\n"); + + GpioInit();//使用GPIO,都需要调用该接口 + + printf("UART init...\r\n"); + usr_uart_config(); + + UartWrite(WIFI_IOT_UART_IDX_2, (unsigned char *)uartWriteBuff, sizeof(uartWriteBuff)); + while(1) + { + + len = UartRead(WIFI_IOT_UART_IDX_2, uartReadBuff, sizeof(uartReadBuff)); + if (len > 0) { + printf("Uart read data:%s", uartReadBuff); + } + usleep(100000); + } + + return NULL; +} + +//2.任务入口函数 +static void UartDemo_Entry(void) +{ + osThreadAttr_t attr = {0}; + + printf("[UartDemo] UartDemo_Entry()\n"); + + attr.name = "UartDemo_Task"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024;//堆栈大小 + attr.priority = osPriorityNormal;//优先级 + + if (osThreadNew((osThreadFunc_t)UartDemo_Task, NULL, &attr) == NULL) + { + printf("[UartDemo] Falied to create UartDemo_Task!\n"); + } +} + +//3.注册模块 +SYS_RUN(UartDemo_Entry); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..c2235f1a49735b0c411b48c0acc1fd5e93db2af2 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/BUILD.gn" @@ -0,0 +1,36 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") + +lite_component("app") { + features = [ + "ssd1306:oled_ssd1306", + "examples:oled_test", + "libm_port:libm_port" + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..a696398ed6feac830485be9d66e5ee05c6446e0c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/README.md" @@ -0,0 +1,116 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--OpenHarmony-ssd1306 + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + + + +## 一、I2C API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ------------------------------- | +| I2cInit (WifiIotI2cIdx id, unsigned int baudrate) | 用指定的波特速率初始化I2C设备 | +| I2cDeinit (WifiIotI2cIdx id) | 取消初始化I2C设备 | +| I2cWrite (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 将数据写入I2C设备 | +| I2cRead (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 从I2C设备中读取数据 | +| I2cWriteread (WifiIotI2cIdx id, unsigned short deviceAddr, const WifiIotI2cData *i2cData) | 向I2C设备发送数据并接收数据响应 | +| I2cRegisterResetBusFunc (WifiIotI2cIdx id, WifiIotI2cFunc pfn) | 注册I2C设备回调 | +| I2cSetBaudrate (WifiIotI2cIdx id, unsigned int baudrate) | 设置I2C设备的波特率 | + +## 二、ssd1306 API + +本样例提供了一个OpenHarmony IoT硬件接口的SSD1306 OLED屏驱动库,其功能如下: + +* 内置了128*64 bit的内存缓冲区,支持全屏刷新; +* 优化了屏幕刷新速率,实测最大帧率10fps; +* `libm_port`是从musl libc中抽取的`sin`和`cos`的实现; + * 用于规避链接Hi3861 SDK中的libm_flash.a报错的问题; +* `gif2imgs.py` 可用于将gif动图中的帧分离出来; + * 依赖 pillow 包,可以使用 `pip install pillow` 命令安装; +* `img2code.py` 可用于将图片转为C数组,每个字节表示8个像素; + * 依赖 opecv-python 包,可以使用 `pip install opencv-python` 命令安装; + +* 使用OpenHarmony的IoT硬件接口; +* 接口简洁易于使用、易于移植; +* 内置了测试程序,可直接进行测试; + +| API名称 | 说明 | +| ------------------------------------------------------------ | -------------------------- | +| void ssd1306_Init(void) | 初始化 | +| void ssd1306_Fill(SSD1306_COLOR color) | 以指定的颜色填充屏幕 | +| void ssd1306_SetCursor(uint8_t x, uint8_t y) | 定位光标 | +| void ssd1306_UpdateScreen(void) | 更新屏幕内容 | +| char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color) | 在屏幕缓冲区绘制1个字符 | +| char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color) | 将完整字符串写入屏幕缓冲区 | +| void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) | 在屏幕缓冲区中绘制一个像素 | +| void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) | 用Bresenhem算法画直线 | +| void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) | 绘制多段线 | +| void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) | 绘制矩形 | +| void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) | 绘图角度 | +| void ssd1306_DrawCircle(uint8_t par_x, uint8_t par_y, uint8_t par_r, SSD1306_COLOR color) | 用Bresenhem算法画圆 | +| void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size) | 绘图位图 | +| void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride) | 绘制区域 | + +## 三、如何编译 + +1. 将此目录复制到openharmony源码的根目录下 + +2. 修改openharmony源码的`build/lite/product/wifiiot.json`文件: + + 将`//applications/sample/wifi-iot/app`替换为`//12_ssd1306:app`保存; + +3. 在openharmony源码目录下执行:`python build.py wifiiot` + + +## 四、编译错误解决 + +本项目代码使用了鸿蒙IoT硬件子系统的I2C API接口,需要连接到hi3861的I2C相关接口;默认情况下,Hi3861的I2C编译配置没有打开,编译时会有如下错误: + +```txt +riscv32-unknown-elf-ld: ohos/libs/libhal_iothardware.a(hal_wifiiot_i2c.o): in function `.L0 ': +hal_wifiiot_i2c.c:(.text.HalI2cWrite+0x12): undefined reference to `hi_i2c_write' +riscv32-unknown-elf-ld: hal_wifiiot_i2c.c:(.text.HalI2cInit+0x12): undefined reference to `hi_i2c_init' +scons: *** [output/bin/Hi3861_wifiiot_app.out] Error 1 +BUILD FAILED!!!! +``` + +**解决方法** + +需要修改vendor\hisi\hi3861\hi3861\build\config\usr_config.mk文件: +`# CONFIG_I2C_SUPPORT is not set`行,修改为:`CONFIG_I2C_SUPPORT=y` + +## 五、效果演示 + +1. 播放gif:https://www.bilibili.com/video/BV1Af4y1B7TD/ + * 使用本项目中的转换脚本将gif每一帧画面提取出来,转成bitmap数组,程序里循环播放 +2. 播放视频:https://www.bilibili.com/video/BV1DK4y1f7yw/ + * C/S架构,开发板作为客户端,PC作为服务端,使用TCP传输每帧画面(因为视频帧数较多,开发板闪存放不下) + * 播放项目源码: https://gitee.com/hihopeorg/harmonyos_oled_player + +## 六、参考链接 + +本项目是基于afiskon的stm32-ssd1306移植的,对部分细节做了修改和优化,原项目链接: + +* https://github.com/afiskon/stm32-ssd1306 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..a6aadc6b9d49b5d0b921f5c789d86e47180f6763 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("oled_test") { + sources = [ + "ssd1306_demo.c", + "ssd1306_tests.c", + ] + + include_dirs = [ + "../ssd1306", + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..9b09c404cac6f3d946dd4c1c2bf462a4f3787986 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_demo.c" @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_adc.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" +#include "wifiiot_watchdog.h" + +#include "ssd1306.h" +#include "ssd1306_tests.h" + +#define OLED_I2C_BAUDRATE 400*1000 + + + +const unsigned char headSize[] = { 64, 64 }; +const unsigned char headData[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x00, +0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00, +0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0xFF, 0x83, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE3, 0xF0, 0x18, 0x00, +0x00, 0x00, 0x01, 0xFF, 0xE3, 0xE0, 0x10, 0x00, 0x00, 0x00, 0x61, 0xFE, 0x03, 0xE1, 0xF8, 0x00, +0x00, 0xC1, 0xF1, 0xF8, 0x97, 0xE0, 0x18, 0x00, 0x00, 0x00, 0xB9, 0xFF, 0xFF, 0xF8, 0x88, 0x00, +0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFD, 0xF8, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFE, 0x78, 0x00, +0x00, 0x00, 0xCD, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x40, 0xDF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, +0x00, 0x40, 0xDF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x40, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, +0x00, 0xA0, 0x7F, 0xFF, 0xFF, 0xFF, 0xF9, 0x00, 0x01, 0x20, 0x3F, 0xFF, 0xFC, 0x47, 0xF8, 0x00, +0x02, 0x10, 0x1F, 0xFF, 0xFF, 0x87, 0xF0, 0x00, 0x0C, 0x18, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x08, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0D, 0x07, 0xFF, 0xFC, 0x07, 0xF0, 0x00, +0x00, 0x05, 0x07, 0xFF, 0xC0, 0x01, 0xF0, 0x00, 0x00, 0x05, 0x07, 0xFF, 0xDF, 0xE1, 0xE0, 0x00, +0x02, 0x06, 0x07, 0xFF, 0xFF, 0x09, 0xE0, 0x00, 0x00, 0x02, 0x07, 0xFF, 0xFE, 0x1F, 0xC0, 0x00, +0x00, 0x02, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x60, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x00, +0x00, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x32, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, +0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, +0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0xF0, 0x00, 0x00, +0x00, 0x07, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x01, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x07, +0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0xE0, 0x3F, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, +}; + +/** + * 汉字字模在线: https://www.23bei.com/tool-223.html + * 数据排列:从左到右从上到下 + * 取模方式:横向8位左高位 +**/ +void TestDrawChinese1(void) +{ + const uint32_t W = 16, H = 16; + uint8_t fonts[][32] = { + { + /*-- ID:0,字符:"你",ASCII编码:C4E3,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x11,0x00,0x11,0x00,0x11,0x00,0x23,0xFC,0x22,0x04,0x64,0x08,0xA8,0x40,0x20,0x40, + 0x21,0x50,0x21,0x48,0x22,0x4C,0x24,0x44,0x20,0x40,0x20,0x40,0x21,0x40,0x20,0x80, + },{ + /*-- ID:1,字符:"好",ASCII编码:BAC3,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x10,0x00,0x11,0xFC,0x10,0x04,0x10,0x08,0xFC,0x10,0x24,0x20,0x24,0x24,0x27,0xFE, + 0x24,0x20,0x44,0x20,0x28,0x20,0x10,0x20,0x28,0x20,0x44,0x20,0x84,0xA0,0x00,0x40, + },{ + /*-- ID:2,字符:"鸿",ASCII编码:BAE8,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x40,0x20,0x30,0x48,0x10,0xFC,0x02,0x88,0x9F,0xA8,0x64,0x88,0x24,0xA8,0x04,0x90, + 0x14,0x84,0x14,0xFE,0xE7,0x04,0x3C,0x24,0x29,0xF4,0x20,0x04,0x20,0x14,0x20,0x08, + },{ + /*-- ID:3,字符:"蒙",ASCII编码:C3C9,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x04,0x48,0x7F,0xFC,0x04,0x40,0x7F,0xFE,0x40,0x02,0x8F,0xE4,0x00,0x00,0x7F,0xFC, + 0x06,0x10,0x3B,0x30,0x05,0xC0,0x1A,0xA0,0x64,0x90,0x18,0x8E,0x62,0x84,0x01,0x00 + } + }; + + ssd1306_Fill(Black); + for (size_t i = 0; i < sizeof(fonts)/sizeof(fonts[0]); i++) { + ssd1306_DrawRegion(i * W, 0, W, H, fonts[i], sizeof(fonts[0]), W); + } + + ssd1306_SetCursor(64, 0); + ssd1306_DrawRegion(64, 0, headSize[0], headSize[1], headData, sizeof(headData), headSize[0]); + ssd1306_UpdateScreen(); +} + +void TestDrawChinese2(void) +{ + const uint32_t W = 12, H = 12, S = 16; + uint8_t fonts[][24] = { + { + /*-- ID:0,字符:"你",ASCII编码:C4E3,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x12,0x00,0x12,0x00,0x27,0xF0,0x24,0x20,0x69,0x40,0xA1,0x00,0x25,0x40,0x25,0x20, + 0x29,0x10,0x31,0x10,0x25,0x00,0x22,0x00, + },{ + /*-- ID:1,字符:"好",ASCII编码:BAC3,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x20,0x00,0x27,0xE0,0x20,0x40,0xF8,0x80,0x48,0x80,0x48,0xA0,0x57,0xF0,0x50,0x80, + 0x30,0x80,0x28,0x80,0x4A,0x80,0x81,0x00, + },{ + /*-- ID:2,字符:"鸿",ASCII编码:BAE8,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x00,0x40,0x80,0x80,0x5D,0xE0,0x09,0x20,0xC9,0xA0,0x09,0x60,0x29,0x00,0xCD,0xF0, + 0x58,0x10,0x43,0xD0,0x40,0x10,0x40,0x60, + },{ + /*-- ID:3,字符:"蒙",ASCII编码:C3C9,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x09,0x00,0x7F,0xE0,0x09,0x00,0x7F,0xF0,0x80,0x10,0x7F,0xE0,0x0C,0x40,0x32,0x80, + 0xC7,0x00,0x0A,0x80,0x32,0x70,0xC6,0x20 + } + }; + + ssd1306_Fill(Black); + for (size_t i = 0; i < sizeof(fonts)/sizeof(fonts[0]); i++) { + ssd1306_DrawRegion(i * H, 0, W, H, fonts[i], sizeof(fonts[0]), S); + } + + ssd1306_SetCursor(64, 0); + ssd1306_DrawRegion(64, 0, headSize[0], headSize[1], headData, sizeof(headData), headSize[0]); + + ssd1306_SetCursor(0, 64 - 8); + ssd1306_DrawString("gitee.com", Font_6x8, White); + + ssd1306_SetCursor(0, 64 - 8*2); + ssd1306_DrawString("@swxu", Font_6x8, White); + + ssd1306_UpdateScreen(); +} + +void TestShowChars(FontDef font, uint8_t w, uint8_t h) +{ + ssd1306_Fill(Black); + + uint8_t x = 0, y = 0; + for (uint8_t c = 1; c < 128; c++) { + if (isprint(c)) { + ssd1306_SetCursor(x, y); + ssd1306_DrawChar((char) c, font, White); + x += w; + if (x >= SSD1306_WIDTH) { + x = 0; + y += h; + } + } + } + + ssd1306_UpdateScreen(); +} + +void Ssd1306TestTask(void* arg) +{ + (void) arg; + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); + I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); + + WatchDogDisable(); + + usleep(20*1000); + ssd1306_Init(); + ssd1306_Fill(Black); + ssd1306_SetCursor(0, 0); + ssd1306_DrawString("Hello OpenHarmony!", Font_7x10, White); + + uint32_t start = HAL_GetTick(); + ssd1306_UpdateScreen(); + uint32_t end = HAL_GetTick(); + printf("ssd1306_UpdateScreen time cost: %d ms.\r\n", end - start); + + while (1) { + TestDrawChinese1(); + osDelay(500); + + TestDrawChinese2(); + osDelay(500); + + TestShowChars(Font_6x8, 6, 8); + osDelay(500); + + TestShowChars(Font_7x10, 7, 10); + osDelay(500); + + ssd1306_TestAll(); + } +} + +void Ssd1306TestDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "Ssd1306Task"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(Ssd1306TestTask, NULL, &attr) == NULL) { + printf("[Ssd1306TestDemo] Falied to create Ssd1306TestTask!\n"); + } +} +APP_FEATURE_INIT(Ssd1306TestDemo); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.c" new file mode 100755 index 0000000000000000000000000000000000000000..6d5331d6df6f0f5c17e4eb9ab11cbbb65fbd4d26 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.c" @@ -0,0 +1,231 @@ +#include +#include +#include "ssd1306.h" +#include "ssd1306_tests.h" + +void ssd1306_TestBorder() { + ssd1306_Fill(Black); + + uint32_t start = HAL_GetTick(); + uint32_t end = start; + uint8_t x = 0; + uint8_t y = 0; + do { + ssd1306_DrawPixel(x, y, Black); + + if((y == 0) && (x < 127)) + x++; + else if((x == 127) && (y < 63)) + y++; + else if((y == 63) && (x > 0)) + x--; + else + y--; + + ssd1306_DrawPixel(x, y, White); + ssd1306_UpdateScreen(); + + end = HAL_GetTick(); + } while((end - start) < 8000); + + HAL_Delay(1000); +} + +void ssd1306_TestFonts() { + ssd1306_Fill(Black); + ssd1306_SetCursor(2, 0); + ssd1306_DrawString("Font 16x26", Font_16x26, White); + ssd1306_SetCursor(2, 26); + ssd1306_DrawString("Font 11x18", Font_11x18, White); + ssd1306_SetCursor(2, 26+18); + ssd1306_DrawString("Font 7x10", Font_7x10, White); + ssd1306_SetCursor(2, 26+18+10); + ssd1306_DrawString("Font 6x8", Font_6x8, White); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestFPS() { + ssd1306_Fill(White); + + uint32_t start = HAL_GetTick(); + uint32_t end = start; + int fps = 0; + char message[] = "ABCDEFGHIJK"; + + ssd1306_SetCursor(2,0); + ssd1306_DrawString("Testing...", Font_11x18, Black); + + do { + ssd1306_SetCursor(2, 18); + ssd1306_DrawString(message, Font_11x18, Black); + ssd1306_UpdateScreen(); + + char ch = message[0]; + memmove(message, message+1, sizeof(message)-2); + message[sizeof(message)-2] = ch; + + fps++; + end = HAL_GetTick(); + } while((end - start) < 5000); + + HAL_Delay(1000); + + char buff[64]; + fps = (float)fps / ((end - start) / 1000.0); + snprintf(buff, sizeof(buff), "~%d FPS", fps); + + ssd1306_Fill(White); + ssd1306_SetCursor(2, 18); + ssd1306_DrawString(buff, Font_11x18, Black); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestLine() { + + ssd1306_DrawLine(1,1,SSD1306_WIDTH - 1,SSD1306_HEIGHT - 1,White); + ssd1306_DrawLine(SSD1306_WIDTH - 1,1,1,SSD1306_HEIGHT - 1,White); + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestRectangle() { + uint32_t delta; + + for(delta = 0; delta < 5; delta ++) { + ssd1306_DrawRectangle(1 + (5*delta),1 + (5*delta) ,SSD1306_WIDTH-1 - (5*delta),SSD1306_HEIGHT-1 - (5*delta),White); + } + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestCircle() { + uint32_t delta; + + for(delta = 0; delta < 5; delta ++) { + ssd1306_DrawCircle(20* delta+30, 30, 10, White); + } + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestArc() { + + ssd1306_DrawArc(30, 30, 30, 20, 270, White); + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestPolyline() { + SSD1306_VERTEX loc_vertex[] = + { + {35,40}, + {40,20}, + {45,28}, + {50,10}, + {45,16}, + {50,10}, + {53,16} + }; + + ssd1306_DrawPolyline(loc_vertex,sizeof(loc_vertex)/sizeof(loc_vertex[0]),White); + ssd1306_UpdateScreen(); + return; +} + +static const unsigned char bitmap[] = { +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xF8, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x7F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x7F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x3F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x03, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x87, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x07, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFC, 0x03, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFE, 0x07, 0xFC, 0x3E, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xF8, 0x0F, 0xFE, 0x7F, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xF0, 0xFF, 0xFE, 0x7F, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF8, 0xFF, 0xFC, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFC, 0xFF, 0x1B, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x7E, 0x37, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x81, 0xEF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +void ssd1306_TestBitmap(void) { + ssd1306_Fill(Black); + ssd1306_DrawBitmap(bitmap, sizeof(bitmap)); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestAll() { + ssd1306_Init(); + ssd1306_TestBitmap(); + HAL_Delay(2000); + ssd1306_TestFPS(); + HAL_Delay(1000); + ssd1306_TestBorder(); + ssd1306_TestFonts(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestRectangle(); + ssd1306_TestLine(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestPolyline(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestArc(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestCircle(); + HAL_Delay(3000); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.h" new file mode 100755 index 0000000000000000000000000000000000000000..e16002a3f56ec48b770300f0c14034a6cb59bb26 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/examples/ssd1306_tests.h" @@ -0,0 +1,22 @@ +#ifndef __SSD1306_TEST_H__ +#define __SSD1306_TEST_H__ + +#include <_ansi.h> + +_BEGIN_STD_C + +void ssd1306_TestBorder(void); +void ssd1306_TestFonts(void); +void ssd1306_TestFPS(void); +void ssd1306_TestAll(void); +void ssd1306_TestLine(void); +void ssd1306_TestRectangle(void); +void ssd1306_TestCircle(void); +void ssd1306_TestArc(void); +void ssd1306_TestPolyline(void); + + + +_END_STD_C + +#endif // __SSD1306_TEST_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/gif2imgs.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/gif2imgs.py" new file mode 100755 index 0000000000000000000000000000000000000000..17ed9cc8ba44c349e1f65367333cc1e7eda13773 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/gif2imgs.py" @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import os +import sys +from PIL import Image + +if len(sys.argv) < 2: + print('Usage: {} gif outdir'.format(sys.argv[0])) + exit(-1) + +gifimg = sys.argv[1] +outdir = sys.argv[2] + +im = Image.open(gifimg) +if not os.path.exists(outdir): + os.mkdir(outdir) + +i = 0 +try: + while True: + im.seek(i) + im.save(os.path.join(outdir, 'frame' + str(i) + '.png')) + i += 1 +except: + pass +print('images:', i) diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/img2code.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/img2code.py" new file mode 100755 index 0000000000000000000000000000000000000000..c79463d26c23a288eb79e60efef5f20c0e73599b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/img2code.py" @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import cv2 +import sys +import os +from datetime import datetime + +DEBUG = False +DEBUG = True +TARGET_WIDTH = 128 +TARGET_HEIGHT = 64 +PIXEL_PER_BYTE = 8 +WIDTH_BYTES = int(TARGET_WIDTH/PIXEL_PER_BYTE) +PIXEL_THRESHOLD = 128.0 + +# 将多个灰度像素打包到一个整数中 +def pack_pixels(pixels, threshold): + value = 0 + for gray in pixels: + bit = 1 if gray >= threshold else 0 # 二值化 + value = (value << 1) + bit # 多个二值化像素值拼接为一个字节值 + return value + +frameCount = 0 +def resize_and_binarize_image(frame, width, height, threshold): + data = [] + # count = 0 # for debug + start = datetime.now() + frame = cv2.resize(frame, (width, height)) # 缩放 + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 转为灰度图 + _, binary = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY) # 二值化 + + for r in range(height): + for b in range(int(width / PIXEL_PER_BYTE)): + colStart = b * PIXEL_PER_BYTE + pixels = frame[r, colStart: colStart + PIXEL_PER_BYTE] + byte = pack_pixels(pixels, threshold) + data.append(byte) + if DEBUG: + global frameCount + cv2.imwrite(os.path.join('debug', str(frameCount) + '.png'), frame) + cv2.imwrite(os.path.join('debug', str(frameCount) + '-bin.png'), binary) + frameCount += 1 + end = datetime.now() + print('time cost:', end - start) + return bytes(data) + +def convert_frame_to_bytes(frame): + return resize_and_binarize_image(frame, TARGET_WIDTH, TARGET_HEIGHT, PIXEL_THRESHOLD) + +def main(): + if len(sys.argv) < 3: + print("Usage: {} input outdir [width] [height] [threshod]".format(sys.argv[0])) + exit(-1) + + imgPath = sys.argv[1] + outdir = sys.argv[2] + width = len(sys.argv) > 3 and int(sys.argv[3]) or TARGET_WIDTH + height = len(sys.argv) > 4 and int(sys.argv[4]) or TARGET_HEIGHT + threshold = len(sys.argv) > 5 and int(sys.argv[5]) or PIXEL_THRESHOLD + imgFile = os.path.split(imgPath)[-1] + imgBase = imgFile.split('.')[-2] + codeFile = os.path.join(outdir, imgBase + '.c') + if not os.path.exists(outdir): + os.mkdir(outdir) + + frame = cv2.imread(imgPath) # 加载图片 + bitmap = resize_and_binarize_image(frame, width, height, threshold) # 转为目标格式的数组 + + with open(codeFile, 'w+') as f: # 输出到.c文件 + f.write('const unsigned char {}_size[] = {{ {}, {} }};\n'.format(imgBase, width, height)) + f.write('const unsigned char {}[] = {{\n'.format(imgBase)) + for i in range(len(bitmap)): + v = bitmap[i] + sep = '\n' if (i+1) % (TARGET_WIDTH/PIXEL_PER_BYTE) == 0 else ' ' + f.write('0x%02X,%s' % (v, sep)) + f.write('};\n') + print(imgFile, '=>', codeFile, 'done!') + +if __name__ == "__main__": + main() diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..0d9e08dd082b70aae807de96a425d1b08bc31406 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/BUILD.gn" @@ -0,0 +1,43 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("libm_port") { + sources = [ + "__sin.c", + "__cos.c", + "__rem_pio2.c", + "__rem_pio2_large.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__cos.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__cos.c" new file mode 100755 index 0000000000000000000000000000000000000000..46cefb38134398a4e0e7b40621eb6ea6e514ca38 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__cos.c" @@ -0,0 +1,71 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * __cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) ~ 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy, rearrange to + * cos(x+y) ~ w + (tmp + (r-x*y)) + * where w = 1 - x*x/2 and tmp is a tiny correction term + * (1 - x*x/2 == w + tmp exactly in infinite precision). + * The exactness of w + tmp in infinite precision depends on w + * and tmp having the same precision as x. If they have extra + * precision due to compiler bugs, then the extra precision is + * only good provided it is retained in all terms of the final + * expression for cos(). Retention happens in all cases tested + * under FreeBSD, so don't pessimize things by forcibly clipping + * any extra precision in w. + */ + +#include "libm.h" + +static const double +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +double __cos(double x, double y) +{ + double_t hz,z,r,w; + + z = x*x; + w = z*z; + r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); + hz = 0.5*z; + w = 1.0-hz; + return w + (((1.0-w)-hz) + (z*r-x*y)); +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2.c" new file mode 100755 index 0000000000000000000000000000000000000000..d403f81c792217a195d9680d9356eec17f734f41 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2.c" @@ -0,0 +1,177 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + * Optimized by Bruce D. Evans. + */ +/* __rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __rem_pio2_large() for large x + */ + +#include "libm.h" + +#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 +#define EPS DBL_EPSILON +#elif FLT_EVAL_METHOD==2 +#define EPS LDBL_EPSILON +#endif + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ +static const double +toint = 1.5/EPS, +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ +int __rem_pio2(double x, double *y) +{ + union {double f; uint64_t i;} u = {x}; + double_t z,w,t,r,fn; + double tx[3],ty[2]; + uint32_t ix; + int sign, n, ex, ey, i; + + sign = u.i>>63; + ix = u.i>>32 & 0x7fffffff; + if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ + if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ + goto medium; /* cancellation -- use medium case */ + if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ + if (!sign) { + z = x - pio2_1; /* one round good to 85 bits */ + y[0] = z - pio2_1t; + y[1] = (z-y[0]) - pio2_1t; + return 1; + } else { + z = x + pio2_1; + y[0] = z + pio2_1t; + y[1] = (z-y[0]) + pio2_1t; + return -1; + } + } else { + if (!sign) { + z = x - 2*pio2_1; + y[0] = z - 2*pio2_1t; + y[1] = (z-y[0]) - 2*pio2_1t; + return 2; + } else { + z = x + 2*pio2_1; + y[0] = z + 2*pio2_1t; + y[1] = (z-y[0]) + 2*pio2_1t; + return -2; + } + } + } + if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ + if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ + if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ + goto medium; + if (!sign) { + z = x - 3*pio2_1; + y[0] = z - 3*pio2_1t; + y[1] = (z-y[0]) - 3*pio2_1t; + return 3; + } else { + z = x + 3*pio2_1; + y[0] = z + 3*pio2_1t; + y[1] = (z-y[0]) + 3*pio2_1t; + return -3; + } + } else { + if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ + goto medium; + if (!sign) { + z = x - 4*pio2_1; + y[0] = z - 4*pio2_1t; + y[1] = (z-y[0]) - 4*pio2_1t; + return 4; + } else { + z = x + 4*pio2_1; + y[0] = z + 4*pio2_1t; + y[1] = (z-y[0]) + 4*pio2_1t; + return -4; + } + } + } + if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ +medium: + /* rint(x/(pi/2)), Assume round-to-nearest. */ + fn = (double_t)x*invpio2 + toint - toint; + n = (int32_t)fn; + r = x - fn*pio2_1; + w = fn*pio2_1t; /* 1st round, good to 85 bits */ + y[0] = r - w; + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + ex = ix>>20; + if (ex - ey > 16) { /* 2nd round, good to 118 bits */ + t = r; + w = fn*pio2_2; + r = t - w; + w = fn*pio2_2t - ((t-r)-w); + y[0] = r - w; + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ + t = r; + w = fn*pio2_3; + r = t - w; + w = fn*pio2_3t - ((t-r)-w); + y[0] = r - w; + } + } + y[1] = (r - y[0]) - w; + return n; + } + /* + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { /* x is inf or NaN */ + y[0] = y[1] = x - x; + return 0; + } + /* set z = scalbn(|x|,-ilogb(x)+23) */ + u.f = x; + u.i &= (uint64_t)-1>>12; + u.i |= (uint64_t)(0x3ff + 23)<<52; + z = u.f; + for (i=0; i < 2; i++) { + tx[i] = (double)(int32_t)z; + z = (z-tx[i])*0x1p24; + } + tx[i] = z; + /* skip zero terms, first term is non-zero */ + while (tx[i] == 0.0) + i--; + n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); + if (sign) { + y[0] = -ty[0]; + y[1] = -ty[1]; + return -n; + } + y[0] = ty[0]; + y[1] = ty[1]; + return n; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2_large.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2_large.c" new file mode 100755 index 0000000000000000000000000000000000000000..958f28c2557caf23ce9476771f1787cf071d19de --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__rem_pio2_large.c" @@ -0,0 +1,442 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * __rem_pio2_large(x,y,e0,nx,prec) + * double x[],y[]; int e0,nx,prec; + * + * __rem_pio2_large return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y[1]; + * w = (long double)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0]. Must be <= 16360 or you need to + * expand the ipio2 table. + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The minimum and recommended value + * for jk is 3,4,4,6 for single, double, extended, and quad. + * jk+1 must be 2 larger than you might expect so that our + * recomputation test works. (Up to 24 bits in the integer + * part (the 24 bits of it that we compute) and 23 bits in + * the fraction part may be lost to cancelation before we + * recompute.) + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ +/* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "libm.h" + +static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + * + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * NB: This table must have at least (e0-3)/24 + jk terms. + * For quad precision (e0 <= 16360, jk = 6), this is 686. + */ +static const int32_t ipio2[] = { +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, + +#if LDBL_MAX_EXP > 1024 +0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, +0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, +0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, +0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, +0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, +0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, +0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, +0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, +0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, +0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, +0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, +0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, +0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, +0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, +0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, +0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, +0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, +0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, +0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, +0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, +0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, +0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, +0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, +0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, +0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, +0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, +0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, +0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, +0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, +0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, +0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, +0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, +0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, +0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, +0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, +0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, +0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, +0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, +0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, +0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, +0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, +0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, +0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, +0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, +0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, +0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, +0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, +0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, +0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, +0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, +0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, +0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, +0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, +0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, +0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, +0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, +0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, +0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, +0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, +0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, +0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, +0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, +0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, +0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, +0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, +0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, +0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, +0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, +0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, +0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, +0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, +0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, +0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, +0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, +0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, +0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, +0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, +0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, +0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, +0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, +0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, +0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, +0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, +0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, +0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, +0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, +0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, +0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, +0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, +0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, +0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, +0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, +0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, +0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, +0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, +0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, +0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, +0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, +0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, +0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, +0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, +0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, +0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, +0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, +#endif +}; + +static const double PIo2[] = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) +{ + int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; + double z,fw,f[20],fq[20],q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/24; if(jv<0) jv=0; + q0 = e0-24*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for (i=0; i<=m; i++,j++) + f[i] = j<0 ? 0.0 : (double)ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0; i<=jk; i++) { + for (j=0,fw=0.0; j<=jx; j++) + fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { + fw = (double)(int32_t)(0x1p-24*z); + iq[i] = (int32_t)(z - 0x1p24*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbn(z,q0); /* actual value of z */ + z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ + n = (int32_t)z; + z -= (double)n; + ih = 0; + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = iq[jz-1]>>(24-q0); n += i; + iq[jz-1] -= i<<(24-q0); + ih = iq[jz-1]>>(23-q0); + } + else if (q0 == 0) ih = iq[jz-1]>>23; + else if (z >= 0.5) ih = 2; + + if (ih > 0) { /* q > 0.5 */ + n += 1; carry = 0; + for (i=0; i 0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7fffff; break; + case 2: + iq[jz-1] &= 0x3fffff; break; + } + } + if (ih == 2) { + z = 1.0 - z; + if (carry != 0) + z -= scalbn(1.0,q0); + } + } + + /* check if recomputation is needed */ + if (z == 0.0) { + j = 0; + for (i=jz-1; i>=jk; i--) j |= iq[i]; + if (j == 0) { /* need recomputation */ + for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */ + + for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (double)ipio2[jv+i]; + for (j=0,fw=0.0; j<=jx; j++) + fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if (z == 0.0) { + jz -= 1; + q0 -= 24; + while (iq[jz] == 0) { + jz--; + q0 -= 24; + } + } else { /* break z into 24-bit if necessary */ + z = scalbn(z,-q0); + if (z >= 0x1p24) { + fw = (double)(int32_t)(0x1p-24*z); + iq[jz] = (int32_t)(z - 0x1p24*fw); + jz += 1; + q0 += 24; + iq[jz] = (int32_t)fw; + } else + iq[jz] = (int32_t)z; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(1.0,q0); + for (i=jz; i>=0; i--) { + q[i] = fw*(double)iq[i]; + fw *= 0x1p-24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz; i>=0; i--) { + for (fw=0.0,k=0; k<=jp && k<=jz-i; k++) + fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz; i>=0; i--) + fw += fq[i]; + y[0] = ih==0 ? fw : -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz; i>=0; i--) + fw += fq[i]; + // TODO: drop excess precision here once double_t is used + fw = (double)fw; + y[0] = ih==0 ? fw : -fw; + fw = fq[0]-fw; + for (i=1; i<=jz; i++) + fw += fq[i]; + y[1] = ih==0 ? fw : -fw; + break; + case 3: /* painful */ + for (i=jz; i>0; i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz; i>1; i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz; i>=2; i--) + fw += fq[i]; + if (ih==0) { + y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; + } else { + y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; + } + } + return n&7; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__sin.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__sin.c" new file mode 100755 index 0000000000000000000000000000000000000000..40309496646ea67bc247a46b8cd363a73ca9801e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/__sin.c" @@ -0,0 +1,64 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* __sin( x, y, iy) + * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. Callers must return sin(-0) = -0 without calling here since our + * odd polynomial is not evaluated in a way that preserves -0. + * Callers may do the optimization sin(x) ~ x for tiny x. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "libm.h" + +static const double +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +double __sin(double x, double y, int iy) +{ + double_t z,r,v,w; + + z = x*x; + w = z*z; + r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); + v = z*x; + if (iy == 0) + return x + v*(S1 + z*r); + else + return x - ((z*(0.5*y - v*r) - y) - v*S1); +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/cos.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/cos.c" new file mode 100755 index 0000000000000000000000000000000000000000..ee97f68bbb7be73e473e9324484bed533fcb39bb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/cos.c" @@ -0,0 +1,77 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* cos(x) + * Return cosine function of x. + * + * kernel function: + * __sin ... sine function on [-pi/4,pi/4] + * __cos ... cosine function on [-pi/4,pi/4] + * __rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "libm.h" + +double cos(double x) +{ + double y[2]; + uint32_t ix; + unsigned n; + + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + /* |x| ~< pi/4 */ + if (ix <= 0x3fe921fb) { + if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ + /* raise inexact if x!=0 */ + FORCE_EVAL(x + 0x1p120f); + return 1.0; + } + return __cos(x, 0); + } + + /* cos(Inf or NaN) is NaN */ + if (ix >= 0x7ff00000) + return x-x; + + /* argument reduction */ + n = __rem_pio2(x, y); + switch (n&3) { + case 0: return __cos(y[0], y[1]); + case 1: return -__sin(y[0], y[1], 1); + case 2: return -__cos(y[0], y[1]); + default: + return __sin(y[0], y[1], 1); + } +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/features.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/features.h" new file mode 100755 index 0000000000000000000000000000000000000000..aa6c4a73bd5b5f9f95fc94c63f77857e054d089d --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/features.h" @@ -0,0 +1,11 @@ +#ifndef FEATURES_H +#define FEATURES_H + +// #include "../../include/features.h" + +#define weak __attribute__((__weak__)) +#define hidden __attribute__((__visibility__("hidden"))) +#define weak_alias(old, new) \ + extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) + +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/libm.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/libm.h" new file mode 100755 index 0000000000000000000000000000000000000000..a5cb3c15ee854d0ce5aae4f229b61c9e1df3f8a4 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/libm.h" @@ -0,0 +1,277 @@ +#ifndef _LIBM_H +#define _LIBM_H + +#include +#include +#include +#include +// #include "fp_arch.h" +#include "features.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; +}; +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +/* This is the m68k variant of 80-bit long double, and this definition only works + * on archs where the alignment requirement of uint64_t is <= 4. */ +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t pad; + uint64_t m; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +/* Support non-nearest rounding mode. */ +#define WANT_ROUNDING 1 +/* Support signaling NaNs. */ +#define WANT_SNAN 0 + +#if WANT_SNAN +#error SNaN is unsupported +#else +#define issignalingf_inline(x) 0 +#define issignaling_inline(x) 0 +#endif + +#ifndef TOINT_INTRINSICS +#define TOINT_INTRINSICS 0 +#endif + +#if TOINT_INTRINSICS +/* Round x to nearest int in all rounding modes, ties have to be rounded + consistently with converttoint so the results match. If the result + would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ +static double_t roundtoint(double_t); + +/* Convert x to nearest int in all rounding modes, ties have to be rounded + consistently with roundtoint. If the result is not representible in an + int32_t then the semantics is unspecified. */ +static int32_t converttoint(double_t); +#endif + +/* Helps static branch prediction so hot path can be better optimized. */ +#ifdef __GNUC__ +#define predict_true(x) __builtin_expect(!!(x), 1) +#define predict_false(x) __builtin_expect(x, 0) +#else +#define predict_true(x) (x) +#define predict_false(x) (x) +#endif + +/* Evaluate an expression as the specified type. With standard excess + precision handling a type cast or assignment is enough (with + -ffloat-store an assignment is required, in old compilers argument + passing and return statement may not drop excess precision). */ + +static inline float eval_as_float(float x) +{ + float y = x; + return y; +} + +static inline double eval_as_double(double x) +{ + double y = x; + return y; +} + +/* fp_barrier returns its input, but limits code transformations + as if it had a side-effect (e.g. observable io) and returned + an arbitrary value. */ + +#ifndef fp_barrierf +#define fp_barrierf fp_barrierf +static inline float fp_barrierf(float x) +{ + volatile float y = x; + return y; +} +#endif + +#ifndef fp_barrier +#define fp_barrier fp_barrier +static inline double fp_barrier(double x) +{ + volatile double y = x; + return y; +} +#endif + +#ifndef fp_barrierl +#define fp_barrierl fp_barrierl +static inline long double fp_barrierl(long double x) +{ + volatile long double y = x; + return y; +} +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; +} +#endif + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) + +#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i +#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f +#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i +#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f + +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + uint64_t __u = asuint64(d); \ + (hi) = __u >> 32; \ + (lo) = (uint32_t)__u; \ +} while (0) + +#define GET_HIGH_WORD(hi,d) \ +do { \ + (hi) = asuint64(d) >> 32; \ +} while (0) + +#define GET_LOW_WORD(lo,d) \ +do { \ + (lo) = (uint32_t)asuint64(d); \ +} while (0) + +#define INSERT_WORDS(d,hi,lo) \ +do { \ + (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ +} while (0) + +#define SET_HIGH_WORD(d,hi) \ + INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) + +#define SET_LOW_WORD(d,lo) \ + INSERT_WORDS(d, asuint64(d)>>32, lo) + +#define GET_FLOAT_WORD(w,d) \ +do { \ + (w) = asuint(d); \ +} while (0) + +#define SET_FLOAT_WORD(d,w) \ +do { \ + (d) = asfloat(w); \ +} while (0) + +hidden int __rem_pio2_large(double*,double*,int,int,int); + +hidden int __rem_pio2(double,double*); +hidden double __sin(double,double,int); +hidden double __cos(double,double); +hidden double __tan(double,double,int); +hidden double __expo2(double); + +hidden int __rem_pio2f(float,double*); +hidden float __sindf(double); +hidden float __cosdf(double); +hidden float __tandf(double,int); +hidden float __expo2f(float); + +hidden int __rem_pio2l(long double, long double *); +hidden long double __sinl(long double, long double, int); +hidden long double __cosl(long double, long double); +hidden long double __tanl(long double, long double, int); + +hidden long double __polevll(long double, const long double *, int); +hidden long double __p1evll(long double, const long double *, int); + +extern int __signgam; +hidden double __lgamma_r(double, int *); +hidden float __lgammaf_r(float, int *); + +/* error handling functions */ +hidden float __math_xflowf(uint32_t, float); +hidden float __math_uflowf(uint32_t); +hidden float __math_oflowf(uint32_t); +hidden float __math_divzerof(uint32_t); +hidden float __math_invalidf(float); +hidden double __math_xflow(uint32_t, double); +hidden double __math_uflow(uint32_t); +hidden double __math_oflow(uint32_t); +hidden double __math_divzero(uint32_t); +hidden double __math_invalid(double); + +#pragma GCC diagnostic pop + +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/sin.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/sin.c" new file mode 100755 index 0000000000000000000000000000000000000000..055e215bc866d62936992058b7019b374cbcac7c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/libm_port/sin.c" @@ -0,0 +1,78 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __sin ... sine function on [-pi/4,pi/4] + * __cos ... cose function on [-pi/4,pi/4] + * __rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "libm.h" + +double sin(double x) +{ + double y[2]; + uint32_t ix; + unsigned n; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + /* |x| ~< pi/4 */ + if (ix <= 0x3fe921fb) { + if (ix < 0x3e500000) { /* |x| < 2**-26 */ + /* raise inexact if x != 0 and underflow if subnormal*/ + FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); + return x; + } + return __sin(x, 0.0, 0); + } + + /* sin(Inf or NaN) is NaN */ + if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + n = __rem_pio2(x, y); + switch (n&3) { + case 0: return __sin(y[0], y[1], 1); + case 1: return __cos(y[0], y[1]); + case 2: return -__sin(y[0], y[1], 1); + default: + return -__cos(y[0], y[1]); + } +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/requirements.txt" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/requirements.txt" new file mode 100755 index 0000000000000000000000000000000000000000..fedd4b11e93d535ea7b1aaab912df5ccb0f1d031 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/requirements.txt" @@ -0,0 +1,4 @@ +numpy==1.19.2 +opencv-python==4.4.0.44 +Pillow==7.2.0 +pkg-resources==0.0.0 diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..b31cbbececb79cadc7be453e3eeed0c623d1a3cc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("oled_ssd1306") { + sources = [ + "ssd1306.c", + "ssd1306_fonts.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.c" new file mode 100755 index 0000000000000000000000000000000000000000..da2302761ec3a92ba33cf29102a9ca6917a9a825 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.c" @@ -0,0 +1,586 @@ +#include "ssd1306.h" +#include +#include +#include // For memcpy + +#include +#include +#include "cmsis_os2.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" + +#if defined(SSD1306_USE_I2C) + +#define SSD1306_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define SSD1306_CTRL_CMD 0x00 +#define SSD1306_CTRL_DATA 0x40 +#define SSD1306_MASK_CONT (0x1<<7) + +void ssd1306_Reset(void) { + /* for I2C - do nothing */ +} + +void HAL_Delay(uint32_t ms) +{ + uint32_t msPerTick = 1000 / osKernelGetTickFreq(); // 10ms + if (ms >= msPerTick) { + osDelay(ms / msPerTick); + } + + uint32_t restMs = ms % msPerTick; + if (restMs > 0) { + usleep(restMs * 1000); + } +} + +uint32_t HAL_GetTick(void) +{ + uint32_t msPerTick = 1000 / osKernelGetTickFreq(); // 10ms + uint32_t tickMs = osKernelGetTickCount() * msPerTick; + + uint32_t csPerMs = osKernelGetSysTimerFreq() / 1000; // 160K cycle/ms + uint32_t csPerTick = csPerMs * msPerTick; // 1600K cycles/tick + uint32_t restMs = osKernelGetSysTimerCount() % csPerTick / csPerMs; + + return tickMs + restMs; +} + +static uint32_t ssd1306_SendData(uint8_t* data, size_t size) +{ + WifiIotI2cIdx id = SSD1306_I2C_IDX; + WifiIotI2cData i2cData = {0}; + i2cData.sendBuf = data; + i2cData.sendLen = size; + + return I2cWrite(id, SSD1306_I2C_ADDR, &i2cData); +} + +static uint32_t ssd1306_WiteByte(uint8_t regAddr, uint8_t byte) +{ + uint8_t buffer[] = {regAddr, byte}; + return ssd1306_SendData(buffer, sizeof(buffer)); +} + +// Send a byte to the command register +void ssd1306_WriteCommand(uint8_t byte) { + ssd1306_WiteByte(SSD1306_CTRL_CMD, byte); +} + +// Send data +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { + uint8_t data[SSD1306_WIDTH * 2] = {0}; + for (size_t i = 0; i < buff_size; i++) { + data[i*2] = SSD1306_CTRL_DATA | SSD1306_MASK_CONT; + data[i*2+1] = buffer[i]; + } + data[(buff_size - 1) * 2] = SSD1306_CTRL_DATA; + ssd1306_SendData(data, sizeof(data)); +} + +#elif defined(SSD1306_USE_SPI) + +void ssd1306_Reset(void) { + // CS = High (not selected) + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); + + // Reset the OLED + HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET); + HAL_Delay(10); + HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET); + HAL_Delay(10); +} + +// Send a byte to the command register +void ssd1306_WriteCommand(uint8_t byte) { + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED + HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // command + HAL_SPI_Transmit(&SSD1306_SPI_PORT, (uint8_t *) &byte, 1, HAL_MAX_DELAY); + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED +} + +// Send data +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED + HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // data + HAL_SPI_Transmit(&SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY); + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED +} + +#else +#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro" +#endif + + +// Screenbuffer +static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE]; + +// Screen object +static SSD1306_t SSD1306; + +/* Fills the Screenbuffer with values from a given buffer of a fixed length */ +SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len) { + SSD1306_Error_t ret = SSD1306_ERR; + if (len <= SSD1306_BUFFER_SIZE) { + memcpy(SSD1306_Buffer,buf,len); + ret = SSD1306_OK; + } + return ret; +} + +// Initialize the oled screen +void ssd1306_Init(void) { + // Reset OLED + ssd1306_Reset(); + + // Wait for the screen to boot + HAL_Delay(100); + + // Init OLED + ssd1306_SetDisplayOn(0); //display off + + ssd1306_WriteCommand(0x20); //Set Memory Addressing Mode + ssd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode; + // 10b,Page Addressing Mode (RESET); 11b,Invalid + + ssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 + +#ifdef SSD1306_MIRROR_VERT + ssd1306_WriteCommand(0xC0); // Mirror vertically +#else + ssd1306_WriteCommand(0xC8); //Set COM Output Scan Direction +#endif + + ssd1306_WriteCommand(0x00); //---set low column address + ssd1306_WriteCommand(0x10); //---set high column address + + ssd1306_WriteCommand(0x40); //--set start line address - CHECK + + ssd1306_SetContrast(0xFF); + +#ifdef SSD1306_MIRROR_HORIZ + ssd1306_WriteCommand(0xA0); // Mirror horizontally +#else + ssd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK +#endif + +#ifdef SSD1306_INVERSE_COLOR + ssd1306_WriteCommand(0xA7); //--set inverse color +#else + ssd1306_WriteCommand(0xA6); //--set normal color +#endif + +// Set multiplex ratio. +#if (SSD1306_HEIGHT == 128) + // Found in the Luma Python lib for SH1106. + ssd1306_WriteCommand(0xFF); +#else + ssd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK +#endif + +#if (SSD1306_HEIGHT == 32) + ssd1306_WriteCommand(0x1F); // +#elif (SSD1306_HEIGHT == 64) + ssd1306_WriteCommand(0x3F); // +#elif (SSD1306_HEIGHT == 128) + ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too. +#else +#error "Only 32, 64, or 128 lines of height are supported!" +#endif + + ssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content + + ssd1306_WriteCommand(0xD3); //-set display offset - CHECK + ssd1306_WriteCommand(0x00); //-not offset + + ssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency + ssd1306_WriteCommand(0xF0); //--set divide ratio + + ssd1306_WriteCommand(0xD9); //--set pre-charge period + ssd1306_WriteCommand(0x11); // 0x22 by default + + ssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK +#if (SSD1306_HEIGHT == 32) + ssd1306_WriteCommand(0x02); +#elif (SSD1306_HEIGHT == 64) + ssd1306_WriteCommand(0x12); +#elif (SSD1306_HEIGHT == 128) + ssd1306_WriteCommand(0x12); +#else +#error "Only 32, 64, or 128 lines of height are supported!" +#endif + + ssd1306_WriteCommand(0xDB); //--set vcomh + ssd1306_WriteCommand(0x30); //0x20,0.77xVcc, 0x30,0.83xVcc + + ssd1306_WriteCommand(0x8D); //--set DC-DC enable + ssd1306_WriteCommand(0x14); // + ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel + + // Clear screen + ssd1306_Fill(Black); + + // Flush buffer to screen + ssd1306_UpdateScreen(); + + // Set default values for screen object + SSD1306.CurrentX = 0; + SSD1306.CurrentY = 0; + + SSD1306.Initialized = 1; +} + +// Fill the whole screen with the given color +void ssd1306_Fill(SSD1306_COLOR color) { + /* Set memory */ + uint32_t i; + + for(i = 0; i < sizeof(SSD1306_Buffer); i++) { + SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF; + } +} + +// Write the screenbuffer with changed to the screen +void ssd1306_UpdateScreen(void) { + // Write data to each page of RAM. Number of pages + // depends on the screen height: + // + // * 32px == 4 pages + // * 64px == 8 pages + // * 128px == 16 pages + + uint8_t cmd[] = { + 0X21, // 设置列起始和结束地址 + 0X00, // 列起始地址 0 + 0X7F, // 列终止地址 127 + 0X22, // 设置页起始和结束地址 + 0X00, // 页起始地址 0 + 0X07, // 页终止地址 7 + }; + uint32_t count = 0; + uint8_t data[sizeof(cmd)*2 + SSD1306_BUFFER_SIZE + 1] = {}; + + // copy cmd + for (uint32_t i = 0; i < sizeof(cmd)/sizeof(cmd[0]); i++) { + data[count++] = SSD1306_CTRL_CMD | SSD1306_MASK_CONT; + data[count++] = cmd[i]; + } + + // copy frame data + data[count++] = SSD1306_CTRL_DATA; + memcpy(&data[count], SSD1306_Buffer, sizeof(SSD1306_Buffer)); + count += sizeof(SSD1306_Buffer); + + // send to i2c bus + uint32_t retval = ssd1306_SendData(data, count); + if (retval != WIFI_IOT_SUCCESS) { + printf("ssd1306_UpdateScreen send frame data filed: %d!\r\n", retval); + } +} + +// Draw one pixel in the screenbuffer +// X => X Coordinate +// Y => Y Coordinate +// color => Pixel color +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) { + if(x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) { + // Don't write outside the buffer + return; + } + + // Check if pixel should be inverted + if(SSD1306.Inverted) { + color = (SSD1306_COLOR)!color; + } + + // Draw in the right color + if(color == White) { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); + } else { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); + } +} + +// Draw 1 char to the screen buffer +// ch => char om weg te schrijven +// Font => Font waarmee we gaan schrijven +// color => Black or White +char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color) { + uint32_t i, b, j; + + // Check if character is valid + if (ch < 32 || ch > 126) + return 0; + + // Check remaining space on current line + if (SSD1306_WIDTH < (SSD1306.CurrentX + Font.FontWidth) || + SSD1306_HEIGHT < (SSD1306.CurrentY + Font.FontHeight)) + { + // Not enough space on current line + return 0; + } + + // Use the font to write + for(i = 0; i < Font.FontHeight; i++) { + b = Font.data[(ch - 32) * Font.FontHeight + i]; + for(j = 0; j < Font.FontWidth; j++) { + if((b << j) & 0x8000) { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color); + } else { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color); + } + } + } + + // The current space is now taken + SSD1306.CurrentX += Font.FontWidth; + + // Return written char for validation + return ch; +} + +// Write full string to screenbuffer +char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color) { + // Write until null-byte + while (*str) { + if (ssd1306_DrawChar(*str, Font, color) != *str) { + // Char could not be written + return *str; + } + + // Next char + str++; + } + + // Everything ok + return *str; +} + +// Position the cursor +void ssd1306_SetCursor(uint8_t x, uint8_t y) { + SSD1306.CurrentX = x; + SSD1306.CurrentY = y; +} + +// Draw line by Bresenhem's algorithm +void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) { + int32_t deltaX = abs(x2 - x1); + int32_t deltaY = abs(y2 - y1); + int32_t signX = ((x1 < x2) ? 1 : -1); + int32_t signY = ((y1 < y2) ? 1 : -1); + int32_t error = deltaX - deltaY; + int32_t error2; + + ssd1306_DrawPixel(x2, y2, color); + while((x1 != x2) || (y1 != y2)) + { + ssd1306_DrawPixel(x1, y1, color); + error2 = error * 2; + if(error2 > -deltaY) + { + error -= deltaY; + x1 += signX; + } + else + { + /*nothing to do*/ + } + + if(error2 < deltaX) + { + error += deltaX; + y1 += signY; + } + else + { + /*nothing to do*/ + } + } + return; +} +//Draw polyline +void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) { + uint16_t i; + if(par_vertex != 0){ + for(i = 1; i < par_size; i++){ + ssd1306_DrawLine(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color); + } + } + else + { + /*nothing to do*/ + } + return; +} +/*Convert Degrees to Radians*/ +static float ssd1306_DegToRad(float par_deg) { + return par_deg * 3.14 / 180.0; +} +/*Normalize degree to [0;360]*/ +static uint16_t ssd1306_NormalizeTo0_360(uint16_t par_deg) { + uint16_t loc_angle; + if(par_deg <= 360) + { + loc_angle = par_deg; + } + else + { + loc_angle = par_deg % 360; + loc_angle = ((par_deg != 0)?par_deg:360); + } + return loc_angle; +} +/*DrawArc. Draw angle is beginning from 4 quart of trigonometric circle (3pi/2) + * start_angle in degree + * sweep in degree + */ +void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) { + #define CIRCLE_APPROXIMATION_SEGMENTS 36 + float approx_degree; + uint32_t approx_segments; + uint8_t xp1,xp2; + uint8_t yp1,yp2; + uint32_t count = 0; + uint32_t loc_sweep = 0; + float rad; + + loc_sweep = ssd1306_NormalizeTo0_360(sweep); + + count = (ssd1306_NormalizeTo0_360(start_angle) * CIRCLE_APPROXIMATION_SEGMENTS) / 360; + approx_segments = (loc_sweep * CIRCLE_APPROXIMATION_SEGMENTS) / 360; + approx_degree = loc_sweep / (float)approx_segments; + while(count < approx_segments) + { + rad = ssd1306_DegToRad(count*approx_degree); + xp1 = x + (int8_t)(sin(rad)*radius); + yp1 = y + (int8_t)(cos(rad)*radius); + count++; + if(count != approx_segments) + { + rad = ssd1306_DegToRad(count*approx_degree); + } + else + { + rad = ssd1306_DegToRad(loc_sweep); + } + xp2 = x + (int8_t)(sin(rad)*radius); + yp2 = y + (int8_t)(cos(rad)*radius); + ssd1306_DrawLine(xp1,yp1,xp2,yp2,color); + } + + return; +} +//Draw circle by Bresenhem's algorithm +void ssd1306_DrawCircle(uint8_t par_x,uint8_t par_y,uint8_t par_r,SSD1306_COLOR par_color) { + int32_t x = -par_r; + int32_t y = 0; + int32_t err = 2 - 2 * par_r; + int32_t e2; + + if (par_x >= SSD1306_WIDTH || par_y >= SSD1306_HEIGHT) { + return; + } + + do { + ssd1306_DrawPixel(par_x - x, par_y + y, par_color); + ssd1306_DrawPixel(par_x + x, par_y + y, par_color); + ssd1306_DrawPixel(par_x + x, par_y - y, par_color); + ssd1306_DrawPixel(par_x - x, par_y - y, par_color); + e2 = err; + if (e2 <= y) { + y++; + err = err + (y * 2 + 1); + if(-x == y && e2 <= x) { + e2 = 0; + } + else + { + /*nothing to do*/ + } + } + else + { + /*nothing to do*/ + } + if(e2 > x) { + x++; + err = err + (x * 2 + 1); + } + else + { + /*nothing to do*/ + } + } while(x <= 0); + + return; +} + +//Draw rectangle +void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) { + ssd1306_DrawLine(x1,y1,x2,y1,color); + ssd1306_DrawLine(x2,y1,x2,y2,color); + ssd1306_DrawLine(x2,y2,x1,y2,color); + ssd1306_DrawLine(x1,y2,x1,y1,color); + + return; +} + +void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size) +{ + uint8_t rows = size * 8 / SSD1306_WIDTH; + if (rows > SSD1306_HEIGHT) { + rows = SSD1306_HEIGHT; + } + for (uint8_t y = 0; y < rows; y++) { + for (uint8_t x = 0; x < SSD1306_WIDTH; x++) { + uint8_t byte = bitmap[(y * SSD1306_WIDTH / 8) + (x / 8)]; + uint8_t bit = byte & (0x80 >> (x % 8)); + ssd1306_DrawPixel(x, y, bit ? White : Black); + } + } +} + +void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride) +{ + if (x + w > SSD1306_WIDTH || y + h > SSD1306_HEIGHT || w * h == 0) { + printf("%dx%d @ %d,%d out of range or invalid!\r\n", w, h, x, y); + return; + } + + w = (w <= SSD1306_WIDTH ? w : SSD1306_WIDTH); + h = (h <= SSD1306_HEIGHT ? h : SSD1306_HEIGHT); + stride = (stride == 0 ? w : stride); + + uint8_t rows = size * 8 / stride; + for (uint8_t i = 0; i < rows; i++) { + uint32_t base = i * stride / 8; + for (uint8_t j = 0; j < w; j++) { + uint32_t idx = base + (j / 8); + uint8_t byte = idx < size ? data[idx] : 0; + uint8_t bit = byte & (0x80 >> (j % 8)); + ssd1306_DrawPixel(x + j, y + i, bit ? White : Black); + } + } +} + +void ssd1306_SetContrast(const uint8_t value) { + const uint8_t kSetContrastControlRegister = 0x81; + ssd1306_WriteCommand(kSetContrastControlRegister); + ssd1306_WriteCommand(value); +} + +void ssd1306_SetDisplayOn(const uint8_t on) { + uint8_t value; + if (on) { + value = 0xAF; // Display on + SSD1306.DisplayOn = 1; + } else { + value = 0xAE; // Display off + SSD1306.DisplayOn = 0; + } + ssd1306_WriteCommand(value); +} + +uint8_t ssd1306_GetDisplayOn() { + return SSD1306.DisplayOn; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.h" new file mode 100755 index 0000000000000000000000000000000000000000..97942c642bd24da5216b9a0f5e7ee8ce6fe71883 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306.h" @@ -0,0 +1,181 @@ +/** + * This Library was originally written by Olivier Van den Eede (4ilo) in 2016. + * Some refactoring was done and SPI support was added by Aleksander Alekseev (afiskon) in 2018. + * + * https://github.com/afiskon/stm32-ssd1306 + */ + +#ifndef __SSD1306_H__ +#define __SSD1306_H__ + +#include +#include <_ansi.h> + +_BEGIN_STD_C + +#include "ssd1306_conf.h" + +#if defined(STM32F0) +#include "stm32f0xx_hal.h" +#elif defined(STM32F1) +#include "stm32f1xx_hal.h" +#elif defined(STM32F4) +#include "stm32f4xx_hal.h" +#include "stm32f4xx_hal_gpio.h" +#elif defined(STM32L0) +#include "stm32l0xx_hal.h" +#elif defined(STM32L4) +#include "stm32l4xx_hal.h" +#elif defined(STM32F3) +#include "stm32f3xx_hal.h" +#elif defined(STM32H7) +#include "stm32h7xx_hal.h" +#elif defined(STM32F7) +#include "stm32f7xx_hal.h" +#else +// #error "SSD1306 library was tested only on STM32F0, STM32F1, STM32F3, STM32F4, STM32F7, STM32L0, STM32L4, STM32H7 MCU families. Please modify ssd1306.h if you know what you are doing. Also please send a pull request if it turns out the library works on other MCU's as well!" +#endif + +#include "ssd1306_fonts.h" + +/* vvv I2C config vvv */ + +#ifndef SSD1306_I2C_PORT +#define SSD1306_I2C_PORT hi2c1 +#endif + +#ifndef SSD1306_I2C_ADDR +#define SSD1306_I2C_ADDR (0x3C << 1) +#endif + +/* ^^^ I2C config ^^^ */ + +/* vvv SPI config vvv */ + +#ifndef SSD1306_SPI_PORT +#define SSD1306_SPI_PORT hspi2 +#endif + +#ifndef SSD1306_CS_Port +#define SSD1306_CS_Port GPIOB +#endif +#ifndef SSD1306_CS_Pin +#define SSD1306_CS_Pin GPIO_PIN_12 +#endif + +#ifndef SSD1306_DC_Port +#define SSD1306_DC_Port GPIOB +#endif +#ifndef SSD1306_DC_Pin +#define SSD1306_DC_Pin GPIO_PIN_14 +#endif + +#ifndef SSD1306_Reset_Port +#define SSD1306_Reset_Port GPIOA +#endif +#ifndef SSD1306_Reset_Pin +#define SSD1306_Reset_Pin GPIO_PIN_8 +#endif + +/* ^^^ SPI config ^^^ */ + +#if defined(SSD1306_USE_I2C) +// extern I2C_HandleTypeDef SSD1306_I2C_PORT; +#elif defined(SSD1306_USE_SPI) +extern SPI_HandleTypeDef SSD1306_SPI_PORT; +#else +#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro!" +#endif + +// SSD1306 OLED height in pixels +#ifndef SSD1306_HEIGHT +#define SSD1306_HEIGHT 64 +#endif + +// SSD1306 width in pixels +#ifndef SSD1306_WIDTH +#define SSD1306_WIDTH 128 +#endif + +// some LEDs don't display anything in first two columns +// #define SSD1306_WIDTH 130 + +#ifndef SSD1306_BUFFER_SIZE +#define SSD1306_BUFFER_SIZE SSD1306_WIDTH * SSD1306_HEIGHT / 8 +#endif + +// Enumeration for screen colors +typedef enum { + Black = 0x00, // Black color, no pixel + White = 0x01 // Pixel is set. Color depends on OLED +} SSD1306_COLOR; + +typedef enum { + SSD1306_OK = 0x00, + SSD1306_ERR = 0x01 // Generic error. +} SSD1306_Error_t; + +// Struct to store transformations +typedef struct { + uint16_t CurrentX; + uint16_t CurrentY; + uint8_t Inverted; + uint8_t Initialized; + uint8_t DisplayOn; +} SSD1306_t; +typedef struct { + uint8_t x; + uint8_t y; +} SSD1306_VERTEX; + +// Procedure definitions +void ssd1306_Init(void); +void ssd1306_Fill(SSD1306_COLOR color); +void ssd1306_SetCursor(uint8_t x, uint8_t y); +void ssd1306_UpdateScreen(void); + +char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color); +char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color); + +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); +void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color); +void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color); +void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color); +void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color); +void ssd1306_DrawCircle(uint8_t par_x, uint8_t par_y, uint8_t par_r, SSD1306_COLOR color); +void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size); + +void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride); + +/** + * @brief Sets the contrast of the display. + * @param[in] value contrast to set. + * @note Contrast increases as the value increases. + * @note RESET = 7Fh. + */ +void ssd1306_SetContrast(const uint8_t value); +/** + * @brief Set Display ON/OFF. + * @param[in] on 0 for OFF, any for ON. + */ +void ssd1306_SetDisplayOn(const uint8_t on); +/** + * @brief Reads DisplayOn state. + * @return 0: OFF. + * 1: ON. + */ +uint8_t ssd1306_GetDisplayOn(void); + +void HAL_Delay(uint32_t ms); + +uint32_t HAL_GetTick(void); // in ms + +// Low-level procedures +void ssd1306_Reset(void); +void ssd1306_WriteCommand(uint8_t byte); +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size); +SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len); + +_END_STD_C + +#endif // __SSD1306_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_conf.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_conf.h" new file mode 100755 index 0000000000000000000000000000000000000000..4dd7a6dd117b7acb456854cf4dfe38bc7b8fac23 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_conf.h" @@ -0,0 +1,40 @@ +/** + * Private configuration file for the SSD1306 library. + * This example is configured for STM32F0, I2C and including all fonts. + */ + +#ifndef __SSD1306_CONF_H__ +#define __SSD1306_CONF_H__ + +// Choose a microcontroller family +// #define STM32F0 +//#define STM32F1 +//#define STM32F4 +//#define STM32L0 +//#define STM32L4 +//#define STM32F3 +//#define STM32H7 +//#define STM32F7 + +// Choose a bus +#define SSD1306_USE_I2C +//#define SSD1306_USE_SPI + +// I2C Configuration +// #define SSD1306_I2C_PORT hi2c1 +#define SSD1306_I2C_ADDR (0x3C << 1) + +// Mirror the screen if needed +// #define SSD1306_MIRROR_VERT +// #define SSD1306_MIRROR_HORIZ + +// Set inverse color if needed +// # define SSD1306_INVERSE_COLOR + +// Include only needed fonts +#define SSD1306_INCLUDE_FONT_6x8 +#define SSD1306_INCLUDE_FONT_7x10 +#define SSD1306_INCLUDE_FONT_11x18 +#define SSD1306_INCLUDE_FONT_16x26 + +#endif /* __SSD1306_CONF_H__ */ \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.c" new file mode 100755 index 0000000000000000000000000000000000000000..9bed638647affd3b451d92307a646a59e393b455 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.c" @@ -0,0 +1,413 @@ + +#include "ssd1306_fonts.h" + +#ifdef SSD1306_INCLUDE_FONT_7x10 +static const uint16_t Font7x10 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ! +0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // # +0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $ +0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // % +0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // & +0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // ( +0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // ) +0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // . +0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // / +0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0 +0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1 +0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2 +0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3 +0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4 +0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5 +0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6 +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7 +0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8 +0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ; +0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // > +0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ? +0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @ +0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A +0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B +0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C +0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D +0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E +0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F +0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G +0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H +0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J +0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K +0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L +0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M +0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R +0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S +0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T +0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U +0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V +0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W +0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X +0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z +0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [ +0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */ +0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ] +0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _ +0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c +0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e +0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j +0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k +0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q +0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s +0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y +0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z +0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // { +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // | +0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // } +0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif + +#ifdef SSD1306_INCLUDE_FONT_11x18 +static const uint16_t Font11x18 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ! +0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300, 0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // # +0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700, 0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $ +0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00, 0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // % +0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0, 0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // & +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // ( +0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // ) +0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // . +0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // / +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0 +0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1 +0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2 +0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3 +0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600, 0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4 +0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5 +0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6 +0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7 +0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00, 0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8 +0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ; +0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000, 0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180, 0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // > +0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ? +0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80, 0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @ +0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180, 0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A +0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00, 0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C +0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380, 0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H +0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J +0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00, 0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L +0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M +0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80, 0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R +0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700, 0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S +0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U +0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V +0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80, 0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W +0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X +0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y +0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z +0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [ +0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */ +0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ] +0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _ +0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180, 0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e +0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h +0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i +0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00, 0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k +0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000, 0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s +0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500, 0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z +0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // { +0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // | +0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // } +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80, 0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +static const uint16_t Font16x26 [] = { +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [ ] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x03C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [!] +0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ["] +0x01CE,0x03CE,0x03DE,0x039E,0x039C,0x079C,0x3FFF,0x7FFF,0x0738,0x0F38,0x0F78,0x0F78,0x0E78,0xFFFF,0xFFFF,0x1EF0,0x1CF0,0x1CE0,0x3CE0,0x3DE0,0x39E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [#] +0x03FC,0x0FFE,0x1FEE,0x1EE0,0x1EE0,0x1EE0,0x1EE0,0x1FE0,0x0FE0,0x07E0,0x03F0,0x01FC,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x3DFE,0x3FFC,0x0FF0,0x01E0,0x01E0,0x0000,0x0000,0x0000, // Ascii = [$] +0x3E03,0xF707,0xE78F,0xE78E,0xE39E,0xE3BC,0xE7B8,0xE7F8,0xF7F0,0x3FE0,0x01C0,0x03FF,0x07FF,0x07F3,0x0FF3,0x1EF3,0x3CF3,0x38F3,0x78F3,0xF07F,0xE03F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [%] +0x07E0,0x0FF8,0x0F78,0x1F78,0x1F78,0x1F78,0x0F78,0x0FF0,0x0FE0,0x1F80,0x7FC3,0xFBC3,0xF3E7,0xF1F7,0xF0F7,0xF0FF,0xF07F,0xF83E,0x7C7F,0x3FFF,0x1FEF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [&] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ['] +0x003F,0x007C,0x01F0,0x01E0,0x03C0,0x07C0,0x0780,0x0780,0x0F80,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F80,0x0780,0x0780,0x07C0,0x03C0,0x01E0,0x01F0,0x007C,0x003F,0x000F,0x0000, // Ascii = [(] +0x7E00,0x1F00,0x07C0,0x03C0,0x01E0,0x01F0,0x00F0,0x00F0,0x00F8,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x00F8,0x00F0,0x00F0,0x01F0,0x01E0,0x03C0,0x07C0,0x1F00,0x7E00,0x7800,0x0000, // Ascii = [)] +0x03E0,0x03C0,0x01C0,0x39CE,0x3FFF,0x3F7F,0x0320,0x0370,0x07F8,0x0F78,0x1F3C,0x0638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [*] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0xFFFF,0xFFFF,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [+] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x01C0,0x0380, // Ascii = [,] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [-] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [.] +0x000F,0x000F,0x001E,0x001E,0x003C,0x003C,0x0078,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0780,0x0F00,0x0F00,0x1E00,0x1E00,0x3C00,0x3C00,0x7800,0x7800,0xF000,0x0000, // Ascii = [/] +0x07F0,0x0FF8,0x1F7C,0x3E3E,0x3C1E,0x7C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x7C1F,0x3C1E,0x3E3E,0x1F7C,0x0FF8,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [0] +0x00F0,0x07F0,0x3FF0,0x3FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [1] +0x0FE0,0x3FF8,0x3C7C,0x003C,0x003E,0x003E,0x003E,0x003C,0x003C,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0780,0x0F00,0x1E00,0x3E00,0x3C00,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [2] +0x0FF0,0x1FF8,0x1C7C,0x003E,0x003E,0x003E,0x003C,0x003C,0x00F8,0x0FF0,0x0FF8,0x007C,0x003E,0x001E,0x001E,0x001E,0x001E,0x003E,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [3] +0x0078,0x00F8,0x00F8,0x01F8,0x03F8,0x07F8,0x07F8,0x0F78,0x1E78,0x1E78,0x3C78,0x7878,0x7878,0xFFFF,0xFFFF,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [4] +0x1FFC,0x1FFC,0x1FFC,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FE0,0x1FF8,0x00FC,0x007C,0x003E,0x003E,0x001E,0x003E,0x003E,0x003C,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [5] +0x01FC,0x07FE,0x0F8E,0x1F00,0x1E00,0x3E00,0x3C00,0x3C00,0x3DF8,0x3FFC,0x7F3E,0x7E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3E0F,0x1E1F,0x1F3E,0x0FFC,0x03F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [6] +0x3FFF,0x3FFF,0x3FFF,0x000F,0x001E,0x001E,0x003C,0x0038,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0F80,0x0F80,0x0F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [7] +0x07F8,0x0FFC,0x1F3E,0x1E1E,0x3E1E,0x3E1E,0x1E1E,0x1F3C,0x0FF8,0x07F0,0x0FF8,0x1EFC,0x3E3E,0x3C1F,0x7C1F,0x7C0F,0x7C0F,0x3C1F,0x3F3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [8] +0x07F0,0x0FF8,0x1E7C,0x3C3E,0x3C1E,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x3C1F,0x3E3F,0x1FFF,0x07EF,0x001F,0x001E,0x001E,0x003E,0x003C,0x38F8,0x3FF0,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [9] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [:] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x03C0,0x0380, // Ascii = [;] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0x000F,0x003F,0x00FC,0x03F0,0x0FC0,0x3F00,0xFE00,0x3F00,0x0FC0,0x03F0,0x00FC,0x003F,0x000F,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [<] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [=] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE000,0xF800,0x7E00,0x1F80,0x07E0,0x01F8,0x007E,0x001F,0x007E,0x01F8,0x07E0,0x1F80,0x7E00,0xF800,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [>] +0x1FF0,0x3FFC,0x383E,0x381F,0x381F,0x001E,0x001E,0x003C,0x0078,0x00F0,0x01E0,0x03C0,0x03C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [?] +0x03F8,0x0FFE,0x1F1E,0x3E0F,0x3C7F,0x78FF,0x79EF,0x73C7,0xF3C7,0xF38F,0xF38F,0xF38F,0xF39F,0xF39F,0x73FF,0x7BFF,0x79F7,0x3C00,0x1F1C,0x0FFC,0x03F8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [@] +0x0000,0x0000,0x0000,0x03E0,0x03E0,0x07F0,0x07F0,0x07F0,0x0F78,0x0F78,0x0E7C,0x1E3C,0x1E3C,0x3C3E,0x3FFE,0x3FFF,0x781F,0x780F,0xF00F,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [A] +0x0000,0x0000,0x0000,0x3FF8,0x3FFC,0x3C3E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7C,0x3FF0,0x3FF8,0x3C7E,0x3C1F,0x3C1F,0x3C0F,0x3C0F,0x3C1F,0x3FFE,0x3FF8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [B] +0x0000,0x0000,0x0000,0x01FF,0x07FF,0x1F87,0x3E00,0x3C00,0x7C00,0x7800,0x7800,0x7800,0x7800,0x7800,0x7C00,0x7C00,0x3E00,0x3F00,0x1F83,0x07FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [C] +0x0000,0x0000,0x0000,0x7FF0,0x7FFC,0x787E,0x781F,0x781F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x781F,0x781E,0x787E,0x7FF8,0x7FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [D] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFE,0x3FFE,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [E] +0x0000,0x0000,0x0000,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [F] +0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x7C00,0x7C00,0x7800,0xF800,0xF800,0xF87F,0xF87F,0x780F,0x7C0F,0x7C0F,0x3E0F,0x1F8F,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [G] +0x0000,0x0000,0x0000,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7FFF,0x7FFF,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [H] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [I] +0x0000,0x0000,0x0000,0x1FFC,0x1FFC,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x0078,0x0078,0x38F8,0x3FF0,0x3FC0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [J] +0x0000,0x0000,0x0000,0x3C1F,0x3C1E,0x3C3C,0x3C78,0x3CF0,0x3DE0,0x3FE0,0x3FC0,0x3F80,0x3FC0,0x3FE0,0x3DF0,0x3CF0,0x3C78,0x3C7C,0x3C3E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [K] +0x0000,0x0000,0x0000,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [L] +0x0000,0x0000,0x0000,0xF81F,0xFC1F,0xFC1F,0xFE3F,0xFE3F,0xFE3F,0xFF7F,0xFF77,0xFF77,0xF7F7,0xF7E7,0xF3E7,0xF3E7,0xF3C7,0xF007,0xF007,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [M] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7E0F,0x7F0F,0x7F0F,0x7F8F,0x7F8F,0x7FCF,0x7BEF,0x79EF,0x79FF,0x78FF,0x78FF,0x787F,0x783F,0x783F,0x781F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [N] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [O] +0x0000,0x0000,0x0000,0x3FFC,0x3FFF,0x3E1F,0x3E0F,0x3E0F,0x3E0F,0x3E0F,0x3E1F,0x3E3F,0x3FFC,0x3FF0,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [P] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F8,0x007C,0x003F,0x000F,0x0003,0x0000, // Ascii = [Q] +0x0000,0x0000,0x0000,0x3FF0,0x3FFC,0x3C7E,0x3C3E,0x3C1E,0x3C1E,0x3C3E,0x3C3C,0x3CFC,0x3FF0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [R] +0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x3E0E,0x3C00,0x3C00,0x3C00,0x3E00,0x1FC0,0x0FF8,0x03FE,0x007F,0x001F,0x000F,0x000F,0x201F,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [S] +0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [T] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x3C1E,0x3C1E,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [U] +0x0000,0x0000,0x0000,0xF007,0xF007,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1F3C,0x1F78,0x0F78,0x0FF8,0x07F0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [V] +0x0000,0x0000,0x0000,0xE003,0xF003,0xF003,0xF007,0xF3E7,0xF3E7,0xF3E7,0x73E7,0x7BF7,0x7FF7,0x7FFF,0x7F7F,0x7F7F,0x7F7E,0x3F7E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [W] +0x0000,0x0000,0x0000,0xF807,0x7C0F,0x3E1E,0x3E3E,0x1F3C,0x0FF8,0x07F0,0x07E0,0x03E0,0x03E0,0x07F0,0x0FF8,0x0F7C,0x1E7C,0x3C3E,0x781F,0x780F,0xF00F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [X] +0x0000,0x0000,0x0000,0xF807,0x7807,0x7C0F,0x3C1E,0x3E1E,0x1F3C,0x0F78,0x0FF8,0x07F0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Y] +0x0000,0x0000,0x0000,0x7FFF,0x7FFF,0x000F,0x001F,0x003E,0x007C,0x00F8,0x00F0,0x01E0,0x03E0,0x07C0,0x0F80,0x0F00,0x1E00,0x3E00,0x7C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Z] +0x07FF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07FF,0x07FF,0x0000, // Ascii = [[] +0x7800,0x7800,0x3C00,0x3C00,0x1E00,0x1E00,0x0F00,0x0F00,0x0780,0x0780,0x03C0,0x03C0,0x01E0,0x01E0,0x00F0,0x00F0,0x0078,0x0078,0x003C,0x003C,0x001E,0x001E,0x000F,0x000F,0x0007,0x0000, // Ascii = [\] +0x7FF0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x7FF0,0x7FF0,0x0000, // Ascii = []] +0x00C0,0x01C0,0x01C0,0x03E0,0x03E0,0x07F0,0x07F0,0x0778,0x0F78,0x0F38,0x1E3C,0x1E3C,0x3C1E,0x3C1E,0x380F,0x780F,0x7807,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [^] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // Ascii = [_] +0x00F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [`] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FF8,0x3FFC,0x3C7C,0x003E,0x003E,0x003E,0x07FE,0x1FFE,0x3E3E,0x7C3E,0x783E,0x7C3E,0x7C7E,0x3FFF,0x1FCF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [a] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3C1E,0x3F3E,0x3FFC,0x3BF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [b] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x3E00,0x3C00,0x7C00,0x7C00,0x7C00,0x3C00,0x3E00,0x3E00,0x1F87,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [c] +0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x07FF,0x1FFF,0x3E3F,0x3C1F,0x7C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [d] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0FFC,0x1F3E,0x3E1E,0x3C1F,0x7C1F,0x7FFF,0x7FFF,0x7C00,0x7C00,0x3C00,0x3E00,0x1F07,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [e] +0x01FF,0x03E1,0x03C0,0x07C0,0x07C0,0x07C0,0x7FFF,0x7FFF,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [f] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EF,0x1FFF,0x3E7F,0x3C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x001E,0x001E,0x001E,0x387C,0x3FF8, // Ascii = [g] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [h] +0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x7FE0,0x7FE0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [i] +0x00F8,0x00F8,0x0000,0x0000,0x0000,0x0000,0x3FF8,0x3FF8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F0,0x71F0,0x7FE0, // Ascii = [j] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C1F,0x3C3E,0x3C7C,0x3CF8,0x3DF0,0x3DE0,0x3FC0,0x3FC0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [k] +0x7FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [l] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF79E,0xFFFF,0xFFFF,0xFFFF,0xFBE7,0xF9E7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [m] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [n] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x3C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x3C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [o] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3E1E,0x3F3E,0x3FFC,0x3FF8,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00, // Ascii = [p] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EE,0x1FFE,0x3E7E,0x3C1E,0x7C1E,0x781E,0x781E,0x781E,0x781E,0x781E,0x7C1E,0x7C3E,0x3E7E,0x1FFE,0x0FDE,0x001E,0x001E,0x001E,0x001E,0x001E, // Ascii = [q] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1F7F,0x1FFF,0x1FE7,0x1FC7,0x1F87,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [r] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x1E0E,0x3E00,0x3E00,0x3F00,0x1FE0,0x07FC,0x00FE,0x003E,0x001E,0x001E,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [s] +0x0000,0x0000,0x0000,0x0780,0x0780,0x0780,0x7FFF,0x7FFF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07C0,0x03FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [t] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7E,0x3EFE,0x1FFE,0x0FDE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [u] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF007,0x780F,0x780F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1E3C,0x0F78,0x0F78,0x0FF0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [v] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF003,0xF1E3,0xF3E3,0xF3E7,0xF3F7,0xF3F7,0x7FF7,0x7F77,0x7F7F,0x7F7F,0x7F7F,0x3E3E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [w] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C0F,0x3E1E,0x3E3C,0x1F3C,0x0FF8,0x07F0,0x07F0,0x03E0,0x07F0,0x07F8,0x0FF8,0x1E7C,0x3E3E,0x3C1F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [x] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x1E3C,0x1E3C,0x1F3C,0x0F78,0x0FF8,0x07F0,0x07F0,0x03E0,0x03E0,0x03C0,0x03C0,0x03C0,0x0780,0x0F80,0x7F00, // Ascii = [y] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x001F,0x003E,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0F80,0x1F00,0x1E00,0x3C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [z] +0x01FE,0x03E0,0x03C0,0x03C0,0x03C0,0x03C0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x3F80,0x3F80,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x03C0,0x03C0,0x03C0,0x03C0,0x03E0,0x01FE,0x007E,0x0000, // Ascii = [{] +0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000, // Ascii = [|] +0x3FC0,0x03E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x00FE,0x00FE,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x01E0,0x03E0,0x3FC0,0x3F00,0x0000, // Ascii = [}] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3F07,0x7FC7,0x73E7,0xF1FF,0xF07E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [~] +}; +#endif +#ifdef SSD1306_INCLUDE_FONT_6x8 +static const uint16_t Font6x8 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x0000, // ! +0x5000, 0x5000, 0x5000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x5000, 0x5000, 0xf800, 0x5000, 0xf800, 0x5000, 0x5000, 0x0000, // # +0x2000, 0x7800, 0xa000, 0x7000, 0x2800, 0xf000, 0x2000, 0x0000, // $ +0xc000, 0xc800, 0x1000, 0x2000, 0x4000, 0x9800, 0x1800, 0x0000, // % +0x4000, 0xa000, 0xa000, 0x4000, 0xa800, 0x9000, 0x6800, 0x0000, // & +0x3000, 0x3000, 0x2000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x1000, 0x2000, 0x4000, 0x4000, 0x4000, 0x2000, 0x1000, 0x0000, // ( +0x4000, 0x2000, 0x1000, 0x1000, 0x1000, 0x2000, 0x4000, 0x0000, // ) +0x2000, 0xa800, 0x7000, 0xf800, 0x7000, 0xa800, 0x2000, 0x0000, // * +0x0000, 0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x2000, 0x0000, // , +0x0000, 0x0000, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, // . +0x0000, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, 0x0000, // / +0x7000, 0x8800, 0x9800, 0xa800, 0xc800, 0x8800, 0x7000, 0x0000, // 0 +0x2000, 0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // 1 +0x7000, 0x8800, 0x0800, 0x7000, 0x8000, 0x8000, 0xf800, 0x0000, // 2 +0xf800, 0x0800, 0x1000, 0x3000, 0x0800, 0x8800, 0x7000, 0x0000, // 3 +0x1000, 0x3000, 0x5000, 0x9000, 0xf800, 0x1000, 0x1000, 0x0000, // 4 +0xf800, 0x8000, 0xf000, 0x0800, 0x0800, 0x8800, 0x7000, 0x0000, // 5 +0x3800, 0x4000, 0x8000, 0xf000, 0x8800, 0x8800, 0x7000, 0x0000, // 6 +0xf800, 0x0800, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, // 7 +0x7000, 0x8800, 0x8800, 0x7000, 0x8800, 0x8800, 0x7000, 0x0000, // 8 +0x7000, 0x8800, 0x8800, 0x7800, 0x0800, 0x1000, 0xe000, 0x0000, // 9 +0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x2000, 0x4000, 0x0000, // ; +0x0800, 0x1000, 0x2000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, // < +0x0000, 0x0000, 0xf800, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, // = +0x4000, 0x2000, 0x1000, 0x0800, 0x1000, 0x2000, 0x4000, 0x0000, // > +0x7000, 0x8800, 0x0800, 0x3000, 0x2000, 0x0000, 0x2000, 0x0000, // ? +0x7000, 0x8800, 0xa800, 0xb800, 0xb000, 0x8000, 0x7800, 0x0000, // @ +0x2000, 0x5000, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x0000, // A +0xf000, 0x8800, 0x8800, 0xf000, 0x8800, 0x8800, 0xf000, 0x0000, // B +0x7000, 0x8800, 0x8000, 0x8000, 0x8000, 0x8800, 0x7000, 0x0000, // C +0xf000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0xf000, 0x0000, // D +0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0xf800, 0x0000, // E +0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // F +0x7800, 0x8800, 0x8000, 0x8000, 0x9800, 0x8800, 0x7800, 0x0000, // G +0x8800, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x8800, 0x0000, // H +0x7000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // I +0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // J +0x8800, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x8800, 0x0000, // K +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xf800, 0x0000, // L +0x8800, 0xd800, 0xa800, 0xa800, 0xa800, 0x8800, 0x8800, 0x0000, // M +0x8800, 0x8800, 0xc800, 0xa800, 0x9800, 0x8800, 0x8800, 0x0000, // N +0x7000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // O +0xf000, 0x8800, 0x8800, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // P +0x7000, 0x8800, 0x8800, 0x8800, 0xa800, 0x9000, 0x6800, 0x0000, // Q +0xf000, 0x8800, 0x8800, 0xf000, 0xa000, 0x9000, 0x8800, 0x0000, // R +0x7000, 0x8800, 0x8000, 0x7000, 0x0800, 0x8800, 0x7000, 0x0000, // S +0xf800, 0xa800, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // T +0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // U +0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // V +0x8800, 0x8800, 0x8800, 0xa800, 0xa800, 0xa800, 0x5000, 0x0000, // W +0x8800, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x8800, 0x0000, // X +0x8800, 0x8800, 0x5000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // Y +0xf800, 0x0800, 0x1000, 0x7000, 0x4000, 0x8000, 0xf800, 0x0000, // Z +0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7800, 0x0000, // [ +0x0000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, 0x0000, /* \ */ +0x7800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x7800, 0x0000, // ] +0x2000, 0x5000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf800, 0x0000, // _ +0x6000, 0x6000, 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x6000, 0x1000, 0x7000, 0x9000, 0x7800, 0x0000, // a +0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0xc800, 0xb000, 0x0000, // b +0x0000, 0x0000, 0x7000, 0x8800, 0x8000, 0x8800, 0x7000, 0x0000, // c +0x0800, 0x0800, 0x6800, 0x9800, 0x8800, 0x9800, 0x6800, 0x0000, // d +0x0000, 0x0000, 0x7000, 0x8800, 0xf800, 0x8000, 0x7000, 0x0000, // e +0x1000, 0x2800, 0x2000, 0x7000, 0x2000, 0x2000, 0x2000, 0x0000, // f +0x0000, 0x0000, 0x7000, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // g +0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // h +0x2000, 0x0000, 0x6000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // i +0x1000, 0x0000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // j +0x8000, 0x8000, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x0000, // k +0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // l +0x0000, 0x0000, 0xd000, 0xa800, 0xa800, 0xa800, 0xa800, 0x0000, // m +0x0000, 0x0000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // n +0x0000, 0x0000, 0x7000, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // o +0x0000, 0x0000, 0xb000, 0xc800, 0xc800, 0xb000, 0x8000, 0x0000, // p +0x0000, 0x0000, 0x6800, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // q +0x0000, 0x0000, 0xb000, 0xc800, 0x8000, 0x8000, 0x8000, 0x0000, // r +0x0000, 0x0000, 0x7800, 0x8000, 0x7000, 0x0800, 0xf000, 0x0000, // s +0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x2800, 0x1000, 0x0000, // t +0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x9800, 0x6800, 0x0000, // u +0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // v +0x0000, 0x0000, 0x8800, 0x8800, 0xa800, 0xa800, 0x5000, 0x0000, // w +0x0000, 0x0000, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x0000, // x +0x0000, 0x0000, 0x8800, 0x8800, 0x7800, 0x0800, 0x8800, 0x0000, // y +0x0000, 0x0000, 0xf800, 0x1000, 0x2000, 0x4000, 0xf800, 0x0000, // z +0x1000, 0x2000, 0x2000, 0x4000, 0x2000, 0x2000, 0x1000, 0x0000, // { +0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x2000, 0x2000, 0x0000, // | +0x4000, 0x2000, 0x2000, 0x1000, 0x2000, 0x2000, 0x4000, 0x0000, // } +0x4000, 0xa800, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif + +#ifdef SSD1306_INCLUDE_FONT_6x8 +FontDef Font_6x8 = {6,8,Font6x8}; +#endif +#ifdef SSD1306_INCLUDE_FONT_7x10 +FontDef Font_7x10 = {7,10,Font7x10}; +#endif +#ifdef SSD1306_INCLUDE_FONT_11x18 +FontDef Font_11x18 = {11,18,Font11x18}; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +FontDef Font_16x26 = {16,26,Font16x26}; +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.h" new file mode 100755 index 0000000000000000000000000000000000000000..53543346d27fec87dc968698028efea9b71614b7 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/12_ssd1306/ssd1306/ssd1306_fonts.h" @@ -0,0 +1,26 @@ +#include + +#ifndef __SSD1306_FONTS_H__ +#define __SSD1306_FONTS_H__ + +#include "ssd1306_conf.h" + +typedef struct { + const uint8_t FontWidth; /*!< Font width in pixels */ + uint8_t FontHeight; /*!< Font height in pixels */ + const uint16_t *data; /*!< Pointer to data font data array */ +} FontDef; + +#ifdef SSD1306_INCLUDE_FONT_6x8 +extern FontDef Font_6x8; +#endif +#ifdef SSD1306_INCLUDE_FONT_7x10 +extern FontDef Font_7x10; +#endif +#ifdef SSD1306_INCLUDE_FONT_11x18 +extern FontDef Font_11x18; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +extern FontDef Font_16x26; +#endif +#endif // __SSD1306_FONTS_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..725b42de89a4b1304645ec2a4513ee99f2f0e0e5 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/BUILD.gn" @@ -0,0 +1,36 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") + +lite_component("app") { + features = [ + "oled/ssd1306:oled_ssd1306", + "oled/libm_port:libm_port", + "play:stream_player", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/LICENSE" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/LICENSE" new file mode 100755 index 0000000000000000000000000000000000000000..32b4eb974c990c9888afc967812a3d42e4999e77 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/LICENSE" @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2020, Siwei Xu +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..70fa103c7f2b1246e819e91a80a0e86954ff3729 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/README.md" @@ -0,0 +1,79 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--oled_player + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、简介 + +* 基于HiSpark WiFi IoT套件(Hi3861芯片),板载0.96寸 128x64 分辨率的 OLED屏 +* 板端程序使用了[鸿蒙OS SSD1306 OLED屏驱动库](https://gitee.com/hihopeorg/hispark-hm-pegasus/tree/master/sample/12_ssd1306),用于实现每帧画面的绘制; +* PC端使用了`opencv-python`,用于实现视频解码、画面缩放、二值化和帧数据打包; + +## 二、如何编译 + +1. 将此目录复制到openharmony源码的根目录下 +2. 修改openharmony源码的`build\lite\product\wifiiot.json`文件: + * 将其中的`//applications/sample/wifi-iot/app`替换为`//13_oledplayer:app` + +3. 在openharmony源码顶层目录下执行:`python build.py wifiiot` + +## 三、如何运行 + +网络环境:一个无线热点,一台PC,PC连接在该热点上; + +### 准备视频资源 + +1. 选择准备播放的视频,使用工具将帧率转为10fps; + * 目前ssd1306库实测的最大帧率为10fps; + * ffmpeg转换命令:`ffmpeg -i input.mp4 -r 10 output.mp4` + * ffmpeg在Ubuntu上可以直接试用`sudo apt install ffmpeg`安装,Windows上可以在官网下载二进制包:https://ffmpeg.org/download.html#build-windows +2. 运行命令:`./video2bin.py output.mp4 out.bin`,将视频转为bin文件; +3. video2bin.py 依赖 `opencv-python` 包,使用 `pip install opencv-python` 命令安装; + + +### 运行程序 + +1. PC上运行命令:`./bin2stream.py out.bin`,将会启动一个TCP服务器,默认监听`5678`端口 +2. 根据热点信息(SSID,PSK)和PC的IP地址,修改`play/net_params.h`文件中的相关参数: +3. 重新编译:`python build.py wifiiot` +4. 将重新编译好的固件烧录到WiFi IoT开发板上,并复位设备; + * 板子启动后,首先会连上你的热点,然后会连接PC上的TCP服务; + * 然后就可以看到视频的在OLED屏播放了; + + + +## 四、原理介绍 + +整体为C/S架构: + +* 使用TCP传输帧数据,实现了简单的二进制协议: + * 请求格式:帧ID(4B); + * 响应格式:状态码(4B) + 帧数据长度(4B)+ 帧数据(可选); +* PC上运行服务端,默认监听`5678`端口,使用Python开发; + * 启动时加载整个bin文件,并将其按照帧数据大小分割,放入一个list中; + * 客户端请求特定帧时,直接根据下标索引取出对应帧,并发送给客户端; + * 这样的设计(视频预先转换好),可以保证服务端的响应尽可能快; +* 板上运行客户端; + * 主动发送帧请求,并接收服务端的回应; + * 收到帧数据后通过I2C向OLED屏发送帧数据; + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/bin2stream.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/bin2stream.py" new file mode 100755 index 0000000000000000000000000000000000000000..134fd1e0596cb1c6d82d3f3147ccb1411de7d1ee --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/bin2stream.py" @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +import sys +import struct +import signal +from threading import Thread +from datetime import datetime +from socketserver import ThreadingTCPServer, StreamRequestHandler + +TARGET_WIDTH = 128 +TARGET_HEIGHT = 64 +PIXEL_PER_BYTE = 8 + +BIN_FRAME_SIZE = int(TARGET_WIDTH * TARGET_HEIGHT / PIXEL_PER_BYTE) + +DEFAULT_PORT = 5678 + +REQUEST_SIZE = 4 +STATUS_SUCCESS = 0 +STATUS_FAILURE = 255 + +class EncodeHandler(StreamRequestHandler): + bitmapList = [] + + def handle(self): + addr = self.request.getpeername() + print('Got connection from', addr) + + while True: + startTime = datetime.now() + req = self.rfile.read(REQUEST_SIZE) + if not req: + break + # recv request from client + frameId = int.from_bytes(req, 'big') # bytes request + + # prepare response + status, body = None, bytes() + if frameId < len(EncodeHandler.bitmapList): + status = STATUS_SUCCESS + body = EncodeHandler.bitmapList[frameId] + else: + status = STATUS_FAILURE + print('frameId out of range!') + break + # response header is: status(4B) + body length(4B) + head = struct.pack('>II', status, len(body)) + + # send response(header + body) to client + self.wfile.write(head + body) + + currentTime = datetime.now() + timeCost = currentTime - startTime + print('frameId:', frameId, 'timeCost: %.3f' % timeCost.total_seconds()) + print('handle request from', addr, 'done!') + self.wfile.close() + +def load_video_bin(binFile): + binFrames = [] + print('loading', binFile, '...') + with open(binFile, 'rb') as f: + while True: + blob = f.read(BIN_FRAME_SIZE) + if len(blob) == 0: + break + binFrames.append(blob) + print('load', binFile, 'done!') + return binFrames + +def main(): + if len(sys.argv) < 2: + print("Usage: {} binFile [port]\n\t".format(sys.argv[0])) + exit(-1) + + binFile = sys.argv[1] + port = DEFAULT_PORT if len(sys.argv) < 3 else int(sys.argv[2]) + + print('binFile:', binFile, 'port:', port) + server = ThreadingTCPServer(('', port), EncodeHandler) + + def sigint_handler(signum, frame): + print('sig {} raised: {}'.format(signum, frame)) + server.socket.close() + server.shutdown() + sys.exit(0) + signal.signal(signal.SIGINT, sigint_handler) # main thread will handle signals + + try: + EncodeHandler.bitmapList = load_video_bin(binFile) + waiterThread = Thread(target=server.serve_forever, args=()) + waiterThread.start() + waiterThread.join() + except Exception as e: + print('exception raised:', e) + finally: + server.socket.close() + server.shutdown() + +if __name__ == "__main__": + main() diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..c2235f1a49735b0c411b48c0acc1fd5e93db2af2 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/BUILD.gn" @@ -0,0 +1,36 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import("//build/lite/config/component/lite_component.gni") + +lite_component("app") { + features = [ + "ssd1306:oled_ssd1306", + "examples:oled_test", + "libm_port:libm_port" + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..a6aadc6b9d49b5d0b921f5c789d86e47180f6763 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("oled_test") { + sources = [ + "ssd1306_demo.c", + "ssd1306_tests.c", + ] + + include_dirs = [ + "../ssd1306", + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..9b09c404cac6f3d946dd4c1c2bf462a4f3787986 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_demo.c" @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_adc.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" +#include "wifiiot_watchdog.h" + +#include "ssd1306.h" +#include "ssd1306_tests.h" + +#define OLED_I2C_BAUDRATE 400*1000 + + + +const unsigned char headSize[] = { 64, 64 }; +const unsigned char headData[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0x80, 0x00, +0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00, +0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x00, 0x00, 0xFF, 0x83, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE3, 0xF0, 0x18, 0x00, +0x00, 0x00, 0x01, 0xFF, 0xE3, 0xE0, 0x10, 0x00, 0x00, 0x00, 0x61, 0xFE, 0x03, 0xE1, 0xF8, 0x00, +0x00, 0xC1, 0xF1, 0xF8, 0x97, 0xE0, 0x18, 0x00, 0x00, 0x00, 0xB9, 0xFF, 0xFF, 0xF8, 0x88, 0x00, +0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFD, 0xF8, 0x00, 0x00, 0x00, 0xFD, 0xFF, 0xFF, 0xFE, 0x78, 0x00, +0x00, 0x00, 0xCD, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x40, 0xDF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, +0x00, 0x40, 0xDF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x40, 0x7F, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, +0x00, 0xA0, 0x7F, 0xFF, 0xFF, 0xFF, 0xF9, 0x00, 0x01, 0x20, 0x3F, 0xFF, 0xFC, 0x47, 0xF8, 0x00, +0x02, 0x10, 0x1F, 0xFF, 0xFF, 0x87, 0xF0, 0x00, 0x0C, 0x18, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, +0x00, 0x08, 0x07, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0D, 0x07, 0xFF, 0xFC, 0x07, 0xF0, 0x00, +0x00, 0x05, 0x07, 0xFF, 0xC0, 0x01, 0xF0, 0x00, 0x00, 0x05, 0x07, 0xFF, 0xDF, 0xE1, 0xE0, 0x00, +0x02, 0x06, 0x07, 0xFF, 0xFF, 0x09, 0xE0, 0x00, 0x00, 0x02, 0x07, 0xFF, 0xFE, 0x1F, 0xC0, 0x00, +0x00, 0x02, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x60, 0x3F, 0xFF, 0xFF, 0xFF, 0x80, 0x00, +0x00, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x32, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, +0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, +0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0xF0, 0x00, 0x00, +0x00, 0x07, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x01, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x07, +0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xF0, 0xE0, 0x3F, 0x00, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, +}; + +/** + * 汉字字模在线: https://www.23bei.com/tool-223.html + * 数据排列:从左到右从上到下 + * 取模方式:横向8位左高位 +**/ +void TestDrawChinese1(void) +{ + const uint32_t W = 16, H = 16; + uint8_t fonts[][32] = { + { + /*-- ID:0,字符:"你",ASCII编码:C4E3,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x11,0x00,0x11,0x00,0x11,0x00,0x23,0xFC,0x22,0x04,0x64,0x08,0xA8,0x40,0x20,0x40, + 0x21,0x50,0x21,0x48,0x22,0x4C,0x24,0x44,0x20,0x40,0x20,0x40,0x21,0x40,0x20,0x80, + },{ + /*-- ID:1,字符:"好",ASCII编码:BAC3,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x10,0x00,0x11,0xFC,0x10,0x04,0x10,0x08,0xFC,0x10,0x24,0x20,0x24,0x24,0x27,0xFE, + 0x24,0x20,0x44,0x20,0x28,0x20,0x10,0x20,0x28,0x20,0x44,0x20,0x84,0xA0,0x00,0x40, + },{ + /*-- ID:2,字符:"鸿",ASCII编码:BAE8,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x40,0x20,0x30,0x48,0x10,0xFC,0x02,0x88,0x9F,0xA8,0x64,0x88,0x24,0xA8,0x04,0x90, + 0x14,0x84,0x14,0xFE,0xE7,0x04,0x3C,0x24,0x29,0xF4,0x20,0x04,0x20,0x14,0x20,0x08, + },{ + /*-- ID:3,字符:"蒙",ASCII编码:C3C9,对应字:宽x高=16x16,画布:宽W=16 高H=16,共32字节*/ + 0x04,0x48,0x7F,0xFC,0x04,0x40,0x7F,0xFE,0x40,0x02,0x8F,0xE4,0x00,0x00,0x7F,0xFC, + 0x06,0x10,0x3B,0x30,0x05,0xC0,0x1A,0xA0,0x64,0x90,0x18,0x8E,0x62,0x84,0x01,0x00 + } + }; + + ssd1306_Fill(Black); + for (size_t i = 0; i < sizeof(fonts)/sizeof(fonts[0]); i++) { + ssd1306_DrawRegion(i * W, 0, W, H, fonts[i], sizeof(fonts[0]), W); + } + + ssd1306_SetCursor(64, 0); + ssd1306_DrawRegion(64, 0, headSize[0], headSize[1], headData, sizeof(headData), headSize[0]); + ssd1306_UpdateScreen(); +} + +void TestDrawChinese2(void) +{ + const uint32_t W = 12, H = 12, S = 16; + uint8_t fonts[][24] = { + { + /*-- ID:0,字符:"你",ASCII编码:C4E3,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x12,0x00,0x12,0x00,0x27,0xF0,0x24,0x20,0x69,0x40,0xA1,0x00,0x25,0x40,0x25,0x20, + 0x29,0x10,0x31,0x10,0x25,0x00,0x22,0x00, + },{ + /*-- ID:1,字符:"好",ASCII编码:BAC3,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x20,0x00,0x27,0xE0,0x20,0x40,0xF8,0x80,0x48,0x80,0x48,0xA0,0x57,0xF0,0x50,0x80, + 0x30,0x80,0x28,0x80,0x4A,0x80,0x81,0x00, + },{ + /*-- ID:2,字符:"鸿",ASCII编码:BAE8,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x00,0x40,0x80,0x80,0x5D,0xE0,0x09,0x20,0xC9,0xA0,0x09,0x60,0x29,0x00,0xCD,0xF0, + 0x58,0x10,0x43,0xD0,0x40,0x10,0x40,0x60, + },{ + /*-- ID:3,字符:"蒙",ASCII编码:C3C9,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/ + 0x09,0x00,0x7F,0xE0,0x09,0x00,0x7F,0xF0,0x80,0x10,0x7F,0xE0,0x0C,0x40,0x32,0x80, + 0xC7,0x00,0x0A,0x80,0x32,0x70,0xC6,0x20 + } + }; + + ssd1306_Fill(Black); + for (size_t i = 0; i < sizeof(fonts)/sizeof(fonts[0]); i++) { + ssd1306_DrawRegion(i * H, 0, W, H, fonts[i], sizeof(fonts[0]), S); + } + + ssd1306_SetCursor(64, 0); + ssd1306_DrawRegion(64, 0, headSize[0], headSize[1], headData, sizeof(headData), headSize[0]); + + ssd1306_SetCursor(0, 64 - 8); + ssd1306_DrawString("gitee.com", Font_6x8, White); + + ssd1306_SetCursor(0, 64 - 8*2); + ssd1306_DrawString("@swxu", Font_6x8, White); + + ssd1306_UpdateScreen(); +} + +void TestShowChars(FontDef font, uint8_t w, uint8_t h) +{ + ssd1306_Fill(Black); + + uint8_t x = 0, y = 0; + for (uint8_t c = 1; c < 128; c++) { + if (isprint(c)) { + ssd1306_SetCursor(x, y); + ssd1306_DrawChar((char) c, font, White); + x += w; + if (x >= SSD1306_WIDTH) { + x = 0; + y += h; + } + } + } + + ssd1306_UpdateScreen(); +} + +void Ssd1306TestTask(void* arg) +{ + (void) arg; + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); + I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); + + WatchDogDisable(); + + usleep(20*1000); + ssd1306_Init(); + ssd1306_Fill(Black); + ssd1306_SetCursor(0, 0); + ssd1306_DrawString("Hello OpenHarmony!", Font_7x10, White); + + uint32_t start = HAL_GetTick(); + ssd1306_UpdateScreen(); + uint32_t end = HAL_GetTick(); + printf("ssd1306_UpdateScreen time cost: %d ms.\r\n", end - start); + + while (1) { + TestDrawChinese1(); + osDelay(500); + + TestDrawChinese2(); + osDelay(500); + + TestShowChars(Font_6x8, 6, 8); + osDelay(500); + + TestShowChars(Font_7x10, 7, 10); + osDelay(500); + + ssd1306_TestAll(); + } +} + +void Ssd1306TestDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "Ssd1306Task"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(Ssd1306TestTask, NULL, &attr) == NULL) { + printf("[Ssd1306TestDemo] Falied to create Ssd1306TestTask!\n"); + } +} +APP_FEATURE_INIT(Ssd1306TestDemo); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.c" new file mode 100755 index 0000000000000000000000000000000000000000..6d5331d6df6f0f5c17e4eb9ab11cbbb65fbd4d26 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.c" @@ -0,0 +1,231 @@ +#include +#include +#include "ssd1306.h" +#include "ssd1306_tests.h" + +void ssd1306_TestBorder() { + ssd1306_Fill(Black); + + uint32_t start = HAL_GetTick(); + uint32_t end = start; + uint8_t x = 0; + uint8_t y = 0; + do { + ssd1306_DrawPixel(x, y, Black); + + if((y == 0) && (x < 127)) + x++; + else if((x == 127) && (y < 63)) + y++; + else if((y == 63) && (x > 0)) + x--; + else + y--; + + ssd1306_DrawPixel(x, y, White); + ssd1306_UpdateScreen(); + + end = HAL_GetTick(); + } while((end - start) < 8000); + + HAL_Delay(1000); +} + +void ssd1306_TestFonts() { + ssd1306_Fill(Black); + ssd1306_SetCursor(2, 0); + ssd1306_DrawString("Font 16x26", Font_16x26, White); + ssd1306_SetCursor(2, 26); + ssd1306_DrawString("Font 11x18", Font_11x18, White); + ssd1306_SetCursor(2, 26+18); + ssd1306_DrawString("Font 7x10", Font_7x10, White); + ssd1306_SetCursor(2, 26+18+10); + ssd1306_DrawString("Font 6x8", Font_6x8, White); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestFPS() { + ssd1306_Fill(White); + + uint32_t start = HAL_GetTick(); + uint32_t end = start; + int fps = 0; + char message[] = "ABCDEFGHIJK"; + + ssd1306_SetCursor(2,0); + ssd1306_DrawString("Testing...", Font_11x18, Black); + + do { + ssd1306_SetCursor(2, 18); + ssd1306_DrawString(message, Font_11x18, Black); + ssd1306_UpdateScreen(); + + char ch = message[0]; + memmove(message, message+1, sizeof(message)-2); + message[sizeof(message)-2] = ch; + + fps++; + end = HAL_GetTick(); + } while((end - start) < 5000); + + HAL_Delay(1000); + + char buff[64]; + fps = (float)fps / ((end - start) / 1000.0); + snprintf(buff, sizeof(buff), "~%d FPS", fps); + + ssd1306_Fill(White); + ssd1306_SetCursor(2, 18); + ssd1306_DrawString(buff, Font_11x18, Black); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestLine() { + + ssd1306_DrawLine(1,1,SSD1306_WIDTH - 1,SSD1306_HEIGHT - 1,White); + ssd1306_DrawLine(SSD1306_WIDTH - 1,1,1,SSD1306_HEIGHT - 1,White); + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestRectangle() { + uint32_t delta; + + for(delta = 0; delta < 5; delta ++) { + ssd1306_DrawRectangle(1 + (5*delta),1 + (5*delta) ,SSD1306_WIDTH-1 - (5*delta),SSD1306_HEIGHT-1 - (5*delta),White); + } + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestCircle() { + uint32_t delta; + + for(delta = 0; delta < 5; delta ++) { + ssd1306_DrawCircle(20* delta+30, 30, 10, White); + } + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestArc() { + + ssd1306_DrawArc(30, 30, 30, 20, 270, White); + ssd1306_UpdateScreen(); + return; +} + +void ssd1306_TestPolyline() { + SSD1306_VERTEX loc_vertex[] = + { + {35,40}, + {40,20}, + {45,28}, + {50,10}, + {45,16}, + {50,10}, + {53,16} + }; + + ssd1306_DrawPolyline(loc_vertex,sizeof(loc_vertex)/sizeof(loc_vertex[0]),White); + ssd1306_UpdateScreen(); + return; +} + +static const unsigned char bitmap[] = { +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0F, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7F, 0xF8, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0x80, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x7F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x03, 0xE0, 0x7F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF0, 0x3F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x0F, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x07, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFF, 0x03, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x87, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x07, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFC, 0x03, 0xFC, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFE, 0x07, 0xFC, 0x3E, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xF8, 0x0F, 0xFE, 0x7F, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xF0, 0xFF, 0xFE, 0x7F, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xF8, 0xFF, 0xFC, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xFC, 0xFF, 0x1B, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x7E, 0x37, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0x81, 0xEF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xDF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +void ssd1306_TestBitmap(void) { + ssd1306_Fill(Black); + ssd1306_DrawBitmap(bitmap, sizeof(bitmap)); + ssd1306_UpdateScreen(); +} + +void ssd1306_TestAll() { + ssd1306_Init(); + ssd1306_TestBitmap(); + HAL_Delay(2000); + ssd1306_TestFPS(); + HAL_Delay(1000); + ssd1306_TestBorder(); + ssd1306_TestFonts(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestRectangle(); + ssd1306_TestLine(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestPolyline(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestArc(); + HAL_Delay(3000); + ssd1306_Fill(Black); + ssd1306_TestCircle(); + HAL_Delay(3000); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.h" new file mode 100755 index 0000000000000000000000000000000000000000..e16002a3f56ec48b770300f0c14034a6cb59bb26 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/examples/ssd1306_tests.h" @@ -0,0 +1,22 @@ +#ifndef __SSD1306_TEST_H__ +#define __SSD1306_TEST_H__ + +#include <_ansi.h> + +_BEGIN_STD_C + +void ssd1306_TestBorder(void); +void ssd1306_TestFonts(void); +void ssd1306_TestFPS(void); +void ssd1306_TestAll(void); +void ssd1306_TestLine(void); +void ssd1306_TestRectangle(void); +void ssd1306_TestCircle(void); +void ssd1306_TestArc(void); +void ssd1306_TestPolyline(void); + + + +_END_STD_C + +#endif // __SSD1306_TEST_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/gif2imgs.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/gif2imgs.py" new file mode 100755 index 0000000000000000000000000000000000000000..17ed9cc8ba44c349e1f65367333cc1e7eda13773 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/gif2imgs.py" @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +import os +import sys +from PIL import Image + +if len(sys.argv) < 2: + print('Usage: {} gif outdir'.format(sys.argv[0])) + exit(-1) + +gifimg = sys.argv[1] +outdir = sys.argv[2] + +im = Image.open(gifimg) +if not os.path.exists(outdir): + os.mkdir(outdir) + +i = 0 +try: + while True: + im.seek(i) + im.save(os.path.join(outdir, 'frame' + str(i) + '.png')) + i += 1 +except: + pass +print('images:', i) diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/img2code.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/img2code.py" new file mode 100755 index 0000000000000000000000000000000000000000..c79463d26c23a288eb79e60efef5f20c0e73599b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/img2code.py" @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import cv2 +import sys +import os +from datetime import datetime + +DEBUG = False +DEBUG = True +TARGET_WIDTH = 128 +TARGET_HEIGHT = 64 +PIXEL_PER_BYTE = 8 +WIDTH_BYTES = int(TARGET_WIDTH/PIXEL_PER_BYTE) +PIXEL_THRESHOLD = 128.0 + +# 将多个灰度像素打包到一个整数中 +def pack_pixels(pixels, threshold): + value = 0 + for gray in pixels: + bit = 1 if gray >= threshold else 0 # 二值化 + value = (value << 1) + bit # 多个二值化像素值拼接为一个字节值 + return value + +frameCount = 0 +def resize_and_binarize_image(frame, width, height, threshold): + data = [] + # count = 0 # for debug + start = datetime.now() + frame = cv2.resize(frame, (width, height)) # 缩放 + frame = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) # 转为灰度图 + _, binary = cv2.threshold(frame, threshold, 255, cv2.THRESH_BINARY) # 二值化 + + for r in range(height): + for b in range(int(width / PIXEL_PER_BYTE)): + colStart = b * PIXEL_PER_BYTE + pixels = frame[r, colStart: colStart + PIXEL_PER_BYTE] + byte = pack_pixels(pixels, threshold) + data.append(byte) + if DEBUG: + global frameCount + cv2.imwrite(os.path.join('debug', str(frameCount) + '.png'), frame) + cv2.imwrite(os.path.join('debug', str(frameCount) + '-bin.png'), binary) + frameCount += 1 + end = datetime.now() + print('time cost:', end - start) + return bytes(data) + +def convert_frame_to_bytes(frame): + return resize_and_binarize_image(frame, TARGET_WIDTH, TARGET_HEIGHT, PIXEL_THRESHOLD) + +def main(): + if len(sys.argv) < 3: + print("Usage: {} input outdir [width] [height] [threshod]".format(sys.argv[0])) + exit(-1) + + imgPath = sys.argv[1] + outdir = sys.argv[2] + width = len(sys.argv) > 3 and int(sys.argv[3]) or TARGET_WIDTH + height = len(sys.argv) > 4 and int(sys.argv[4]) or TARGET_HEIGHT + threshold = len(sys.argv) > 5 and int(sys.argv[5]) or PIXEL_THRESHOLD + imgFile = os.path.split(imgPath)[-1] + imgBase = imgFile.split('.')[-2] + codeFile = os.path.join(outdir, imgBase + '.c') + if not os.path.exists(outdir): + os.mkdir(outdir) + + frame = cv2.imread(imgPath) # 加载图片 + bitmap = resize_and_binarize_image(frame, width, height, threshold) # 转为目标格式的数组 + + with open(codeFile, 'w+') as f: # 输出到.c文件 + f.write('const unsigned char {}_size[] = {{ {}, {} }};\n'.format(imgBase, width, height)) + f.write('const unsigned char {}[] = {{\n'.format(imgBase)) + for i in range(len(bitmap)): + v = bitmap[i] + sep = '\n' if (i+1) % (TARGET_WIDTH/PIXEL_PER_BYTE) == 0 else ' ' + f.write('0x%02X,%s' % (v, sep)) + f.write('};\n') + print(imgFile, '=>', codeFile, 'done!') + +if __name__ == "__main__": + main() diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..0d9e08dd082b70aae807de96a425d1b08bc31406 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/BUILD.gn" @@ -0,0 +1,43 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("libm_port") { + sources = [ + "__sin.c", + "__cos.c", + "__rem_pio2.c", + "__rem_pio2_large.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__cos.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__cos.c" new file mode 100755 index 0000000000000000000000000000000000000000..46cefb38134398a4e0e7b40621eb6ea6e514ca38 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__cos.c" @@ -0,0 +1,71 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_cos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * __cos( x, y ) + * kernel cos function on [-pi/4, pi/4], pi/4 ~ 0.785398164 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * + * Algorithm + * 1. Since cos(-x) = cos(x), we need only to consider positive x. + * 2. if x < 2^-27 (hx<0x3e400000 0), return 1 with inexact if x!=0. + * 3. cos(x) is approximated by a polynomial of degree 14 on + * [0,pi/4] + * 4 14 + * cos(x) ~ 1 - x*x/2 + C1*x + ... + C6*x + * where the remez error is + * + * | 2 4 6 8 10 12 14 | -58 + * |cos(x)-(1-.5*x +C1*x +C2*x +C3*x +C4*x +C5*x +C6*x )| <= 2 + * | | + * + * 4 6 8 10 12 14 + * 4. let r = C1*x +C2*x +C3*x +C4*x +C5*x +C6*x , then + * cos(x) ~ 1 - x*x/2 + r + * since cos(x+y) ~ cos(x) - sin(x)*y + * ~ cos(x) - x*y, + * a correction term is necessary in cos(x) and hence + * cos(x+y) = 1 - (x*x/2 - (r - x*y)) + * For better accuracy, rearrange to + * cos(x+y) ~ w + (tmp + (r-x*y)) + * where w = 1 - x*x/2 and tmp is a tiny correction term + * (1 - x*x/2 == w + tmp exactly in infinite precision). + * The exactness of w + tmp in infinite precision depends on w + * and tmp having the same precision as x. If they have extra + * precision due to compiler bugs, then the extra precision is + * only good provided it is retained in all terms of the final + * expression for cos(). Retention happens in all cases tested + * under FreeBSD, so don't pessimize things by forcibly clipping + * any extra precision in w. + */ + +#include "libm.h" + +static const double +C1 = 4.16666666666666019037e-02, /* 0x3FA55555, 0x5555554C */ +C2 = -1.38888888888741095749e-03, /* 0xBF56C16C, 0x16C15177 */ +C3 = 2.48015872894767294178e-05, /* 0x3EFA01A0, 0x19CB1590 */ +C4 = -2.75573143513906633035e-07, /* 0xBE927E4F, 0x809C52AD */ +C5 = 2.08757232129817482790e-09, /* 0x3E21EE9E, 0xBDB4B1C4 */ +C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ + +double __cos(double x, double y) +{ + double_t hz,z,r,w; + + z = x*x; + w = z*z; + r = z*(C1+z*(C2+z*C3)) + w*w*(C4+z*(C5+z*C6)); + hz = 0.5*z; + w = 1.0-hz; + return w + (((1.0-w)-hz) + (z*r-x*y)); +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2.c" new file mode 100755 index 0000000000000000000000000000000000000000..d403f81c792217a195d9680d9356eec17f734f41 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2.c" @@ -0,0 +1,177 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/e_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + * Optimized by Bruce D. Evans. + */ +/* __rem_pio2(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __rem_pio2_large() for large x + */ + +#include "libm.h" + +#if FLT_EVAL_METHOD==0 || FLT_EVAL_METHOD==1 +#define EPS DBL_EPSILON +#elif FLT_EVAL_METHOD==2 +#define EPS LDBL_EPSILON +#endif + +/* + * invpio2: 53 bits of 2/pi + * pio2_1: first 33 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 33 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 33 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ +static const double +toint = 1.5/EPS, +invpio2 = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */ +pio2_1 = 1.57079632673412561417e+00, /* 0x3FF921FB, 0x54400000 */ +pio2_1t = 6.07710050650619224932e-11, /* 0x3DD0B461, 0x1A626331 */ +pio2_2 = 6.07710050630396597660e-11, /* 0x3DD0B461, 0x1A600000 */ +pio2_2t = 2.02226624879595063154e-21, /* 0x3BA3198A, 0x2E037073 */ +pio2_3 = 2.02226624871116645580e-21, /* 0x3BA3198A, 0x2E000000 */ +pio2_3t = 8.47842766036889956997e-32; /* 0x397B839A, 0x252049C1 */ + +/* caller must handle the case when reduction is not needed: |x| ~<= pi/4 */ +int __rem_pio2(double x, double *y) +{ + union {double f; uint64_t i;} u = {x}; + double_t z,w,t,r,fn; + double tx[3],ty[2]; + uint32_t ix; + int sign, n, ex, ey, i; + + sign = u.i>>63; + ix = u.i>>32 & 0x7fffffff; + if (ix <= 0x400f6a7a) { /* |x| ~<= 5pi/4 */ + if ((ix & 0xfffff) == 0x921fb) /* |x| ~= pi/2 or 2pi/2 */ + goto medium; /* cancellation -- use medium case */ + if (ix <= 0x4002d97c) { /* |x| ~<= 3pi/4 */ + if (!sign) { + z = x - pio2_1; /* one round good to 85 bits */ + y[0] = z - pio2_1t; + y[1] = (z-y[0]) - pio2_1t; + return 1; + } else { + z = x + pio2_1; + y[0] = z + pio2_1t; + y[1] = (z-y[0]) + pio2_1t; + return -1; + } + } else { + if (!sign) { + z = x - 2*pio2_1; + y[0] = z - 2*pio2_1t; + y[1] = (z-y[0]) - 2*pio2_1t; + return 2; + } else { + z = x + 2*pio2_1; + y[0] = z + 2*pio2_1t; + y[1] = (z-y[0]) + 2*pio2_1t; + return -2; + } + } + } + if (ix <= 0x401c463b) { /* |x| ~<= 9pi/4 */ + if (ix <= 0x4015fdbc) { /* |x| ~<= 7pi/4 */ + if (ix == 0x4012d97c) /* |x| ~= 3pi/2 */ + goto medium; + if (!sign) { + z = x - 3*pio2_1; + y[0] = z - 3*pio2_1t; + y[1] = (z-y[0]) - 3*pio2_1t; + return 3; + } else { + z = x + 3*pio2_1; + y[0] = z + 3*pio2_1t; + y[1] = (z-y[0]) + 3*pio2_1t; + return -3; + } + } else { + if (ix == 0x401921fb) /* |x| ~= 4pi/2 */ + goto medium; + if (!sign) { + z = x - 4*pio2_1; + y[0] = z - 4*pio2_1t; + y[1] = (z-y[0]) - 4*pio2_1t; + return 4; + } else { + z = x + 4*pio2_1; + y[0] = z + 4*pio2_1t; + y[1] = (z-y[0]) + 4*pio2_1t; + return -4; + } + } + } + if (ix < 0x413921fb) { /* |x| ~< 2^20*(pi/2), medium size */ +medium: + /* rint(x/(pi/2)), Assume round-to-nearest. */ + fn = (double_t)x*invpio2 + toint - toint; + n = (int32_t)fn; + r = x - fn*pio2_1; + w = fn*pio2_1t; /* 1st round, good to 85 bits */ + y[0] = r - w; + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + ex = ix>>20; + if (ex - ey > 16) { /* 2nd round, good to 118 bits */ + t = r; + w = fn*pio2_2; + r = t - w; + w = fn*pio2_2t - ((t-r)-w); + y[0] = r - w; + u.f = y[0]; + ey = u.i>>52 & 0x7ff; + if (ex - ey > 49) { /* 3rd round, good to 151 bits, covers all cases */ + t = r; + w = fn*pio2_3; + r = t - w; + w = fn*pio2_3t - ((t-r)-w); + y[0] = r - w; + } + } + y[1] = (r - y[0]) - w; + return n; + } + /* + * all other (large) arguments + */ + if (ix >= 0x7ff00000) { /* x is inf or NaN */ + y[0] = y[1] = x - x; + return 0; + } + /* set z = scalbn(|x|,-ilogb(x)+23) */ + u.f = x; + u.i &= (uint64_t)-1>>12; + u.i |= (uint64_t)(0x3ff + 23)<<52; + z = u.f; + for (i=0; i < 2; i++) { + tx[i] = (double)(int32_t)z; + z = (z-tx[i])*0x1p24; + } + tx[i] = z; + /* skip zero terms, first term is non-zero */ + while (tx[i] == 0.0) + i--; + n = __rem_pio2_large(tx,ty,(int)(ix>>20)-(0x3ff+23),i+1,1); + if (sign) { + y[0] = -ty[0]; + y[1] = -ty[1]; + return -n; + } + y[0] = ty[0]; + y[1] = ty[1]; + return n; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2_large.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2_large.c" new file mode 100755 index 0000000000000000000000000000000000000000..958f28c2557caf23ce9476771f1787cf071d19de --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__rem_pio2_large.c" @@ -0,0 +1,442 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_rem_pio2.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* + * __rem_pio2_large(x,y,e0,nx,prec) + * double x[],y[]; int e0,nx,prec; + * + * __rem_pio2_large return the last three digits of N with + * y = x - N*pi/2 + * so that |y| < pi/2. + * + * The method is to compute the integer (mod 8) and fraction parts of + * (2/pi)*x without doing the full multiplication. In general we + * skip the part of the product that are known to be a huge integer ( + * more accurately, = 0 mod 8 ). Thus the number of operations are + * independent of the exponent of the input. + * + * (2/pi) is represented by an array of 24-bit integers in ipio2[]. + * + * Input parameters: + * x[] The input value (must be positive) is broken into nx + * pieces of 24-bit integers in double precision format. + * x[i] will be the i-th 24 bit of x. The scaled exponent + * of x[0] is given in input parameter e0 (i.e., x[0]*2^e0 + * match x's up to 24 bits. + * + * Example of breaking a double positive z into x[0]+x[1]+x[2]: + * e0 = ilogb(z)-23 + * z = scalbn(z,-e0) + * for i = 0,1,2 + * x[i] = floor(z) + * z = (z-x[i])*2**24 + * + * + * y[] ouput result in an array of double precision numbers. + * The dimension of y[] is: + * 24-bit precision 1 + * 53-bit precision 2 + * 64-bit precision 2 + * 113-bit precision 3 + * The actual value is the sum of them. Thus for 113-bit + * precison, one may have to do something like: + * + * long double t,w,r_head, r_tail; + * t = (long double)y[2] + (long double)y[1]; + * w = (long double)y[0]; + * r_head = t+w; + * r_tail = w - (r_head - t); + * + * e0 The exponent of x[0]. Must be <= 16360 or you need to + * expand the ipio2 table. + * + * nx dimension of x[] + * + * prec an integer indicating the precision: + * 0 24 bits (single) + * 1 53 bits (double) + * 2 64 bits (extended) + * 3 113 bits (quad) + * + * External function: + * double scalbn(), floor(); + * + * + * Here is the description of some local variables: + * + * jk jk+1 is the initial number of terms of ipio2[] needed + * in the computation. The minimum and recommended value + * for jk is 3,4,4,6 for single, double, extended, and quad. + * jk+1 must be 2 larger than you might expect so that our + * recomputation test works. (Up to 24 bits in the integer + * part (the 24 bits of it that we compute) and 23 bits in + * the fraction part may be lost to cancelation before we + * recompute.) + * + * jz local integer variable indicating the number of + * terms of ipio2[] used. + * + * jx nx - 1 + * + * jv index for pointing to the suitable ipio2[] for the + * computation. In general, we want + * ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8 + * is an integer. Thus + * e0-3-24*jv >= 0 or (e0-3)/24 >= jv + * Hence jv = max(0,(e0-3)/24). + * + * jp jp+1 is the number of terms in PIo2[] needed, jp = jk. + * + * q[] double array with integral value, representing the + * 24-bits chunk of the product of x and 2/pi. + * + * q0 the corresponding exponent of q[0]. Note that the + * exponent for q[i] would be q0-24*i. + * + * PIo2[] double precision array, obtained by cutting pi/2 + * into 24 bits chunks. + * + * f[] ipio2[] in floating point + * + * iq[] integer array by breaking up q[] in 24-bits chunk. + * + * fq[] final product of x*(2/pi) in fq[0],..,fq[jk] + * + * ih integer. If >0 it indicates q[] is >= 0.5, hence + * it also indicates the *sign* of the result. + * + */ +/* + * Constants: + * The hexadecimal values are the intended ones for the following + * constants. The decimal values may be used, provided that the + * compiler will convert from decimal to binary accurately enough + * to produce the hexadecimal values shown. + */ + +#include "libm.h" + +static const int init_jk[] = {3,4,4,6}; /* initial value for jk */ + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + * + * integer array, contains the (24*i)-th to (24*i+23)-th + * bit of 2/pi after binary point. The corresponding + * floating value is + * + * ipio2[i] * 2^(-24(i+1)). + * + * NB: This table must have at least (e0-3)/24 + jk terms. + * For quad precision (e0 <= 16360, jk = 6), this is 686. + */ +static const int32_t ipio2[] = { +0xA2F983, 0x6E4E44, 0x1529FC, 0x2757D1, 0xF534DD, 0xC0DB62, +0x95993C, 0x439041, 0xFE5163, 0xABDEBB, 0xC561B7, 0x246E3A, +0x424DD2, 0xE00649, 0x2EEA09, 0xD1921C, 0xFE1DEB, 0x1CB129, +0xA73EE8, 0x8235F5, 0x2EBB44, 0x84E99C, 0x7026B4, 0x5F7E41, +0x3991D6, 0x398353, 0x39F49C, 0x845F8B, 0xBDF928, 0x3B1FF8, +0x97FFDE, 0x05980F, 0xEF2F11, 0x8B5A0A, 0x6D1F6D, 0x367ECF, +0x27CB09, 0xB74F46, 0x3F669E, 0x5FEA2D, 0x7527BA, 0xC7EBE5, +0xF17B3D, 0x0739F7, 0x8A5292, 0xEA6BFB, 0x5FB11F, 0x8D5D08, +0x560330, 0x46FC7B, 0x6BABF0, 0xCFBC20, 0x9AF436, 0x1DA9E3, +0x91615E, 0xE61B08, 0x659985, 0x5F14A0, 0x68408D, 0xFFD880, +0x4D7327, 0x310606, 0x1556CA, 0x73A8C9, 0x60E27B, 0xC08C6B, + +#if LDBL_MAX_EXP > 1024 +0x47C419, 0xC367CD, 0xDCE809, 0x2A8359, 0xC4768B, 0x961CA6, +0xDDAF44, 0xD15719, 0x053EA5, 0xFF0705, 0x3F7E33, 0xE832C2, +0xDE4F98, 0x327DBB, 0xC33D26, 0xEF6B1E, 0x5EF89F, 0x3A1F35, +0xCAF27F, 0x1D87F1, 0x21907C, 0x7C246A, 0xFA6ED5, 0x772D30, +0x433B15, 0xC614B5, 0x9D19C3, 0xC2C4AD, 0x414D2C, 0x5D000C, +0x467D86, 0x2D71E3, 0x9AC69B, 0x006233, 0x7CD2B4, 0x97A7B4, +0xD55537, 0xF63ED7, 0x1810A3, 0xFC764D, 0x2A9D64, 0xABD770, +0xF87C63, 0x57B07A, 0xE71517, 0x5649C0, 0xD9D63B, 0x3884A7, +0xCB2324, 0x778AD6, 0x23545A, 0xB91F00, 0x1B0AF1, 0xDFCE19, +0xFF319F, 0x6A1E66, 0x615799, 0x47FBAC, 0xD87F7E, 0xB76522, +0x89E832, 0x60BFE6, 0xCDC4EF, 0x09366C, 0xD43F5D, 0xD7DE16, +0xDE3B58, 0x929BDE, 0x2822D2, 0xE88628, 0x4D58E2, 0x32CAC6, +0x16E308, 0xCB7DE0, 0x50C017, 0xA71DF3, 0x5BE018, 0x34132E, +0x621283, 0x014883, 0x5B8EF5, 0x7FB0AD, 0xF2E91E, 0x434A48, +0xD36710, 0xD8DDAA, 0x425FAE, 0xCE616A, 0xA4280A, 0xB499D3, +0xF2A606, 0x7F775C, 0x83C2A3, 0x883C61, 0x78738A, 0x5A8CAF, +0xBDD76F, 0x63A62D, 0xCBBFF4, 0xEF818D, 0x67C126, 0x45CA55, +0x36D9CA, 0xD2A828, 0x8D61C2, 0x77C912, 0x142604, 0x9B4612, +0xC459C4, 0x44C5C8, 0x91B24D, 0xF31700, 0xAD43D4, 0xE54929, +0x10D5FD, 0xFCBE00, 0xCC941E, 0xEECE70, 0xF53E13, 0x80F1EC, +0xC3E7B3, 0x28F8C7, 0x940593, 0x3E71C1, 0xB3092E, 0xF3450B, +0x9C1288, 0x7B20AB, 0x9FB52E, 0xC29247, 0x2F327B, 0x6D550C, +0x90A772, 0x1FE76B, 0x96CB31, 0x4A1679, 0xE27941, 0x89DFF4, +0x9794E8, 0x84E6E2, 0x973199, 0x6BED88, 0x365F5F, 0x0EFDBB, +0xB49A48, 0x6CA467, 0x427271, 0x325D8D, 0xB8159F, 0x09E5BC, +0x25318D, 0x3974F7, 0x1C0530, 0x010C0D, 0x68084B, 0x58EE2C, +0x90AA47, 0x02E774, 0x24D6BD, 0xA67DF7, 0x72486E, 0xEF169F, +0xA6948E, 0xF691B4, 0x5153D1, 0xF20ACF, 0x339820, 0x7E4BF5, +0x6863B2, 0x5F3EDD, 0x035D40, 0x7F8985, 0x295255, 0xC06437, +0x10D86D, 0x324832, 0x754C5B, 0xD4714E, 0x6E5445, 0xC1090B, +0x69F52A, 0xD56614, 0x9D0727, 0x50045D, 0xDB3BB4, 0xC576EA, +0x17F987, 0x7D6B49, 0xBA271D, 0x296996, 0xACCCC6, 0x5414AD, +0x6AE290, 0x89D988, 0x50722C, 0xBEA404, 0x940777, 0x7030F3, +0x27FC00, 0xA871EA, 0x49C266, 0x3DE064, 0x83DD97, 0x973FA3, +0xFD9443, 0x8C860D, 0xDE4131, 0x9D3992, 0x8C70DD, 0xE7B717, +0x3BDF08, 0x2B3715, 0xA0805C, 0x93805A, 0x921110, 0xD8E80F, +0xAF806C, 0x4BFFDB, 0x0F9038, 0x761859, 0x15A562, 0xBBCB61, +0xB989C7, 0xBD4010, 0x04F2D2, 0x277549, 0xF6B6EB, 0xBB22DB, +0xAA140A, 0x2F2689, 0x768364, 0x333B09, 0x1A940E, 0xAA3A51, +0xC2A31D, 0xAEEDAF, 0x12265C, 0x4DC26D, 0x9C7A2D, 0x9756C0, +0x833F03, 0xF6F009, 0x8C402B, 0x99316D, 0x07B439, 0x15200C, +0x5BC3D8, 0xC492F5, 0x4BADC6, 0xA5CA4E, 0xCD37A7, 0x36A9E6, +0x9492AB, 0x6842DD, 0xDE6319, 0xEF8C76, 0x528B68, 0x37DBFC, +0xABA1AE, 0x3115DF, 0xA1AE00, 0xDAFB0C, 0x664D64, 0xB705ED, +0x306529, 0xBF5657, 0x3AFF47, 0xB9F96A, 0xF3BE75, 0xDF9328, +0x3080AB, 0xF68C66, 0x15CB04, 0x0622FA, 0x1DE4D9, 0xA4B33D, +0x8F1B57, 0x09CD36, 0xE9424E, 0xA4BE13, 0xB52333, 0x1AAAF0, +0xA8654F, 0xA5C1D2, 0x0F3F0B, 0xCD785B, 0x76F923, 0x048B7B, +0x721789, 0x53A6C6, 0xE26E6F, 0x00EBEF, 0x584A9B, 0xB7DAC4, +0xBA66AA, 0xCFCF76, 0x1D02D1, 0x2DF1B1, 0xC1998C, 0x77ADC3, +0xDA4886, 0xA05DF7, 0xF480C6, 0x2FF0AC, 0x9AECDD, 0xBC5C3F, +0x6DDED0, 0x1FC790, 0xB6DB2A, 0x3A25A3, 0x9AAF00, 0x9353AD, +0x0457B6, 0xB42D29, 0x7E804B, 0xA707DA, 0x0EAA76, 0xA1597B, +0x2A1216, 0x2DB7DC, 0xFDE5FA, 0xFEDB89, 0xFDBE89, 0x6C76E4, +0xFCA906, 0x70803E, 0x156E85, 0xFF87FD, 0x073E28, 0x336761, +0x86182A, 0xEABD4D, 0xAFE7B3, 0x6E6D8F, 0x396795, 0x5BBF31, +0x48D784, 0x16DF30, 0x432DC7, 0x356125, 0xCE70C9, 0xB8CB30, +0xFD6CBF, 0xA200A4, 0xE46C05, 0xA0DD5A, 0x476F21, 0xD21262, +0x845CB9, 0x496170, 0xE0566B, 0x015299, 0x375550, 0xB7D51E, +0xC4F133, 0x5F6E13, 0xE4305D, 0xA92E85, 0xC3B21D, 0x3632A1, +0xA4B708, 0xD4B1EA, 0x21F716, 0xE4698F, 0x77FF27, 0x80030C, +0x2D408D, 0xA0CD4F, 0x99A520, 0xD3A2B3, 0x0A5D2F, 0x42F9B4, +0xCBDA11, 0xD0BE7D, 0xC1DB9B, 0xBD17AB, 0x81A2CA, 0x5C6A08, +0x17552E, 0x550027, 0xF0147F, 0x8607E1, 0x640B14, 0x8D4196, +0xDEBE87, 0x2AFDDA, 0xB6256B, 0x34897B, 0xFEF305, 0x9EBFB9, +0x4F6A68, 0xA82A4A, 0x5AC44F, 0xBCF82D, 0x985AD7, 0x95C7F4, +0x8D4D0D, 0xA63A20, 0x5F57A4, 0xB13F14, 0x953880, 0x0120CC, +0x86DD71, 0xB6DEC9, 0xF560BF, 0x11654D, 0x6B0701, 0xACB08C, +0xD0C0B2, 0x485551, 0x0EFB1E, 0xC37295, 0x3B06A3, 0x3540C0, +0x7BDC06, 0xCC45E0, 0xFA294E, 0xC8CAD6, 0x41F3E8, 0xDE647C, +0xD8649B, 0x31BED9, 0xC397A4, 0xD45877, 0xC5E369, 0x13DAF0, +0x3C3ABA, 0x461846, 0x5F7555, 0xF5BDD2, 0xC6926E, 0x5D2EAC, +0xED440E, 0x423E1C, 0x87C461, 0xE9FD29, 0xF3D6E7, 0xCA7C22, +0x35916F, 0xC5E008, 0x8DD7FF, 0xE26A6E, 0xC6FDB0, 0xC10893, +0x745D7C, 0xB2AD6B, 0x9D6ECD, 0x7B723E, 0x6A11C6, 0xA9CFF7, +0xDF7329, 0xBAC9B5, 0x5100B7, 0x0DB2E2, 0x24BA74, 0x607DE5, +0x8AD874, 0x2C150D, 0x0C1881, 0x94667E, 0x162901, 0x767A9F, +0xBEFDFD, 0xEF4556, 0x367ED9, 0x13D9EC, 0xB9BA8B, 0xFC97C4, +0x27A831, 0xC36EF1, 0x36C594, 0x56A8D8, 0xB5A8B4, 0x0ECCCF, +0x2D8912, 0x34576F, 0x89562C, 0xE3CE99, 0xB920D6, 0xAA5E6B, +0x9C2A3E, 0xCC5F11, 0x4A0BFD, 0xFBF4E1, 0x6D3B8E, 0x2C86E2, +0x84D4E9, 0xA9B4FC, 0xD1EEEF, 0xC9352E, 0x61392F, 0x442138, +0xC8D91B, 0x0AFC81, 0x6A4AFB, 0xD81C2F, 0x84B453, 0x8C994E, +0xCC2254, 0xDC552A, 0xD6C6C0, 0x96190B, 0xB8701A, 0x649569, +0x605A26, 0xEE523F, 0x0F117F, 0x11B5F4, 0xF5CBFC, 0x2DBC34, +0xEEBC34, 0xCC5DE8, 0x605EDD, 0x9B8E67, 0xEF3392, 0xB817C9, +0x9B5861, 0xBC57E1, 0xC68351, 0x103ED8, 0x4871DD, 0xDD1C2D, +0xA118AF, 0x462C21, 0xD7F359, 0x987AD9, 0xC0549E, 0xFA864F, +0xFC0656, 0xAE79E5, 0x362289, 0x22AD38, 0xDC9367, 0xAAE855, +0x382682, 0x9BE7CA, 0xA40D51, 0xB13399, 0x0ED7A9, 0x480569, +0xF0B265, 0xA7887F, 0x974C88, 0x36D1F9, 0xB39221, 0x4A827B, +0x21CF98, 0xDC9F40, 0x5547DC, 0x3A74E1, 0x42EB67, 0xDF9DFE, +0x5FD45E, 0xA4677B, 0x7AACBA, 0xA2F655, 0x23882B, 0x55BA41, +0x086E59, 0x862A21, 0x834739, 0xE6E389, 0xD49EE5, 0x40FB49, +0xE956FF, 0xCA0F1C, 0x8A59C5, 0x2BFA94, 0xC5C1D3, 0xCFC50F, +0xAE5ADB, 0x86C547, 0x624385, 0x3B8621, 0x94792C, 0x876110, +0x7B4C2A, 0x1A2C80, 0x12BF43, 0x902688, 0x893C78, 0xE4C4A8, +0x7BDBE5, 0xC23AC4, 0xEAF426, 0x8A67F7, 0xBF920D, 0x2BA365, +0xB1933D, 0x0B7CBD, 0xDC51A4, 0x63DD27, 0xDDE169, 0x19949A, +0x9529A8, 0x28CE68, 0xB4ED09, 0x209F44, 0xCA984E, 0x638270, +0x237C7E, 0x32B90F, 0x8EF5A7, 0xE75614, 0x08F121, 0x2A9DB5, +0x4D7E6F, 0x5119A5, 0xABF9B5, 0xD6DF82, 0x61DD96, 0x023616, +0x9F3AC4, 0xA1A283, 0x6DED72, 0x7A8D39, 0xA9B882, 0x5C326B, +0x5B2746, 0xED3400, 0x7700D2, 0x55F4FC, 0x4D5901, 0x8071E0, +#endif +}; + +static const double PIo2[] = { + 1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */ + 7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */ + 5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */ + 3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */ + 1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */ + 1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */ + 2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */ + 2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */ +}; + +int __rem_pio2_large(double *x, double *y, int e0, int nx, int prec) +{ + int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; + double z,fw,f[20],fq[20],q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/24; if(jv<0) jv=0; + q0 = e0-24*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for (i=0; i<=m; i++,j++) + f[i] = j<0 ? 0.0 : (double)ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0; i<=jk; i++) { + for (j=0,fw=0.0; j<=jx; j++) + fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for (i=0,j=jz,z=q[jz]; j>0; i++,j--) { + fw = (double)(int32_t)(0x1p-24*z); + iq[i] = (int32_t)(z - 0x1p24*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbn(z,q0); /* actual value of z */ + z -= 8.0*floor(z*0.125); /* trim off integer >= 8 */ + n = (int32_t)z; + z -= (double)n; + ih = 0; + if (q0 > 0) { /* need iq[jz-1] to determine n */ + i = iq[jz-1]>>(24-q0); n += i; + iq[jz-1] -= i<<(24-q0); + ih = iq[jz-1]>>(23-q0); + } + else if (q0 == 0) ih = iq[jz-1]>>23; + else if (z >= 0.5) ih = 2; + + if (ih > 0) { /* q > 0.5 */ + n += 1; carry = 0; + for (i=0; i 0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7fffff; break; + case 2: + iq[jz-1] &= 0x3fffff; break; + } + } + if (ih == 2) { + z = 1.0 - z; + if (carry != 0) + z -= scalbn(1.0,q0); + } + } + + /* check if recomputation is needed */ + if (z == 0.0) { + j = 0; + for (i=jz-1; i>=jk; i--) j |= iq[i]; + if (j == 0) { /* need recomputation */ + for (k=1; iq[jk-k]==0; k++); /* k = no. of terms needed */ + + for (i=jz+1; i<=jz+k; i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (double)ipio2[jv+i]; + for (j=0,fw=0.0; j<=jx; j++) + fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if (z == 0.0) { + jz -= 1; + q0 -= 24; + while (iq[jz] == 0) { + jz--; + q0 -= 24; + } + } else { /* break z into 24-bit if necessary */ + z = scalbn(z,-q0); + if (z >= 0x1p24) { + fw = (double)(int32_t)(0x1p-24*z); + iq[jz] = (int32_t)(z - 0x1p24*fw); + jz += 1; + q0 += 24; + iq[jz] = (int32_t)fw; + } else + iq[jz] = (int32_t)z; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbn(1.0,q0); + for (i=jz; i>=0; i--) { + q[i] = fw*(double)iq[i]; + fw *= 0x1p-24; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz; i>=0; i--) { + for (fw=0.0,k=0; k<=jp && k<=jz-i; k++) + fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz; i>=0; i--) + fw += fq[i]; + y[0] = ih==0 ? fw : -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz; i>=0; i--) + fw += fq[i]; + // TODO: drop excess precision here once double_t is used + fw = (double)fw; + y[0] = ih==0 ? fw : -fw; + fw = fq[0]-fw; + for (i=1; i<=jz; i++) + fw += fq[i]; + y[1] = ih==0 ? fw : -fw; + break; + case 3: /* painful */ + for (i=jz; i>0; i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz; i>1; i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz; i>=2; i--) + fw += fq[i]; + if (ih==0) { + y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; + } else { + y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; + } + } + return n&7; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__sin.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__sin.c" new file mode 100755 index 0000000000000000000000000000000000000000..40309496646ea67bc247a46b8cd363a73ca9801e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/__sin.c" @@ -0,0 +1,64 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/k_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* __sin( x, y, iy) + * kernel sin function on ~[-pi/4, pi/4] (except on -0), pi/4 ~ 0.7854 + * Input x is assumed to be bounded by ~pi/4 in magnitude. + * Input y is the tail of x. + * Input iy indicates whether y is 0. (if iy=0, y assume to be 0). + * + * Algorithm + * 1. Since sin(-x) = -sin(x), we need only to consider positive x. + * 2. Callers must return sin(-0) = -0 without calling here since our + * odd polynomial is not evaluated in a way that preserves -0. + * Callers may do the optimization sin(x) ~ x for tiny x. + * 3. sin(x) is approximated by a polynomial of degree 13 on + * [0,pi/4] + * 3 13 + * sin(x) ~ x + S1*x + ... + S6*x + * where + * + * |sin(x) 2 4 6 8 10 12 | -58 + * |----- - (1+S1*x +S2*x +S3*x +S4*x +S5*x +S6*x )| <= 2 + * | x | + * + * 4. sin(x+y) = sin(x) + sin'(x')*y + * ~ sin(x) + (1-x*x/2)*y + * For better accuracy, let + * 3 2 2 2 2 + * r = x *(S2+x *(S3+x *(S4+x *(S5+x *S6)))) + * then 3 2 + * sin(x) = x + (S1*x + (x *(r-y/2)+y)) + */ + +#include "libm.h" + +static const double +S1 = -1.66666666666666324348e-01, /* 0xBFC55555, 0x55555549 */ +S2 = 8.33333333332248946124e-03, /* 0x3F811111, 0x1110F8A6 */ +S3 = -1.98412698298579493134e-04, /* 0xBF2A01A0, 0x19C161D5 */ +S4 = 2.75573137070700676789e-06, /* 0x3EC71DE3, 0x57B1FE7D */ +S5 = -2.50507602534068634195e-08, /* 0xBE5AE5E6, 0x8A2B9CEB */ +S6 = 1.58969099521155010221e-10; /* 0x3DE5D93A, 0x5ACFD57C */ + +double __sin(double x, double y, int iy) +{ + double_t z,r,v,w; + + z = x*x; + w = z*z; + r = S2 + z*(S3 + z*S4) + z*w*(S5 + z*S6); + v = z*x; + if (iy == 0) + return x + v*(S1 + z*r); + else + return x - ((z*(0.5*y - v*r) - y) - v*S1); +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/cos.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/cos.c" new file mode 100755 index 0000000000000000000000000000000000000000..ee97f68bbb7be73e473e9324484bed533fcb39bb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/cos.c" @@ -0,0 +1,77 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_cos.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* cos(x) + * Return cosine function of x. + * + * kernel function: + * __sin ... sine function on [-pi/4,pi/4] + * __cos ... cosine function on [-pi/4,pi/4] + * __rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "libm.h" + +double cos(double x) +{ + double y[2]; + uint32_t ix; + unsigned n; + + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + /* |x| ~< pi/4 */ + if (ix <= 0x3fe921fb) { + if (ix < 0x3e46a09e) { /* |x| < 2**-27 * sqrt(2) */ + /* raise inexact if x!=0 */ + FORCE_EVAL(x + 0x1p120f); + return 1.0; + } + return __cos(x, 0); + } + + /* cos(Inf or NaN) is NaN */ + if (ix >= 0x7ff00000) + return x-x; + + /* argument reduction */ + n = __rem_pio2(x, y); + switch (n&3) { + case 0: return __cos(y[0], y[1]); + case 1: return -__sin(y[0], y[1], 1); + case 2: return -__cos(y[0], y[1]); + default: + return __sin(y[0], y[1], 1); + } +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/features.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/features.h" new file mode 100755 index 0000000000000000000000000000000000000000..aa6c4a73bd5b5f9f95fc94c63f77857e054d089d --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/features.h" @@ -0,0 +1,11 @@ +#ifndef FEATURES_H +#define FEATURES_H + +// #include "../../include/features.h" + +#define weak __attribute__((__weak__)) +#define hidden __attribute__((__visibility__("hidden"))) +#define weak_alias(old, new) \ + extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) + +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/libm.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/libm.h" new file mode 100755 index 0000000000000000000000000000000000000000..a5cb3c15ee854d0ce5aae4f229b61c9e1df3f8a4 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/libm.h" @@ -0,0 +1,277 @@ +#ifndef _LIBM_H +#define _LIBM_H + +#include +#include +#include +#include +// #include "fp_arch.h" +#include "features.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t m; + uint16_t se; + } i; +}; +#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +/* This is the m68k variant of 80-bit long double, and this definition only works + * on archs where the alignment requirement of uint64_t is <= 4. */ +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t pad; + uint64_t m; + } i; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __LITTLE_ENDIAN +union ldshape { + long double f; + struct { + uint64_t lo; + uint32_t mid; + uint16_t top; + uint16_t se; + } i; + struct { + uint64_t lo; + uint64_t hi; + } i2; +}; +#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384 && __BYTE_ORDER == __BIG_ENDIAN +union ldshape { + long double f; + struct { + uint16_t se; + uint16_t top; + uint32_t mid; + uint64_t lo; + } i; + struct { + uint64_t hi; + uint64_t lo; + } i2; +}; +#else +#error Unsupported long double representation +#endif + +/* Support non-nearest rounding mode. */ +#define WANT_ROUNDING 1 +/* Support signaling NaNs. */ +#define WANT_SNAN 0 + +#if WANT_SNAN +#error SNaN is unsupported +#else +#define issignalingf_inline(x) 0 +#define issignaling_inline(x) 0 +#endif + +#ifndef TOINT_INTRINSICS +#define TOINT_INTRINSICS 0 +#endif + +#if TOINT_INTRINSICS +/* Round x to nearest int in all rounding modes, ties have to be rounded + consistently with converttoint so the results match. If the result + would be outside of [-2^31, 2^31-1] then the semantics is unspecified. */ +static double_t roundtoint(double_t); + +/* Convert x to nearest int in all rounding modes, ties have to be rounded + consistently with roundtoint. If the result is not representible in an + int32_t then the semantics is unspecified. */ +static int32_t converttoint(double_t); +#endif + +/* Helps static branch prediction so hot path can be better optimized. */ +#ifdef __GNUC__ +#define predict_true(x) __builtin_expect(!!(x), 1) +#define predict_false(x) __builtin_expect(x, 0) +#else +#define predict_true(x) (x) +#define predict_false(x) (x) +#endif + +/* Evaluate an expression as the specified type. With standard excess + precision handling a type cast or assignment is enough (with + -ffloat-store an assignment is required, in old compilers argument + passing and return statement may not drop excess precision). */ + +static inline float eval_as_float(float x) +{ + float y = x; + return y; +} + +static inline double eval_as_double(double x) +{ + double y = x; + return y; +} + +/* fp_barrier returns its input, but limits code transformations + as if it had a side-effect (e.g. observable io) and returned + an arbitrary value. */ + +#ifndef fp_barrierf +#define fp_barrierf fp_barrierf +static inline float fp_barrierf(float x) +{ + volatile float y = x; + return y; +} +#endif + +#ifndef fp_barrier +#define fp_barrier fp_barrier +static inline double fp_barrier(double x) +{ + volatile double y = x; + return y; +} +#endif + +#ifndef fp_barrierl +#define fp_barrierl fp_barrierl +static inline long double fp_barrierl(long double x) +{ + volatile long double y = x; + return y; +} +#endif + +/* fp_force_eval ensures that the input value is computed when that's + otherwise unused. To prevent the constant folding of the input + expression, an additional fp_barrier may be needed or a compilation + mode that does so (e.g. -frounding-math in gcc). Then it can be + used to evaluate an expression for its fenv side-effects only. */ + +#ifndef fp_force_evalf +#define fp_force_evalf fp_force_evalf +static inline void fp_force_evalf(float x) +{ + volatile float y; + y = x; +} +#endif + +#ifndef fp_force_eval +#define fp_force_eval fp_force_eval +static inline void fp_force_eval(double x) +{ + volatile double y; + y = x; +} +#endif + +#ifndef fp_force_evall +#define fp_force_evall fp_force_evall +static inline void fp_force_evall(long double x) +{ + volatile long double y; + y = x; +} +#endif + +#define FORCE_EVAL(x) do { \ + if (sizeof(x) == sizeof(float)) { \ + fp_force_evalf(x); \ + } else if (sizeof(x) == sizeof(double)) { \ + fp_force_eval(x); \ + } else { \ + fp_force_evall(x); \ + } \ +} while(0) + +#define asuint(f) ((union{float _f; uint32_t _i;}){f})._i +#define asfloat(i) ((union{uint32_t _i; float _f;}){i})._f +#define asuint64(f) ((union{double _f; uint64_t _i;}){f})._i +#define asdouble(i) ((union{uint64_t _i; double _f;}){i})._f + +#define EXTRACT_WORDS(hi,lo,d) \ +do { \ + uint64_t __u = asuint64(d); \ + (hi) = __u >> 32; \ + (lo) = (uint32_t)__u; \ +} while (0) + +#define GET_HIGH_WORD(hi,d) \ +do { \ + (hi) = asuint64(d) >> 32; \ +} while (0) + +#define GET_LOW_WORD(lo,d) \ +do { \ + (lo) = (uint32_t)asuint64(d); \ +} while (0) + +#define INSERT_WORDS(d,hi,lo) \ +do { \ + (d) = asdouble(((uint64_t)(hi)<<32) | (uint32_t)(lo)); \ +} while (0) + +#define SET_HIGH_WORD(d,hi) \ + INSERT_WORDS(d, hi, (uint32_t)asuint64(d)) + +#define SET_LOW_WORD(d,lo) \ + INSERT_WORDS(d, asuint64(d)>>32, lo) + +#define GET_FLOAT_WORD(w,d) \ +do { \ + (w) = asuint(d); \ +} while (0) + +#define SET_FLOAT_WORD(d,w) \ +do { \ + (d) = asfloat(w); \ +} while (0) + +hidden int __rem_pio2_large(double*,double*,int,int,int); + +hidden int __rem_pio2(double,double*); +hidden double __sin(double,double,int); +hidden double __cos(double,double); +hidden double __tan(double,double,int); +hidden double __expo2(double); + +hidden int __rem_pio2f(float,double*); +hidden float __sindf(double); +hidden float __cosdf(double); +hidden float __tandf(double,int); +hidden float __expo2f(float); + +hidden int __rem_pio2l(long double, long double *); +hidden long double __sinl(long double, long double, int); +hidden long double __cosl(long double, long double); +hidden long double __tanl(long double, long double, int); + +hidden long double __polevll(long double, const long double *, int); +hidden long double __p1evll(long double, const long double *, int); + +extern int __signgam; +hidden double __lgamma_r(double, int *); +hidden float __lgammaf_r(float, int *); + +/* error handling functions */ +hidden float __math_xflowf(uint32_t, float); +hidden float __math_uflowf(uint32_t); +hidden float __math_oflowf(uint32_t); +hidden float __math_divzerof(uint32_t); +hidden float __math_invalidf(float); +hidden double __math_xflow(uint32_t, double); +hidden double __math_uflow(uint32_t); +hidden double __math_oflow(uint32_t); +hidden double __math_divzero(uint32_t); +hidden double __math_invalid(double); + +#pragma GCC diagnostic pop + +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/sin.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/sin.c" new file mode 100755 index 0000000000000000000000000000000000000000..055e215bc866d62936992058b7019b374cbcac7c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/libm_port/sin.c" @@ -0,0 +1,78 @@ +/* origin: FreeBSD /usr/src/lib/msun/src/s_sin.c */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ +/* sin(x) + * Return sine function of x. + * + * kernel function: + * __sin ... sine function on [-pi/4,pi/4] + * __cos ... cose function on [-pi/4,pi/4] + * __rem_pio2 ... argument reduction routine + * + * Method. + * Let S,C and T denote the sin, cos and tan respectively on + * [-PI/4, +PI/4]. Reduce the argument x to y1+y2 = x-k*pi/2 + * in [-pi/4 , +pi/4], and let n = k mod 4. + * We have + * + * n sin(x) cos(x) tan(x) + * ---------------------------------------------------------- + * 0 S C T + * 1 C -S -1/T + * 2 -S -C T + * 3 -C S -1/T + * ---------------------------------------------------------- + * + * Special cases: + * Let trig be any of sin, cos, or tan. + * trig(+-INF) is NaN, with signals; + * trig(NaN) is that NaN; + * + * Accuracy: + * TRIG(x) returns trig(x) nearly rounded + */ + +#include "libm.h" + +double sin(double x) +{ + double y[2]; + uint32_t ix; + unsigned n; + + /* High word of x. */ + GET_HIGH_WORD(ix, x); + ix &= 0x7fffffff; + + /* |x| ~< pi/4 */ + if (ix <= 0x3fe921fb) { + if (ix < 0x3e500000) { /* |x| < 2**-26 */ + /* raise inexact if x != 0 and underflow if subnormal*/ + FORCE_EVAL(ix < 0x00100000 ? x/0x1p120f : x+0x1p120f); + return x; + } + return __sin(x, 0.0, 0); + } + + /* sin(Inf or NaN) is NaN */ + if (ix >= 0x7ff00000) + return x - x; + + /* argument reduction needed */ + n = __rem_pio2(x, y); + switch (n&3) { + case 0: return __sin(y[0], y[1], 1); + case 1: return __cos(y[0], y[1]); + case 2: return -__sin(y[0], y[1], 1); + default: + return -__cos(y[0], y[1]); + } +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..b31cbbececb79cadc7be453e3eeed0c623d1a3cc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("oled_ssd1306") { + sources = [ + "ssd1306.c", + "ssd1306_fonts.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.c" new file mode 100755 index 0000000000000000000000000000000000000000..da2302761ec3a92ba33cf29102a9ca6917a9a825 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.c" @@ -0,0 +1,586 @@ +#include "ssd1306.h" +#include +#include +#include // For memcpy + +#include +#include +#include "cmsis_os2.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" + +#if defined(SSD1306_USE_I2C) + +#define SSD1306_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define SSD1306_CTRL_CMD 0x00 +#define SSD1306_CTRL_DATA 0x40 +#define SSD1306_MASK_CONT (0x1<<7) + +void ssd1306_Reset(void) { + /* for I2C - do nothing */ +} + +void HAL_Delay(uint32_t ms) +{ + uint32_t msPerTick = 1000 / osKernelGetTickFreq(); // 10ms + if (ms >= msPerTick) { + osDelay(ms / msPerTick); + } + + uint32_t restMs = ms % msPerTick; + if (restMs > 0) { + usleep(restMs * 1000); + } +} + +uint32_t HAL_GetTick(void) +{ + uint32_t msPerTick = 1000 / osKernelGetTickFreq(); // 10ms + uint32_t tickMs = osKernelGetTickCount() * msPerTick; + + uint32_t csPerMs = osKernelGetSysTimerFreq() / 1000; // 160K cycle/ms + uint32_t csPerTick = csPerMs * msPerTick; // 1600K cycles/tick + uint32_t restMs = osKernelGetSysTimerCount() % csPerTick / csPerMs; + + return tickMs + restMs; +} + +static uint32_t ssd1306_SendData(uint8_t* data, size_t size) +{ + WifiIotI2cIdx id = SSD1306_I2C_IDX; + WifiIotI2cData i2cData = {0}; + i2cData.sendBuf = data; + i2cData.sendLen = size; + + return I2cWrite(id, SSD1306_I2C_ADDR, &i2cData); +} + +static uint32_t ssd1306_WiteByte(uint8_t regAddr, uint8_t byte) +{ + uint8_t buffer[] = {regAddr, byte}; + return ssd1306_SendData(buffer, sizeof(buffer)); +} + +// Send a byte to the command register +void ssd1306_WriteCommand(uint8_t byte) { + ssd1306_WiteByte(SSD1306_CTRL_CMD, byte); +} + +// Send data +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { + uint8_t data[SSD1306_WIDTH * 2] = {0}; + for (size_t i = 0; i < buff_size; i++) { + data[i*2] = SSD1306_CTRL_DATA | SSD1306_MASK_CONT; + data[i*2+1] = buffer[i]; + } + data[(buff_size - 1) * 2] = SSD1306_CTRL_DATA; + ssd1306_SendData(data, sizeof(data)); +} + +#elif defined(SSD1306_USE_SPI) + +void ssd1306_Reset(void) { + // CS = High (not selected) + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); + + // Reset the OLED + HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_RESET); + HAL_Delay(10); + HAL_GPIO_WritePin(SSD1306_Reset_Port, SSD1306_Reset_Pin, GPIO_PIN_SET); + HAL_Delay(10); +} + +// Send a byte to the command register +void ssd1306_WriteCommand(uint8_t byte) { + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED + HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_RESET); // command + HAL_SPI_Transmit(&SSD1306_SPI_PORT, (uint8_t *) &byte, 1, HAL_MAX_DELAY); + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED +} + +// Send data +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size) { + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_RESET); // select OLED + HAL_GPIO_WritePin(SSD1306_DC_Port, SSD1306_DC_Pin, GPIO_PIN_SET); // data + HAL_SPI_Transmit(&SSD1306_SPI_PORT, buffer, buff_size, HAL_MAX_DELAY); + HAL_GPIO_WritePin(SSD1306_CS_Port, SSD1306_CS_Pin, GPIO_PIN_SET); // un-select OLED +} + +#else +#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro" +#endif + + +// Screenbuffer +static uint8_t SSD1306_Buffer[SSD1306_BUFFER_SIZE]; + +// Screen object +static SSD1306_t SSD1306; + +/* Fills the Screenbuffer with values from a given buffer of a fixed length */ +SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len) { + SSD1306_Error_t ret = SSD1306_ERR; + if (len <= SSD1306_BUFFER_SIZE) { + memcpy(SSD1306_Buffer,buf,len); + ret = SSD1306_OK; + } + return ret; +} + +// Initialize the oled screen +void ssd1306_Init(void) { + // Reset OLED + ssd1306_Reset(); + + // Wait for the screen to boot + HAL_Delay(100); + + // Init OLED + ssd1306_SetDisplayOn(0); //display off + + ssd1306_WriteCommand(0x20); //Set Memory Addressing Mode + ssd1306_WriteCommand(0x00); // 00b,Horizontal Addressing Mode; 01b,Vertical Addressing Mode; + // 10b,Page Addressing Mode (RESET); 11b,Invalid + + ssd1306_WriteCommand(0xB0); //Set Page Start Address for Page Addressing Mode,0-7 + +#ifdef SSD1306_MIRROR_VERT + ssd1306_WriteCommand(0xC0); // Mirror vertically +#else + ssd1306_WriteCommand(0xC8); //Set COM Output Scan Direction +#endif + + ssd1306_WriteCommand(0x00); //---set low column address + ssd1306_WriteCommand(0x10); //---set high column address + + ssd1306_WriteCommand(0x40); //--set start line address - CHECK + + ssd1306_SetContrast(0xFF); + +#ifdef SSD1306_MIRROR_HORIZ + ssd1306_WriteCommand(0xA0); // Mirror horizontally +#else + ssd1306_WriteCommand(0xA1); //--set segment re-map 0 to 127 - CHECK +#endif + +#ifdef SSD1306_INVERSE_COLOR + ssd1306_WriteCommand(0xA7); //--set inverse color +#else + ssd1306_WriteCommand(0xA6); //--set normal color +#endif + +// Set multiplex ratio. +#if (SSD1306_HEIGHT == 128) + // Found in the Luma Python lib for SH1106. + ssd1306_WriteCommand(0xFF); +#else + ssd1306_WriteCommand(0xA8); //--set multiplex ratio(1 to 64) - CHECK +#endif + +#if (SSD1306_HEIGHT == 32) + ssd1306_WriteCommand(0x1F); // +#elif (SSD1306_HEIGHT == 64) + ssd1306_WriteCommand(0x3F); // +#elif (SSD1306_HEIGHT == 128) + ssd1306_WriteCommand(0x3F); // Seems to work for 128px high displays too. +#else +#error "Only 32, 64, or 128 lines of height are supported!" +#endif + + ssd1306_WriteCommand(0xA4); //0xa4,Output follows RAM content;0xa5,Output ignores RAM content + + ssd1306_WriteCommand(0xD3); //-set display offset - CHECK + ssd1306_WriteCommand(0x00); //-not offset + + ssd1306_WriteCommand(0xD5); //--set display clock divide ratio/oscillator frequency + ssd1306_WriteCommand(0xF0); //--set divide ratio + + ssd1306_WriteCommand(0xD9); //--set pre-charge period + ssd1306_WriteCommand(0x11); // 0x22 by default + + ssd1306_WriteCommand(0xDA); //--set com pins hardware configuration - CHECK +#if (SSD1306_HEIGHT == 32) + ssd1306_WriteCommand(0x02); +#elif (SSD1306_HEIGHT == 64) + ssd1306_WriteCommand(0x12); +#elif (SSD1306_HEIGHT == 128) + ssd1306_WriteCommand(0x12); +#else +#error "Only 32, 64, or 128 lines of height are supported!" +#endif + + ssd1306_WriteCommand(0xDB); //--set vcomh + ssd1306_WriteCommand(0x30); //0x20,0.77xVcc, 0x30,0.83xVcc + + ssd1306_WriteCommand(0x8D); //--set DC-DC enable + ssd1306_WriteCommand(0x14); // + ssd1306_SetDisplayOn(1); //--turn on SSD1306 panel + + // Clear screen + ssd1306_Fill(Black); + + // Flush buffer to screen + ssd1306_UpdateScreen(); + + // Set default values for screen object + SSD1306.CurrentX = 0; + SSD1306.CurrentY = 0; + + SSD1306.Initialized = 1; +} + +// Fill the whole screen with the given color +void ssd1306_Fill(SSD1306_COLOR color) { + /* Set memory */ + uint32_t i; + + for(i = 0; i < sizeof(SSD1306_Buffer); i++) { + SSD1306_Buffer[i] = (color == Black) ? 0x00 : 0xFF; + } +} + +// Write the screenbuffer with changed to the screen +void ssd1306_UpdateScreen(void) { + // Write data to each page of RAM. Number of pages + // depends on the screen height: + // + // * 32px == 4 pages + // * 64px == 8 pages + // * 128px == 16 pages + + uint8_t cmd[] = { + 0X21, // 设置列起始和结束地址 + 0X00, // 列起始地址 0 + 0X7F, // 列终止地址 127 + 0X22, // 设置页起始和结束地址 + 0X00, // 页起始地址 0 + 0X07, // 页终止地址 7 + }; + uint32_t count = 0; + uint8_t data[sizeof(cmd)*2 + SSD1306_BUFFER_SIZE + 1] = {}; + + // copy cmd + for (uint32_t i = 0; i < sizeof(cmd)/sizeof(cmd[0]); i++) { + data[count++] = SSD1306_CTRL_CMD | SSD1306_MASK_CONT; + data[count++] = cmd[i]; + } + + // copy frame data + data[count++] = SSD1306_CTRL_DATA; + memcpy(&data[count], SSD1306_Buffer, sizeof(SSD1306_Buffer)); + count += sizeof(SSD1306_Buffer); + + // send to i2c bus + uint32_t retval = ssd1306_SendData(data, count); + if (retval != WIFI_IOT_SUCCESS) { + printf("ssd1306_UpdateScreen send frame data filed: %d!\r\n", retval); + } +} + +// Draw one pixel in the screenbuffer +// X => X Coordinate +// Y => Y Coordinate +// color => Pixel color +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color) { + if(x >= SSD1306_WIDTH || y >= SSD1306_HEIGHT) { + // Don't write outside the buffer + return; + } + + // Check if pixel should be inverted + if(SSD1306.Inverted) { + color = (SSD1306_COLOR)!color; + } + + // Draw in the right color + if(color == White) { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] |= 1 << (y % 8); + } else { + SSD1306_Buffer[x + (y / 8) * SSD1306_WIDTH] &= ~(1 << (y % 8)); + } +} + +// Draw 1 char to the screen buffer +// ch => char om weg te schrijven +// Font => Font waarmee we gaan schrijven +// color => Black or White +char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color) { + uint32_t i, b, j; + + // Check if character is valid + if (ch < 32 || ch > 126) + return 0; + + // Check remaining space on current line + if (SSD1306_WIDTH < (SSD1306.CurrentX + Font.FontWidth) || + SSD1306_HEIGHT < (SSD1306.CurrentY + Font.FontHeight)) + { + // Not enough space on current line + return 0; + } + + // Use the font to write + for(i = 0; i < Font.FontHeight; i++) { + b = Font.data[(ch - 32) * Font.FontHeight + i]; + for(j = 0; j < Font.FontWidth; j++) { + if((b << j) & 0x8000) { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR) color); + } else { + ssd1306_DrawPixel(SSD1306.CurrentX + j, (SSD1306.CurrentY + i), (SSD1306_COLOR)!color); + } + } + } + + // The current space is now taken + SSD1306.CurrentX += Font.FontWidth; + + // Return written char for validation + return ch; +} + +// Write full string to screenbuffer +char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color) { + // Write until null-byte + while (*str) { + if (ssd1306_DrawChar(*str, Font, color) != *str) { + // Char could not be written + return *str; + } + + // Next char + str++; + } + + // Everything ok + return *str; +} + +// Position the cursor +void ssd1306_SetCursor(uint8_t x, uint8_t y) { + SSD1306.CurrentX = x; + SSD1306.CurrentY = y; +} + +// Draw line by Bresenhem's algorithm +void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) { + int32_t deltaX = abs(x2 - x1); + int32_t deltaY = abs(y2 - y1); + int32_t signX = ((x1 < x2) ? 1 : -1); + int32_t signY = ((y1 < y2) ? 1 : -1); + int32_t error = deltaX - deltaY; + int32_t error2; + + ssd1306_DrawPixel(x2, y2, color); + while((x1 != x2) || (y1 != y2)) + { + ssd1306_DrawPixel(x1, y1, color); + error2 = error * 2; + if(error2 > -deltaY) + { + error -= deltaY; + x1 += signX; + } + else + { + /*nothing to do*/ + } + + if(error2 < deltaX) + { + error += deltaX; + y1 += signY; + } + else + { + /*nothing to do*/ + } + } + return; +} +//Draw polyline +void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color) { + uint16_t i; + if(par_vertex != 0){ + for(i = 1; i < par_size; i++){ + ssd1306_DrawLine(par_vertex[i - 1].x, par_vertex[i - 1].y, par_vertex[i].x, par_vertex[i].y, color); + } + } + else + { + /*nothing to do*/ + } + return; +} +/*Convert Degrees to Radians*/ +static float ssd1306_DegToRad(float par_deg) { + return par_deg * 3.14 / 180.0; +} +/*Normalize degree to [0;360]*/ +static uint16_t ssd1306_NormalizeTo0_360(uint16_t par_deg) { + uint16_t loc_angle; + if(par_deg <= 360) + { + loc_angle = par_deg; + } + else + { + loc_angle = par_deg % 360; + loc_angle = ((par_deg != 0)?par_deg:360); + } + return loc_angle; +} +/*DrawArc. Draw angle is beginning from 4 quart of trigonometric circle (3pi/2) + * start_angle in degree + * sweep in degree + */ +void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color) { + #define CIRCLE_APPROXIMATION_SEGMENTS 36 + float approx_degree; + uint32_t approx_segments; + uint8_t xp1,xp2; + uint8_t yp1,yp2; + uint32_t count = 0; + uint32_t loc_sweep = 0; + float rad; + + loc_sweep = ssd1306_NormalizeTo0_360(sweep); + + count = (ssd1306_NormalizeTo0_360(start_angle) * CIRCLE_APPROXIMATION_SEGMENTS) / 360; + approx_segments = (loc_sweep * CIRCLE_APPROXIMATION_SEGMENTS) / 360; + approx_degree = loc_sweep / (float)approx_segments; + while(count < approx_segments) + { + rad = ssd1306_DegToRad(count*approx_degree); + xp1 = x + (int8_t)(sin(rad)*radius); + yp1 = y + (int8_t)(cos(rad)*radius); + count++; + if(count != approx_segments) + { + rad = ssd1306_DegToRad(count*approx_degree); + } + else + { + rad = ssd1306_DegToRad(loc_sweep); + } + xp2 = x + (int8_t)(sin(rad)*radius); + yp2 = y + (int8_t)(cos(rad)*radius); + ssd1306_DrawLine(xp1,yp1,xp2,yp2,color); + } + + return; +} +//Draw circle by Bresenhem's algorithm +void ssd1306_DrawCircle(uint8_t par_x,uint8_t par_y,uint8_t par_r,SSD1306_COLOR par_color) { + int32_t x = -par_r; + int32_t y = 0; + int32_t err = 2 - 2 * par_r; + int32_t e2; + + if (par_x >= SSD1306_WIDTH || par_y >= SSD1306_HEIGHT) { + return; + } + + do { + ssd1306_DrawPixel(par_x - x, par_y + y, par_color); + ssd1306_DrawPixel(par_x + x, par_y + y, par_color); + ssd1306_DrawPixel(par_x + x, par_y - y, par_color); + ssd1306_DrawPixel(par_x - x, par_y - y, par_color); + e2 = err; + if (e2 <= y) { + y++; + err = err + (y * 2 + 1); + if(-x == y && e2 <= x) { + e2 = 0; + } + else + { + /*nothing to do*/ + } + } + else + { + /*nothing to do*/ + } + if(e2 > x) { + x++; + err = err + (x * 2 + 1); + } + else + { + /*nothing to do*/ + } + } while(x <= 0); + + return; +} + +//Draw rectangle +void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color) { + ssd1306_DrawLine(x1,y1,x2,y1,color); + ssd1306_DrawLine(x2,y1,x2,y2,color); + ssd1306_DrawLine(x2,y2,x1,y2,color); + ssd1306_DrawLine(x1,y2,x1,y1,color); + + return; +} + +void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size) +{ + uint8_t rows = size * 8 / SSD1306_WIDTH; + if (rows > SSD1306_HEIGHT) { + rows = SSD1306_HEIGHT; + } + for (uint8_t y = 0; y < rows; y++) { + for (uint8_t x = 0; x < SSD1306_WIDTH; x++) { + uint8_t byte = bitmap[(y * SSD1306_WIDTH / 8) + (x / 8)]; + uint8_t bit = byte & (0x80 >> (x % 8)); + ssd1306_DrawPixel(x, y, bit ? White : Black); + } + } +} + +void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride) +{ + if (x + w > SSD1306_WIDTH || y + h > SSD1306_HEIGHT || w * h == 0) { + printf("%dx%d @ %d,%d out of range or invalid!\r\n", w, h, x, y); + return; + } + + w = (w <= SSD1306_WIDTH ? w : SSD1306_WIDTH); + h = (h <= SSD1306_HEIGHT ? h : SSD1306_HEIGHT); + stride = (stride == 0 ? w : stride); + + uint8_t rows = size * 8 / stride; + for (uint8_t i = 0; i < rows; i++) { + uint32_t base = i * stride / 8; + for (uint8_t j = 0; j < w; j++) { + uint32_t idx = base + (j / 8); + uint8_t byte = idx < size ? data[idx] : 0; + uint8_t bit = byte & (0x80 >> (j % 8)); + ssd1306_DrawPixel(x + j, y + i, bit ? White : Black); + } + } +} + +void ssd1306_SetContrast(const uint8_t value) { + const uint8_t kSetContrastControlRegister = 0x81; + ssd1306_WriteCommand(kSetContrastControlRegister); + ssd1306_WriteCommand(value); +} + +void ssd1306_SetDisplayOn(const uint8_t on) { + uint8_t value; + if (on) { + value = 0xAF; // Display on + SSD1306.DisplayOn = 1; + } else { + value = 0xAE; // Display off + SSD1306.DisplayOn = 0; + } + ssd1306_WriteCommand(value); +} + +uint8_t ssd1306_GetDisplayOn() { + return SSD1306.DisplayOn; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.h" new file mode 100755 index 0000000000000000000000000000000000000000..97942c642bd24da5216b9a0f5e7ee8ce6fe71883 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306.h" @@ -0,0 +1,181 @@ +/** + * This Library was originally written by Olivier Van den Eede (4ilo) in 2016. + * Some refactoring was done and SPI support was added by Aleksander Alekseev (afiskon) in 2018. + * + * https://github.com/afiskon/stm32-ssd1306 + */ + +#ifndef __SSD1306_H__ +#define __SSD1306_H__ + +#include +#include <_ansi.h> + +_BEGIN_STD_C + +#include "ssd1306_conf.h" + +#if defined(STM32F0) +#include "stm32f0xx_hal.h" +#elif defined(STM32F1) +#include "stm32f1xx_hal.h" +#elif defined(STM32F4) +#include "stm32f4xx_hal.h" +#include "stm32f4xx_hal_gpio.h" +#elif defined(STM32L0) +#include "stm32l0xx_hal.h" +#elif defined(STM32L4) +#include "stm32l4xx_hal.h" +#elif defined(STM32F3) +#include "stm32f3xx_hal.h" +#elif defined(STM32H7) +#include "stm32h7xx_hal.h" +#elif defined(STM32F7) +#include "stm32f7xx_hal.h" +#else +// #error "SSD1306 library was tested only on STM32F0, STM32F1, STM32F3, STM32F4, STM32F7, STM32L0, STM32L4, STM32H7 MCU families. Please modify ssd1306.h if you know what you are doing. Also please send a pull request if it turns out the library works on other MCU's as well!" +#endif + +#include "ssd1306_fonts.h" + +/* vvv I2C config vvv */ + +#ifndef SSD1306_I2C_PORT +#define SSD1306_I2C_PORT hi2c1 +#endif + +#ifndef SSD1306_I2C_ADDR +#define SSD1306_I2C_ADDR (0x3C << 1) +#endif + +/* ^^^ I2C config ^^^ */ + +/* vvv SPI config vvv */ + +#ifndef SSD1306_SPI_PORT +#define SSD1306_SPI_PORT hspi2 +#endif + +#ifndef SSD1306_CS_Port +#define SSD1306_CS_Port GPIOB +#endif +#ifndef SSD1306_CS_Pin +#define SSD1306_CS_Pin GPIO_PIN_12 +#endif + +#ifndef SSD1306_DC_Port +#define SSD1306_DC_Port GPIOB +#endif +#ifndef SSD1306_DC_Pin +#define SSD1306_DC_Pin GPIO_PIN_14 +#endif + +#ifndef SSD1306_Reset_Port +#define SSD1306_Reset_Port GPIOA +#endif +#ifndef SSD1306_Reset_Pin +#define SSD1306_Reset_Pin GPIO_PIN_8 +#endif + +/* ^^^ SPI config ^^^ */ + +#if defined(SSD1306_USE_I2C) +// extern I2C_HandleTypeDef SSD1306_I2C_PORT; +#elif defined(SSD1306_USE_SPI) +extern SPI_HandleTypeDef SSD1306_SPI_PORT; +#else +#error "You should define SSD1306_USE_SPI or SSD1306_USE_I2C macro!" +#endif + +// SSD1306 OLED height in pixels +#ifndef SSD1306_HEIGHT +#define SSD1306_HEIGHT 64 +#endif + +// SSD1306 width in pixels +#ifndef SSD1306_WIDTH +#define SSD1306_WIDTH 128 +#endif + +// some LEDs don't display anything in first two columns +// #define SSD1306_WIDTH 130 + +#ifndef SSD1306_BUFFER_SIZE +#define SSD1306_BUFFER_SIZE SSD1306_WIDTH * SSD1306_HEIGHT / 8 +#endif + +// Enumeration for screen colors +typedef enum { + Black = 0x00, // Black color, no pixel + White = 0x01 // Pixel is set. Color depends on OLED +} SSD1306_COLOR; + +typedef enum { + SSD1306_OK = 0x00, + SSD1306_ERR = 0x01 // Generic error. +} SSD1306_Error_t; + +// Struct to store transformations +typedef struct { + uint16_t CurrentX; + uint16_t CurrentY; + uint8_t Inverted; + uint8_t Initialized; + uint8_t DisplayOn; +} SSD1306_t; +typedef struct { + uint8_t x; + uint8_t y; +} SSD1306_VERTEX; + +// Procedure definitions +void ssd1306_Init(void); +void ssd1306_Fill(SSD1306_COLOR color); +void ssd1306_SetCursor(uint8_t x, uint8_t y); +void ssd1306_UpdateScreen(void); + +char ssd1306_DrawChar(char ch, FontDef Font, SSD1306_COLOR color); +char ssd1306_DrawString(char* str, FontDef Font, SSD1306_COLOR color); + +void ssd1306_DrawPixel(uint8_t x, uint8_t y, SSD1306_COLOR color); +void ssd1306_DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color); +void ssd1306_DrawPolyline(const SSD1306_VERTEX *par_vertex, uint16_t par_size, SSD1306_COLOR color); +void ssd1306_DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, SSD1306_COLOR color); +void ssd1306_DrawArc(uint8_t x, uint8_t y, uint8_t radius, uint16_t start_angle, uint16_t sweep, SSD1306_COLOR color); +void ssd1306_DrawCircle(uint8_t par_x, uint8_t par_y, uint8_t par_r, SSD1306_COLOR color); +void ssd1306_DrawBitmap(const uint8_t* bitmap, uint32_t size); + +void ssd1306_DrawRegion(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* data, uint32_t size, uint32_t stride); + +/** + * @brief Sets the contrast of the display. + * @param[in] value contrast to set. + * @note Contrast increases as the value increases. + * @note RESET = 7Fh. + */ +void ssd1306_SetContrast(const uint8_t value); +/** + * @brief Set Display ON/OFF. + * @param[in] on 0 for OFF, any for ON. + */ +void ssd1306_SetDisplayOn(const uint8_t on); +/** + * @brief Reads DisplayOn state. + * @return 0: OFF. + * 1: ON. + */ +uint8_t ssd1306_GetDisplayOn(void); + +void HAL_Delay(uint32_t ms); + +uint32_t HAL_GetTick(void); // in ms + +// Low-level procedures +void ssd1306_Reset(void); +void ssd1306_WriteCommand(uint8_t byte); +void ssd1306_WriteData(uint8_t* buffer, size_t buff_size); +SSD1306_Error_t ssd1306_FillBuffer(uint8_t* buf, uint32_t len); + +_END_STD_C + +#endif // __SSD1306_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_conf.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_conf.h" new file mode 100755 index 0000000000000000000000000000000000000000..4dd7a6dd117b7acb456854cf4dfe38bc7b8fac23 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_conf.h" @@ -0,0 +1,40 @@ +/** + * Private configuration file for the SSD1306 library. + * This example is configured for STM32F0, I2C and including all fonts. + */ + +#ifndef __SSD1306_CONF_H__ +#define __SSD1306_CONF_H__ + +// Choose a microcontroller family +// #define STM32F0 +//#define STM32F1 +//#define STM32F4 +//#define STM32L0 +//#define STM32L4 +//#define STM32F3 +//#define STM32H7 +//#define STM32F7 + +// Choose a bus +#define SSD1306_USE_I2C +//#define SSD1306_USE_SPI + +// I2C Configuration +// #define SSD1306_I2C_PORT hi2c1 +#define SSD1306_I2C_ADDR (0x3C << 1) + +// Mirror the screen if needed +// #define SSD1306_MIRROR_VERT +// #define SSD1306_MIRROR_HORIZ + +// Set inverse color if needed +// # define SSD1306_INVERSE_COLOR + +// Include only needed fonts +#define SSD1306_INCLUDE_FONT_6x8 +#define SSD1306_INCLUDE_FONT_7x10 +#define SSD1306_INCLUDE_FONT_11x18 +#define SSD1306_INCLUDE_FONT_16x26 + +#endif /* __SSD1306_CONF_H__ */ \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.c" new file mode 100755 index 0000000000000000000000000000000000000000..9bed638647affd3b451d92307a646a59e393b455 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.c" @@ -0,0 +1,413 @@ + +#include "ssd1306_fonts.h" + +#ifdef SSD1306_INCLUDE_FONT_7x10 +static const uint16_t Font7x10 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ! +0x2800, 0x2800, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x2400, 0x2400, 0x7C00, 0x2400, 0x4800, 0x7C00, 0x4800, 0x4800, 0x0000, 0x0000, // # +0x3800, 0x5400, 0x5000, 0x3800, 0x1400, 0x5400, 0x5400, 0x3800, 0x1000, 0x0000, // $ +0x2000, 0x5400, 0x5800, 0x3000, 0x2800, 0x5400, 0x1400, 0x0800, 0x0000, 0x0000, // % +0x1000, 0x2800, 0x2800, 0x1000, 0x3400, 0x4800, 0x4800, 0x3400, 0x0000, 0x0000, // & +0x1000, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0800, 0x1000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x1000, 0x0800, // ( +0x2000, 0x1000, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x1000, 0x2000, // ) +0x1000, 0x3800, 0x1000, 0x2800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x1000, 0x1000, 0x7C00, 0x1000, 0x1000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3800, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // . +0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x0000, 0x0000, // / +0x3800, 0x4400, 0x4400, 0x5400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 0 +0x1000, 0x3000, 0x5000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // 1 +0x3800, 0x4400, 0x4400, 0x0400, 0x0800, 0x1000, 0x2000, 0x7C00, 0x0000, 0x0000, // 2 +0x3800, 0x4400, 0x0400, 0x1800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 3 +0x0800, 0x1800, 0x2800, 0x2800, 0x4800, 0x7C00, 0x0800, 0x0800, 0x0000, 0x0000, // 4 +0x7C00, 0x4000, 0x4000, 0x7800, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 5 +0x3800, 0x4400, 0x4000, 0x7800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 6 +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x2000, 0x2000, 0x0000, 0x0000, // 7 +0x3800, 0x4400, 0x4400, 0x3800, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // 8 +0x3800, 0x4400, 0x4400, 0x4400, 0x3C00, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x1000, 0x0000, 0x0000, 0x0000, 0x1000, 0x1000, 0x1000, // ; +0x0000, 0x0000, 0x0C00, 0x3000, 0x4000, 0x3000, 0x0C00, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x7C00, 0x0000, 0x7C00, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x6000, 0x1800, 0x0400, 0x1800, 0x6000, 0x0000, 0x0000, 0x0000, // > +0x3800, 0x4400, 0x0400, 0x0800, 0x1000, 0x1000, 0x0000, 0x1000, 0x0000, 0x0000, // ? +0x3800, 0x4400, 0x4C00, 0x5400, 0x5C00, 0x4000, 0x4000, 0x3800, 0x0000, 0x0000, // @ +0x1000, 0x2800, 0x2800, 0x2800, 0x2800, 0x7C00, 0x4400, 0x4400, 0x0000, 0x0000, // A +0x7800, 0x4400, 0x4400, 0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x0000, 0x0000, // B +0x3800, 0x4400, 0x4000, 0x4000, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // C +0x7000, 0x4800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4800, 0x7000, 0x0000, 0x0000, // D +0x7C00, 0x4000, 0x4000, 0x7C00, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // E +0x7C00, 0x4000, 0x4000, 0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // F +0x3800, 0x4400, 0x4000, 0x4000, 0x5C00, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // G +0x4400, 0x4400, 0x4400, 0x7C00, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // H +0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3800, 0x0000, 0x0000, // I +0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // J +0x4400, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // K +0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7C00, 0x0000, 0x0000, // L +0x4400, 0x6C00, 0x6C00, 0x5400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // M +0x4400, 0x6400, 0x6400, 0x5400, 0x5400, 0x4C00, 0x4C00, 0x4400, 0x0000, 0x0000, // N +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // O +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // P +0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x5400, 0x3800, 0x0400, 0x0000, // Q +0x7800, 0x4400, 0x4400, 0x4400, 0x7800, 0x4800, 0x4800, 0x4400, 0x0000, 0x0000, // R +0x3800, 0x4400, 0x4000, 0x3000, 0x0800, 0x0400, 0x4400, 0x3800, 0x0000, 0x0000, // S +0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // T +0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // U +0x4400, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x1000, 0x0000, 0x0000, // V +0x4400, 0x4400, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // W +0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, // X +0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // Y +0x7C00, 0x0400, 0x0800, 0x1000, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // Z +0x1800, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1800, // [ +0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x0000, 0x0000, /* \ */ +0x3000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x3000, // ] +0x1000, 0x2800, 0x2800, 0x4400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFE00, // _ +0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x3800, 0x4400, 0x3C00, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // a +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x3800, 0x4400, 0x4000, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // c +0x0400, 0x0400, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x3800, 0x4400, 0x7C00, 0x4000, 0x4400, 0x3800, 0x0000, 0x0000, // e +0x0C00, 0x1000, 0x7C00, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x7800, // g +0x4000, 0x4000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // h +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // i +0x1000, 0x0000, 0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0xE000, // j +0x4000, 0x4000, 0x4800, 0x5000, 0x6000, 0x5000, 0x4800, 0x4400, 0x0000, 0x0000, // k +0x7000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x7800, 0x5400, 0x5400, 0x5400, 0x5400, 0x5400, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x4400, 0x4400, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x3800, 0x4400, 0x4400, 0x4400, 0x4400, 0x3800, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x5800, 0x6400, 0x4400, 0x4400, 0x6400, 0x5800, 0x4000, 0x4000, // p +0x0000, 0x0000, 0x3400, 0x4C00, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0400, 0x0400, // q +0x0000, 0x0000, 0x5800, 0x6400, 0x4000, 0x4000, 0x4000, 0x4000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x3800, 0x4400, 0x3000, 0x0800, 0x4400, 0x3800, 0x0000, 0x0000, // s +0x2000, 0x2000, 0x7800, 0x2000, 0x2000, 0x2000, 0x2000, 0x1800, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x4400, 0x4400, 0x4400, 0x4400, 0x4C00, 0x3400, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x2800, 0x1000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x5400, 0x5400, 0x5400, 0x6C00, 0x2800, 0x2800, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x4400, 0x2800, 0x1000, 0x1000, 0x2800, 0x4400, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x4400, 0x4400, 0x2800, 0x2800, 0x1000, 0x1000, 0x1000, 0x6000, // y +0x0000, 0x0000, 0x7C00, 0x0800, 0x1000, 0x2000, 0x4000, 0x7C00, 0x0000, 0x0000, // z +0x1800, 0x1000, 0x1000, 0x1000, 0x2000, 0x2000, 0x1000, 0x1000, 0x1000, 0x1800, // { +0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, // | +0x3000, 0x1000, 0x1000, 0x1000, 0x0800, 0x0800, 0x1000, 0x1000, 0x1000, 0x3000, // } +0x0000, 0x0000, 0x0000, 0x7400, 0x4C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif + +#ifdef SSD1306_INCLUDE_FONT_11x18 +static const uint16_t Font11x18 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ! +0x0000, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x0000, 0x1980, 0x1980, 0x1980, 0x1980, 0x7FC0, 0x7FC0, 0x1980, 0x3300, 0x7FC0, 0x7FC0, 0x3300, 0x3300, 0x3300, 0x3300, 0x0000, 0x0000, 0x0000, // # +0x0000, 0x1E00, 0x3F00, 0x7580, 0x6580, 0x7400, 0x3C00, 0x1E00, 0x0700, 0x0580, 0x6580, 0x6580, 0x7580, 0x3F00, 0x1E00, 0x0400, 0x0400, 0x0000, // $ +0x0000, 0x7000, 0xD800, 0xD840, 0xD8C0, 0xD980, 0x7300, 0x0600, 0x0C00, 0x1B80, 0x36C0, 0x66C0, 0x46C0, 0x06C0, 0x0380, 0x0000, 0x0000, 0x0000, // % +0x0000, 0x1E00, 0x3F00, 0x3300, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x3CC0, 0x66C0, 0x6380, 0x6180, 0x6380, 0x3EC0, 0x1C80, 0x0000, 0x0000, 0x0000, // & +0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x0080, 0x0100, 0x0300, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0300, 0x0100, 0x0080, // ( +0x2000, 0x1000, 0x1800, 0x0C00, 0x0C00, 0x0400, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0400, 0x0C00, 0x0C00, 0x1800, 0x1000, 0x2000, // ) +0x0000, 0x0C00, 0x2D00, 0x3F00, 0x1E00, 0x3300, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // * +0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // , +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x1E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // . +0x0000, 0x0300, 0x0300, 0x0300, 0x0600, 0x0600, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // / +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6D80, 0x6D80, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 0 +0x0000, 0x0600, 0x0E00, 0x1E00, 0x3600, 0x2600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 1 +0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // 2 +0x0000, 0x1C00, 0x3E00, 0x6300, 0x6300, 0x0300, 0x0E00, 0x0E00, 0x0300, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 3 +0x0000, 0x0600, 0x0E00, 0x0E00, 0x1E00, 0x1E00, 0x1600, 0x3600, 0x3600, 0x6600, 0x7F80, 0x7F80, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // 4 +0x0000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x6380, 0x0180, 0x0180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 5 +0x0000, 0x1E00, 0x3F00, 0x3380, 0x6180, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x3380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 6 +0x0000, 0x7F80, 0x7F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0600, 0x0C00, 0x0C00, 0x0C00, 0x0800, 0x1800, 0x1800, 0x1800, 0x0000, 0x0000, 0x0000, // 7 +0x0000, 0x1E00, 0x3F00, 0x6380, 0x6180, 0x6180, 0x2100, 0x1E00, 0x3F00, 0x6180, 0x6180, 0x6180, 0x6180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 8 +0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6180, 0x7300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // 9 +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0C00, 0x0C00, 0x0400, 0x0400, 0x0800, // ; +0x0000, 0x0000, 0x0000, 0x0000, 0x0080, 0x0380, 0x0E00, 0x3800, 0x6000, 0x3800, 0x0E00, 0x0380, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // < +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // = +0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x7000, 0x1C00, 0x0700, 0x0180, 0x0700, 0x1C00, 0x7000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // > +0x0000, 0x1F00, 0x3F80, 0x71C0, 0x60C0, 0x00C0, 0x01C0, 0x0380, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0000, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // ? +0x0000, 0x1E00, 0x3F00, 0x3180, 0x7180, 0x6380, 0x6F80, 0x6D80, 0x6D80, 0x6F80, 0x6780, 0x6000, 0x3200, 0x3E00, 0x1C00, 0x0000, 0x0000, 0x0000, // @ +0x0000, 0x0E00, 0x0E00, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x3180, 0x3180, 0x3F80, 0x3F80, 0x3180, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // A +0x0000, 0x7C00, 0x7E00, 0x6300, 0x6300, 0x6300, 0x6300, 0x7E00, 0x7E00, 0x6300, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x0000, 0x0000, 0x0000, // B +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // C +0x0000, 0x7C00, 0x7F00, 0x6300, 0x6380, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6300, 0x6300, 0x7E00, 0x7C00, 0x0000, 0x0000, 0x0000, // D +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // E +0x0000, 0x7F80, 0x7F80, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F00, 0x7F00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // F +0x0000, 0x1E00, 0x3F00, 0x3180, 0x6180, 0x6000, 0x6000, 0x6000, 0x6380, 0x6380, 0x6180, 0x6180, 0x3180, 0x3F80, 0x1E00, 0x0000, 0x0000, 0x0000, // G +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7F80, 0x7F80, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // H +0x0000, 0x3F00, 0x3F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3F00, 0x3F00, 0x0000, 0x0000, 0x0000, // I +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x0180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // J +0x0000, 0x60C0, 0x6180, 0x6300, 0x6600, 0x6600, 0x6C00, 0x7800, 0x7C00, 0x6600, 0x6600, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // K +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // L +0x0000, 0x71C0, 0x71C0, 0x7BC0, 0x7AC0, 0x6AC0, 0x6AC0, 0x6EC0, 0x64C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x60C0, 0x0000, 0x0000, 0x0000, // M +0x0000, 0x7180, 0x7180, 0x7980, 0x7980, 0x7980, 0x6D80, 0x6D80, 0x6D80, 0x6580, 0x6780, 0x6780, 0x6780, 0x6380, 0x6380, 0x0000, 0x0000, 0x0000, // N +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x3300, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // O +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6000, 0x6000, 0x6000, 0x6000, 0x6000, 0x0000, 0x0000, 0x0000, // P +0x0000, 0x1E00, 0x3F00, 0x3300, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6580, 0x6780, 0x3300, 0x3F80, 0x1E40, 0x0000, 0x0000, 0x0000, // Q +0x0000, 0x7E00, 0x7F00, 0x6380, 0x6180, 0x6180, 0x6380, 0x7F00, 0x7E00, 0x6600, 0x6300, 0x6300, 0x6180, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // R +0x0000, 0x0E00, 0x1F00, 0x3180, 0x3180, 0x3000, 0x3800, 0x1E00, 0x0700, 0x0380, 0x6180, 0x6180, 0x3180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // S +0x0000, 0xFFC0, 0xFFC0, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // T +0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // U +0x0000, 0x60C0, 0x60C0, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x0400, 0x0000, 0x0000, 0x0000, // V +0x0000, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xC0C0, 0xCCC0, 0x4C80, 0x4C80, 0x5E80, 0x5280, 0x5280, 0x7380, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // W +0x0000, 0xC0C0, 0x6080, 0x6180, 0x3300, 0x3B00, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x1F00, 0x3B00, 0x7180, 0x6180, 0xC0C0, 0x0000, 0x0000, 0x0000, // X +0x0000, 0xC0C0, 0x6180, 0x6180, 0x3300, 0x3300, 0x1E00, 0x1E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // Y +0x0000, 0x3F80, 0x3F80, 0x0180, 0x0300, 0x0300, 0x0600, 0x0C00, 0x0C00, 0x1800, 0x1800, 0x3000, 0x6000, 0x7F80, 0x7F80, 0x0000, 0x0000, 0x0000, // Z +0x0F00, 0x0F00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0F00, 0x0F00, // [ +0x0000, 0x1800, 0x1800, 0x1800, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0300, 0x0300, 0x0300, 0x0000, 0x0000, 0x0000, /* \ */ +0x1E00, 0x1E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x1E00, 0x1E00, // ] +0x0000, 0x0C00, 0x0C00, 0x1E00, 0x1200, 0x3300, 0x3300, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFE0, 0x0000, // _ +0x0000, 0x3800, 0x1800, 0x0C00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1F00, 0x3F80, 0x6180, 0x0180, 0x1F80, 0x3F80, 0x6180, 0x6380, 0x7F80, 0x38C0, 0x0000, 0x0000, 0x0000, // a +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x0000, 0x0000, 0x0000, // b +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6000, 0x6000, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // c +0x0000, 0x0180, 0x0180, 0x0180, 0x0180, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0000, 0x0000, 0x0000, // d +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7300, 0x6180, 0x7F80, 0x7F80, 0x6000, 0x7180, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // e +0x0000, 0x07C0, 0x0FC0, 0x0C00, 0x0C00, 0x7F80, 0x7F80, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0000, 0x0000, 0x0000, // f +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x6380, 0x7F00, 0x3E00, // g +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // h +0x0000, 0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // i +0x0600, 0x0600, 0x0000, 0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x4600, 0x7E00, 0x3C00, // j +0x0000, 0x6000, 0x6000, 0x6000, 0x6000, 0x6180, 0x6300, 0x6600, 0x6C00, 0x7C00, 0x7600, 0x6300, 0x6300, 0x6180, 0x60C0, 0x0000, 0x0000, 0x0000, // k +0x0000, 0x3E00, 0x3E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, // l +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xFFC0, 0xCEC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0xCCC0, 0x0000, 0x0000, 0x0000, // m +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6F00, 0x7F80, 0x7180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x0000, 0x0000, 0x0000, // n +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F00, 0x1E00, 0x0000, 0x0000, 0x0000, // o +0x0000, 0x0000, 0x0000, 0x0000, 0x6E00, 0x7F00, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x7F00, 0x6E00, 0x6000, 0x6000, 0x6000, 0x6000, // p +0x0000, 0x0000, 0x0000, 0x0000, 0x1D80, 0x3F80, 0x7380, 0x6180, 0x6180, 0x6180, 0x6180, 0x7380, 0x3F80, 0x1D80, 0x0180, 0x0180, 0x0180, 0x0180, // q +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6700, 0x3F80, 0x3900, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x0000, 0x0000, 0x0000, // r +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1E00, 0x3F80, 0x6180, 0x6000, 0x7F00, 0x3F80, 0x0180, 0x6180, 0x7F00, 0x1E00, 0x0000, 0x0000, 0x0000, // s +0x0000, 0x0000, 0x0800, 0x1800, 0x1800, 0x7F00, 0x7F00, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1800, 0x1F80, 0x0F80, 0x0000, 0x0000, 0x0000, // t +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6180, 0x6380, 0x7F80, 0x3D80, 0x0000, 0x0000, 0x0000, // u +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x60C0, 0x3180, 0x3180, 0x3180, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0600, 0x0000, 0x0000, 0x0000, // v +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xDD80, 0xDD80, 0xDD80, 0x5500, 0x5500, 0x5500, 0x7700, 0x7700, 0x2200, 0x2200, 0x0000, 0x0000, 0x0000, // w +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x3300, 0x3300, 0x1E00, 0x0C00, 0x0C00, 0x1E00, 0x3300, 0x3300, 0x6180, 0x0000, 0x0000, 0x0000, // x +0x0000, 0x0000, 0x0000, 0x0000, 0x6180, 0x6180, 0x3180, 0x3300, 0x3300, 0x1B00, 0x1B00, 0x1B00, 0x0E00, 0x0E00, 0x0E00, 0x1C00, 0x7C00, 0x7000, // y +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x7FC0, 0x7FC0, 0x0180, 0x0300, 0x0600, 0x0C00, 0x1800, 0x3000, 0x7FC0, 0x7FC0, 0x0000, 0x0000, 0x0000, // z +0x0380, 0x0780, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0E00, 0x1C00, 0x1C00, 0x0E00, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0780, 0x0380, // { +0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, 0x0600, // | +0x3800, 0x3C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0E00, 0x0700, 0x0700, 0x0E00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x0C00, 0x3C00, 0x3800, // } +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3880, 0x7F80, 0x4700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +static const uint16_t Font16x26 [] = { +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [ ] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x03C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [!] +0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x1E3C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ["] +0x01CE,0x03CE,0x03DE,0x039E,0x039C,0x079C,0x3FFF,0x7FFF,0x0738,0x0F38,0x0F78,0x0F78,0x0E78,0xFFFF,0xFFFF,0x1EF0,0x1CF0,0x1CE0,0x3CE0,0x3DE0,0x39E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [#] +0x03FC,0x0FFE,0x1FEE,0x1EE0,0x1EE0,0x1EE0,0x1EE0,0x1FE0,0x0FE0,0x07E0,0x03F0,0x01FC,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x01FE,0x3DFE,0x3FFC,0x0FF0,0x01E0,0x01E0,0x0000,0x0000,0x0000, // Ascii = [$] +0x3E03,0xF707,0xE78F,0xE78E,0xE39E,0xE3BC,0xE7B8,0xE7F8,0xF7F0,0x3FE0,0x01C0,0x03FF,0x07FF,0x07F3,0x0FF3,0x1EF3,0x3CF3,0x38F3,0x78F3,0xF07F,0xE03F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [%] +0x07E0,0x0FF8,0x0F78,0x1F78,0x1F78,0x1F78,0x0F78,0x0FF0,0x0FE0,0x1F80,0x7FC3,0xFBC3,0xF3E7,0xF1F7,0xF0F7,0xF0FF,0xF07F,0xF83E,0x7C7F,0x3FFF,0x1FEF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [&] +0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = ['] +0x003F,0x007C,0x01F0,0x01E0,0x03C0,0x07C0,0x0780,0x0780,0x0F80,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F00,0x0F80,0x0780,0x0780,0x07C0,0x03C0,0x01E0,0x01F0,0x007C,0x003F,0x000F,0x0000, // Ascii = [(] +0x7E00,0x1F00,0x07C0,0x03C0,0x01E0,0x01F0,0x00F0,0x00F0,0x00F8,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x00F8,0x00F0,0x00F0,0x01F0,0x01E0,0x03C0,0x07C0,0x1F00,0x7E00,0x7800,0x0000, // Ascii = [)] +0x03E0,0x03C0,0x01C0,0x39CE,0x3FFF,0x3F7F,0x0320,0x0370,0x07F8,0x0F78,0x1F3C,0x0638,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [*] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0xFFFF,0xFFFF,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [+] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x01C0,0x0380, // Ascii = [,] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [-] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [.] +0x000F,0x000F,0x001E,0x001E,0x003C,0x003C,0x0078,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0780,0x0F00,0x0F00,0x1E00,0x1E00,0x3C00,0x3C00,0x7800,0x7800,0xF000,0x0000, // Ascii = [/] +0x07F0,0x0FF8,0x1F7C,0x3E3E,0x3C1E,0x7C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x7C1F,0x3C1E,0x3E3E,0x1F7C,0x0FF8,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [0] +0x00F0,0x07F0,0x3FF0,0x3FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [1] +0x0FE0,0x3FF8,0x3C7C,0x003C,0x003E,0x003E,0x003E,0x003C,0x003C,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0780,0x0F00,0x1E00,0x3E00,0x3C00,0x3FFE,0x3FFE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [2] +0x0FF0,0x1FF8,0x1C7C,0x003E,0x003E,0x003E,0x003C,0x003C,0x00F8,0x0FF0,0x0FF8,0x007C,0x003E,0x001E,0x001E,0x001E,0x001E,0x003E,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [3] +0x0078,0x00F8,0x00F8,0x01F8,0x03F8,0x07F8,0x07F8,0x0F78,0x1E78,0x1E78,0x3C78,0x7878,0x7878,0xFFFF,0xFFFF,0x0078,0x0078,0x0078,0x0078,0x0078,0x0078,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [4] +0x1FFC,0x1FFC,0x1FFC,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FE0,0x1FF8,0x00FC,0x007C,0x003E,0x003E,0x001E,0x003E,0x003E,0x003C,0x1C7C,0x1FF8,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [5] +0x01FC,0x07FE,0x0F8E,0x1F00,0x1E00,0x3E00,0x3C00,0x3C00,0x3DF8,0x3FFC,0x7F3E,0x7E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3E0F,0x1E1F,0x1F3E,0x0FFC,0x03F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [6] +0x3FFF,0x3FFF,0x3FFF,0x000F,0x001E,0x001E,0x003C,0x0038,0x0078,0x00F0,0x00F0,0x01E0,0x01E0,0x03C0,0x03C0,0x0780,0x0F80,0x0F80,0x0F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [7] +0x07F8,0x0FFC,0x1F3E,0x1E1E,0x3E1E,0x3E1E,0x1E1E,0x1F3C,0x0FF8,0x07F0,0x0FF8,0x1EFC,0x3E3E,0x3C1F,0x7C1F,0x7C0F,0x7C0F,0x3C1F,0x3F3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [8] +0x07F0,0x0FF8,0x1E7C,0x3C3E,0x3C1E,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x3C1F,0x3E3F,0x1FFF,0x07EF,0x001F,0x001E,0x001E,0x003E,0x003C,0x38F8,0x3FF0,0x1FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [9] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [:] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03E0,0x03E0,0x03E0,0x03E0,0x01E0,0x01E0,0x01E0,0x03C0,0x0380, // Ascii = [;] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0003,0x000F,0x003F,0x00FC,0x03F0,0x0FC0,0x3F00,0xFE00,0x3F00,0x0FC0,0x03F0,0x00FC,0x003F,0x000F,0x0003,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [<] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [=] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xE000,0xF800,0x7E00,0x1F80,0x07E0,0x01F8,0x007E,0x001F,0x007E,0x01F8,0x07E0,0x1F80,0x7E00,0xF800,0xE000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [>] +0x1FF0,0x3FFC,0x383E,0x381F,0x381F,0x001E,0x001E,0x003C,0x0078,0x00F0,0x01E0,0x03C0,0x03C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [?] +0x03F8,0x0FFE,0x1F1E,0x3E0F,0x3C7F,0x78FF,0x79EF,0x73C7,0xF3C7,0xF38F,0xF38F,0xF38F,0xF39F,0xF39F,0x73FF,0x7BFF,0x79F7,0x3C00,0x1F1C,0x0FFC,0x03F8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [@] +0x0000,0x0000,0x0000,0x03E0,0x03E0,0x07F0,0x07F0,0x07F0,0x0F78,0x0F78,0x0E7C,0x1E3C,0x1E3C,0x3C3E,0x3FFE,0x3FFF,0x781F,0x780F,0xF00F,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [A] +0x0000,0x0000,0x0000,0x3FF8,0x3FFC,0x3C3E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7C,0x3FF0,0x3FF8,0x3C7E,0x3C1F,0x3C1F,0x3C0F,0x3C0F,0x3C1F,0x3FFE,0x3FF8,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [B] +0x0000,0x0000,0x0000,0x01FF,0x07FF,0x1F87,0x3E00,0x3C00,0x7C00,0x7800,0x7800,0x7800,0x7800,0x7800,0x7C00,0x7C00,0x3E00,0x3F00,0x1F83,0x07FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [C] +0x0000,0x0000,0x0000,0x7FF0,0x7FFC,0x787E,0x781F,0x781F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x780F,0x781F,0x781E,0x787E,0x7FF8,0x7FE0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [D] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFE,0x3FFE,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [E] +0x0000,0x0000,0x0000,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1FFF,0x1FFF,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x1E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [F] +0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x7C00,0x7C00,0x7800,0xF800,0xF800,0xF87F,0xF87F,0x780F,0x7C0F,0x7C0F,0x3E0F,0x1F8F,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [G] +0x0000,0x0000,0x0000,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7FFF,0x7FFF,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x7C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [H] +0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [I] +0x0000,0x0000,0x0000,0x1FFC,0x1FFC,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x007C,0x0078,0x0078,0x38F8,0x3FF0,0x3FC0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [J] +0x0000,0x0000,0x0000,0x3C1F,0x3C1E,0x3C3C,0x3C78,0x3CF0,0x3DE0,0x3FE0,0x3FC0,0x3F80,0x3FC0,0x3FE0,0x3DF0,0x3CF0,0x3C78,0x3C7C,0x3C3E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [K] +0x0000,0x0000,0x0000,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3FFF,0x3FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [L] +0x0000,0x0000,0x0000,0xF81F,0xFC1F,0xFC1F,0xFE3F,0xFE3F,0xFE3F,0xFF7F,0xFF77,0xFF77,0xF7F7,0xF7E7,0xF3E7,0xF3E7,0xF3C7,0xF007,0xF007,0xF007,0xF007,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [M] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7E0F,0x7F0F,0x7F0F,0x7F8F,0x7F8F,0x7FCF,0x7BEF,0x79EF,0x79FF,0x78FF,0x78FF,0x787F,0x783F,0x783F,0x781F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [N] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [O] +0x0000,0x0000,0x0000,0x3FFC,0x3FFF,0x3E1F,0x3E0F,0x3E0F,0x3E0F,0x3E0F,0x3E1F,0x3E3F,0x3FFC,0x3FF0,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x3E00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [P] +0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x7C1F,0x780F,0x780F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0xF80F,0x780F,0x780F,0x7C1F,0x3E3E,0x1FFC,0x07F8,0x007C,0x003F,0x000F,0x0003,0x0000, // Ascii = [Q] +0x0000,0x0000,0x0000,0x3FF0,0x3FFC,0x3C7E,0x3C3E,0x3C1E,0x3C1E,0x3C3E,0x3C3C,0x3CFC,0x3FF0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1E,0x3C1F,0x3C0F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [R] +0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x3E0E,0x3C00,0x3C00,0x3C00,0x3E00,0x1FC0,0x0FF8,0x03FE,0x007F,0x001F,0x000F,0x000F,0x201F,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [S] +0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [T] +0x0000,0x0000,0x0000,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x7C0F,0x3C1E,0x3C1E,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [U] +0x0000,0x0000,0x0000,0xF007,0xF007,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1F3C,0x1F78,0x0F78,0x0FF8,0x07F0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [V] +0x0000,0x0000,0x0000,0xE003,0xF003,0xF003,0xF007,0xF3E7,0xF3E7,0xF3E7,0x73E7,0x7BF7,0x7FF7,0x7FFF,0x7F7F,0x7F7F,0x7F7E,0x3F7E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [W] +0x0000,0x0000,0x0000,0xF807,0x7C0F,0x3E1E,0x3E3E,0x1F3C,0x0FF8,0x07F0,0x07E0,0x03E0,0x03E0,0x07F0,0x0FF8,0x0F7C,0x1E7C,0x3C3E,0x781F,0x780F,0xF00F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [X] +0x0000,0x0000,0x0000,0xF807,0x7807,0x7C0F,0x3C1E,0x3E1E,0x1F3C,0x0F78,0x0FF8,0x07F0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Y] +0x0000,0x0000,0x0000,0x7FFF,0x7FFF,0x000F,0x001F,0x003E,0x007C,0x00F8,0x00F0,0x01E0,0x03E0,0x07C0,0x0F80,0x0F00,0x1E00,0x3E00,0x7C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [Z] +0x07FF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07FF,0x07FF,0x0000, // Ascii = [[] +0x7800,0x7800,0x3C00,0x3C00,0x1E00,0x1E00,0x0F00,0x0F00,0x0780,0x0780,0x03C0,0x03C0,0x01E0,0x01E0,0x00F0,0x00F0,0x0078,0x0078,0x003C,0x003C,0x001E,0x001E,0x000F,0x000F,0x0007,0x0000, // Ascii = [\] +0x7FF0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x00F0,0x7FF0,0x7FF0,0x0000, // Ascii = []] +0x00C0,0x01C0,0x01C0,0x03E0,0x03E0,0x07F0,0x07F0,0x0778,0x0F78,0x0F38,0x1E3C,0x1E3C,0x3C1E,0x3C1E,0x380F,0x780F,0x7807,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [^] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xFFFF,0xFFFF,0x0000,0x0000,0x0000, // Ascii = [_] +0x00F0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [`] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0FF8,0x3FFC,0x3C7C,0x003E,0x003E,0x003E,0x07FE,0x1FFE,0x3E3E,0x7C3E,0x783E,0x7C3E,0x7C7E,0x3FFF,0x1FCF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [a] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3C1E,0x3F3E,0x3FFC,0x3BF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [b] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03FE,0x0FFF,0x1F87,0x3E00,0x3E00,0x3C00,0x7C00,0x7C00,0x7C00,0x3C00,0x3E00,0x3E00,0x1F87,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [c] +0x001F,0x001F,0x001F,0x001F,0x001F,0x001F,0x07FF,0x1FFF,0x3E3F,0x3C1F,0x7C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [d] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x03F8,0x0FFC,0x1F3E,0x3E1E,0x3C1F,0x7C1F,0x7FFF,0x7FFF,0x7C00,0x7C00,0x3C00,0x3E00,0x1F07,0x0FFF,0x03FE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [e] +0x01FF,0x03E1,0x03C0,0x07C0,0x07C0,0x07C0,0x7FFF,0x7FFF,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x07C0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [f] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EF,0x1FFF,0x3E7F,0x3C1F,0x7C1F,0x7C1F,0x781F,0x781F,0x781F,0x7C1F,0x7C1F,0x3C3F,0x3E7F,0x1FFF,0x0FDF,0x001E,0x001E,0x001E,0x387C,0x3FF8, // Ascii = [g] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [h] +0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x7FE0,0x7FE0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [i] +0x00F8,0x00F8,0x0000,0x0000,0x0000,0x0000,0x3FF8,0x3FF8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F8,0x00F0,0x71F0,0x7FE0, // Ascii = [j] +0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00,0x3C1F,0x3C3E,0x3C7C,0x3CF8,0x3DF0,0x3DE0,0x3FC0,0x3FC0,0x3FE0,0x3DF0,0x3CF8,0x3C7C,0x3C3E,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [k] +0x7FF0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x01F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [l] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF79E,0xFFFF,0xFFFF,0xFFFF,0xFBE7,0xF9E7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0xF1C7,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [m] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DFC,0x3FFE,0x3F9E,0x3F1F,0x3E1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x3C1F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [n] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07F0,0x1FFC,0x3E3E,0x3C1F,0x7C1F,0x780F,0x780F,0x780F,0x780F,0x780F,0x7C1F,0x3C1F,0x3E3E,0x1FFC,0x07F0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [o] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3DF8,0x3FFE,0x3F3E,0x3E1F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C0F,0x3C1F,0x3E1E,0x3F3E,0x3FFC,0x3FF8,0x3C00,0x3C00,0x3C00,0x3C00,0x3C00, // Ascii = [p] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07EE,0x1FFE,0x3E7E,0x3C1E,0x7C1E,0x781E,0x781E,0x781E,0x781E,0x781E,0x7C1E,0x7C3E,0x3E7E,0x1FFE,0x0FDE,0x001E,0x001E,0x001E,0x001E,0x001E, // Ascii = [q] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1F7F,0x1FFF,0x1FE7,0x1FC7,0x1F87,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x1F00,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [r] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x07FC,0x1FFE,0x1E0E,0x3E00,0x3E00,0x3F00,0x1FE0,0x07FC,0x00FE,0x003E,0x001E,0x001E,0x3C3E,0x3FFC,0x1FF0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [s] +0x0000,0x0000,0x0000,0x0780,0x0780,0x0780,0x7FFF,0x7FFF,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x0780,0x07C0,0x03FF,0x01FF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [t] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C1E,0x3C3E,0x3C7E,0x3EFE,0x1FFE,0x0FDE,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [u] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF007,0x780F,0x780F,0x3C1E,0x3C1E,0x3E1E,0x1E3C,0x1E3C,0x0F78,0x0F78,0x0FF0,0x07F0,0x07F0,0x03E0,0x03E0,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [v] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF003,0xF1E3,0xF3E3,0xF3E7,0xF3F7,0xF3F7,0x7FF7,0x7F77,0x7F7F,0x7F7F,0x7F7F,0x3E3E,0x3E3E,0x3E3E,0x3E3E,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [w] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x7C0F,0x3E1E,0x3E3C,0x1F3C,0x0FF8,0x07F0,0x07F0,0x03E0,0x07F0,0x07F8,0x0FF8,0x1E7C,0x3E3E,0x3C1F,0x781F,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [x] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0xF807,0x780F,0x7C0F,0x3C1E,0x3C1E,0x1E3C,0x1E3C,0x1F3C,0x0F78,0x0FF8,0x07F0,0x07F0,0x03E0,0x03E0,0x03C0,0x03C0,0x03C0,0x0780,0x0F80,0x7F00, // Ascii = [y] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3FFF,0x3FFF,0x001F,0x003E,0x007C,0x00F8,0x01F0,0x03E0,0x07C0,0x0F80,0x1F00,0x1E00,0x3C00,0x7FFF,0x7FFF,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [z] +0x01FE,0x03E0,0x03C0,0x03C0,0x03C0,0x03C0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x3F80,0x3F80,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x03C0,0x03C0,0x03C0,0x03C0,0x03E0,0x01FE,0x007E,0x0000, // Ascii = [{] +0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x01C0,0x0000, // Ascii = [|] +0x3FC0,0x03E0,0x01E0,0x01E0,0x01E0,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x00FE,0x00FE,0x01E0,0x01C0,0x03C0,0x03C0,0x01C0,0x01E0,0x01E0,0x01E0,0x01E0,0x03E0,0x3FC0,0x3F00,0x0000, // Ascii = [}] +0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x3F07,0x7FC7,0x73E7,0xF1FF,0xF07E,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // Ascii = [~] +}; +#endif +#ifdef SSD1306_INCLUDE_FONT_6x8 +static const uint16_t Font6x8 [] = { +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // sp +0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x0000, // ! +0x5000, 0x5000, 0x5000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // " +0x5000, 0x5000, 0xf800, 0x5000, 0xf800, 0x5000, 0x5000, 0x0000, // # +0x2000, 0x7800, 0xa000, 0x7000, 0x2800, 0xf000, 0x2000, 0x0000, // $ +0xc000, 0xc800, 0x1000, 0x2000, 0x4000, 0x9800, 0x1800, 0x0000, // % +0x4000, 0xa000, 0xa000, 0x4000, 0xa800, 0x9000, 0x6800, 0x0000, // & +0x3000, 0x3000, 0x2000, 0x4000, 0x0000, 0x0000, 0x0000, 0x0000, // ' +0x1000, 0x2000, 0x4000, 0x4000, 0x4000, 0x2000, 0x1000, 0x0000, // ( +0x4000, 0x2000, 0x1000, 0x1000, 0x1000, 0x2000, 0x4000, 0x0000, // ) +0x2000, 0xa800, 0x7000, 0xf800, 0x7000, 0xa800, 0x2000, 0x0000, // * +0x0000, 0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x0000, 0x0000, // + +0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x2000, 0x0000, // , +0x0000, 0x0000, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, 0x0000, // - +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x3000, 0x3000, 0x0000, // . +0x0000, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, 0x0000, // / +0x7000, 0x8800, 0x9800, 0xa800, 0xc800, 0x8800, 0x7000, 0x0000, // 0 +0x2000, 0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // 1 +0x7000, 0x8800, 0x0800, 0x7000, 0x8000, 0x8000, 0xf800, 0x0000, // 2 +0xf800, 0x0800, 0x1000, 0x3000, 0x0800, 0x8800, 0x7000, 0x0000, // 3 +0x1000, 0x3000, 0x5000, 0x9000, 0xf800, 0x1000, 0x1000, 0x0000, // 4 +0xf800, 0x8000, 0xf000, 0x0800, 0x0800, 0x8800, 0x7000, 0x0000, // 5 +0x3800, 0x4000, 0x8000, 0xf000, 0x8800, 0x8800, 0x7000, 0x0000, // 6 +0xf800, 0x0800, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 0x0000, // 7 +0x7000, 0x8800, 0x8800, 0x7000, 0x8800, 0x8800, 0x7000, 0x0000, // 8 +0x7000, 0x8800, 0x8800, 0x7800, 0x0800, 0x1000, 0xe000, 0x0000, // 9 +0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x0000, 0x0000, 0x0000, // : +0x0000, 0x0000, 0x2000, 0x0000, 0x2000, 0x2000, 0x4000, 0x0000, // ; +0x0800, 0x1000, 0x2000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, // < +0x0000, 0x0000, 0xf800, 0x0000, 0xf800, 0x0000, 0x0000, 0x0000, // = +0x4000, 0x2000, 0x1000, 0x0800, 0x1000, 0x2000, 0x4000, 0x0000, // > +0x7000, 0x8800, 0x0800, 0x3000, 0x2000, 0x0000, 0x2000, 0x0000, // ? +0x7000, 0x8800, 0xa800, 0xb800, 0xb000, 0x8000, 0x7800, 0x0000, // @ +0x2000, 0x5000, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x0000, // A +0xf000, 0x8800, 0x8800, 0xf000, 0x8800, 0x8800, 0xf000, 0x0000, // B +0x7000, 0x8800, 0x8000, 0x8000, 0x8000, 0x8800, 0x7000, 0x0000, // C +0xf000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0xf000, 0x0000, // D +0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0xf800, 0x0000, // E +0xf800, 0x8000, 0x8000, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // F +0x7800, 0x8800, 0x8000, 0x8000, 0x9800, 0x8800, 0x7800, 0x0000, // G +0x8800, 0x8800, 0x8800, 0xf800, 0x8800, 0x8800, 0x8800, 0x0000, // H +0x7000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // I +0x3800, 0x1000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // J +0x8800, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x8800, 0x0000, // K +0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0xf800, 0x0000, // L +0x8800, 0xd800, 0xa800, 0xa800, 0xa800, 0x8800, 0x8800, 0x0000, // M +0x8800, 0x8800, 0xc800, 0xa800, 0x9800, 0x8800, 0x8800, 0x0000, // N +0x7000, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // O +0xf000, 0x8800, 0x8800, 0xf000, 0x8000, 0x8000, 0x8000, 0x0000, // P +0x7000, 0x8800, 0x8800, 0x8800, 0xa800, 0x9000, 0x6800, 0x0000, // Q +0xf000, 0x8800, 0x8800, 0xf000, 0xa000, 0x9000, 0x8800, 0x0000, // R +0x7000, 0x8800, 0x8000, 0x7000, 0x0800, 0x8800, 0x7000, 0x0000, // S +0xf800, 0xa800, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // T +0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // U +0x8800, 0x8800, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // V +0x8800, 0x8800, 0x8800, 0xa800, 0xa800, 0xa800, 0x5000, 0x0000, // W +0x8800, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x8800, 0x0000, // X +0x8800, 0x8800, 0x5000, 0x2000, 0x2000, 0x2000, 0x2000, 0x0000, // Y +0xf800, 0x0800, 0x1000, 0x7000, 0x4000, 0x8000, 0xf800, 0x0000, // Z +0x7800, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x7800, 0x0000, // [ +0x0000, 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0000, 0x0000, /* \ */ +0x7800, 0x0800, 0x0800, 0x0800, 0x0800, 0x0800, 0x7800, 0x0000, // ] +0x2000, 0x5000, 0x8800, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ^ +0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xf800, 0x0000, // _ +0x6000, 0x6000, 0x2000, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, // ` +0x0000, 0x0000, 0x6000, 0x1000, 0x7000, 0x9000, 0x7800, 0x0000, // a +0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0xc800, 0xb000, 0x0000, // b +0x0000, 0x0000, 0x7000, 0x8800, 0x8000, 0x8800, 0x7000, 0x0000, // c +0x0800, 0x0800, 0x6800, 0x9800, 0x8800, 0x9800, 0x6800, 0x0000, // d +0x0000, 0x0000, 0x7000, 0x8800, 0xf800, 0x8000, 0x7000, 0x0000, // e +0x1000, 0x2800, 0x2000, 0x7000, 0x2000, 0x2000, 0x2000, 0x0000, // f +0x0000, 0x0000, 0x7000, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // g +0x8000, 0x8000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // h +0x2000, 0x0000, 0x6000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // i +0x1000, 0x0000, 0x1000, 0x1000, 0x1000, 0x9000, 0x6000, 0x0000, // j +0x8000, 0x8000, 0x9000, 0xa000, 0xc000, 0xa000, 0x9000, 0x0000, // k +0x6000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x7000, 0x0000, // l +0x0000, 0x0000, 0xd000, 0xa800, 0xa800, 0xa800, 0xa800, 0x0000, // m +0x0000, 0x0000, 0xb000, 0xc800, 0x8800, 0x8800, 0x8800, 0x0000, // n +0x0000, 0x0000, 0x7000, 0x8800, 0x8800, 0x8800, 0x7000, 0x0000, // o +0x0000, 0x0000, 0xb000, 0xc800, 0xc800, 0xb000, 0x8000, 0x0000, // p +0x0000, 0x0000, 0x6800, 0x9800, 0x9800, 0x6800, 0x0800, 0x0000, // q +0x0000, 0x0000, 0xb000, 0xc800, 0x8000, 0x8000, 0x8000, 0x0000, // r +0x0000, 0x0000, 0x7800, 0x8000, 0x7000, 0x0800, 0xf000, 0x0000, // s +0x2000, 0x2000, 0xf800, 0x2000, 0x2000, 0x2800, 0x1000, 0x0000, // t +0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x9800, 0x6800, 0x0000, // u +0x0000, 0x0000, 0x8800, 0x8800, 0x8800, 0x5000, 0x2000, 0x0000, // v +0x0000, 0x0000, 0x8800, 0x8800, 0xa800, 0xa800, 0x5000, 0x0000, // w +0x0000, 0x0000, 0x8800, 0x5000, 0x2000, 0x5000, 0x8800, 0x0000, // x +0x0000, 0x0000, 0x8800, 0x8800, 0x7800, 0x0800, 0x8800, 0x0000, // y +0x0000, 0x0000, 0xf800, 0x1000, 0x2000, 0x4000, 0xf800, 0x0000, // z +0x1000, 0x2000, 0x2000, 0x4000, 0x2000, 0x2000, 0x1000, 0x0000, // { +0x2000, 0x2000, 0x2000, 0x0000, 0x2000, 0x2000, 0x2000, 0x0000, // | +0x4000, 0x2000, 0x2000, 0x1000, 0x2000, 0x2000, 0x4000, 0x0000, // } +0x4000, 0xa800, 0x1000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // ~ +}; +#endif + +#ifdef SSD1306_INCLUDE_FONT_6x8 +FontDef Font_6x8 = {6,8,Font6x8}; +#endif +#ifdef SSD1306_INCLUDE_FONT_7x10 +FontDef Font_7x10 = {7,10,Font7x10}; +#endif +#ifdef SSD1306_INCLUDE_FONT_11x18 +FontDef Font_11x18 = {11,18,Font11x18}; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +FontDef Font_16x26 = {16,26,Font16x26}; +#endif diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.h" new file mode 100755 index 0000000000000000000000000000000000000000..53543346d27fec87dc968698028efea9b71614b7 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/oled/ssd1306/ssd1306_fonts.h" @@ -0,0 +1,26 @@ +#include + +#ifndef __SSD1306_FONTS_H__ +#define __SSD1306_FONTS_H__ + +#include "ssd1306_conf.h" + +typedef struct { + const uint8_t FontWidth; /*!< Font width in pixels */ + uint8_t FontHeight; /*!< Font height in pixels */ + const uint16_t *data; /*!< Pointer to data font data array */ +} FontDef; + +#ifdef SSD1306_INCLUDE_FONT_6x8 +extern FontDef Font_6x8; +#endif +#ifdef SSD1306_INCLUDE_FONT_7x10 +extern FontDef Font_7x10; +#endif +#ifdef SSD1306_INCLUDE_FONT_11x18 +extern FontDef Font_11x18; +#endif +#ifdef SSD1306_INCLUDE_FONT_16x26 +extern FontDef Font_16x26; +#endif +#endif // __SSD1306_FONTS_H__ diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..c8a19a7ca2376385e33d3d33c8cd96b67ad76f87 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/BUILD.gn" @@ -0,0 +1,45 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("stream_player") { + sources = [ + "stream_player.c", + "wifi_connecter.c", + ] + + include_dirs = [ + "../oled/ssd1306", + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} + + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/net_params.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/net_params.h" new file mode 100755 index 0000000000000000000000000000000000000000..24933563b9cf90436b2b1e6fae3a25e1fba5396c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/net_params.h" @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_PARAMS_H +#define NET_PARAMS_H + +#define PARAM_HOTSPOT_SSID "ABCD" // your AP SSID +#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK + +#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h + +#define PARAM_SERVER_ADDR "192.168.1.100" // your PC IP address +#define PARAM_SERVER_PORT 5678 + +#endif // NET_PARAMS_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/stream_player.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/stream_player.c" new file mode 100755 index 0000000000000000000000000000000000000000..03753a2930b813053785e9a0a1c7db6044c11d15 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/stream_player.c" @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_adc.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" +#include "wifiiot_watchdog.h" +#include "wifi_device.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" +#include "lwip/sockets.h" + +#include "ssd1306.h" +#include "net_params.h" +#include "wifi_connecter.h" + +#define OLED_I2C_BAUDRATE 400*1000 + +#define STATUS_OK 0 + +static int g_serverPort = PARAM_SERVER_PORT; +static const char* g_serverIp = PARAM_SERVER_ADDR; + +static uint8_t g_streamBuffer[SSD1306_BUFFER_SIZE]; + +static uint32_t PlayStream(void) +{ + uint32_t frameId = 0; + int sockfd = lwip_socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + printf("lwip_socket failed!\r\n"); + return 0; + } + + struct sockaddr_in serverAddr = {0}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = lwip_htons(g_serverPort); + if (lwip_inet_pton(AF_INET, g_serverIp, &serverAddr.sin_addr) <= 0) { + printf("lwip_inet_pton failed!\r\n"); + goto do_close; + } + + if (lwip_connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { + printf("lwip_connect failed!\r\n"); + goto do_close; + } + printf("connect to server %s success!\r\n", g_serverIp); + + frameId = 1; + while (1) { + printf("send frameId request %d to server\r\n", frameId); + uint32_t request = lwip_htonl(frameId); // to big endian + ssize_t retval = lwip_send(sockfd, &request, sizeof(request), 0); + if (retval < 0) { + printf("lwip_send for frame %d failed!\r\n", frameId); + break; + } + + // printf("recving status from server...\r\n"); + uint32_t status = 0; + retval = lwip_recv(sockfd, &status, sizeof(status), 0); + if (retval != sizeof(status)) { + printf("lwip_recv status for frame %d failed or done, %d!\r\n", frameId, retval); + break; + } + status = lwip_ntohl(status); + if (status != STATUS_OK) { + break; + } + + // printf("recving bodyLen from server...\r\n"); + ssize_t bodyLen = 0; + retval = lwip_recv(sockfd, &bodyLen, sizeof(bodyLen), 0); + if (retval != sizeof(bodyLen)) { + printf("lwip_recv bodyLen for frame %d failed or done, %d!\r\n", frameId, retval); + break; + } + bodyLen = lwip_ntohl(bodyLen); + printf("status: %d, bodyLen: %d\r\n", status, bodyLen); + + ssize_t bodyReceived = 0; + while (bodyReceived < bodyLen) { + retval = lwip_recv(sockfd, &g_streamBuffer[bodyReceived], bodyLen, 0); + if (retval != bodyLen) { + printf("lwip_recv for frame %d failed or done, %d!\r\n", frameId, retval); + break; + } + bodyReceived += retval; + printf("recved body %d/%d...\r\n", bodyReceived, bodyLen); + } + + ssd1306_Fill(Black); + ssd1306_DrawBitmap(g_streamBuffer, sizeof(g_streamBuffer)); + ssd1306_UpdateScreen(); + frameId++; + } + printf("playing video done, played frames: %d!\r\n", frameId); + +do_close: + lwip_close(sockfd); + return frameId; +} + +static void Ssd1306PlayTask(void* arg) +{ + (void) arg; + + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); + I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); + + WatchDogDisable(); + + osDelay(2); + ssd1306_Init(); + + ssd1306_Fill(Black); + ssd1306_SetCursor(0, 0); + ssd1306_DrawString("Hello OpenHarmony!", Font_7x10, White); + ssd1306_UpdateScreen(); + + // prepare hotspot prarams + WifiDeviceConfig apConfig = {}; + strcpy(apConfig.ssid, PARAM_HOTSPOT_SSID); + strcpy(apConfig.preSharedKey, PARAM_HOTSPOT_PSK); + apConfig.securityType = PARAM_HOTSPOT_TYPE; + + int netId = ConnectToHotspot(&apConfig); + if (netId < 0) { + printf("connect to hotspot failed!\r\n"); + } + + uint32_t start = osKernelGetTickCount(); + uint32_t frames = PlayStream(); + uint32_t end = osKernelGetTickCount(); + + printf("frames: %d, time cost: %.2f\r\n", frames, (end - start) / (float)osKernelGetTickFreq()); + osDelay(50); // 500 ms + + DisconnectWithHotspot(netId); +} + +static void Ssd1306PlayDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "Ssd1306Task"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(Ssd1306PlayTask, NULL, &attr) == NULL) { + printf("[Ssd1306PlayDemo] Falied to create Ssd1306PlayTask!\n"); + } +} +APP_FEATURE_INIT(Ssd1306PlayDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.c" new file mode 100755 index 0000000000000000000000000000000000000000..2aaa6cde7bb8bc1c29d78b429259271945b38e42 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.c" @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wifi_device.h" +#include "cmsis_os2.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" +#include "lwip/sockets.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static volatile int g_connected = 0; + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +int ConnectToHotspot(WifiDeviceConfig* apConfig) +{ + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + + struct netif* iface = netifapi_netif_find("wlan0"); + if (iface) { + err_t ret = netifapi_dhcp_start(iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // wait DHCP server give me IP + ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + return netId; +} + +void DisconnectWithHotspot(int netId) +{ + WifiErrorCode errCode; + errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(netId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.h" new file mode 100755 index 0000000000000000000000000000000000000000..cbd4d01ed9adb0b0df58ec2891694c3f212f263b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/play/wifi_connecter.h" @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WIFI_CONNECTER_H +#define WIFI_CONNECTER_H + +#include "wifi_device.h" + +int ConnectToHotspot(WifiDeviceConfig* apConfig); + +void DisconnectWithHotspot(int netId); + +#endif // WIFI_CONNECTER_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/video2bin.py" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/video2bin.py" new file mode 100755 index 0000000000000000000000000000000000000000..71b3e3c451e004a6c5ff2f9b871b6ac487b01d0c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/13_oledplayer/video2bin.py" @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +import sys +import cv2 as cv +from oled.img2code import convert_frame_to_bytes + +DEFAULT_PORT = 5678 + +def convert_video_to_bin(videoFile, binFile): + cap = cv.VideoCapture(videoFile) + frameCount = cap.get(cv.CAP_PROP_FRAME_COUNT) + print('frame count:', frameCount) + print('frame width:', cap.get(cv.CAP_PROP_FRAME_WIDTH)) + print('frame height:', cap.get(cv.CAP_PROP_FRAME_HEIGHT)) + lastPercent = 0 + with open(binFile, 'wb+') as f: + while True: + retval, frame = cap.read() + if not retval: + print('video done!') + break + bitmap = convert_frame_to_bytes(frame) + f.write(bitmap) + pos = cap.get(cv.CAP_PROP_POS_FRAMES) + percent = pos / frameCount * 100 + if percent - lastPercent >= 1: + lastPercent = percent + sys.stdout.write('=') + sys.stdout.flush() + print('convert all frames done!') + cap.release() + +def main(): + if len(sys.argv) < 3: + print("Usage: {} videoFile binFile\n\t".format(sys.argv[0])) + exit(-1) + + try: + videoFile = sys.argv[1] + binFile = sys.argv[2] + convert_video_to_bin(videoFile, binFile) + except Exception as e: + print('exception raised:', e) + +if __name__ == "__main__": + main() diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..b7d6128d28ddb2b18326de28cd2944603d6119ba --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("pwm_beer_demo") { + sources = [ + "pwm_beer_demo.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..fc3a8c62ce8382dc6dca0ff2004cb525fdb29c65 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/README.md" @@ -0,0 +1,59 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--PWM(pwm_beer) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、PWM API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ----------------- | +| unsigned int PwmInit(WifiIotPwmPort port); | PWM模块初始化 | +| unsigned int PwmStart(WifiIotPwmPort port, unsigned short duty, unsigned short freq); | 开始输出PWM信号 | +| unsigned int PwmStop(WifiIotPwmPort port); | 停止输出PWM信号 | +| unsigned int PwmDeinit(WifiIotPwmPort port); | 解除PWM模块初始化 | +| unsigned int PwmSetClock(WifiIotPwmClkSource clkSource); | 设置PWM模块时钟源 | + +## 二、交通灯板蜂鸣器按键与主控芯片(Pegasus)引脚的对应关系 + +- **蜂鸣器:**GPIO9/PWM0 +- **按键:**GPIO8 + +## 三、如何编译 + +1. 将此目录下的 `pwm_beer_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:pwm_beer_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,程序开始运行,按下按键后,蜂鸣器会响,再次按下按键,蜂鸣器不再发出响声 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/pwm_beer_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/pwm_beer_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..31865a8f8bf81446d4e98cb99006fc35d3cb11cc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/14_pwmbeer/pwm_beer_demo.c" @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_watchdog.h" +#include "wifiiot_pwm.h" + +static int g_beepState = 0; + +static void *PWMBeerTask(const char *arg) +{ + (void)arg; + + printf("PWMBeerTask start!\r\n"); + + while (1) { + if (g_beepState) { + PwmStart(WIFI_IOT_PWM_PORT_PWM0, 20*1000, 40*1000); + } else { + PwmStop(WIFI_IOT_PWM_PORT_PWM0); + } + } + + return NULL; +} + +static void OnButtonPressed(char *arg) +{ + (void) arg; + g_beepState = !g_beepState; +} + +static void StartPWMBeerTask(void) +{ + osThreadAttr_t attr; + + GpioInit(); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN); + IoSetPull(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_PULL_UP); + GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_INT_TYPE_EDGE, WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW, + OnButtonPressed, NULL); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT); + PwmInit(WIFI_IOT_PWM_PORT_PWM0); + + WatchDogDisable(); + + attr.name = "PWMBeerTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)PWMBeerTask, NULL, &attr) == NULL) { + printf("[StartPWMBeerTask] Falied to create PWMBeerTask!\n"); + } +} + +APP_FEATURE_INIT(StartPWMBeerTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..30256d0f7befddd9083751664a93be30e705a639 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("beeper_music_demo") { + sources = [ + "beeper_music_demo.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..4c3a14436392d20e846d81ceacc9f6df79177ec5 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/README.md" @@ -0,0 +1,58 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--PWM(pwm_beer) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、PWM API + +| API名称 | 说明 | +| ------------------------------------------------------------ | ----------------- | +| unsigned int PwmInit(WifiIotPwmPort port); | PWM模块初始化 | +| unsigned int PwmStart(WifiIotPwmPort port, unsigned short duty, unsigned short freq); | 开始输出PWM信号 | +| unsigned int PwmStop(WifiIotPwmPort port); | 停止输出PWM信号 | +| unsigned int PwmDeinit(WifiIotPwmPort port); | 解除PWM模块初始化 | +| unsigned int PwmSetClock(WifiIotPwmClkSource clkSource); | 设置PWM模块时钟源 | + +## 二、交通灯板蜂鸣器与主控芯片(Pegasus)引脚的对应关系 + +- **蜂鸣器:**GPIO9/PWM0/输出PWM波控制蜂鸣器发出声音 + +## 三、如何编译 + +1. 将此目录下的 `beeper_music_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:beeper_music_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +烧录文件后,按下reset按键,程序开始运行,蜂鸣器会播放《两只老虎》 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/beeper_music_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/beeper_music_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..2982425fcc3d3d417485b45a94ef1dcbedf2d28c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/15_pwmbeermusic/beeper_music_demo.c" @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_watchdog.h" +#include "wifiiot_pwm.h" + +#include "hi_pwm.h" + +static volatile int g_buttonPressed = 0; +static const uint16_t g_tuneFreqs[] = { + 0, // 40M Hz 对应的分频系数: + 38223, // 1046.5 + 34052, // 1174.7 + 30338, // 1318.5 + 28635, // 1396.9 + 25511, // 1568 + 22728, // 1760 + 20249, // 1975.5 + 51021 // 5_ 783.99 // 第一个八度的 5 +}; + +// 曲谱音符 +static const uint8_t g_scoreNotes[] = { + // 《两只老虎》简谱:http://www.jianpu.cn/pu/33/33945.htm + 1, 2, 3, 1, 1, 2, 3, 1, 3, 4, 5, 3, 4, 5, + 5, 6, 5, 4, 3, 1, 5, 6, 5, 4, 3, 1, 1, 8, 1, 1, 8, 1, // 最后两个 5 应该是低八度的,链接图片中的曲谱不对,声音到最后听起来不太对劲 +}; + +// 曲谱时值 +static const uint8_t g_scoreDurations[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 4, 4, 8, + 3, 1, 3, 1, 4, 4, 3, 1, 3, 1, 4, 4, 4, 4, 8, 4, 4, 8, +}; + +static void *BeeperMusicTask(const char *arg) +{ + (void)arg; + + printf("BeeperMusicTask start!\r\n"); + + hi_pwm_set_clock(PWM_CLK_XTAL); // 设置时钟源为晶体时钟(40MHz,默认时钟源160MHz) + + for (size_t i = 0; i < sizeof(g_scoreNotes)/sizeof(g_scoreNotes[0]); i++) { + uint32_t tune = g_scoreNotes[i]; // 音符 + uint16_t freqDivisor = g_tuneFreqs[tune]; + uint32_t tuneInterval = g_scoreDurations[i] * (125*1000); // 音符时间 + printf("%d %d %d %d\r\n", tune, (40*1000*1000) / freqDivisor, freqDivisor, tuneInterval); + PwmStart(WIFI_IOT_PWM_PORT_PWM0, freqDivisor/2, freqDivisor); + usleep(tuneInterval); + PwmStop(WIFI_IOT_PWM_PORT_PWM0); + } + + return NULL; +} + +static void StartBeepMusicTask(void) +{ + osThreadAttr_t attr; + + GpioInit(); + + // 蜂鸣器引脚 设置为 PWM功能 + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT); + PwmInit(WIFI_IOT_PWM_PORT_PWM0); + + WatchDogDisable(); + + attr.name = "BeeperMusicTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)BeeperMusicTask, NULL, &attr) == NULL) { + printf("[LedExample] Falied to create BeeperMusicTask!\n"); + } +} + +SYS_RUN(StartBeepMusicTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..2458415047f1552aa895c2d49bf7cc059d0b1281 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("traffic_light_demo") { + sources = [ + "traffic_light_demo.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..b7358b4b97ce35c9993404b02f6a6abde7f5cdad --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/README.md" @@ -0,0 +1,65 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--traffic_light_demo + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + + + +## 一、交通灯板上外设与主控芯片(Pegasus)引脚的对应关系 + +* 交通灯板 + * GPIO_9 连接蜂鸣器,输出PWM波控制蜂鸣器发出声音 + * GPIO_8 连接按键,按键中断切换亮的LED灯,同时切换蜂鸣器响或者不响 + * GPIO_10 连接红色LED,输出高电平点亮红色LED灯 + * GPIO_11 连接绿色LED,输出高电平点亮绿色LED灯 + * GPIO_12 连接黄色LED,输出高电平点亮黄色LED灯 + + + +## 二、如何编译 + +1. 将此目录下的 `traffic_light_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: +```python + features = [ + "iothardware:traffic_light_demo", + ] +``` +3. 在openharmony源码顶层目录执行:`python build.py wifiiot` + +### 报错解决 + +1. 编译过程中报错:undefined reference to `hi_pwm_init` 等几个 `hi_pwm_`开头的函数, + * **原因:** 因为默认情况下,hi3861_sdk中,PWM的CONFIG选项没有打开 + * **解决:** 修改`vendor\hisi\hi3861\hi3861\build\config\usr_config.mk`文件中的`CONFIG_PWM_SUPPORT`行: + * `# CONFIG_PWM_SUPPORT is not set`修改为`CONFIG_PWM_SUPPORT=y` + +## 三、运行结果 + +烧录文件后,按下reset按键,程序开始运行: + +* 交通灯板红黄绿三个灯循环闪烁四次 + +* 按下按键会控制三个灯的亮暗状态以及蜂鸣器的是否会发出声音 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/traffic_light_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/traffic_light_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..eceb970efaa44a686061045950ec68dff153037d --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/16_trafficlight/traffic_light_demo.c" @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_watchdog.h" +#include "wifiiot_pwm.h" + +static int g_ledStates[3] = {0, 0, 0}; +static int g_currentBright = 0; +static int g_beepState = 0; + +static void *TrafficLightTask(const char *arg) +{ + (void)arg; + + printf("TrafficLightTask start!\r\n"); + WifiIotGpioIdx pins[] = {WIFI_IOT_GPIO_IDX_10, WIFI_IOT_GPIO_IDX_11, WIFI_IOT_GPIO_IDX_12}; + for (int i = 0; i < 4; i++) { + for (unsigned int j = 0; j < 3; j++) { + GpioSetOutputVal(pins[j], WIFI_IOT_GPIO_VALUE1); + usleep(200*1000); + + GpioSetOutputVal(pins[j], WIFI_IOT_GPIO_VALUE0); + usleep(100*1000); + } + } + + while (1) { + for (unsigned int j = 0; j < 3; j++) { + GpioSetOutputVal(pins[j], g_ledStates[j]); + } + if (g_beepState) { + PwmStart(WIFI_IOT_PWM_PORT_PWM0, 20*1000, 40*1000); + } else { + PwmStop(WIFI_IOT_PWM_PORT_PWM0); + } + } + + return NULL; +} + +static void OnButtonPressed(char *arg) +{ + (void) arg; + for (int i = 0; i < 3; i++) { + if (i == g_currentBright) { + g_ledStates[i] = 1; + } else { + g_ledStates[i] = 0; + } + } + g_currentBright++; + if (g_currentBright == 3) g_currentBright = 0; + + g_beepState = !g_beepState; +} + +static void StartTrafficLightTask(void) +{ + osThreadAttr_t attr; + + GpioInit(); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_IO_FUNC_GPIO_10_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_10, WIFI_IOT_GPIO_DIR_OUT); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_11, WIFI_IOT_IO_FUNC_GPIO_11_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_11, WIFI_IOT_GPIO_DIR_OUT); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_IO_FUNC_GPIO_12_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_GPIO_DIR_OUT); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_IN); + IoSetPull(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_PULL_UP); + GpioRegisterIsrFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_INT_TYPE_EDGE, WIFI_IOT_GPIO_EDGE_FALL_LEVEL_LOW, + OnButtonPressed, NULL); + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT); + GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT); + PwmInit(WIFI_IOT_PWM_PORT_PWM0); + + WatchDogDisable(); + + attr.name = "TrafficLightTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 1024; + attr.priority = osPriorityNormal; + + if (osThreadNew((osThreadFunc_t)TrafficLightTask, NULL, &attr) == NULL) { + printf("[LedExample] Falied to create TrafficLightTask!\n"); + } +} + +APP_FEATURE_INIT(StartTrafficLightTask); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..e9ce40ffd18680c4d7def422c0744ab27956c1cc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("colorful_light_demo") { + sources = [ + "colorful_light_demo.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..951d95fe21349651802c07ea8b9acf80af3a4589 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/README.md" @@ -0,0 +1,69 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--colorful_light_demo + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + + + +## 一、炫彩灯板上外设与主控芯片(Pegasus)引脚的对应关系 + +* 三色LED——PWM占空比控制颜色 + - GPIO10\PWM1: 红 + - GPIO11\PWM2: 绿 + - GPIO12\pwm3: 蓝 +* 光敏电阻——ADC采集值和电压对应,电压和电阻对应,电阻和光照强度对应 + - GPIO09: ADC4 +* 人体红外传感器——ADC采集值反应是否有人靠近 + - GPIO07: ADC3 + + + +## 二、如何编译 + +1. 将此目录下的 `colorful_light_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: +```python + features = [ + "iothardware:colorful_light_demo", + ] +``` +3. 在openharmony源码顶层目录执行:`python build.py wifiiot` + +### 报错解决 + +1. 编译过程中报错:undefined reference to `hi_pwm_init` 等几个 `hi_pwm_`开头的函数, + * **原因:** 因为默认情况下,hi3861_sdk中,PWM的CONFIG选项没有打开 + * **解决:** 修改`vendor\hisi\hi3861\hi3861\build\config\usr_config.mk`文件中的`CONFIG_PWM_SUPPORT`行: + * `# CONFIG_PWM_SUPPORT is not set`修改为`CONFIG_PWM_SUPPORT=y` + +## 三、运行结果 + +烧录文件后,按下reset按键,程序开始运行: + +* 炫彩灯板的三色灯会先依次按照红绿蓝三色闪烁两次 + +* 三色灯会呈现蓝色,亮度变化 + +* 循环:三色灯会分别呈现红色、绿色,亮度变化 + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/colorful_light_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/colorful_light_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..f871df7cd657cc5cd1e321c5deb9b2a500003e0e --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/17_colorfullight/colorful_light_demo.c" @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_adc.h" +#include "wifiiot_errno.h" + +#define HUMAN_SENSOR_CHAN_NAME WIFI_IOT_ADC_CHANNEL_3 +#define LIGHT_SENSOR_CHAN_NAME WIFI_IOT_ADC_CHANNEL_4 +// #define HUMAN_SENSOR_PIN_NAME WIFI_IOT_IO_NAME_GPIO_7 +// #define LIGHT_SENSOR_PIN_NAME WIFI_IOT_IO_NAME_GPIO_9 + +#define RED_LED_PIN_NAME WIFI_IOT_IO_NAME_GPIO_10 +#define RED_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_10_GPIO + +#define GREEN_LED_PIN_NAME WIFI_IOT_IO_NAME_GPIO_11 +#define GREEN_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_11_GPIO + +#define BLUE_LED_PIN_NAME WIFI_IOT_IO_NAME_GPIO_12 +#define BLUE_LED_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_12_GPIO + +#define LED_DELAY_TIME_US 300000 +#define LED_BRIGHT WIFI_IOT_GPIO_VALUE1 +#define LED_DARK WIFI_IOT_GPIO_VALUE0 + +#define NUM_LEDS 3 +#define NUM_BLINKS 2 +#define NUM_SENSORS 2 + +#define ADC_RESOLUTION 4096 +#define PWM_FREQ_DIVITION 64000 + +static void CorlorfulLightTask(void *arg) +{ + (void)arg; + static const WifiIotGpioIdx pins[] = {RED_LED_PIN_NAME, GREEN_LED_PIN_NAME, BLUE_LED_PIN_NAME}; + + for (int i = 0; i < NUM_BLINKS; i++) { + for (unsigned j = 0; j < sizeof(pins)/sizeof(pins[0]); j++) { + GpioSetOutputVal(pins[j], LED_BRIGHT); + usleep(LED_DELAY_TIME_US); + GpioSetOutputVal(pins[j], LED_DARK); + usleep(LED_DELAY_TIME_US); + } + } + + // GpioDeinit(); + IoSetFunc(RED_LED_PIN_NAME, WIFI_IOT_IO_FUNC_GPIO_10_PWM1_OUT); + IoSetFunc(GREEN_LED_PIN_NAME, WIFI_IOT_IO_FUNC_GPIO_11_PWM2_OUT); + IoSetFunc(BLUE_LED_PIN_NAME, WIFI_IOT_IO_FUNC_GPIO_12_PWM3_OUT); + + PwmInit(WIFI_IOT_PWM_PORT_PWM1); // R + PwmInit(WIFI_IOT_PWM_PORT_PWM2); // G + PwmInit(WIFI_IOT_PWM_PORT_PWM3); // B + + // use PWM control BLUE LED brightness + for (int i = 1; i <= ADC_RESOLUTION; i *= 2) { + PwmStart(WIFI_IOT_PWM_PORT_PWM3, i, PWM_FREQ_DIVITION); + usleep(250000); + PwmStop(WIFI_IOT_PWM_PORT_PWM3); + } + + while (1) { + unsigned short duty[NUM_SENSORS] = {0, 0}; + unsigned short data[NUM_SENSORS] = {0, 0}; + static const WifiIotAdcChannelIndex chan[] = {HUMAN_SENSOR_CHAN_NAME, LIGHT_SENSOR_CHAN_NAME}; + static const WifiIotPwmPort port[] = {WIFI_IOT_PWM_PORT_PWM1, WIFI_IOT_PWM_PORT_PWM2}; + + for (size_t i = 0; i < sizeof(chan)/sizeof(chan[0]); i++) { + if (AdcRead(chan[i], &data[i], WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0) + == WIFI_IOT_SUCCESS) { + duty[i] = PWM_FREQ_DIVITION * (unsigned int)data[i] / ADC_RESOLUTION; + } + PwmStart(port[i], duty[i], PWM_FREQ_DIVITION); + usleep(10000); + PwmStop(port[i]); + } + } +} + +static void ColorfulLightDemo(void) +{ + osThreadAttr_t attr; + + GpioInit(); + + // set Red/Green/Blue LED pin to GPIO function + IoSetFunc(RED_LED_PIN_NAME, RED_LED_PIN_FUNCTION); + IoSetFunc(GREEN_LED_PIN_NAME, GREEN_LED_PIN_FUNCTION); + IoSetFunc(BLUE_LED_PIN_NAME, BLUE_LED_PIN_FUNCTION); + + // set Red/Green/Blue LED pin as output + GpioSetDir(RED_LED_PIN_NAME, WIFI_IOT_GPIO_DIR_OUT); + GpioSetDir(GREEN_LED_PIN_NAME, WIFI_IOT_GPIO_DIR_OUT); + GpioSetDir(BLUE_LED_PIN_NAME, WIFI_IOT_GPIO_DIR_OUT); + + attr.name = "CorlorfulLightTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 4096; + attr.priority = osPriorityNormal; + + if (osThreadNew(CorlorfulLightTask, NULL, &attr) == NULL) { + printf("[ColorfulLightDemo] Falied to create CorlorfulLightTask!\n"); + } +} + +APP_FEATURE_INIT(ColorfulLightDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..89759e48b5cc9752b1aea8d9f728ea77c58dd14c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/BUILD.gn" @@ -0,0 +1,38 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("sensing_demo") { + sources = [ + "envrionment_demo.c", "oled_ssd1306.c", "aht20.c" + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..3bd843349a5c8f87f04a4df3e4b54e2094e6685b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/README.md" @@ -0,0 +1,69 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--envrionment_demo + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + + + +## 一、环境监测板上外设与主控芯片(Pegasus)引脚的对应关系 + +* 蜂鸣器——PWM控制声音的评率和音量 + - GPIO09: PWM0 +* MQ2 燃气传感器——ADC读取模拟值 + - GPIO11: ADC5 +* AHT20 温湿度传感器——I2C接口通信,地址 0x38 + - GPIO13: I2C0_SDA + - GPIO14: I2C0_SCL + +## 二、如何编译 + +1. 将此目录下的文件 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: +```python + features = [ + "iothardware:envrionment_demo", + ] +``` +3. 在openharmony源码顶层目录执行:`python build.py wifiiot` + +### 报错解决 + +1. 编译过程中报错:undefined reference to `hi_pwm_init` 等几个 `hi_pwm_`开头的函数, + * **原因:** 因为默认情况下,hi3861_sdk中,PWM的CONFIG选项没有打开 + * **解决:** 修改`vendor\hisi\hi3861\hi3861\build\config\usr_config.mk`文件中的`CONFIG_PWM_SUPPORT`行: + * `# CONFIG_PWM_SUPPORT is not set`修改为`CONFIG_PWM_SUPPORT=y` +2. 编译过程中报错:undefined reference to `hi_i2c_init` 等几个 `hi_i2c_`开头的函数, + - **原因:** 因为默认情况下,hi3861_sdk中,I2C的CONFIG选项没有打开 + - **解决:** 修改`vendor\hisi\hi3861\hi3861\build\config\usr_config.mk`文件中的`CONFIG_I2C_SUPPORT`行: + - `# CONFIG_I2C_SUPPORT is not set`修改为`CONFIG_I2C_SUPPORT=y` + +## 三、运行结果 + +烧录文件后,按下reset按键,程序开始运行: + +* 蜂鸣器:倒计时响三声 + +* oled屏:显示temp、humi、gas数值 + + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.c" new file mode 100755 index 0000000000000000000000000000000000000000..0ebb404bfdd5bb19b94323b67b69f7cd0ae387c3 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.c" @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "aht20.h" + +#include +#include +#include + +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" + +#define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define AHT20_STARTUP_TIME 20*1000 // 上电启动时间 +#define AHT20_CALIBRATION_TIME 40*1000 // 初始化(校准)时间 +#define AHT20_MEASURE_TIME 75*1000 // 测量时间 + +#define AHT20_DEVICE_ADDR 0x38 +#define AHT20_READ_ADDR ((0x38<<1)|0x1) +#define AHT20_WRITE_ADDR ((0x38<<1)|0x0) + +#define AHT20_CMD_CALIBRATION 0xBE // 初始化(校准)命令 +#define AHT20_CMD_CALIBRATION_ARG0 0x08 +#define AHT20_CMD_CALIBRATION_ARG1 0x00 + +/** + * 传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。 + * 若状态比特位[Bit7]为0代表数据可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。 + **/ +#define AHT20_CMD_TRIGGER 0xAC // 触发测量命令 +#define AHT20_CMD_TRIGGER_ARG0 0x33 +#define AHT20_CMD_TRIGGER_ARG1 0x00 + +// 用于在无需关闭和再次打开电源的情况下,重新启动传感器系统,软复位所需时间不超过20 毫秒 +#define AHT20_CMD_RESET 0xBA // 软复位命令 + +#define AHT20_CMD_STATUS 0x71 // 获取状态命令 + +/** + * STATUS 命令回复: + * 1. 初始化后触发测量之前,STATUS 只回复 1B 状态值; + * 2. 触发测量之后,STATUS 回复6B: 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度 + * RH = Srh / 2^20 * 100% + * T = St / 2^20 * 200 - 50 + **/ +#define AHT20_STATUS_BUSY_SHIFT 7 // bit[7] Busy indication +#define AHT20_STATUS_BUSY_MASK (0x1<> AHT20_STATUS_BUSY_SHIFT) + +#define AHT20_STATUS_MODE_SHIFT 5 // bit[6:5] Mode Status +#define AHT20_STATUS_MODE_MASK (0x3<> AHT20_STATUS_MODE_SHIFT) + + // bit[4] Reserved +#define AHT20_STATUS_CALI_SHIFT 3 // bit[3] CAL Enable +#define AHT20_STATUS_CALI_MASK (0x1<> AHT20_STATUS_CALI_SHIFT) + // bit[2:0] Reserved + +#define AHT20_STATUS_RESPONSE_MAX 6 + +#define AHT20_RESLUTION (1<<20) // 2^20 + +#define AHT20_MAX_RETRY 10 + +static uint32_t AHT20_Read(uint8_t* buffer, uint32_t buffLen) +{ + WifiIotI2cData data = { 0 }; + data.receiveBuf = buffer; + data.receiveLen = buffLen; + uint32_t retval = I2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, &data); + if (retval != WIFI_IOT_SUCCESS) { + printf("I2cRead() failed, %0X!\n", retval); + return retval; + } + return WIFI_IOT_SUCCESS; +} + +static uint32_t AHT20_Write(uint8_t* buffer, uint32_t buffLen) +{ + WifiIotI2cData data = { 0 }; + data.sendBuf = buffer; + data.sendLen = buffLen; + uint32_t retval = I2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, &data); + if (retval != WIFI_IOT_SUCCESS) { + printf("I2cWrite(%02X) failed, %0X!\n", buffer[0], retval); + return retval; + } + return WIFI_IOT_SUCCESS; +} + +// 发送获取状态命令 +static uint32_t AHT20_StatusCommand(void) +{ + uint8_t statusCmd[] = { AHT20_CMD_STATUS }; + return AHT20_Write(statusCmd, sizeof(statusCmd)); +} + +// 发送软复位命令 +static uint32_t AHT20_ResetCommand(void) +{ + uint8_t resetCmd[] = {AHT20_CMD_RESET}; + return AHT20_Write(resetCmd, sizeof(resetCmd)); +} + +// 发送初始化校准命令 +static uint32_t AHT20_CalibrateCommand(void) +{ + uint8_t clibrateCmd[] = {AHT20_CMD_CALIBRATION, AHT20_CMD_CALIBRATION_ARG0, AHT20_CMD_CALIBRATION_ARG1}; + return AHT20_Write(clibrateCmd, sizeof(clibrateCmd)); +} + +// 读取温湿度值之前, 首先要看状态字的校准使能位Bit[3]是否为 1(通过发送0x71可以获取一个字节的状态字), +// 如果不为1,要发送0xBE命令(初始化),此命令参数有两个字节, 第一个字节为0x08,第二个字节为0x00。 +uint32_t AHT20_Calibrate(void) +{ + uint32_t retval = 0; + uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { AHT20_CMD_STATUS }; + memset(&buffer, 0x0, sizeof(buffer)); + + retval = AHT20_StatusCommand(); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + retval = AHT20_Read(buffer, sizeof(buffer)); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + if (AHT20_STATUS_BUSY(buffer[0]) || !AHT20_STATUS_CALI(buffer[0])) { + retval = AHT20_ResetCommand(); + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + usleep(AHT20_STARTUP_TIME); + retval = AHT20_CalibrateCommand(); + usleep(AHT20_CALIBRATION_TIME); + return retval; + } + + return WIFI_IOT_SUCCESS; +} + +// 发送 触发测量 命令,开始测量 +uint32_t AHT20_StartMeasure(void) +{ + uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1}; + return AHT20_Write(triggerCmd, sizeof(triggerCmd)); +} + +// 接收测量结果,拼接转换为标准值 +uint32_t AHT20_GetMeasureResult(float* temp, float* humi) +{ + uint32_t retval = 0, i = 0; + if (temp == NULL || humi == NULL) { + return WIFI_IOT_FAILURE; + } + + uint8_t buffer[AHT20_STATUS_RESPONSE_MAX] = { 0 }; + memset(&buffer, 0x0, sizeof(buffer)); + retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + + for (i = 0; AHT20_STATUS_BUSY(buffer[0]) && i < AHT20_MAX_RETRY; i++) { + // printf("AHT20 device busy, retry %d/%d!\r\n", i, AHT20_MAX_RETRY); + usleep(AHT20_MEASURE_TIME); + retval = AHT20_Read(buffer, sizeof(buffer)); // recv status command result + if (retval != WIFI_IOT_SUCCESS) { + return retval; + } + } + if (i >= AHT20_MAX_RETRY) { + printf("AHT20 device always busy!\r\n"); + return WIFI_IOT_FAILURE; + } + + uint32_t humiRaw = buffer[1]; + humiRaw = (humiRaw << 8) | buffer[2]; + humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4); + *humi = humiRaw / (float)AHT20_RESLUTION * 100; + + uint32_t tempRaw = buffer[3] & 0x0F; + tempRaw = (tempRaw << 8) | buffer[4]; + tempRaw = (tempRaw << 8) | buffer[5]; + *temp = tempRaw / (float)AHT20_RESLUTION * 200 - 50; + // printf("humi = %05X, %f, temp= %05X, %f\r\n", humiRaw, *humi, tempRaw, *temp); + return WIFI_IOT_SUCCESS; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.h" new file mode 100755 index 0000000000000000000000000000000000000000..d07615c5bf1da4b18328538b15f53fa82e3041e3 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/aht20.h" @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef AHT20_H +#define AHT20_H + +#include + +uint32_t AHT20_Calibrate(void); + +uint32_t AHT20_StartMeasure(void); + +uint32_t AHT20_GetMeasureResult(float* temp, float* humi); + +#endif // AHT20_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/envrionment_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/envrionment_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..71baa511727f4626a4481c3ca236e044d4a36e03 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/envrionment_demo.c" @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifiiot_i2c.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_pwm.h" +#include "wifiiot_adc.h" +#include "wifiiot_errno.h" + +#include "aht20.h" +#include "oled_ssd1306.h" + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) +#endif + +#define MS_PER_S 1000 + +#define BEEP_TIMES 3 +#define BEEP_DURATION 100 +#define BEEP_PWM_DUTY 30000 +#define BEEP_PWM_FREQ 60000 +#define BEEP_PIN_NAME WIFI_IOT_IO_NAME_GPIO_9 +#define BEEP_PIN_FUNCTION WIFI_IOT_IO_FUNC_GPIO_9_PWM0_OUT + +#define GAS_SENSOR_CHAN_NAME WIFI_IOT_ADC_CHANNEL_5 +// #define GAS_SENSOR_PIN_NAME WIFI_IOT_IO_NAME_GPIO_11 + +#define AHT20_BAUDRATE 400*1000 +#define AHT20_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define ADC_RESOLUTION 2048 + +static float ConvertToVoltage(unsigned short data) +{ + return (float)data * 1.8 * 4 / 4096; +} + +static void EnvironmentTask(void *arg) +{ + (void)arg; + uint32_t retval = 0; + float humidity = 0.0f; + float temperature = 0.0f; + float gasSensorResistance = 0.0f; + static char line[32] = {0}; + + OledInit(); + OledFillScreen(0); + I2cInit(AHT20_I2C_IDX, AHT20_BAUDRATE); + + // set BEEP pin as PWM function + IoSetFunc(BEEP_PIN_NAME, BEEP_PIN_FUNCTION); + GpioSetDir(BEEP_PIN_NAME, WIFI_IOT_GPIO_DIR_OUT); + PwmInit(WIFI_IOT_PWM_PORT_PWM0); + + for (int i = 0; i < BEEP_TIMES; i++) { + snprintf(line, sizeof(line), "beep %d/%d", (i+1), BEEP_TIMES); + OledShowString(0, 0, line, 1); + + PwmStart(WIFI_IOT_PWM_PORT_PWM0, BEEP_PWM_DUTY, BEEP_PWM_FREQ); + usleep(BEEP_DURATION * 1000); + PwmStop(WIFI_IOT_PWM_PORT_PWM0); + usleep((1000 - BEEP_DURATION) * 1000); + } + + while (WIFI_IOT_SUCCESS != AHT20_Calibrate()) { + printf("AHT20 sensor init failed!\r\n"); + usleep(1000); + } + + while(1) { + retval = AHT20_StartMeasure(); + if (retval != WIFI_IOT_SUCCESS) { + printf("trigger measure failed!\r\n"); + } + + retval = AHT20_GetMeasureResult(&temperature, &humidity); + if (retval != WIFI_IOT_SUCCESS) { + printf("get humidity data failed!\r\n"); + } + + unsigned short data = 0; + if (AdcRead(GAS_SENSOR_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0) + == WIFI_IOT_SUCCESS) { + float Vx = ConvertToVoltage(data); + + // Vcc ADC GND + // | ______ | ______ | + // +---| MG-2 |---+---| 1kom |---+ + // ------ ------ + // 查阅原理图,ADC 引脚位于 1K 电阻和燃气传感器之间,燃气传感器另一端接在 5V 电源正极上 + // 串联电路电压和阻止成正比: + // Vx / 5 == 1kom / (1kom + Rx) + // => Rx + 1 == 5/Vx + // => Rx = 5/Vx - 1 + gasSensorResistance = 5 / Vx - 1; + } + + OledShowString(0, 0, "Sensor values:", 1); + + snprintf(line, sizeof(line), "temp: %.2f", temperature); + OledShowString(0, 1, line, 1); + + snprintf(line, sizeof(line), "humi: %.2f", humidity); + OledShowString(0, 2, line, 1); + + snprintf(line, sizeof(line), "gas: %.2f kom", gasSensorResistance); + OledShowString(0, 3, line, 1); + + sleep(1); + } +} + +static void EnvironmentDemo(void) +{ + osThreadAttr_t attr; + + GpioInit(); + + IoSetFunc(BEEP_PIN_NAME, BEEP_PIN_FUNCTION); + GpioSetDir(BEEP_PIN_NAME, WIFI_IOT_GPIO_DIR_OUT); + PwmInit(WIFI_IOT_PWM_PORT_PWM0); + + attr.name = "EnvironmentTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 4096; + attr.priority = osPriorityNormal; + + if (osThreadNew(EnvironmentTask, NULL, &attr) == NULL) { + printf("[EnvironmentDemo] Falied to create EnvironmentTask!\n"); + } +} + +APP_FEATURE_INIT(EnvironmentDemo); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_fonts.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_fonts.h" new file mode 100755 index 0000000000000000000000000000000000000000..c3cd86580d7326e84e4e8976928a347bb540b024 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_fonts.h" @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OLOED_FONTS_H +#define OLOED_FONTS_H + +/************************************6*8的点阵************************************/ +static unsigned char F6x8[][6] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // sp + { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 }, // ! + { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 }, // " + { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // # + { 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // $ + { 0x00, 0x62, 0x64, 0x08, 0x13, 0x23 }, // % + { 0x00, 0x36, 0x49, 0x55, 0x22, 0x50 }, // & + { 0x00, 0x00, 0x05, 0x03, 0x00, 0x00 }, // ' + { 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00 }, // ( + { 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00 }, // ) + { 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14 }, // * + { 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08 }, // + + { 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00 }, // , + { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08 }, // - + { 0x00, 0x00, 0x60, 0x60, 0x00, 0x00 }, // . + { 0x00, 0x20, 0x10, 0x08, 0x04, 0x02 }, // / + { 0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E }, // 0 + { 0x00, 0x00, 0x42, 0x7F, 0x40, 0x00 }, // 1 + { 0x00, 0x42, 0x61, 0x51, 0x49, 0x46 }, // 2 + { 0x00, 0x21, 0x41, 0x45, 0x4B, 0x31 }, // 3 + { 0x00, 0x18, 0x14, 0x12, 0x7F, 0x10 }, // 4 + { 0x00, 0x27, 0x45, 0x45, 0x45, 0x39 }, // 5 + { 0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30 }, // 6 + { 0x00, 0x01, 0x71, 0x09, 0x05, 0x03 }, // 7 + { 0x00, 0x36, 0x49, 0x49, 0x49, 0x36 }, // 8 + { 0x00, 0x06, 0x49, 0x49, 0x29, 0x1E }, // 9 + { 0x00, 0x00, 0x36, 0x36, 0x00, 0x00 }, // : + { 0x00, 0x00, 0x56, 0x36, 0x00, 0x00 }, // ; + { 0x00, 0x08, 0x14, 0x22, 0x41, 0x00 }, // < + { 0x00, 0x14, 0x14, 0x14, 0x14, 0x14 }, // = + { 0x00, 0x00, 0x41, 0x22, 0x14, 0x08 }, // > + { 0x00, 0x02, 0x01, 0x51, 0x09, 0x06 }, // ? + { 0x00, 0x32, 0x49, 0x59, 0x51, 0x3E }, // @ + { 0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C }, // A + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x36 }, // B + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x22 }, // C + { 0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C }, // D + { 0x00, 0x7F, 0x49, 0x49, 0x49, 0x41 }, // E + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x01 }, // F + { 0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A }, // G + { 0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F }, // H + { 0x00, 0x00, 0x41, 0x7F, 0x41, 0x00 }, // I + { 0x00, 0x20, 0x40, 0x41, 0x3F, 0x01 }, // J + { 0x00, 0x7F, 0x08, 0x14, 0x22, 0x41 }, // K + { 0x00, 0x7F, 0x40, 0x40, 0x40, 0x40 }, // L + { 0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F }, // M + { 0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F }, // N + { 0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E }, // O + { 0x00, 0x7F, 0x09, 0x09, 0x09, 0x06 }, // P + { 0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E }, // Q + { 0x00, 0x7F, 0x09, 0x19, 0x29, 0x46 }, // R + { 0x00, 0x46, 0x49, 0x49, 0x49, 0x31 }, // S + { 0x00, 0x01, 0x01, 0x7F, 0x01, 0x01 }, // T + { 0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F }, // U + { 0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F }, // V + { 0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F }, // W + { 0x00, 0x63, 0x14, 0x08, 0x14, 0x63 }, // X + { 0x00, 0x07, 0x08, 0x70, 0x08, 0x07 }, // Y + { 0x00, 0x61, 0x51, 0x49, 0x45, 0x43 }, // Z + { 0x00, 0x00, 0x7F, 0x41, 0x41, 0x00 }, // [ + { 0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55 }, // 55 + { 0x00, 0x00, 0x41, 0x41, 0x7F, 0x00 }, // ] + { 0x00, 0x04, 0x02, 0x01, 0x02, 0x04 }, // ^ + { 0x00, 0x40, 0x40, 0x40, 0x40, 0x40 }, // _ + { 0x00, 0x00, 0x01, 0x02, 0x04, 0x00 }, // ' + { 0x00, 0x20, 0x54, 0x54, 0x54, 0x78 }, // a + { 0x00, 0x7F, 0x48, 0x44, 0x44, 0x38 }, // b + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x20 }, // c + { 0x00, 0x38, 0x44, 0x44, 0x48, 0x7F }, // d + { 0x00, 0x38, 0x54, 0x54, 0x54, 0x18 }, // e + { 0x00, 0x08, 0x7E, 0x09, 0x01, 0x02 }, // f + { 0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C }, // g + { 0x00, 0x7F, 0x08, 0x04, 0x04, 0x78 }, // h + { 0x00, 0x00, 0x44, 0x7D, 0x40, 0x00 }, // i + { 0x00, 0x40, 0x80, 0x84, 0x7D, 0x00 }, // j + { 0x00, 0x7F, 0x10, 0x28, 0x44, 0x00 }, // k + { 0x00, 0x00, 0x41, 0x7F, 0x40, 0x00 }, // l + { 0x00, 0x7C, 0x04, 0x18, 0x04, 0x78 }, // m + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x78 }, // n + { 0x00, 0x38, 0x44, 0x44, 0x44, 0x38 }, // o + { 0x00, 0xFC, 0x24, 0x24, 0x24, 0x18 }, // p + { 0x00, 0x18, 0x24, 0x24, 0x18, 0xFC }, // q + { 0x00, 0x7C, 0x08, 0x04, 0x04, 0x08 }, // r + { 0x00, 0x48, 0x54, 0x54, 0x54, 0x20 }, // s + { 0x00, 0x04, 0x3F, 0x44, 0x40, 0x20 }, // t + { 0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C }, // u + { 0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C }, // v + { 0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C }, // w + { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 }, // x + { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C }, // y + { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 }, // z + { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }, // horiz lines +}; + +/****************************************8*16的点阵************************************/ +static const unsigned char F8X16[]= +{ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 + 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//! 1 + 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//" 2 + 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//# 3 + 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$ 4 + 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//% 5 + 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//& 6 + 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//' 7 + 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//( 8 + 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//) 9 + 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//* 10 + 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+ 11 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//, 12 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//- 13 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//. 14 + 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,/// 15 + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//0 16 + 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//1 17 + 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//2 18 + 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//3 19 + 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//4 20 + 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//5 21 + 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//6 22 + 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//7 23 + 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//8 24 + 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//9 25 + 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//: 26 + 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//; 27 + 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//< 28 + 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//= 29 + 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//> 30 + 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//? 31 + 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@ 32 + 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A 33 + 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B 34 + 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C 35 + 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D 36 + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E 37 + 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F 38 + 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G 39 + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H 40 + 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I 41 + 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J 42 + 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K 43 + 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L 44 + 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M 45 + 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N 46 + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O 47 + 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P 48 + 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q 49 + 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R 50 + 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S 51 + 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T 52 + 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U 53 + 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V 54 + 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W 55 + 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X 56 + 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y 57 + 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z 58 + 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[ 59 + 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\ 60 + 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//] 61 + 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^ 62 + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_ 63 + 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//` 64 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a 65 + 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b 66 + 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c 67 + 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d 68 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e 69 + 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f 70 + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g 71 + 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h 72 + 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i 73 + 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j 74 + 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k 75 + 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l 76 + 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m 77 + 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n 78 + 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o 79 + 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p 80 + 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q 81 + 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r 82 + 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s 83 + 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t 84 + 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//u 85 + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v 86 + 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w 87 + 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x 88 + 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y 89 + 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z 90 + 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{ 91 + 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//| 92 + 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//} 93 + 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94 +}; + +#endif \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.c" new file mode 100755 index 0000000000000000000000000000000000000000..3f311278f31f69f48c88c7c11a26903c6564beae --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.c" @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "oled_ssd1306.h" +#include "wifiiot_gpio.h" +#include "wifiiot_gpio_ex.h" +#include "wifiiot_i2c.h" +#include "wifiiot_errno.h" +#include "oled_fonts.h" + +#define ARRAY_SIZE(a) sizeof(a)/sizeof(a[0]) + +#define OLED_I2C_IDX WIFI_IOT_I2C_IDX_0 + +#define OLED_WIDTH (128) +#define OLED_I2C_ADDR 0x78 // 默认地址为 0x78 +#define OLED_I2C_CMD 0x00 // 0000 0000 写命令 +#define OLED_I2C_DATA 0x40 // 0100 0000(0x40) 写数据 +#define OLED_I2C_BAUDRATE (400*1000) // 400k + +#define DELAY_100_MS (100*1000) + +// unsigned int I2cSetBaudrate(WifiIotI2cIdx id, unsigned int baudrate); + +static uint32_t I2cWiteByte(uint8_t regAddr, uint8_t byte) +{ + WifiIotI2cIdx id = OLED_I2C_IDX; + uint8_t buffer[] = {regAddr, byte}; + WifiIotI2cData i2cData = {0}; + + i2cData.sendBuf = buffer; + i2cData.sendLen = sizeof(buffer)/sizeof(buffer[0]); + + return I2cWrite(id, OLED_I2C_ADDR, &i2cData); +} + +/** + * @brief Write a command byte to OLED device. + * + * @param cmd the commnad byte to be writen. + * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful; + * returns an error code defined in {@link wifiiot_errno.h} otherwise. + */ +static uint32_t WriteCmd(uint8_t cmd) +{ + return I2cWiteByte(OLED_I2C_CMD, cmd); +} + +/** + * @brief Write a data byte to OLED device. + * + * @param cmd the data byte to be writen. + * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful; + * returns an error code defined in {@link wifiiot_errno.h} otherwise. + */ +static uint32_t WriteData(uint8_t data) +{ + return I2cWiteByte(OLED_I2C_DATA, data); +} + +/** + * @brief ssd1306 OLED Initialize. + */ +uint32_t OledInit(void) +{ + static const uint8_t initCmds[] = { + 0xAE, // --display off + 0x00, // ---set low column address + 0x10, // ---set high column address + 0x40, // --set start line address + 0xB0, // --set page address + 0x81, // contract control + 0xFF, // --128 + 0xA1, // set segment remap + 0xA6, // --normal / reverse + 0xA8, // --set multiplex ratio(1 to 64) + 0x3F, // --1/32 duty + 0xC8, // Com scan direction + 0xD3, // -set display offset + 0x00, // + 0xD5, // set osc division + 0x80, // + 0xD8, // set area color mode off + 0x05, // + 0xD9, // Set Pre-Charge Period + 0xF1, // + 0xDA, // set com pin configuartion + 0x12, // + 0xDB, // set Vcomh + 0x30, // + 0x8D, // set charge pump enable + 0x14, // + 0xAF, // --turn on oled panel + }; + + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA); + IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL); + + I2cInit(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); + // I2cSetBaudrate(WIFI_IOT_I2C_IDX_0, OLED_I2C_BAUDRATE); + + for (size_t i = 0; i < ARRAY_SIZE(initCmds); i++) { + uint32_t status = WriteCmd(initCmds[i]); + if (status != WIFI_IOT_SUCCESS) { + return status; + } + } + return WIFI_IOT_SUCCESS; +} + +void OledSetPosition(uint8_t x, uint8_t y) +{ + WriteCmd(0xb0 + y); + WriteCmd(((x & 0xf0) >> 4) | 0x10); + WriteCmd(x & 0x0f); +} + +/*全屏填充*/ +void OledFillScreen(uint8_t fillData) +{ + uint8_t m = 0; + uint8_t n = 0; + + for (m=0; m < 8; m++) { + WriteCmd(0xb0 + m); + WriteCmd(0x00); + WriteCmd(0x10); + + for (n=0; n < 128; n++) { + WriteData(fillData); + } + } +} + +/** + * @brief 8*16 typeface + * @param x: write positon start from x axis + * @param y: write positon start from y axis + * @param ch: write data + * @param font: selected font + */ +void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font) +{ + uint8_t c = 0; + uint8_t i = 0; + + c = ch - ' '; //得到偏移后的值 + if (x > OLED_WIDTH - 1) { + x = 0; + y = y + 2; + } + + if (font == FONT8x16) { + OledSetPosition(x, y); + for (i = 0; i < 8; i++){ + WriteData(F8X16[c*16 + i]); + } + + OledSetPosition(x, y+1); + for (i = 0; i < 8; i++) { + WriteData(F8X16[c*16 + i + 8]); + } + } else { + OledSetPosition(x, y); + for (i = 0; i < 6; i++) { + WriteData(F6x8[c][i]); + } + } +} + +void OledShowString(uint8_t x, uint8_t y, const char* str, Font font) +{ + uint8_t j = 0; + if (str == NULL) { + printf("param is NULL,Please check!!!\r\n"); + return; + } + + while (str[j]) { + OledShowChar(x, y, str[j], font); + x += 8; + if (x > 120) { + x = 0; + y += 2; + } + j++; + } +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.h" new file mode 100755 index 0000000000000000000000000000000000000000..216ffcdf94c3f47fc6f15877f06b32d9f69cc598 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/18_environment/oled_ssd1306.h" @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef OLED_SSD1306_H +#define OLED_SSD1306_H + +#include + +/** + * @brief ssd1306 OLED Initialize. + */ +uint32_t OledInit(void); + +/** + * @brief Set cursor position + * + * @param x the horizontal posistion of cursor + * @param y the vertical position of cursor + * @return Returns {@link WIFI_IOT_SUCCESS} if the operation is successful; + * returns an error code defined in {@link wifiiot_errno.h} otherwise. + */ +void OledSetPosition(uint8_t x, uint8_t y); + +void OledFillScreen(uint8_t fillData); + +enum Font { + FONT6x8 = 1, + FONT8x16 +}; +typedef enum Font Font; + +void OledShowChar(uint8_t x, uint8_t y, uint8_t ch, Font font); +void OledShowString(uint8_t x, uint8_t y, const char* str, Font font); + +#endif // OLED_SSD1306_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..97ccb0dabe85d81cf79d3edb89f9e515b3c14422 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("wifi_demo") { + sources = [ + "wifi_connect_demo.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..f545e28c07c65470c7469e97a077ef3a44cf1324 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/README.md" @@ -0,0 +1,222 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--wificonnect(STA模式) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + + + +## 一、Wifi STA API + +使用鸿蒙原始WiFI API接口进行编程,STA模式需要使用原始STA接口以及一些DHCP客户端接口。 + +#### 鸿蒙WiFi STA模式相关的API接口文件路径 + +**foundation/communication/interfaces/kits/wifi_lite/wifiservice/wifi_device.h** +所使用的API接口有: + + +| API | 接口说明 | +| ------------------------------------------------------------ | --------------------------------------- | +| WifiErrorCode EnableWifi(void); | 开启STA | +| WifiErrorCode DisableWifi(void); | 关闭STA | +| int IsWifiActive(void); | 查询STA是否已开启 | +| WifiErrorCode Scan(void); | 触发扫描 | +| WifiErrorCode GetScanInfoList(WifiScanInfo* result, unsigned int* size); | 获取扫描结果 | +| WifiErrorCode AddDeviceConfig(const WifiDeviceConfig* config, int* result); | 添加热点配置,成功会通过result传出netld | +| WifiErrorCode GetDeviceConfigs(WifiDeviceConfig* result, unsigned int* size); | 获取本机所有热点配置 | +| WifiErrorCode RemoveDevice(int networkId); | 删除热点配置 | +| WifiErrorCode ConnectTo(int networkId); | 连接到热点 | +| WifiErrorCode Disconnect(void); | 断开热点连接 | +| WifiErrorCode GetLinkedInfo(WifiLinkedInfo* result); | 获取当前连接热点信息 | +| WifiErrorCode RegisterWifiEvent(WifiEvent* event); | 注册事件监听 | +| WifiErrorCode UnRegisterWifiEvent(const WifiEvent* event); | 解除事件监听 | +| WifiErrorCode GetDeviceMacAddress(unsigned char* result); | 获取Mac地址 | +| WifiErrorCode AdvanceScan(WifiScanParams *params); | 高级搜索 | + +#### Hi3861 SDK的DHCP客户端接口: + +| API | 描述 | +| ------------------- | ------------------ | +| netifapi_netif_find | 按名称查找网络接口 | +| netifapi_dhcp_start | 启动DHCP客户端 | +| netifapi_dhcp_stop | 停止DHCP客户端 | + +## 二、代码分析 + +```c +//wifi connect task +static void WifiConnectTask(void *arg) +{ + (void)arg; + WifiErrorCode errCode; + WifiEvent eventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged + }; + WifiDeviceConfig apConfig = {}; + int netId = -1; + + osDelay(10); + errCode = RegisterWifiEvent(&eventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + // 配置要连接的热点的账号密码 + strcpy(apConfig.ssid, "ABCD"); + strcpy(apConfig.preSharedKey, "12345678"); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + while (1) { + //打开wifi + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + osDelay(11); + //添加热点配置 + errCode = AddDeviceConfig(&apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + //连接热点 + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + //等待wifi连接 + while (!g_connected) { + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + osDelay(50); + + + // 联网业务开始 + struct netif* iface = netifapi_netif_find("wlan0"); + if (iface) { + err_t ret = netifapi_dhcp_start(iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(200); // wait DHCP server give me IP + ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + + // 模拟一段时间的联网业务 + int timeout = 60; + while (timeout--) { + osDelay(100); + printf("after %d seconds, I'll disconnect WiFi!\n", timeout); + } + + // 联网业务结束 + err_t ret = netifapi_dhcp_stop(iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + + Disconnect(); // disconnect with your AP + + RemoveDevice(netId); // remove AP config + + errCode = DisableWifi(); //close wifi + printf("DisableWifi: %d\r\n", errCode); + osDelay(200); + } +} + +``` + + + +## 三、如何编译 + +1. 将此目录下的 `wifi_connect_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:wifi_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` + +ready to OS start +sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00 +FileSystem mount ok. +wifi init success! + +00 00:00:00 0 132 D 0/HIVIEW: hilog init success. +00 00:00:00 0 132 D 0/HIVIEW: log limit init success. +00 00:00:00 0 132 I 1/SAMGR: Bootstrap core services(count:3). +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af3e8 TaskPool:0xe4f38 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af3f4 TaskPool:0xe4f58 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af51c TaskPool:0xe4f78 +00 00:00:00 0 164 I 1/SAMGR: Init service 0x4af3f4 success! +00 00:00:00 0 64 I 1/SAMGR: Init service 0x4af3e8 success! +00 00:00:00 0 8 D 0/HIVIEW: hiview init success. +00 00:00:00 0 8 I 1/SAMGR: Init service 0x4af51c success! +00 00:00:00 0 8 I 1/SAMGR: Initialized all core system services! +00 00:00:00 0 64 I 1/SAMGR: Bootstrap system and application services(count:0). +00 00:00:00 0 64 I 1/SAMGR: Initialized all system and application services! +00 00:00:00 0 64 I 1/SAMGR: Bootstrap dynamic registered services(count:0). +RegisterWifiEvent: 0 +EnableWifi: 0 +AddDeviceConfig: 0 +ConnectTo(0): 0 ++NOTICE:SCANFINISH ++NOTICE:CONNECTED +OnWifiConnectionChanged 58, state = 1, info = +bssid: 08:1F:71:24:B8:29, rssi: 0, connState: 0, reason: 0, ssid: ABCD +g_connected: 1 +netifapi_dhcp_start: 0 +server : + server_id : 192.168.0.1 + mask : 255.255.255.0, 1 + gw : 192.168.0.1 + T0 : 7200 + T1 : 3600 + T2 : 6300 +clients <1> : + mac_idx mac addr state lease tries rto + 0 b4c9b96199d6 192.168.0.107 10 0 1 2 +netifapi_netif_common: 0 +after 59 seconds, I'll disconnect WiFi! +after 58 seconds, I'll disconnect WiFi! +after 57 seconds, I'll disconnect WiFi! +... +... +... +after 3 seconds, I'll disconnect WiFi! +after 2 seconds, I'll disconnect WiFi! +after 1 seconds, I'll disconnect WiFi! +after 0 seconds, I'll disconnect WiFi! +netifapi_dhcp_stop: 0 ++NOTICE:DISCONNECTED +OnWifiConnectionChanged 58, state = 0, info = +bssid: 08:1F:71:24:B8:29, rssi: 0, connState: 0, reason: 3, ssid: +DisableWifi: 0 + +``` + + + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)**http://www.hihope.org/** + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/wifi_connect_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/wifi_connect_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..945ae7664eab522281d19df7eeacd8608c935053 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/19_wificonnect/wifi_connect_demo.c" @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifi_device.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static int g_connected = 0; +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static void WifiConnectTask(void *arg) +{ + (void)arg; + WifiErrorCode errCode; + WifiEvent eventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged + }; + WifiDeviceConfig apConfig = {}; + int netId = -1; + + osDelay(10); + errCode = RegisterWifiEvent(&eventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + // setup your AP params + strcpy(apConfig.ssid, "ABCD"); + strcpy(apConfig.preSharedKey, "12345678"); + apConfig.securityType = WIFI_SEC_TYPE_PSK; + + while (1) { + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + osDelay(10); + + errCode = AddDeviceConfig(&apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + osDelay(50); + + // 联网业务开始 + struct netif* iface = netifapi_netif_find("wlan0"); + if (iface) { + err_t ret = netifapi_dhcp_start(iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(200); // wait DHCP server give me IP + ret = netifapi_netif_common(iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); + } + + // 模拟一段时间的联网业务 + int timeout = 60; + while (timeout--) { + osDelay(100); + printf("after %d seconds, I'll disconnect WiFi!\n", timeout); + } + + // 联网业务结束 + err_t ret = netifapi_dhcp_stop(iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + + Disconnect(); // disconnect with your AP + + RemoveDevice(netId); // remove AP config + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); + osDelay(200); + } +} + +static void WifiConnectDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "WifiConnectTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(WifiConnectTask, NULL, &attr) == NULL) { + printf("[WifiConnectDemo] Falied to create WifiConnectTask!\n"); + } +} + +APP_FEATURE_INIT(WifiConnectDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..6e00ad0641ecb79d529cd06d2224147bece9101c --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/BUILD.gn" @@ -0,0 +1,42 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("wifi_demo") { + sources = [ + "wifi_hotspot_demo.c", + ] + + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//base/iot_hardware/interfaces/kits/wifiiot_lite", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} + + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..d085ea2bb6171ba7656fb2789b88c8679f6d158d --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/README.md" @@ -0,0 +1,184 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--wifihotspot(AP模式) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## 一、Wifi STA API + +使用鸿蒙原始WiFI API接口进行编程,AP模式需要使用原始接口以及一些DHCP客户端接口。 + +#### 鸿蒙WiFi AP模式相关的API接口文件路径 + +**foundation/communication/interfaces/kits/wifi_lite/wifiservice/wifi_hotspot_config.h** + +**foundation/communication/interfaces/kits/wifi_lite/wifiservice/wifi_hotspot.h** + +所使用的API接口有: + +| API | 接口说明 | +| ------------------------------------------------------------ | ------------------------ | +| WifiErrorCode EnableHotspot(void); | 打开Wifi AP 模式 | +| WifiErrorCode DisableHotspot(void); | 关闭Wifi AP 模式 | +| WifiErrorCode SetHotspotConfig(const HotspotConfig* config); | 设置当前AP热点的配置参数 | +| WifiErrorCode GetHotspotConfig(HotspotConfig* result); | 获取当前AP热点的配置参数 | +| int IsHotspotActive(void); | 查询AP是否已经开启 | +| WifiErrorCode GetStationList(StationInfo* result, unsigned int* size); | 获取接入的设备列表 | +| int GetSignalLevel(int rssi, int band); | 获取信号强度等级 | +| WifiErrorCode SetBand(int band); | 设置当前频段 | +| WifiErrorCode GetBand(int* result); | 获取当前频段 | + +#### Hi3861 SDK的DHCP客户端接口: + +| API | 描述 | +| ------------------- | ------------------ | +| netifapi_netif_find | 按名称查找网络接口 | +| netifapi_dhcp_start | 启动DHCP客户端 | +| netifapi_dhcp_stop | 停止DHCP客户端 | + +## 二、代码分析 + +```c +//wifi ap task +static void WifiHotspotTask(void *arg) +{ + (void)arg; + WifiErrorCode errCode; + HotspotConfig config = {0}; + + // 配置作为AP热点的ssid和key + strcpy(config.ssid, "HiSpark-AP"); + strcpy(config.preSharedKey, "12345678"); + config.securityType = WIFI_SEC_TYPE_PSK; + config.band = HOTSPOT_BAND_TYPE_2G; + config.channelNum = 7; + + osDelay(10); + + printf("starting AP ...\r\n"); + //开启热点 + errCode = StartHotspot(&config); + printf("StartHotspot: %d\r\n", errCode); + //热点将开启1分钟 + int timeout = 60; + while (timeout--) { + printf("After %d seconds Ap will turn off!\r\n", timeout); + osDelay(100); + } + // 可以通过串口工具发送 AT+PING=192.168.xxx.xxx(如手机连接到该热点后的IP) 去ping连接到该热点的设备的IP地址 + + printf("stop AP ...\r\n"); + //关闭热点 + StopHotspot(); + printf("stop AP ...\r\n"); +} + +``` + + + +## 三、如何编译 + +1. 将此目录下的 `wifi_hotspot_demo.c` 和 `BUILD.gn` 复制到openharmony源码的`applications\sample\wifi-iot\app\iothardware`目录下, +2. 修改openharmony源码的`applications\sample\wifi-iot\app\BUILD.gn`文件,将其中的 `features` 改为: + +``` + features = [ + "iothardware:wifi_demo", + ] +``` + + 3.在openharmony源码顶层目录执行:`python build.py wifiiot` + +## 四、运行结果 + +``` +ready to OS start +sdk ver:Hi3861V100R001C00SPC025 2020-09-03 18:10:00 +FileSystem mount ok. +wifi init success! + +00 00:00:00 0 132 D 0/HIVIEW: hilog init success. +00 00:00:00 0 132 D 0/HIVIEW: log limit init success. +00 00:00:00 0 132 I 1/SAMGR: Bootstrap core services(count:3). +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af278 TaskPool:0xe4b38 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af284 TaskPool:0xe4b58 +00 00:00:00 0 132 I 1/SAMGR: Init service:0x4af3ac TaskPool:0xe4b78 +00 00:00:00 0 164 I 1/SAMGR: Init service 0x4af284 success! +00 00:00:00 0 64 I 1/SAMGR: Init service 0x4af278 success! +00 00:00:00 0 8 D 0/HIVIEW: hiview init success. +00 00:00:00 0 8 I 1/SAMGR: Init service 0x4af3ac success! +00 00:00:00 0 8 I 1/SAMGR: Initialized all core system services! +00 00:00:00 0 64 I 1/SAMGR: Bootstrap system and application services(count:0). +00 00:00:00 0 64 I 1/SAMGR: Initialized all system and application services! +00 00:00:00 0 64 I 1/SAMGR: Bootstrap dynamic registered services(count:0). +starting AP ... +RegisterWifiEvent: 0 +SetHotspotConfig: 0 +OnHotspotStateChanged: 1. +EnableHotspot: 0 +g_hotspotStarted = 1. +netifapi_netif_set_addr: 0 +netifapi_dhcp_start: 0 +StartHotspot: 0 +After 59 seconds Ap will turn off! +After 58 seconds Ap will turn off! +After 57 seconds Ap will turn off! ++NOTICE:STA CONNECTED + PrintStationInfo: mac=54:19:C8:D9:A7:35, reason=0. ++OnHotspotStaJoin: active stations = 1. +After 56 seconds Ap will turn off! +After 55 seconds Ap will turn off! + +AT+PING=192.168.1.2 + ++PING: +[0]Reply from 192.168.1.2:time=90ms TTL=64 +After 49 seconds Ap will turn off! +[1]Reply from 192.168.1.2:time=25ms TTL=64 +After 48 seconds Ap will turn off! +[2]Reply from 192.168.1.2:time=28ms TTL=64 +After 47 seconds Ap will turn off! +[3]Reply from 192.168.1.2:time=4ms TTL=64 +4 packets transmitted, 4 received, 0 loss, rtt min/avg/max = 4/36/90 ms + +OK +... +... +... +After 3 seconds Ap will turn off! +After 2 seconds Ap will turn off! +After 1 seconds Ap will turn off! +After 0 seconds Ap will turn off! +stop AP ... +netifapi_dhcps_stop: 0 +UnRegisterWifiEvent: 0 ++NOTICE:STA DISCONNECTED +EnableHotspot: 0 +stop AP ... + + +``` + + + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)**http://www.hihope.org/** + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/wifi_hotspot_demo.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/wifi_hotspot_demo.c" new file mode 100755 index 0000000000000000000000000000000000000000..a55dfdc83f2d3460925d45c1c38513c6934a3072 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/20_wifihotspot/wifi_hotspot_demo.c" @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" +#include "wifi_hotspot.h" +#include "lwip/netifapi.h" + +static volatile int g_hotspotStarted = 0; + +static void OnHotspotStateChanged(int state) +{ + printf("OnHotspotStateChanged: %d.\r\n", state); + if (state == WIFI_HOTSPOT_ACTIVE) { + g_hotspotStarted = 1; + } else { + g_hotspotStarted = 0; + } +} + +static volatile int g_joinedStations = 0; + +static void PrintStationInfo(StationInfo* info) +{ + if (!info) return; + static char macAddress[32] = {0}; + unsigned char* mac = info->macAddress; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf(" PrintStationInfo: mac=%s, reason=%d.\r\n", macAddress, info->disconnectedReason); +} + +static void OnHotspotStaJoin(StationInfo* info) +{ + g_joinedStations++; + PrintStationInfo(info); + printf("+OnHotspotStaJoin: active stations = %d.\r\n", g_joinedStations); +} + +static void OnHotspotStaLeave(StationInfo* info) +{ + g_joinedStations--; + PrintStationInfo(info); + printf("-OnHotspotStaLeave: active stations = %d.\r\n", g_joinedStations); +} + +WifiEvent g_defaultWifiEventListener = { + .OnHotspotStaJoin = OnHotspotStaJoin, + .OnHotspotStaLeave = OnHotspotStaLeave, + .OnHotspotStateChanged = OnHotspotStateChanged, +}; + +static struct netif* g_iface = NULL; + +int StartHotspot(const HotspotConfig* config) +{ + WifiErrorCode errCode = WIFI_SUCCESS; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = SetHotspotConfig(config); + printf("SetHotspotConfig: %d\r\n", errCode); + + g_hotspotStarted = 0; + errCode = EnableHotspot(); + printf("EnableHotspot: %d\r\n", errCode); + + while (!g_hotspotStarted) { + osDelay(10); + } + printf("g_hotspotStarted = %d.\r\n", g_hotspotStarted); + + g_iface = netifapi_netif_find("ap0"); + if (g_iface) { + ip4_addr_t ipaddr; + ip4_addr_t gateway; + ip4_addr_t netmask; + + IP4_ADDR(&ipaddr, 192, 168, 1, 1); /* input your IP for example: 192.168.1.1 */ + IP4_ADDR(&gateway, 192, 168, 1, 1); /* input your gateway for example: 192.168.1.1 */ + IP4_ADDR(&netmask, 255, 255, 255, 0); /* input your netmask for example: 255.255.255.0 */ + err_t ret = netifapi_netif_set_addr(g_iface, &ipaddr, &netmask, &gateway); + printf("netifapi_netif_set_addr: %d\r\n", ret); + + ret = netifapi_dhcps_start(g_iface, 0, 0); // 海思扩展的HDCP服务接口 + printf("netifapi_dhcp_start: %d\r\n", ret); + } + return errCode; +} + +void StopHotspot(void) +{ + if (g_iface) { + err_t ret = netifapi_dhcps_stop(g_iface); // 海思扩展的HDCP服务接口 + printf("netifapi_dhcps_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + errCode = DisableHotspot(); + printf("EnableHotspot: %d\r\n", errCode); +} + + +static void WifiHotspotTask(void *arg) +{ + (void)arg; + WifiErrorCode errCode; + HotspotConfig config = {0}; + + // 准备AP的配置参数 + strcpy(config.ssid, "HiSpark-AP"); + strcpy(config.preSharedKey, "12345678"); + config.securityType = WIFI_SEC_TYPE_PSK; + config.band = HOTSPOT_BAND_TYPE_2G; + config.channelNum = 7; + + osDelay(10); + + printf("starting AP ...\r\n"); + errCode = StartHotspot(&config); + printf("StartHotspot: %d\r\n", errCode); + + int timeout = 60; + while (timeout--) { + printf("After %d seconds Ap will turn off!\r\n", timeout); + osDelay(100); + } + + printf("stop AP ...\r\n"); + StopHotspot(); + printf("stop AP ...\r\n"); +} + +static void WifiHotspotDemo(void) +{ + osThreadAttr_t attr; + + attr.name = "WifiHotspotTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(WifiHotspotTask, NULL, &attr) == NULL) { + printf("[WifiHotspotDemo] Falied to create WifiHotspotTask!\n"); + } +} + +APP_FEATURE_INIT(WifiHotspotDemo); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..df787f08714866a65f1d71e2893ab90dafcbe2a2 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/BUILD.gn" @@ -0,0 +1,40 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +static_library("net_demo") { + # uncomment one of following line, to enable one test: + sources = ["tcp_client_test.c"] + + sources += ["demo_entry_cmsis.c", "wifi_connecter.c"] + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/Makefile" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/Makefile" new file mode 100755 index 0000000000000000000000000000000000000000..849287a8dd2f060180fc91640c4c6f812547417b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/Makefile" @@ -0,0 +1,48 @@ +CC := gcc +CFLAGS := -Wall + +COMMON_SRCS := demo_entry_posix.c + +TCP_CLIENT_SRCS := tcp_client_test.c +TCP_SERVER_SRCS := tcp_server_test.c +UDP_CLIENT_SRCS := udp_client_test.c +UDP_SERVER_SRCS := udp_server_test.c + +TCP_CLIENT_TARGET := tcp_client_test +TCP_SERVER_TARGET := tcp_server_test +UDP_CLIENT_TARGET := udp_client_test +UDP_SERVER_TARGET := udp_server_test + +########################################################################################################### + +COMMON_OBJS := $(addsuffix .o, $(notdir $(basename $(COMMON_SRCS)))) +TCP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_CLIENT_SRCS)))) +TCP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_SERVER_SRCS)))) +UDP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_CLIENT_SRCS)))) +UDP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_SERVER_SRCS)))) + +SRCS := $(COMMON_SRCS) $(TCP_CLIENT_SRCS) $(TCP_SERVER_SRCS) $(UDP_CLIENT_SRCS) $(UDP_SERVER_SRCS) +OBJS := $(addsuffix .o, $(notdir $(basename $(SRCS)))) + +TARGETS := $(TCP_CLIENT_TARGET) $(TCP_SERVER_TARGET) $(UDP_CLIENT_TARGET) $(UDP_SERVER_TARGET) + +########################################################################################################### + +all: $(TARGETS) + +$(TCP_CLIENT_TARGET): $(TCP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(TCP_SERVER_TARGET): $(TCP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_CLIENT_TARGET): $(UDP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_SERVER_TARGET): $(UDP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +clean: + rm $(OBJS) $(TARGETS) || echo + +.PHONY: clean all diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..e532930079e83a8903717ada0ec3684391014794 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/README.md" @@ -0,0 +1,201 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--网络编程(tcpclient) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## netcat简介 + +### netcat 是什么? + +netcat是一个非常强大的网络实用工具,可以用它来调试TCP/UDP应用程序; + +### netcat 如何安装? + +Linux上可以使用发行版的包管理器安装,例如Debian/Ubuntu上: + +* `sudo apt-get install netcat` + +Windows上,MobaXterm工具上也可以用 `apt-get install netcat` 安装; + +### netcat 如何使用? + +开始之前,先简单介绍一下 netcat 的几种用法: + +1. TCP服务端模式: `netcat -l 5678` ,会启动一个TCP服务器,监听`5678`端口,你可以换成其他端口; +2. TCP客户端模式: `netcat localhost 5678`, `localhost`是目标主机参数,可以换成其他你想要连接的主机(主机名、IP地址、域名都可以),`5678`是端口; + * 你如果在同一台机器的两个终端中分别执行上述两条命令,它们两者之间就会建立连接一条TCP连接,此时你在其中一个终端上输入字符,敲回车就会发送到另一个终端中; +3. UDP服务端模式: `netcat -u -l 6789`, 没错,只需要加一个`-u`参数,就可以启动一个UDP服务端; +4. UDP客户端模式: `netcat -u localhost 6789`, + * 类似的,在同一台机器的两个终端中分别执行上述两条命令,他们两者之间也可以收发消息,只不过是UDP报文; + + + + +## LwIP简介 + +### LwIP是什么? + +> A Lightweight TCP/IP stack +> 一个轻量级的TCP/IP协议栈 + +详细介绍请参考LwIP项目官网:https://savannah.nongnu.org/projects/lwip/ + +### LwIP在openharmony上的应用情况 + +目前,openharmony源码树有两份LwIP: + +1. third_party/lwip + * 源码形式编译 + * 供liteos-a内核使用 + * 还有一部分代码在kernel/liteos_a中,一起编译 +2. vendor/hisi/hi3861/hi3861/third_party/lwip_sack + * hi3861-sdk的一部分 + * 静态库形式编译 + * 不可修改配置 + * 可以查看当前配置(vend + + + +## 下载源码 + +建议将本教程的源码下载到鸿蒙源码树的顶层目录,即和`applications`、`build`等目录平级的地方: + +* 执行命令`git clone https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development.git` + + + +## 文件说明 + +文件: + +| 文件名 | 说明 | +| ------------------ | ----------------------------------------------------------- | +| BUILD.gn | 鸿蒙构建脚本,支持Hi3861、Hi3518、Hi3516开发板 | +| demo_entry_cmsis.c | 鸿蒙liteos-m程序入口,支持Hi3861 | +| demo_entry_posix.c | 鸿蒙liteos-a和Unix系统程序入口,Hi3516、Hi3518、PC | +| Makefile | Unix系统构建脚本,支持Linux/Mac OS | +| net_common.h | 系统网络接口头文件 | +| net_demo.h | demo脚手架头文件 | +| net_params.h | 网络参数,包括WiFi热点信息,服务器IP、端口信息 | +| tcp_client_test.c | TCP客户端 | +| tcp_server_test.c | TCP服务端 | +| udp_client_test.c | UDP客户端 | +| udp_server_test.c | UDP服务端 | +| wifi_connecter.c | 鸿蒙WiFi STA模式API的封装实现文件,比鸿蒙原始接口更容易使用 | +| wifi_connecter.h | 鸿蒙WiFi STA模式API的封装头文件,比鸿蒙原始接口更容易使用 | + + + +## Linux主机实验指南 + +### 编译测试程序 + +使用如下命令进行编译: + +1. `make` 编译测试程序,该命令会生成4个可执行文件和几个.o文件 +2. `make clean`删除可执行程序和.o文件 + +### 运行测试程序 + +Linux系统可以在同一台机器上,使用多个终端进行测试; + +* TCP客户端测试: + 1. 在一个终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 在另一个终端中启动TCP客户端测试程序:`./tcp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现TCP客户端测试程序发来的:`Hello`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* TCP服务端测试: + 1. 在一个终端中启动TCP服务端测试程序:`./tcp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个TCP客户端,并尝试连接测试程序:`netcat 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是TCP服务端测试程序发送回来的,同时终端上会有相关打印; +* UDP客户端测试: + 1. 在一个终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 2. 在另一个终端中启动UDP客户端测试程序:`./udp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* UDP服务端测试: + 1. 在一个终端中启动UDP服务端测试程序:`./udp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个UDP客户端,并尝试连接测试程序:`netcat -u 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时终端上会有相关打印; + + + +## Hi3861开发板实验指南 + +### 准备网络环境 + +在Hi3861开发板上运行上述四个测试程序之前,需要先准备网络环境: + +1. 准备一个无线路由器, +2. 将Linux系统的PC连接到这个无线路由器, + * 如果是虚拟机运行的Linux系统,需要通过网线连接路由器,并且将虚拟机网口设置为“桥接网卡”,确保**能够从路由器分到IP地址**(这一点非常重要,因为默认是NAT模式,只能通过虚拟机访问外部环境,外部环境无法通过网络访问虚拟机); + +### 修改网络参数 + +在Hi3861开发板上运行上述四个测试程序之前,需要根据你的无线路由、Linux系统IP修改`net_params.h`文件的相关代码: + +* PARAM_HOTSPOT_SSID 修改为你的热点名称 +* PARAM_HOTSPOT_PSK 修改为你的热点密码; +* PARAM_SERVER_ADDR 修改为你的Linux主机IP地址; + +### 编译和烧录测试程序 + +在Hi3861开发板上运行上述四个测试程序,需要分别编译、烧录程序; + +1. 需要修改`BUILD.gn`代码,取消你想要执行的测试程序的注释: + * 编译TCP客户端测试程序,取消 `sources = ["tcp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译TCP服务端测试程序,取消 `sources = ["tcp_server_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP客户端测试程序,取消 `sources = ["udp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP服务端测试程序,取消 `sources = ["udp_server_test.c"]` 的注释,保留其余三行的`sources`注释; +2. 确认你已经修改了hi3861开发板的编译配置文件`build/lite/product/wifiiot.json`: + * `"//applications/sample/wifi-iot/app"`替换为:`"//HarmonyOS-IoT-Application-Development:app"` +3. 使用`python build.py wifiiot`进行编译; +4. 使用DevEco Device Tool或者HiBurn将二进制程序烧录到Hi3861开发板上; +5. 烧录成功后暂时不要复位程序; + + + +### 运行测试程序 + +Hi3861开发板上运行测试程序的操作流程和Linux上大体相同,只是Linux终端执行测试程序变成了——开发板复位后自动运行; + +* TCP客户端测试: + 1. 在Linux终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的TCP服务端; + 3. 在Linux终端中应该会出现开发板上TCP客户端通过发来的`Hello`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* TCP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["tcp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动TCP服务端,并监听`5678`端口; + * 这里需要从串口日志上查看开发板的IP地址,下一步操作需要用到 + 3. 在Linux终端中使用netcat启动一个TCP客户端,并尝试连接到开发板:`netcat board_ip 5678`,其中`board_ip`是开发板的IP地址; + 4. 在Linux终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是开发板上TCP服务端序发送回来的,同时开发板的串口会有相关打印; +* UDP客户端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_client_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 在Linux终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 3. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的UDP服务端; + 4. 在Linux终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* UDP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动UDP服务端,并监听`5678`端口; + 3. 在Linux终端中使用netcat启动一个UDP客户端,并尝试连接到开发板:`netcat -u 127.0.0.1 5678`; + 4. 在Linux终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时开发板的串口会有相关打印; + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_cmsis.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_cmsis.c" new file mode 100755 index 0000000000000000000000000000000000000000..3e10d0d0ac8b24900a2719ad372eedf258224f93 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_cmsis.c" @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#include "net_demo.h" +#include "net_params.h" +#include "wifi_connecter.h" + +static void NetDemoTask(void *arg) +{ + (void)arg; + WifiDeviceConfig config = {0}; + + // 准备AP的配置参数 + strcpy(config.ssid, PARAM_HOTSPOT_SSID); + strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK); + config.securityType = PARAM_HOTSPOT_TYPE; + + osDelay(10); + + int netId = ConnectToHotspot(&config); + + int timeout = 10; + while (timeout--) { + printf("After %d seconds, I will start %s test!\r\n", timeout, GetNetDemoName()); + osDelay(100); + } + + NetDemoTest(PARAM_SERVER_PORT, PARAM_SERVER_ADDR); + + printf("disconnect to AP ...\r\n"); + DisconnectWithHotspot(netId); + printf("disconnect to AP done!\r\n"); +} + +static void NetDemoEntry(void) +{ + osThreadAttr_t attr; + + attr.name = "NetDemoTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(NetDemoTask, NULL, &attr) == NULL) { + printf("[NetDemoEntry] Falied to create NetDemoTask!\n"); + } +} + +SYS_RUN(NetDemoEntry); + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_posix.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_posix.c" new file mode 100755 index 0000000000000000000000000000000000000000..3f6d197f1e208e7f3b8ffacb1c7fa38f5b5fdfcb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/demo_entry_posix.c" @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "net_demo.h" +#include "net_params.h" + +int main(int argc, char* argv[]) +{ + printf("Usage: %s [port] [host]\n", argv[0]); + + short port = argc > 1 ? atoi(argv[1]) : PARAM_SERVER_PORT; + char* host = argc > 2 ? argv[2] : PARAM_SERVER_ADDR; + + NetDemoTest(port, host); + return 0; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_common.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_common.h" new file mode 100755 index 0000000000000000000000000000000000000000..54cded81c6dc7cbdd9d4b9bbbeab32ad9027b0bc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_common.h" @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_COMMON_H +#define NET_COMMON_H + +// __arm__ and __aarch64__ for OpenHarmony with liteos-a kernel, __i386__ and __x86_64__ for Unix like OS +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#define HAVE_BSD_SOCKET 1 +#else +#define HAVE_BSD_SOCKET 0 +#endif + +#if defined(__riscv) // for wifiiot(OpenHarmony on Hi3861 with liteos-m kernel) +#define HAVE_LWIP_SOCKET 1 +#else +#define HAVE_LWIP_SOCKET 0 +#endif + +#if HAVE_BSD_SOCKET +#include // for AF_INET SOCK_STREAM +#include // for socket +#include // for sockaddr_in +#include // for inet_pton +#elif HAVE_LWIP_SOCKET +#include "lwip/sockets.h" +#ifndef close +#define close(fd) lwip_close(fd) +#endif +#else +#error "Unknow platform!" +#endif + +#endif // NET_COMMON_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_demo.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_demo.h" new file mode 100755 index 0000000000000000000000000000000000000000..6259ded29d8bd8fda097d14a3aa081e7c33eeed1 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_demo.h" @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_DEMO_COMMON_H +#define NET_DEMO_COMMON_H + +#include + +void NetDemoTest(unsigned short port, const char* host); + +const char* GetNetDemoName(void); + +#define IMPL_GET_NET_DEMO_NAME(testFunc) \ + const char* GetNetDemoName() { \ + static const char* demoName = #testFunc; \ + return demoName; \ + } + +#define CLIENT_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will connect to %s:%d\r\n", host, port); \ + testFunc(host, port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#define SERVER_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will listen on :%d\r\n", port); \ + testFunc(port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#endif // NET_DEMO_COMMON_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_params.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_params.h" new file mode 100755 index 0000000000000000000000000000000000000000..5aea9837afc3afc0a504b5d4097ed120e3136682 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/net_params.h" @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_PARAMS_H +#define NET_PARAMS_H + +#ifndef PARAM_HOTSPOT_SSID +#define PARAM_HOTSPOT_SSID "ABCD" // your AP SSID +#endif + +#ifndef PARAM_HOTSPOT_PSK +#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK +#endif + +#ifndef PARAM_HOTSPOT_TYPE +#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h +#endif + +#ifndef PARAM_SERVER_ADDR +#define PARAM_SERVER_ADDR "192.168.1.100" // your PC IP address +#endif + +#ifndef PARAM_SERVER_PORT +#define PARAM_SERVER_PORT 5678 +#endif + +#endif // NET_PARAMS_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/tcp_client_test.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/tcp_client_test.c" new file mode 100755 index 0000000000000000000000000000000000000000..9afa1b297c7ec87f275ac9417d206162edb8e155 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/tcp_client_test.c" @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "net_demo.h" +#include "net_common.h" + +static char request[] = "Hello"; +static char response[128] = ""; + +void TcpClientTest(const char* host, unsigned short port) +{ + ssize_t retval = 0; + int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket + + struct sockaddr_in serverAddr = {0}; + serverAddr.sin_family = AF_INET; // AF_INET表示IPv4协议 + serverAddr.sin_port = htons(port); // 端口号,从主机字节序转为网络字节序 + if (inet_pton(AF_INET, host, &serverAddr.sin_addr) <= 0) { // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数) + printf("inet_pton failed!\r\n"); + goto do_cleanup; + } + + // 尝试和目标主机建立连接,连接成功会返回0 ,失败返回 -1 + if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { + printf("connect failed!\r\n"); + goto do_cleanup; + } + printf("connect to server %s success!\r\n", host); + + // 建立连接成功之后,这个TCP socket描述符 —— sockfd 就具有了 “连接状态”,发送、接收 对端都是 connect 参数指定的目标主机和端口 + retval = send(sockfd, request, sizeof(request), 0); + if (retval < 0) { + printf("send request failed!\r\n"); + goto do_cleanup; + } + printf("send request{%s} %ld to server done!\r\n", request, retval); + + retval = recv(sockfd, &response, sizeof(response), 0); + if (retval <= 0) { + printf("send response from server failed or done, %ld!\r\n", retval); + goto do_cleanup; + } + response[retval] = '\0'; + printf("recv response{%s} %ld from server done!\r\n", response, retval); + +do_cleanup: + printf("do_cleanup...\r\n"); + close(sockfd); +} + +CLIENT_TEST_DEMO(TcpClientTest); \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.c" new file mode 100755 index 0000000000000000000000000000000000000000..d400786714c57f13ad2bff726b027e6db4088bb8 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.c" @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wifi_device.h" +#include "cmsis_os2.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static volatile int g_connected = 0; + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static struct netif* g_iface = NULL; + +err_t netifapi_set_hostname(struct netif *netif, char *hostname, u8_t namelen); + +int ConnectToHotspot(WifiDeviceConfig* apConfig) +{ + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = 0; + char* hostname = "hispark"; + ret = netifapi_set_hostname(g_iface, hostname, strlen(hostname)); + printf("netifapi_set_hostname: %d\r\n", ret); + + ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // wait DHCP server give me IP +#if 1 + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); +#else + // 下面这种方式也可以打印 IP、网关、子网掩码信息 + ip4_addr_t ip = {0}; + ip4_addr_t netmask = {0}; + ip4_addr_t gw = {0}; + ret = netifapi_netif_get_addr(g_iface, &ip, &netmask, &gw); + if (ret == ERR_OK) { + printf("ip = %s\r\n", ip4addr_ntoa(&ip)); + printf("netmask = %s\r\n", ip4addr_ntoa(&netmask)); + printf("gw = %s\r\n", ip4addr_ntoa(&gw)); + } + printf("netifapi_netif_get_addr: %d\r\n", ret); +#endif + } + return netId; +} + +void DisconnectWithHotspot(int netId) +{ + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(netId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.h" new file mode 100755 index 0000000000000000000000000000000000000000..cbd4d01ed9adb0b0df58ec2891694c3f212f263b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/21_tcpclient/wifi_connecter.h" @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WIFI_CONNECTER_H +#define WIFI_CONNECTER_H + +#include "wifi_device.h" + +int ConnectToHotspot(WifiDeviceConfig* apConfig); + +void DisconnectWithHotspot(int netId); + +#endif // WIFI_CONNECTER_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..d38996ad84ecaeab535e44e200ea65ff4c501b7f --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/BUILD.gn" @@ -0,0 +1,39 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("net_demo") { + # uncomment one of following line, to enable one test: + sources = ["tcp_server_test.c"] + + sources += ["demo_entry_cmsis.c", "wifi_connecter.c"] + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/Makefile" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/Makefile" new file mode 100755 index 0000000000000000000000000000000000000000..849287a8dd2f060180fc91640c4c6f812547417b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/Makefile" @@ -0,0 +1,48 @@ +CC := gcc +CFLAGS := -Wall + +COMMON_SRCS := demo_entry_posix.c + +TCP_CLIENT_SRCS := tcp_client_test.c +TCP_SERVER_SRCS := tcp_server_test.c +UDP_CLIENT_SRCS := udp_client_test.c +UDP_SERVER_SRCS := udp_server_test.c + +TCP_CLIENT_TARGET := tcp_client_test +TCP_SERVER_TARGET := tcp_server_test +UDP_CLIENT_TARGET := udp_client_test +UDP_SERVER_TARGET := udp_server_test + +########################################################################################################### + +COMMON_OBJS := $(addsuffix .o, $(notdir $(basename $(COMMON_SRCS)))) +TCP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_CLIENT_SRCS)))) +TCP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_SERVER_SRCS)))) +UDP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_CLIENT_SRCS)))) +UDP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_SERVER_SRCS)))) + +SRCS := $(COMMON_SRCS) $(TCP_CLIENT_SRCS) $(TCP_SERVER_SRCS) $(UDP_CLIENT_SRCS) $(UDP_SERVER_SRCS) +OBJS := $(addsuffix .o, $(notdir $(basename $(SRCS)))) + +TARGETS := $(TCP_CLIENT_TARGET) $(TCP_SERVER_TARGET) $(UDP_CLIENT_TARGET) $(UDP_SERVER_TARGET) + +########################################################################################################### + +all: $(TARGETS) + +$(TCP_CLIENT_TARGET): $(TCP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(TCP_SERVER_TARGET): $(TCP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_CLIENT_TARGET): $(UDP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_SERVER_TARGET): $(UDP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +clean: + rm $(OBJS) $(TARGETS) || echo + +.PHONY: clean all diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..1b38abde5c8052e772e066604619cb1b4df3b296 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/README.md" @@ -0,0 +1,201 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--网络编程(tcpserver) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## netcat简介 + +### netcat 是什么? + +netcat是一个非常强大的网络实用工具,可以用它来调试TCP/UDP应用程序; + +### netcat 如何安装? + +Linux上可以使用发行版的包管理器安装,例如Debian/Ubuntu上: + +* `sudo apt-get install netcat` + +Windows上,MobaXterm工具上也可以用 `apt-get install netcat` 安装; + +### netcat 如何使用? + +开始之前,先简单介绍一下 netcat 的几种用法: + +1. TCP服务端模式: `netcat -l 5678` ,会启动一个TCP服务器,监听`5678`端口,你可以换成其他端口; +2. TCP客户端模式: `netcat localhost 5678`, `localhost`是目标主机参数,可以换成其他你想要连接的主机(主机名、IP地址、域名都可以),`5678`是端口; + * 你如果在同一台机器的两个终端中分别执行上述两条命令,它们两者之间就会建立连接一条TCP连接,此时你在其中一个终端上输入字符,敲回车就会发送到另一个终端中; +3. UDP服务端模式: `netcat -u -l 6789`, 没错,只需要加一个`-u`参数,就可以启动一个UDP服务端; +4. UDP客户端模式: `netcat -u localhost 6789`, + * 类似的,在同一台机器的两个终端中分别执行上述两条命令,他们两者之间也可以收发消息,只不过是UDP报文; + + + + +## LwIP简介 + +### LwIP是什么? + +> A Lightweight TCP/IP stack +> 一个轻量级的TCP/IP协议栈 + +详细介绍请参考LwIP项目官网:https://savannah.nongnu.org/projects/lwip/ + +### LwIP在openharmony上的应用情况 + +目前,openharmony源码树有两份LwIP: + +1. third_party/lwip + * 源码形式编译 + * 供liteos-a内核使用 + * 还有一部分代码在kernel/liteos_a中,一起编译 +2. vendor/hisi/hi3861/hi3861/third_party/lwip_sack + * hi3861-sdk的一部分 + * 静态库形式编译 + * 不可修改配置 + * 可以查看当前配置(vend + + + +## 下载源码 + +建议将本教程的源码下载到鸿蒙源码树的顶层目录,即和`applications`、`build`等目录平级的地方: + +* 执行命令`git clone https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development.git` + + + +## 文件说明 + +文件: + +| 文件名 | 说明 | +| ------------------ | ----------------------------------------------------------- | +| BUILD.gn | 鸿蒙构建脚本,支持Hi3861、Hi3518、Hi3516开发板 | +| demo_entry_cmsis.c | 鸿蒙liteos-m程序入口,支持Hi3861 | +| demo_entry_posix.c | 鸿蒙liteos-a和Unix系统程序入口,Hi3516、Hi3518、PC | +| Makefile | Unix系统构建脚本,支持Linux/Mac OS | +| net_common.h | 系统网络接口头文件 | +| net_demo.h | demo脚手架头文件 | +| net_params.h | 网络参数,包括WiFi热点信息,服务器IP、端口信息 | +| tcp_client_test.c | TCP客户端 | +| tcp_server_test.c | TCP服务端 | +| udp_client_test.c | UDP客户端 | +| udp_server_test.c | UDP服务端 | +| wifi_connecter.c | 鸿蒙WiFi STA模式API的封装实现文件,比鸿蒙原始接口更容易使用 | +| wifi_connecter.h | 鸿蒙WiFi STA模式API的封装头文件,比鸿蒙原始接口更容易使用 | + + + +## Linux主机实验指南 + +### 编译测试程序 + +使用如下命令进行编译: + +1. `make` 编译测试程序,该命令会生成4个可执行文件和几个.o文件 +2. `make clean`删除可执行程序和.o文件 + +### 运行测试程序 + +Linux系统可以在同一台机器上,使用多个终端进行测试; + +* TCP客户端测试: + 1. 在一个终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 在另一个终端中启动TCP客户端测试程序:`./tcp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现TCP客户端测试程序发来的:`Hello`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* TCP服务端测试: + 1. 在一个终端中启动TCP服务端测试程序:`./tcp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个TCP客户端,并尝试连接测试程序:`netcat 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是TCP服务端测试程序发送回来的,同时终端上会有相关打印; +* UDP客户端测试: + 1. 在一个终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 2. 在另一个终端中启动UDP客户端测试程序:`./udp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* UDP服务端测试: + 1. 在一个终端中启动UDP服务端测试程序:`./udp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个UDP客户端,并尝试连接测试程序:`netcat -u 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时终端上会有相关打印; + + + +## Hi3861开发板实验指南 + +### 准备网络环境 + +在Hi3861开发板上运行上述四个测试程序之前,需要先准备网络环境: + +1. 准备一个无线路由器, +2. 将Linux系统的PC连接到这个无线路由器, + * 如果是虚拟机运行的Linux系统,需要通过网线连接路由器,并且将虚拟机网口设置为“桥接网卡”,确保**能够从路由器分到IP地址**(这一点非常重要,因为默认是NAT模式,只能通过虚拟机访问外部环境,外部环境无法通过网络访问虚拟机); + +### 修改网络参数 + +在Hi3861开发板上运行上述四个测试程序之前,需要根据你的无线路由、Linux系统IP修改`net_params.h`文件的相关代码: + +* PARAM_HOTSPOT_SSID 修改为你的热点名称 +* PARAM_HOTSPOT_PSK 修改为你的热点密码; +* PARAM_SERVER_ADDR 修改为你的Linux主机IP地址; + +### 编译和烧录测试程序 + +在Hi3861开发板上运行上述四个测试程序,需要分别编译、烧录程序; + +1. 需要修改`BUILD.gn`代码,取消你想要执行的测试程序的注释: + * 编译TCP客户端测试程序,取消 `sources = ["tcp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译TCP服务端测试程序,取消 `sources = ["tcp_server_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP客户端测试程序,取消 `sources = ["udp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP服务端测试程序,取消 `sources = ["udp_server_test.c"]` 的注释,保留其余三行的`sources`注释; +2. 确认你已经修改了hi3861开发板的编译配置文件`build/lite/product/wifiiot.json`: + * `"//applications/sample/wifi-iot/app"`替换为:`"//HarmonyOS-IoT-Application-Development:app"` +3. 使用`python build.py wifiiot`进行编译; +4. 使用DevEco Device Tool或者HiBurn将二进制程序烧录到Hi3861开发板上; +5. 烧录成功后暂时不要复位程序; + + + +### 运行测试程序 + +Hi3861开发板上运行测试程序的操作流程和Linux上大体相同,只是Linux终端执行测试程序变成了——开发板复位后自动运行; + +* TCP客户端测试: + 1. 在Linux终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的TCP服务端; + 3. 在Linux终端中应该会出现开发板上TCP客户端通过发来的`Hello`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* TCP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["tcp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动TCP服务端,并监听`5678`端口; + * 这里需要从串口日志上查看开发板的IP地址,下一步操作需要用到 + 3. 在Linux终端中使用netcat启动一个TCP客户端,并尝试连接到开发板:`netcat board_ip 5678`,其中`board_ip`是开发板的IP地址; + 4. 在Linux终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是开发板上TCP服务端序发送回来的,同时开发板的串口会有相关打印; +* UDP客户端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_client_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 在Linux终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 3. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的UDP服务端; + 4. 在Linux终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* UDP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动UDP服务端,并监听`5678`端口; + 3. 在Linux终端中使用netcat启动一个UDP客户端,并尝试连接到开发板:`netcat -u 127.0.0.1 5678`; + 4. 在Linux终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时开发板的串口会有相关打印; + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_cmsis.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_cmsis.c" new file mode 100755 index 0000000000000000000000000000000000000000..3e10d0d0ac8b24900a2719ad372eedf258224f93 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_cmsis.c" @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#include "net_demo.h" +#include "net_params.h" +#include "wifi_connecter.h" + +static void NetDemoTask(void *arg) +{ + (void)arg; + WifiDeviceConfig config = {0}; + + // 准备AP的配置参数 + strcpy(config.ssid, PARAM_HOTSPOT_SSID); + strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK); + config.securityType = PARAM_HOTSPOT_TYPE; + + osDelay(10); + + int netId = ConnectToHotspot(&config); + + int timeout = 10; + while (timeout--) { + printf("After %d seconds, I will start %s test!\r\n", timeout, GetNetDemoName()); + osDelay(100); + } + + NetDemoTest(PARAM_SERVER_PORT, PARAM_SERVER_ADDR); + + printf("disconnect to AP ...\r\n"); + DisconnectWithHotspot(netId); + printf("disconnect to AP done!\r\n"); +} + +static void NetDemoEntry(void) +{ + osThreadAttr_t attr; + + attr.name = "NetDemoTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(NetDemoTask, NULL, &attr) == NULL) { + printf("[NetDemoEntry] Falied to create NetDemoTask!\n"); + } +} + +SYS_RUN(NetDemoEntry); + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_posix.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_posix.c" new file mode 100755 index 0000000000000000000000000000000000000000..3f6d197f1e208e7f3b8ffacb1c7fa38f5b5fdfcb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/demo_entry_posix.c" @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "net_demo.h" +#include "net_params.h" + +int main(int argc, char* argv[]) +{ + printf("Usage: %s [port] [host]\n", argv[0]); + + short port = argc > 1 ? atoi(argv[1]) : PARAM_SERVER_PORT; + char* host = argc > 2 ? argv[2] : PARAM_SERVER_ADDR; + + NetDemoTest(port, host); + return 0; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_common.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_common.h" new file mode 100755 index 0000000000000000000000000000000000000000..54cded81c6dc7cbdd9d4b9bbbeab32ad9027b0bc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_common.h" @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_COMMON_H +#define NET_COMMON_H + +// __arm__ and __aarch64__ for OpenHarmony with liteos-a kernel, __i386__ and __x86_64__ for Unix like OS +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#define HAVE_BSD_SOCKET 1 +#else +#define HAVE_BSD_SOCKET 0 +#endif + +#if defined(__riscv) // for wifiiot(OpenHarmony on Hi3861 with liteos-m kernel) +#define HAVE_LWIP_SOCKET 1 +#else +#define HAVE_LWIP_SOCKET 0 +#endif + +#if HAVE_BSD_SOCKET +#include // for AF_INET SOCK_STREAM +#include // for socket +#include // for sockaddr_in +#include // for inet_pton +#elif HAVE_LWIP_SOCKET +#include "lwip/sockets.h" +#ifndef close +#define close(fd) lwip_close(fd) +#endif +#else +#error "Unknow platform!" +#endif + +#endif // NET_COMMON_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_demo.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_demo.h" new file mode 100755 index 0000000000000000000000000000000000000000..6259ded29d8bd8fda097d14a3aa081e7c33eeed1 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_demo.h" @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_DEMO_COMMON_H +#define NET_DEMO_COMMON_H + +#include + +void NetDemoTest(unsigned short port, const char* host); + +const char* GetNetDemoName(void); + +#define IMPL_GET_NET_DEMO_NAME(testFunc) \ + const char* GetNetDemoName() { \ + static const char* demoName = #testFunc; \ + return demoName; \ + } + +#define CLIENT_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will connect to %s:%d\r\n", host, port); \ + testFunc(host, port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#define SERVER_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will listen on :%d\r\n", port); \ + testFunc(port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#endif // NET_DEMO_COMMON_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_params.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_params.h" new file mode 100755 index 0000000000000000000000000000000000000000..5aea9837afc3afc0a504b5d4097ed120e3136682 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/net_params.h" @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_PARAMS_H +#define NET_PARAMS_H + +#ifndef PARAM_HOTSPOT_SSID +#define PARAM_HOTSPOT_SSID "ABCD" // your AP SSID +#endif + +#ifndef PARAM_HOTSPOT_PSK +#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK +#endif + +#ifndef PARAM_HOTSPOT_TYPE +#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h +#endif + +#ifndef PARAM_SERVER_ADDR +#define PARAM_SERVER_ADDR "192.168.1.100" // your PC IP address +#endif + +#ifndef PARAM_SERVER_PORT +#define PARAM_SERVER_PORT 5678 +#endif + +#endif // NET_PARAMS_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/tcp_server_test.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/tcp_server_test.c" new file mode 100755 index 0000000000000000000000000000000000000000..36623bf253b700469a50e74c389e56d1d5cde72d --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/tcp_server_test.c" @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "net_demo.h" +#include "net_common.h" + +static char request[128] = ""; +void TcpServerTest(unsigned short port) +{ + ssize_t retval = 0; + int backlog = 1; + int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket + int connfd = -1; + + struct sockaddr_in clientAddr = {0}; + socklen_t clientAddrLen = sizeof(clientAddr); + struct sockaddr_in serverAddr = {0}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); // 端口号,从主机字节序转为网络字节序 + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // 允许任意主机接入, 0.0.0.0 + + retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); // 绑定端口 + if (retval < 0) { + printf("bind failed, %ld!\r\n", retval); + goto do_cleanup; + } + printf("bind to port %d success!\r\n", port); + + retval = listen(sockfd, backlog); // 开始监听 + if (retval < 0) { + printf("listen failed!\r\n"); + goto do_cleanup; + } + printf("listen with %d backlog success!\r\n", backlog); + + // 接受客户端连接,成功会返回一个表示连接的 socket , clientAddr 参数将会携带客户端主机和端口信息 ;失败返回 -1 + // 此后的 收、发 都在 表示连接的 socket 上进行;之后 sockfd 依然可以继续接受其他客户端的连接, + // UNIX系统上经典的并发模型是“每个连接一个进程”——创建子进程处理连接,父进程继续接受其他客户端的连接 + // 鸿蒙liteos-a内核之上,可以使用UNIX的“每个连接一个进程”的并发模型 + // liteos-m内核之上,可以使用“每个连接一个线程”的并发模型 + connfd = accept(sockfd, (struct sockaddr *)&clientAddr, &clientAddrLen); + if (connfd < 0) { + printf("accept failed, %d, %d\r\n", connfd, errno); + goto do_cleanup; + } + printf("accept success, connfd = %d!\r\n", connfd); + printf("client addr info: host = %s, port = %d\r\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); + + // 后续 收、发 都在 表示连接的 socket 上进行; + retval = recv(connfd, request, sizeof(request), 0); + if (retval < 0) { + printf("recv request failed, %ld!\r\n", retval); + goto do_disconnect; + } + printf("recv request{%s} from client done!\r\n", request); + + retval = send(connfd, request, strlen(request), 0); + if (retval <= 0) { + printf("send response failed, %ld!\r\n", retval); + goto do_disconnect; + } + printf("send response{%s} to client done!\r\n", request); + +do_disconnect: + sleep(1); + close(connfd); + sleep(1); // for debug + +do_cleanup: + printf("do_cleanup...\r\n"); + + close(sockfd); +} + +SERVER_TEST_DEMO(TcpServerTest); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.c" new file mode 100755 index 0000000000000000000000000000000000000000..d400786714c57f13ad2bff726b027e6db4088bb8 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.c" @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wifi_device.h" +#include "cmsis_os2.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static volatile int g_connected = 0; + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static struct netif* g_iface = NULL; + +err_t netifapi_set_hostname(struct netif *netif, char *hostname, u8_t namelen); + +int ConnectToHotspot(WifiDeviceConfig* apConfig) +{ + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = 0; + char* hostname = "hispark"; + ret = netifapi_set_hostname(g_iface, hostname, strlen(hostname)); + printf("netifapi_set_hostname: %d\r\n", ret); + + ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // wait DHCP server give me IP +#if 1 + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); +#else + // 下面这种方式也可以打印 IP、网关、子网掩码信息 + ip4_addr_t ip = {0}; + ip4_addr_t netmask = {0}; + ip4_addr_t gw = {0}; + ret = netifapi_netif_get_addr(g_iface, &ip, &netmask, &gw); + if (ret == ERR_OK) { + printf("ip = %s\r\n", ip4addr_ntoa(&ip)); + printf("netmask = %s\r\n", ip4addr_ntoa(&netmask)); + printf("gw = %s\r\n", ip4addr_ntoa(&gw)); + } + printf("netifapi_netif_get_addr: %d\r\n", ret); +#endif + } + return netId; +} + +void DisconnectWithHotspot(int netId) +{ + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(netId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.h" new file mode 100755 index 0000000000000000000000000000000000000000..cbd4d01ed9adb0b0df58ec2891694c3f212f263b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/22_tcpserver/wifi_connecter.h" @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WIFI_CONNECTER_H +#define WIFI_CONNECTER_H + +#include "wifi_device.h" + +int ConnectToHotspot(WifiDeviceConfig* apConfig); + +void DisconnectWithHotspot(int netId); + +#endif // WIFI_CONNECTER_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..0ba21722cfe30f5036e50e1239018bae1eb8a018 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/BUILD.gn" @@ -0,0 +1,39 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("net_demo") { + # uncomment one of following line, to enable one test: + sources = ["udp_client_test.c"] + + sources += ["demo_entry_cmsis.c", "wifi_connecter.c"] + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/Makefile" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/Makefile" new file mode 100755 index 0000000000000000000000000000000000000000..849287a8dd2f060180fc91640c4c6f812547417b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/Makefile" @@ -0,0 +1,48 @@ +CC := gcc +CFLAGS := -Wall + +COMMON_SRCS := demo_entry_posix.c + +TCP_CLIENT_SRCS := tcp_client_test.c +TCP_SERVER_SRCS := tcp_server_test.c +UDP_CLIENT_SRCS := udp_client_test.c +UDP_SERVER_SRCS := udp_server_test.c + +TCP_CLIENT_TARGET := tcp_client_test +TCP_SERVER_TARGET := tcp_server_test +UDP_CLIENT_TARGET := udp_client_test +UDP_SERVER_TARGET := udp_server_test + +########################################################################################################### + +COMMON_OBJS := $(addsuffix .o, $(notdir $(basename $(COMMON_SRCS)))) +TCP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_CLIENT_SRCS)))) +TCP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_SERVER_SRCS)))) +UDP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_CLIENT_SRCS)))) +UDP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_SERVER_SRCS)))) + +SRCS := $(COMMON_SRCS) $(TCP_CLIENT_SRCS) $(TCP_SERVER_SRCS) $(UDP_CLIENT_SRCS) $(UDP_SERVER_SRCS) +OBJS := $(addsuffix .o, $(notdir $(basename $(SRCS)))) + +TARGETS := $(TCP_CLIENT_TARGET) $(TCP_SERVER_TARGET) $(UDP_CLIENT_TARGET) $(UDP_SERVER_TARGET) + +########################################################################################################### + +all: $(TARGETS) + +$(TCP_CLIENT_TARGET): $(TCP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(TCP_SERVER_TARGET): $(TCP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_CLIENT_TARGET): $(UDP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_SERVER_TARGET): $(UDP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +clean: + rm $(OBJS) $(TARGETS) || echo + +.PHONY: clean all diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..35519ec3ed3d54923fad3c5879e78d717133879b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/README.md" @@ -0,0 +1,201 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--网络编程(udpclient) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## netcat简介 + +### netcat 是什么? + +netcat是一个非常强大的网络实用工具,可以用它来调试TCP/UDP应用程序; + +### netcat 如何安装? + +Linux上可以使用发行版的包管理器安装,例如Debian/Ubuntu上: + +* `sudo apt-get install netcat` + +Windows上,MobaXterm工具上也可以用 `apt-get install netcat` 安装; + +### netcat 如何使用? + +开始之前,先简单介绍一下 netcat 的几种用法: + +1. TCP服务端模式: `netcat -l 5678` ,会启动一个TCP服务器,监听`5678`端口,你可以换成其他端口; +2. TCP客户端模式: `netcat localhost 5678`, `localhost`是目标主机参数,可以换成其他你想要连接的主机(主机名、IP地址、域名都可以),`5678`是端口; + * 你如果在同一台机器的两个终端中分别执行上述两条命令,它们两者之间就会建立连接一条TCP连接,此时你在其中一个终端上输入字符,敲回车就会发送到另一个终端中; +3. UDP服务端模式: `netcat -u -l 6789`, 没错,只需要加一个`-u`参数,就可以启动一个UDP服务端; +4. UDP客户端模式: `netcat -u localhost 6789`, + * 类似的,在同一台机器的两个终端中分别执行上述两条命令,他们两者之间也可以收发消息,只不过是UDP报文; + + + + +## LwIP简介 + +### LwIP是什么? + +> A Lightweight TCP/IP stack +> 一个轻量级的TCP/IP协议栈 + +详细介绍请参考LwIP项目官网:https://savannah.nongnu.org/projects/lwip/ + +### LwIP在openharmony上的应用情况 + +目前,openharmony源码树有两份LwIP: + +1. third_party/lwip + * 源码形式编译 + * 供liteos-a内核使用 + * 还有一部分代码在kernel/liteos_a中,一起编译 +2. vendor/hisi/hi3861/hi3861/third_party/lwip_sack + * hi3861-sdk的一部分 + * 静态库形式编译 + * 不可修改配置 + * 可以查看当前配置(vend + + + +## 下载源码 + +建议将本教程的源码下载到鸿蒙源码树的顶层目录,即和`applications`、`build`等目录平级的地方: + +* 执行命令`git clone https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development.git` + + + +## 文件说明 + +文件: + +| 文件名 | 说明 | +| ------------------ | ----------------------------------------------------------- | +| BUILD.gn | 鸿蒙构建脚本,支持Hi3861、Hi3518、Hi3516开发板 | +| demo_entry_cmsis.c | 鸿蒙liteos-m程序入口,支持Hi3861 | +| demo_entry_posix.c | 鸿蒙liteos-a和Unix系统程序入口,Hi3516、Hi3518、PC | +| Makefile | Unix系统构建脚本,支持Linux/Mac OS | +| net_common.h | 系统网络接口头文件 | +| net_demo.h | demo脚手架头文件 | +| net_params.h | 网络参数,包括WiFi热点信息,服务器IP、端口信息 | +| tcp_client_test.c | TCP客户端 | +| tcp_server_test.c | TCP服务端 | +| udp_client_test.c | UDP客户端 | +| udp_server_test.c | UDP服务端 | +| wifi_connecter.c | 鸿蒙WiFi STA模式API的封装实现文件,比鸿蒙原始接口更容易使用 | +| wifi_connecter.h | 鸿蒙WiFi STA模式API的封装头文件,比鸿蒙原始接口更容易使用 | + + + +## Linux主机实验指南 + +### 编译测试程序 + +使用如下命令进行编译: + +1. `make` 编译测试程序,该命令会生成4个可执行文件和几个.o文件 +2. `make clean`删除可执行程序和.o文件 + +### 运行测试程序 + +Linux系统可以在同一台机器上,使用多个终端进行测试; + +* TCP客户端测试: + 1. 在一个终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 在另一个终端中启动TCP客户端测试程序:`./tcp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现TCP客户端测试程序发来的:`Hello`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* TCP服务端测试: + 1. 在一个终端中启动TCP服务端测试程序:`./tcp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个TCP客户端,并尝试连接测试程序:`netcat 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是TCP服务端测试程序发送回来的,同时终端上会有相关打印; +* UDP客户端测试: + 1. 在一个终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 2. 在另一个终端中启动UDP客户端测试程序:`./udp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* UDP服务端测试: + 1. 在一个终端中启动UDP服务端测试程序:`./udp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个UDP客户端,并尝试连接测试程序:`netcat -u 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时终端上会有相关打印; + + + +## Hi3861开发板实验指南 + +### 准备网络环境 + +在Hi3861开发板上运行上述四个测试程序之前,需要先准备网络环境: + +1. 准备一个无线路由器, +2. 将Linux系统的PC连接到这个无线路由器, + * 如果是虚拟机运行的Linux系统,需要通过网线连接路由器,并且将虚拟机网口设置为“桥接网卡”,确保**能够从路由器分到IP地址**(这一点非常重要,因为默认是NAT模式,只能通过虚拟机访问外部环境,外部环境无法通过网络访问虚拟机); + +### 修改网络参数 + +在Hi3861开发板上运行上述四个测试程序之前,需要根据你的无线路由、Linux系统IP修改`net_params.h`文件的相关代码: + +* PARAM_HOTSPOT_SSID 修改为你的热点名称 +* PARAM_HOTSPOT_PSK 修改为你的热点密码; +* PARAM_SERVER_ADDR 修改为你的Linux主机IP地址; + +### 编译和烧录测试程序 + +在Hi3861开发板上运行上述四个测试程序,需要分别编译、烧录程序; + +1. 需要修改`BUILD.gn`代码,取消你想要执行的测试程序的注释: + * 编译TCP客户端测试程序,取消 `sources = ["tcp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译TCP服务端测试程序,取消 `sources = ["tcp_server_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP客户端测试程序,取消 `sources = ["udp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP服务端测试程序,取消 `sources = ["udp_server_test.c"]` 的注释,保留其余三行的`sources`注释; +2. 确认你已经修改了hi3861开发板的编译配置文件`build/lite/product/wifiiot.json`: + * `"//applications/sample/wifi-iot/app"`替换为:`"//HarmonyOS-IoT-Application-Development:app"` +3. 使用`python build.py wifiiot`进行编译; +4. 使用DevEco Device Tool或者HiBurn将二进制程序烧录到Hi3861开发板上; +5. 烧录成功后暂时不要复位程序; + + + +### 运行测试程序 + +Hi3861开发板上运行测试程序的操作流程和Linux上大体相同,只是Linux终端执行测试程序变成了——开发板复位后自动运行; + +* TCP客户端测试: + 1. 在Linux终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的TCP服务端; + 3. 在Linux终端中应该会出现开发板上TCP客户端通过发来的`Hello`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* TCP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["tcp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动TCP服务端,并监听`5678`端口; + * 这里需要从串口日志上查看开发板的IP地址,下一步操作需要用到 + 3. 在Linux终端中使用netcat启动一个TCP客户端,并尝试连接到开发板:`netcat board_ip 5678`,其中`board_ip`是开发板的IP地址; + 4. 在Linux终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是开发板上TCP服务端序发送回来的,同时开发板的串口会有相关打印; +* UDP客户端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_client_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 在Linux终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 3. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的UDP服务端; + 4. 在Linux终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* UDP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动UDP服务端,并监听`5678`端口; + 3. 在Linux终端中使用netcat启动一个UDP客户端,并尝试连接到开发板:`netcat -u 127.0.0.1 5678`; + 4. 在Linux终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时开发板的串口会有相关打印; + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_cmsis.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_cmsis.c" new file mode 100755 index 0000000000000000000000000000000000000000..3e10d0d0ac8b24900a2719ad372eedf258224f93 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_cmsis.c" @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#include "net_demo.h" +#include "net_params.h" +#include "wifi_connecter.h" + +static void NetDemoTask(void *arg) +{ + (void)arg; + WifiDeviceConfig config = {0}; + + // 准备AP的配置参数 + strcpy(config.ssid, PARAM_HOTSPOT_SSID); + strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK); + config.securityType = PARAM_HOTSPOT_TYPE; + + osDelay(10); + + int netId = ConnectToHotspot(&config); + + int timeout = 10; + while (timeout--) { + printf("After %d seconds, I will start %s test!\r\n", timeout, GetNetDemoName()); + osDelay(100); + } + + NetDemoTest(PARAM_SERVER_PORT, PARAM_SERVER_ADDR); + + printf("disconnect to AP ...\r\n"); + DisconnectWithHotspot(netId); + printf("disconnect to AP done!\r\n"); +} + +static void NetDemoEntry(void) +{ + osThreadAttr_t attr; + + attr.name = "NetDemoTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(NetDemoTask, NULL, &attr) == NULL) { + printf("[NetDemoEntry] Falied to create NetDemoTask!\n"); + } +} + +SYS_RUN(NetDemoEntry); + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_posix.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_posix.c" new file mode 100755 index 0000000000000000000000000000000000000000..3f6d197f1e208e7f3b8ffacb1c7fa38f5b5fdfcb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/demo_entry_posix.c" @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "net_demo.h" +#include "net_params.h" + +int main(int argc, char* argv[]) +{ + printf("Usage: %s [port] [host]\n", argv[0]); + + short port = argc > 1 ? atoi(argv[1]) : PARAM_SERVER_PORT; + char* host = argc > 2 ? argv[2] : PARAM_SERVER_ADDR; + + NetDemoTest(port, host); + return 0; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_common.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_common.h" new file mode 100755 index 0000000000000000000000000000000000000000..54cded81c6dc7cbdd9d4b9bbbeab32ad9027b0bc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_common.h" @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_COMMON_H +#define NET_COMMON_H + +// __arm__ and __aarch64__ for OpenHarmony with liteos-a kernel, __i386__ and __x86_64__ for Unix like OS +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#define HAVE_BSD_SOCKET 1 +#else +#define HAVE_BSD_SOCKET 0 +#endif + +#if defined(__riscv) // for wifiiot(OpenHarmony on Hi3861 with liteos-m kernel) +#define HAVE_LWIP_SOCKET 1 +#else +#define HAVE_LWIP_SOCKET 0 +#endif + +#if HAVE_BSD_SOCKET +#include // for AF_INET SOCK_STREAM +#include // for socket +#include // for sockaddr_in +#include // for inet_pton +#elif HAVE_LWIP_SOCKET +#include "lwip/sockets.h" +#ifndef close +#define close(fd) lwip_close(fd) +#endif +#else +#error "Unknow platform!" +#endif + +#endif // NET_COMMON_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_demo.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_demo.h" new file mode 100755 index 0000000000000000000000000000000000000000..6259ded29d8bd8fda097d14a3aa081e7c33eeed1 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_demo.h" @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_DEMO_COMMON_H +#define NET_DEMO_COMMON_H + +#include + +void NetDemoTest(unsigned short port, const char* host); + +const char* GetNetDemoName(void); + +#define IMPL_GET_NET_DEMO_NAME(testFunc) \ + const char* GetNetDemoName() { \ + static const char* demoName = #testFunc; \ + return demoName; \ + } + +#define CLIENT_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will connect to %s:%d\r\n", host, port); \ + testFunc(host, port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#define SERVER_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will listen on :%d\r\n", port); \ + testFunc(port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#endif // NET_DEMO_COMMON_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_params.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_params.h" new file mode 100755 index 0000000000000000000000000000000000000000..5aea9837afc3afc0a504b5d4097ed120e3136682 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/net_params.h" @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_PARAMS_H +#define NET_PARAMS_H + +#ifndef PARAM_HOTSPOT_SSID +#define PARAM_HOTSPOT_SSID "ABCD" // your AP SSID +#endif + +#ifndef PARAM_HOTSPOT_PSK +#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK +#endif + +#ifndef PARAM_HOTSPOT_TYPE +#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h +#endif + +#ifndef PARAM_SERVER_ADDR +#define PARAM_SERVER_ADDR "192.168.1.100" // your PC IP address +#endif + +#ifndef PARAM_SERVER_PORT +#define PARAM_SERVER_PORT 5678 +#endif + +#endif // NET_PARAMS_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/udp_client_test.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/udp_client_test.c" new file mode 100755 index 0000000000000000000000000000000000000000..c3777b3a4cf831d306c502aae44d6e929bba0148 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/udp_client_test.c" @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include + +#include "net_demo.h" +#include "net_common.h" + +static char request[] = "Hello."; +static char response[128] = ""; + +void UdpClientTest(const char* host, unsigned short port) +{ + ssize_t retval = 0; + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP socket + + struct sockaddr_in toAddr = {0}; + toAddr.sin_family = AF_INET; + toAddr.sin_port = htons(port); // 端口号,从主机字节序转为网络字节序 + if (inet_pton(AF_INET, host, &toAddr.sin_addr) <= 0) { // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数) + printf("inet_pton failed!\r\n"); + goto do_cleanup; + } + + // UDP socket 是 “无连接的” ,因此每次发送都必须先指定目标主机和端口,主机可以是多播地址 + retval = sendto(sockfd, request, sizeof(request), 0, (struct sockaddr *)&toAddr, sizeof(toAddr)); + if (retval < 0) { + printf("sendto failed!\r\n"); + goto do_cleanup; + } + printf("send UDP message {%s} %ld done!\r\n", request, retval); + + struct sockaddr_in fromAddr = {0}; + socklen_t fromLen = sizeof(fromAddr); + + // UDP socket 是 “无连接的” ,因此每次接收时前并不知道消息来自何处,通过 fromAddr 参数可以得到发送方的信息(主机、端口号) + retval = recvfrom(sockfd, &response, sizeof(response), 0, (struct sockaddr *)&fromAddr, &fromLen); + if (retval <= 0) { + printf("recvfrom failed or abort, %ld, %d!\r\n", retval, errno); + goto do_cleanup; + } + response[retval] = '\0'; + printf("recv UDP message {%s} %ld done!\r\n", response, retval); + printf("peer info: ipaddr = %s, port = %d\r\n", inet_ntoa(fromAddr.sin_addr), ntohs(fromAddr.sin_port)); + +do_cleanup: + printf("do_cleanup...\r\n"); + close(sockfd); +} + +CLIENT_TEST_DEMO(UdpClientTest); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.c" new file mode 100755 index 0000000000000000000000000000000000000000..d400786714c57f13ad2bff726b027e6db4088bb8 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.c" @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wifi_device.h" +#include "cmsis_os2.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static volatile int g_connected = 0; + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static struct netif* g_iface = NULL; + +err_t netifapi_set_hostname(struct netif *netif, char *hostname, u8_t namelen); + +int ConnectToHotspot(WifiDeviceConfig* apConfig) +{ + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = 0; + char* hostname = "hispark"; + ret = netifapi_set_hostname(g_iface, hostname, strlen(hostname)); + printf("netifapi_set_hostname: %d\r\n", ret); + + ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // wait DHCP server give me IP +#if 1 + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); +#else + // 下面这种方式也可以打印 IP、网关、子网掩码信息 + ip4_addr_t ip = {0}; + ip4_addr_t netmask = {0}; + ip4_addr_t gw = {0}; + ret = netifapi_netif_get_addr(g_iface, &ip, &netmask, &gw); + if (ret == ERR_OK) { + printf("ip = %s\r\n", ip4addr_ntoa(&ip)); + printf("netmask = %s\r\n", ip4addr_ntoa(&netmask)); + printf("gw = %s\r\n", ip4addr_ntoa(&gw)); + } + printf("netifapi_netif_get_addr: %d\r\n", ret); +#endif + } + return netId; +} + +void DisconnectWithHotspot(int netId) +{ + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(netId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.h" new file mode 100755 index 0000000000000000000000000000000000000000..cbd4d01ed9adb0b0df58ec2891694c3f212f263b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/23_udpclient/wifi_connecter.h" @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WIFI_CONNECTER_H +#define WIFI_CONNECTER_H + +#include "wifi_device.h" + +int ConnectToHotspot(WifiDeviceConfig* apConfig); + +void DisconnectWithHotspot(int netId); + +#endif // WIFI_CONNECTER_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/BUILD.gn" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/BUILD.gn" new file mode 100755 index 0000000000000000000000000000000000000000..535ffa3641d223044dc68c8db39bce6a4d5077ec --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/BUILD.gn" @@ -0,0 +1,39 @@ +# Copyright (c) 2020, HiHope Community. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +static_library("net_demo") { + # uncomment one of following line, to enable one test: + sources = ["udp_server_test.c"] + + sources += ["demo_entry_cmsis.c", "wifi_connecter.c"] + include_dirs = [ + "//utils/native/lite/include", + "//kernel/liteos_m/components/cmsis/2.0", + "//foundation/communication/interfaces/kits/wifi_lite/wifiservice", + "//vendor/hisi/hi3861/hi3861/third_party/lwip_sack/include/", + ] +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/Makefile" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/Makefile" new file mode 100755 index 0000000000000000000000000000000000000000..849287a8dd2f060180fc91640c4c6f812547417b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/Makefile" @@ -0,0 +1,48 @@ +CC := gcc +CFLAGS := -Wall + +COMMON_SRCS := demo_entry_posix.c + +TCP_CLIENT_SRCS := tcp_client_test.c +TCP_SERVER_SRCS := tcp_server_test.c +UDP_CLIENT_SRCS := udp_client_test.c +UDP_SERVER_SRCS := udp_server_test.c + +TCP_CLIENT_TARGET := tcp_client_test +TCP_SERVER_TARGET := tcp_server_test +UDP_CLIENT_TARGET := udp_client_test +UDP_SERVER_TARGET := udp_server_test + +########################################################################################################### + +COMMON_OBJS := $(addsuffix .o, $(notdir $(basename $(COMMON_SRCS)))) +TCP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_CLIENT_SRCS)))) +TCP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(TCP_SERVER_SRCS)))) +UDP_CLIENT_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_CLIENT_SRCS)))) +UDP_SERVER_OBJS := $(addsuffix .o, $(notdir $(basename $(UDP_SERVER_SRCS)))) + +SRCS := $(COMMON_SRCS) $(TCP_CLIENT_SRCS) $(TCP_SERVER_SRCS) $(UDP_CLIENT_SRCS) $(UDP_SERVER_SRCS) +OBJS := $(addsuffix .o, $(notdir $(basename $(SRCS)))) + +TARGETS := $(TCP_CLIENT_TARGET) $(TCP_SERVER_TARGET) $(UDP_CLIENT_TARGET) $(UDP_SERVER_TARGET) + +########################################################################################################### + +all: $(TARGETS) + +$(TCP_CLIENT_TARGET): $(TCP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(TCP_SERVER_TARGET): $(TCP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_CLIENT_TARGET): $(UDP_CLIENT_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +$(UDP_SERVER_TARGET): $(UDP_SERVER_OBJS) $(COMMON_OBJS) + $(CC) $(CCFLAGS) -o $@ $^ + +clean: + rm $(OBJS) $(TARGETS) || echo + +.PHONY: clean all diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/README.md" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/README.md" new file mode 100755 index 0000000000000000000000000000000000000000..9a63fdac6de8150d648933c2a9363f1176bc09c1 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/README.md" @@ -0,0 +1,201 @@ +# HiSpark WiFi-IoT 鸿蒙套件样例开发--网络编程(udpserver) + +[HiSpark WiFi-IoT鸿蒙开发套件](https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w5003-23341819265.1.bf644a82Da9PZK&id=622343426064&scene=taobao_shop) 首发于HDC 2020,是首批支持OpenHarmony 2.0的开发套件,亦是鸿蒙官方推荐套件,由润和软件HiHope量身打造,已在鸿蒙社区和广大鸿蒙开发者中得到广泛应用。 + +![wifi_iot](https://gitee.com/hihopeorg/hispark-hm-pegasus/raw/master/docs/figures/wifi_iot.png) + +## netcat简介 + +### netcat 是什么? + +netcat是一个非常强大的网络实用工具,可以用它来调试TCP/UDP应用程序; + +### netcat 如何安装? + +Linux上可以使用发行版的包管理器安装,例如Debian/Ubuntu上: + +* `sudo apt-get install netcat` + +Windows上,MobaXterm工具上也可以用 `apt-get install netcat` 安装; + +### netcat 如何使用? + +开始之前,先简单介绍一下 netcat 的几种用法: + +1. TCP服务端模式: `netcat -l 5678` ,会启动一个TCP服务器,监听`5678`端口,你可以换成其他端口; +2. TCP客户端模式: `netcat localhost 5678`, `localhost`是目标主机参数,可以换成其他你想要连接的主机(主机名、IP地址、域名都可以),`5678`是端口; + * 你如果在同一台机器的两个终端中分别执行上述两条命令,它们两者之间就会建立连接一条TCP连接,此时你在其中一个终端上输入字符,敲回车就会发送到另一个终端中; +3. UDP服务端模式: `netcat -u -l 6789`, 没错,只需要加一个`-u`参数,就可以启动一个UDP服务端; +4. UDP客户端模式: `netcat -u localhost 6789`, + * 类似的,在同一台机器的两个终端中分别执行上述两条命令,他们两者之间也可以收发消息,只不过是UDP报文; + + + + +## LwIP简介 + +### LwIP是什么? + +> A Lightweight TCP/IP stack +> 一个轻量级的TCP/IP协议栈 + +详细介绍请参考LwIP项目官网:https://savannah.nongnu.org/projects/lwip/ + +### LwIP在openharmony上的应用情况 + +目前,openharmony源码树有两份LwIP: + +1. third_party/lwip + * 源码形式编译 + * 供liteos-a内核使用 + * 还有一部分代码在kernel/liteos_a中,一起编译 +2. vendor/hisi/hi3861/hi3861/third_party/lwip_sack + * hi3861-sdk的一部分 + * 静态库形式编译 + * 不可修改配置 + * 可以查看当前配置(vend + + + +## 下载源码 + +建议将本教程的源码下载到鸿蒙源码树的顶层目录,即和`applications`、`build`等目录平级的地方: + +* 执行命令`git clone https://gitee.com/hihopeorg/HarmonyOS-IoT-Application-Development.git` + + + +## 文件说明 + +文件: + +| 文件名 | 说明 | +| ------------------ | ----------------------------------------------------------- | +| BUILD.gn | 鸿蒙构建脚本,支持Hi3861、Hi3518、Hi3516开发板 | +| demo_entry_cmsis.c | 鸿蒙liteos-m程序入口,支持Hi3861 | +| demo_entry_posix.c | 鸿蒙liteos-a和Unix系统程序入口,Hi3516、Hi3518、PC | +| Makefile | Unix系统构建脚本,支持Linux/Mac OS | +| net_common.h | 系统网络接口头文件 | +| net_demo.h | demo脚手架头文件 | +| net_params.h | 网络参数,包括WiFi热点信息,服务器IP、端口信息 | +| tcp_client_test.c | TCP客户端 | +| tcp_server_test.c | TCP服务端 | +| udp_client_test.c | UDP客户端 | +| udp_server_test.c | UDP服务端 | +| wifi_connecter.c | 鸿蒙WiFi STA模式API的封装实现文件,比鸿蒙原始接口更容易使用 | +| wifi_connecter.h | 鸿蒙WiFi STA模式API的封装头文件,比鸿蒙原始接口更容易使用 | + + + +## Linux主机实验指南 + +### 编译测试程序 + +使用如下命令进行编译: + +1. `make` 编译测试程序,该命令会生成4个可执行文件和几个.o文件 +2. `make clean`删除可执行程序和.o文件 + +### 运行测试程序 + +Linux系统可以在同一台机器上,使用多个终端进行测试; + +* TCP客户端测试: + 1. 在一个终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 在另一个终端中启动TCP客户端测试程序:`./tcp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现TCP客户端测试程序发来的:`Hello`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* TCP服务端测试: + 1. 在一个终端中启动TCP服务端测试程序:`./tcp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个TCP客户端,并尝试连接测试程序:`netcat 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是TCP服务端测试程序发送回来的,同时终端上会有相关打印; +* UDP客户端测试: + 1. 在一个终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 2. 在另一个终端中启动UDP客户端测试程序:`./udp_client_test 5678 127.0.0.1` ; + 3. 在netcat终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到测试程序所在终端; +* UDP服务端测试: + 1. 在一个终端中启动UDP服务端测试程序:`./udp_server_test 5678` ; + 2. 在另一个终端中使用netcat启动一个UDP客户端,并尝试连接测试程序:`netcat -u 127.0.0.1 5678`; + 3. 在netcat终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时终端上会有相关打印; + + + +## Hi3861开发板实验指南 + +### 准备网络环境 + +在Hi3861开发板上运行上述四个测试程序之前,需要先准备网络环境: + +1. 准备一个无线路由器, +2. 将Linux系统的PC连接到这个无线路由器, + * 如果是虚拟机运行的Linux系统,需要通过网线连接路由器,并且将虚拟机网口设置为“桥接网卡”,确保**能够从路由器分到IP地址**(这一点非常重要,因为默认是NAT模式,只能通过虚拟机访问外部环境,外部环境无法通过网络访问虚拟机); + +### 修改网络参数 + +在Hi3861开发板上运行上述四个测试程序之前,需要根据你的无线路由、Linux系统IP修改`net_params.h`文件的相关代码: + +* PARAM_HOTSPOT_SSID 修改为你的热点名称 +* PARAM_HOTSPOT_PSK 修改为你的热点密码; +* PARAM_SERVER_ADDR 修改为你的Linux主机IP地址; + +### 编译和烧录测试程序 + +在Hi3861开发板上运行上述四个测试程序,需要分别编译、烧录程序; + +1. 需要修改`BUILD.gn`代码,取消你想要执行的测试程序的注释: + * 编译TCP客户端测试程序,取消 `sources = ["tcp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译TCP服务端测试程序,取消 `sources = ["tcp_server_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP客户端测试程序,取消 `sources = ["udp_client_test.c"]` 的注释,保留其余三行的`sources`注释; + * 编译UDP服务端测试程序,取消 `sources = ["udp_server_test.c"]` 的注释,保留其余三行的`sources`注释; +2. 确认你已经修改了hi3861开发板的编译配置文件`build/lite/product/wifiiot.json`: + * `"//applications/sample/wifi-iot/app"`替换为:`"//HarmonyOS-IoT-Application-Development:app"` +3. 使用`python build.py wifiiot`进行编译; +4. 使用DevEco Device Tool或者HiBurn将二进制程序烧录到Hi3861开发板上; +5. 烧录成功后暂时不要复位程序; + + + +### 运行测试程序 + +Hi3861开发板上运行测试程序的操作流程和Linux上大体相同,只是Linux终端执行测试程序变成了——开发板复位后自动运行; + +* TCP客户端测试: + 1. 在Linux终端中使用netcat启动一个TCP服务端:`netcat -l 5678`; + 2. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的TCP服务端; + 3. 在Linux终端中应该会出现开发板上TCP客户端通过发来的`Hello`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* TCP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["tcp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动TCP服务端,并监听`5678`端口; + * 这里需要从串口日志上查看开发板的IP地址,下一步操作需要用到 + 3. 在Linux终端中使用netcat启动一个TCP客户端,并尝试连接到开发板:`netcat board_ip 5678`,其中`board_ip`是开发板的IP地址; + 4. 在Linux终端中输入`Hello`并回车,终端应该会再输出一行`Hello`,后面一行是开发板上TCP服务端序发送回来的,同时开发板的串口会有相关打印; +* UDP客户端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_client_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 在Linux终端中使用netcat启动一个UDP服务端:`netcat -u -l 5678`; + 3. 连接开发板串口,复位开发板,板上程序启动后,首先会连接WiFi热点,然后会尝试连接到Linux上用netcat启动的UDP服务端; + 4. 在Linux终端中应该会出现UDP客户端测试程序发来的`Hello.`,输入`World`并回车,`World`将会发送到开发板上,同时开发板的串口会有相关打印; +* UDP服务端测试: + 1. 重新修改BUILD.gn,放开`sources = ["udp_server_test.c"]`的注释,保留其他三行的注释,重新编译、烧录到开发板上; + 2. 连接开发板串口,复位开发板,板上程序启动后,会首先连接WiFi热点,然后会启动UDP服务端,并监听`5678`端口; + 3. 在Linux终端中使用netcat启动一个UDP客户端,并尝试连接到开发板:`netcat -u 127.0.0.1 5678`; + 4. 在Linux终端中输入`Hello.`并回车,终端应该会再输出一行`Hello.`,后面一行是UDP服务端测试程序是发送回来的,同时开发板的串口会有相关打印; + + + +### 【套件支持】 + +##### 1. 套件介绍 http://www.hihope.org/pro/pro1.aspx?mtt=8 + +##### 2. 套件购买 https://item.taobao.com/item.htm?id=622343426064&scene=taobao_shop + +##### 3. 技术资料 + +- Gitee码云网站(OpenHarmony Sample Code等) **https://gitee.com/hihopeorg** + +- HiHope官网-资源中心(SDK包、技术文档下载)[**www.hihope.org**](http://www.hihope.org/) + +##### 4. 互动交流 + +- 润和HiHope鸿蒙技术交流-微信群(加群管理员微信13605188699,发送文字#申请加入润和官方鸿蒙群#,予以邀请入群) +- HiHope开发者社区-论坛 **https://bbs.elecfans.com/group_1429** +- 润和HiHope鸿蒙售后服务群(QQ:980599547) +- 售后服务电话(025-52668590) \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_cmsis.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_cmsis.c" new file mode 100755 index 0000000000000000000000000000000000000000..3e10d0d0ac8b24900a2719ad372eedf258224f93 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_cmsis.c" @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include + +#include "ohos_init.h" +#include "cmsis_os2.h" + +#include "net_demo.h" +#include "net_params.h" +#include "wifi_connecter.h" + +static void NetDemoTask(void *arg) +{ + (void)arg; + WifiDeviceConfig config = {0}; + + // 准备AP的配置参数 + strcpy(config.ssid, PARAM_HOTSPOT_SSID); + strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK); + config.securityType = PARAM_HOTSPOT_TYPE; + + osDelay(10); + + int netId = ConnectToHotspot(&config); + + int timeout = 10; + while (timeout--) { + printf("After %d seconds, I will start %s test!\r\n", timeout, GetNetDemoName()); + osDelay(100); + } + + NetDemoTest(PARAM_SERVER_PORT, PARAM_SERVER_ADDR); + + printf("disconnect to AP ...\r\n"); + DisconnectWithHotspot(netId); + printf("disconnect to AP done!\r\n"); +} + +static void NetDemoEntry(void) +{ + osThreadAttr_t attr; + + attr.name = "NetDemoTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = 10240; + attr.priority = osPriorityNormal; + + if (osThreadNew(NetDemoTask, NULL, &attr) == NULL) { + printf("[NetDemoEntry] Falied to create NetDemoTask!\n"); + } +} + +SYS_RUN(NetDemoEntry); + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_posix.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_posix.c" new file mode 100755 index 0000000000000000000000000000000000000000..3f6d197f1e208e7f3b8ffacb1c7fa38f5b5fdfcb --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/demo_entry_posix.c" @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include "net_demo.h" +#include "net_params.h" + +int main(int argc, char* argv[]) +{ + printf("Usage: %s [port] [host]\n", argv[0]); + + short port = argc > 1 ? atoi(argv[1]) : PARAM_SERVER_PORT; + char* host = argc > 2 ? argv[2] : PARAM_SERVER_ADDR; + + NetDemoTest(port, host); + return 0; +} diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_common.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_common.h" new file mode 100755 index 0000000000000000000000000000000000000000..54cded81c6dc7cbdd9d4b9bbbeab32ad9027b0bc --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_common.h" @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_COMMON_H +#define NET_COMMON_H + +// __arm__ and __aarch64__ for OpenHarmony with liteos-a kernel, __i386__ and __x86_64__ for Unix like OS +#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__) +#define HAVE_BSD_SOCKET 1 +#else +#define HAVE_BSD_SOCKET 0 +#endif + +#if defined(__riscv) // for wifiiot(OpenHarmony on Hi3861 with liteos-m kernel) +#define HAVE_LWIP_SOCKET 1 +#else +#define HAVE_LWIP_SOCKET 0 +#endif + +#if HAVE_BSD_SOCKET +#include // for AF_INET SOCK_STREAM +#include // for socket +#include // for sockaddr_in +#include // for inet_pton +#elif HAVE_LWIP_SOCKET +#include "lwip/sockets.h" +#ifndef close +#define close(fd) lwip_close(fd) +#endif +#else +#error "Unknow platform!" +#endif + +#endif // NET_COMMON_H \ No newline at end of file diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_demo.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_demo.h" new file mode 100755 index 0000000000000000000000000000000000000000..6259ded29d8bd8fda097d14a3aa081e7c33eeed1 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_demo.h" @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_DEMO_COMMON_H +#define NET_DEMO_COMMON_H + +#include + +void NetDemoTest(unsigned short port, const char* host); + +const char* GetNetDemoName(void); + +#define IMPL_GET_NET_DEMO_NAME(testFunc) \ + const char* GetNetDemoName() { \ + static const char* demoName = #testFunc; \ + return demoName; \ + } + +#define CLIENT_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will connect to %s:%d\r\n", host, port); \ + testFunc(host, port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#define SERVER_TEST_DEMO(testFunc) \ + void NetDemoTest(unsigned short port, const char* host) { \ + (void) host; \ + printf("%s start\r\n", #testFunc); \ + printf("I will listen on :%d\r\n", port); \ + testFunc(port); \ + printf("%s done!\r\n", #testFunc); \ + } \ + IMPL_GET_NET_DEMO_NAME(testFunc) + +#endif // NET_DEMO_COMMON_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_params.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_params.h" new file mode 100755 index 0000000000000000000000000000000000000000..5aea9837afc3afc0a504b5d4097ed120e3136682 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/net_params.h" @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef NET_PARAMS_H +#define NET_PARAMS_H + +#ifndef PARAM_HOTSPOT_SSID +#define PARAM_HOTSPOT_SSID "ABCD" // your AP SSID +#endif + +#ifndef PARAM_HOTSPOT_PSK +#define PARAM_HOTSPOT_PSK "12345678" // your AP PSK +#endif + +#ifndef PARAM_HOTSPOT_TYPE +#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK // defined in wifi_device_config.h +#endif + +#ifndef PARAM_SERVER_ADDR +#define PARAM_SERVER_ADDR "192.168.1.100" // your PC IP address +#endif + +#ifndef PARAM_SERVER_PORT +#define PARAM_SERVER_PORT 5678 +#endif + +#endif // NET_PARAMS_H diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/udp_server_test.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/udp_server_test.c" new file mode 100755 index 0000000000000000000000000000000000000000..633ec1858c3bdd4be9e475cdfedf28fe9bea00f5 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/udp_server_test.c" @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "net_demo.h" +#include "net_common.h" + +static char message[128] = ""; +void UdpServerTest(unsigned short port) +{ + ssize_t retval = 0; + int sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP socket + + struct sockaddr_in clientAddr = {0}; + socklen_t clientAddrLen = sizeof(clientAddr); + struct sockaddr_in serverAddr = {0}; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + retval = bind(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)); + if (retval < 0) { + printf("bind failed, %ld!\r\n", retval); + goto do_cleanup; + } + printf("bind to port %d success!\r\n", port); + + retval = recvfrom(sockfd, message, sizeof(message), 0, (struct sockaddr *)&clientAddr, &clientAddrLen); + if (retval < 0) { + printf("recvfrom failed, %ld!\r\n", retval); + goto do_cleanup; + } + printf("recv message {%s} %ld done!\r\n", message, retval); + printf("peer info: ipaddr = %s, port = %d\r\n", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port)); + + retval = sendto(sockfd, message, strlen(message), 0, (struct sockaddr *)&clientAddr, sizeof(clientAddr)); + if (retval <= 0) { + printf("send failed, %ld!\r\n", retval); + goto do_cleanup; + } + printf("send message {%s} %ld done!\r\n", message, retval); + +do_cleanup: + printf("do_cleanup...\r\n"); + + close(sockfd); +} + +SERVER_TEST_DEMO(UdpServerTest); diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.c" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.c" new file mode 100755 index 0000000000000000000000000000000000000000..d400786714c57f13ad2bff726b027e6db4088bb8 --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.c" @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "wifi_device.h" +#include "cmsis_os2.h" + +#include "lwip/netifapi.h" +#include "lwip/api_shell.h" + +static void PrintLinkedInfo(WifiLinkedInfo* info) +{ + if (!info) return; + + static char macAddress[32] = {0}; + unsigned char* mac = info->bssid; + snprintf(macAddress, sizeof(macAddress), "%02X:%02X:%02X:%02X:%02X:%02X", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + printf("bssid: %s, rssi: %d, connState: %d, reason: %d, ssid: %s\r\n", + macAddress, info->rssi, info->connState, info->disconnectedReason, info->ssid); +} + +static volatile int g_connected = 0; + +static void OnWifiConnectionChanged(int state, WifiLinkedInfo* info) +{ + if (!info) return; + + printf("%s %d, state = %d, info = \r\n", __FUNCTION__, __LINE__, state); + PrintLinkedInfo(info); + + if (state == WIFI_STATE_AVALIABLE) { + g_connected = 1; + } else { + g_connected = 0; + } +} + +static void OnWifiScanStateChanged(int state, int size) +{ + printf("%s %d, state = %X, size = %d\r\n", __FUNCTION__, __LINE__, state, size); +} + +static WifiEvent g_defaultWifiEventListener = { + .OnWifiConnectionChanged = OnWifiConnectionChanged, + .OnWifiScanStateChanged = OnWifiScanStateChanged +}; + +static struct netif* g_iface = NULL; + +err_t netifapi_set_hostname(struct netif *netif, char *hostname, u8_t namelen); + +int ConnectToHotspot(WifiDeviceConfig* apConfig) +{ + WifiErrorCode errCode; + int netId = -1; + + errCode = RegisterWifiEvent(&g_defaultWifiEventListener); + printf("RegisterWifiEvent: %d\r\n", errCode); + + errCode = EnableWifi(); + printf("EnableWifi: %d\r\n", errCode); + + errCode = AddDeviceConfig(apConfig, &netId); + printf("AddDeviceConfig: %d\r\n", errCode); + + g_connected = 0; + errCode = ConnectTo(netId); + printf("ConnectTo(%d): %d\r\n", netId, errCode); + + while (!g_connected) { // wait until connect to AP + osDelay(10); + } + printf("g_connected: %d\r\n", g_connected); + + g_iface = netifapi_netif_find("wlan0"); + if (g_iface) { + err_t ret = 0; + char* hostname = "hispark"; + ret = netifapi_set_hostname(g_iface, hostname, strlen(hostname)); + printf("netifapi_set_hostname: %d\r\n", ret); + + ret = netifapi_dhcp_start(g_iface); + printf("netifapi_dhcp_start: %d\r\n", ret); + + osDelay(100); // wait DHCP server give me IP +#if 1 + ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL); + printf("netifapi_netif_common: %d\r\n", ret); +#else + // 下面这种方式也可以打印 IP、网关、子网掩码信息 + ip4_addr_t ip = {0}; + ip4_addr_t netmask = {0}; + ip4_addr_t gw = {0}; + ret = netifapi_netif_get_addr(g_iface, &ip, &netmask, &gw); + if (ret == ERR_OK) { + printf("ip = %s\r\n", ip4addr_ntoa(&ip)); + printf("netmask = %s\r\n", ip4addr_ntoa(&netmask)); + printf("gw = %s\r\n", ip4addr_ntoa(&gw)); + } + printf("netifapi_netif_get_addr: %d\r\n", ret); +#endif + } + return netId; +} + +void DisconnectWithHotspot(int netId) +{ + if (g_iface) { + err_t ret = netifapi_dhcp_stop(g_iface); + printf("netifapi_dhcp_stop: %d\r\n", ret); + } + + WifiErrorCode errCode = Disconnect(); // disconnect with your AP + printf("Disconnect: %d\r\n", errCode); + + errCode = UnRegisterWifiEvent(&g_defaultWifiEventListener); + printf("UnRegisterWifiEvent: %d\r\n", errCode); + + RemoveDevice(netId); // remove AP config + printf("RemoveDevice: %d\r\n", errCode); + + errCode = DisableWifi(); + printf("DisableWifi: %d\r\n", errCode); +} + diff --git "a/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.h" "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.h" new file mode 100755 index 0000000000000000000000000000000000000000..cbd4d01ed9adb0b0df58ec2891694c3f212f263b --- /dev/null +++ "b/\347\211\251\350\201\224\347\275\221IoT\351\270\277\350\222\231HiSpark\345\245\227\344\273\266\344\270\200\347\253\231\345\274\217\345\237\271\350\256\255\346\225\231\347\250\213/sample/24_udpserver/wifi_connecter.h" @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020, HiHope Community. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WIFI_CONNECTER_H +#define WIFI_CONNECTER_H + +#include "wifi_device.h" + +int ConnectToHotspot(WifiDeviceConfig* apConfig); + +void DisconnectWithHotspot(int netId); + +#endif // WIFI_CONNECTER_H \ No newline at end of file