├── .gitignore ├── LICENSE ├── README.md ├── board_config.h ├── config.h ├── font.h ├── image.c ├── img2c.py ├── lcd.c ├── lcd.h ├── lpbox.c ├── lpbox.h ├── main.c ├── model ├── LPbox_1_branch.kmodel ├── LPbox_1_branch.tflite └── README.md ├── nt35310.c ├── nt35310.h ├── ov2640.c ├── ov2640.h ├── w25qxx.c └── w25qxx.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | .vscode 107 | .build -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LFFD-LP-K210 2 | 利用 [LFFD](https://github.com/YonghaoHe/A-Light-and-Fast-Face-Detector-for-Edge-Devices) 与 K210 进行车牌检测。 3 | 4 | 5 | ## 存储结构 6 | | 程序文件 | 模型文件 | 7 | |:--------:|:--------:| 8 | | 0x000000 | 0xA00000 | 9 | -------------------------------------------------------------------------------- /board_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _BOARD_CONFIG_ 2 | #define _BOARD_CONFIG_ 3 | 4 | #define OV5640 0 5 | #define OV2640 1 6 | 7 | #define BOARD_KD233 0 8 | #define BOARD_LICHEEDAN 1 9 | #define BOARD_K61 0 10 | 11 | #if (OV5640 && OV2640) || (!OV5640 && !OV2640) 12 | #error ov sensor only choose one 13 | #endif 14 | 15 | #if (BOARD_LICHEEDAN && BOARD_KD233) || (BOARD_LICHEEDAN && BOARD_K61) || (BOARD_K61 && BOARD_KD233) || (!BOARD_LICHEEDAN && !BOARD_KD233 && !BOARD_K61) 16 | #error board only choose one 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H_ 2 | #define _CONFIG_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define KPU_DEBUG 0 10 | 11 | #define PRINTF_KPU_OUTPUT(output, size) \ 12 | { \ 13 | printf("%s addr is %ld\n", #output, (uint64_t)(output)); \ 14 | printf("["); \ 15 | for (size_t i=0; i < (size); i++) { \ 16 | if (i%5 == 0) { \ 17 | printf("\n"); \ 18 | } \ 19 | printf("%f, ", *((output)+i)); \ 20 | } \ 21 | printf("]\n"); \ 22 | } 23 | 24 | /*********************************************************************************/ 25 | #define LOG_ERROR_FLAGE (1 << 1) 26 | #define LOG_WRAN_FLAGE (1 << 2) 27 | #define LOG_INFO_FLAGE (1 << 3) 28 | #define LOG_DEBUG_FLAGE (1 << 4) 29 | 30 | // #define LOG_FLAGE (LOG_ERROR_FLAGE|LOG_WRAN_FLAGE|LOG_INFO_FLAGE|LOG_DEBUG_FLAGE) 31 | #define LOG_FLAGE 0 32 | 33 | #define LOG_PRINT(class, fmt, ...)\ 34 | printf("%s"fmt"[line:%d] [%s]\n", class, ##__VA_ARGS__, __LINE__, __FILE__); 35 | 36 | #if (LOG_ERROR_FLAGE & LOG_FLAGE) 37 | #define LOGE(fmt, ...) LOG_PRINT("[ERROR]", fmt, ##__VA_ARGS__) 38 | #else 39 | #define LOGE(fmt, ...) 40 | #endif // LOG_ERROR_FLAGE 41 | 42 | #if (LOG_WRAN_FLAGE & LOG_FLAGE) 43 | #define LOGW(fmt, ...) LOG_PRINT("[WRAR] ", fmt, ##__VA_ARGS__) 44 | #else 45 | #define LOGW(fmt, ...) 46 | #endif // LOG_WRAN_FLAGE 47 | 48 | #if (LOG_INFO_FLAGE & LOG_FLAGE) 49 | #define LOGI(fmt, ...) LOG_PRINT("[INFO] ", fmt, ##__VA_ARGS__) 50 | #else 51 | #define LOGI(fmt, ...) 52 | #endif // LOG_INFO_FLAGE 53 | 54 | #if (LOG_DEBUG_FLAGE & LOG_FLAGE) 55 | #define LOGD(fmt, ...) LOG_PRINT("[DEBUG]", fmt, ##__VA_ARGS__) 56 | #else 57 | #define LOGD(fmt, ...) 58 | #endif // LOG_DEBUG_FLAGE 59 | /**********************************************************************************/ 60 | 61 | #endif //_CONFIG_H_ -------------------------------------------------------------------------------- /font.h: -------------------------------------------------------------------------------- 1 | #ifndef _FONT_H_ 2 | #define _FONT_H_ 3 | 4 | #include 5 | 6 | uint8_t const ascii0816[] = 7 | { 8 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 9 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 10 | 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF, 11 | 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00, 12 | 0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 13 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 14 | 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 15 | 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 16 | 0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 18 | 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 19 | 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 20 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 21 | 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 22 | 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x0E, 23 | 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, 24 | 0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 26 | 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x63, 27 | 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 29 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 30 | 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0E, 31 | 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 32 | 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 33 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 34 | 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xDB, 35 | 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00, 36 | 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 37 | 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 39 | 0x7E, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 40 | 0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 42 | 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 46 | 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 50 | 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 51 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 53 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 54 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 55 | 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 56 | 0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x06, 0x86, 0xC6, 0x7C, 57 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 58 | 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 59 | 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 60 | 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 62 | 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 63 | 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 66 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 68 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 69 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 | 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xD6, 0xD6, 0xC6, 0xC6, 0x6C, 0x38, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 74 | 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 75 | 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 76 | 0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 78 | 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 79 | 0xC0, 0xC0, 0xFC, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 80 | 0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 81 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 82 | 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 83 | 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 84 | 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 85 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 86 | 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 87 | 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 88 | 0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 89 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 90 | 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 91 | 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 92 | 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 93 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 94 | 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 95 | 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 96 | 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 97 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 98 | 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x6C, 99 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00, 100 | 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 101 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 102 | 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 103 | 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00, 104 | 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 105 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 106 | 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x0C, 107 | 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00, 108 | 0x00, 0x00, 0xE6, 0x66, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 109 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 110 | 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE, 111 | 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 112 | 0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 113 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 114 | 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 115 | 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 116 | 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 117 | 0x0C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 118 | 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 119 | 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 120 | 0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 121 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 122 | 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 123 | 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 124 | 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0xEE, 0x6C, 125 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x7C, 0x38, 0x38, 126 | 0x7C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 127 | 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 128 | 0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 129 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 130 | 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 131 | 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 132 | 0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 133 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 134 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 135 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 136 | 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 137 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 138 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x60, 139 | 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x00, 0x00, 0x00, 0x00, 140 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 141 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 142 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 143 | 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 144 | 0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 145 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 146 | 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, 0x00, 0x00, 0xE0, 0x60, 147 | 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, 148 | 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 149 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 150 | 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0xE0, 0x60, 151 | 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, 152 | 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 153 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 154 | 0xD6, 0xD6, 0xD6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 155 | 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 158 | 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 159 | 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00, 160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x66, 0x60, 0x60, 0x60, 0xF0, 161 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 162 | 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, 163 | 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, 164 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 165 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 166 | 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 167 | 0x00, 0xC6, 0xC6, 0xD6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00, 168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 170 | 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 171 | 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 172 | 0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 173 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 174 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, 175 | 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 176 | 0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 178 | 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 179 | 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00, 180 | 0x00, 0x00, 0xCC, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 181 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 182 | 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 183 | 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 184 | 0x00, 0x00, 0xCC, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 185 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 186 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x38, 187 | 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 188 | 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 189 | 0x3C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 190 | 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 191 | 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 192 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 193 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 194 | 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66, 195 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 196 | 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 197 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 198 | 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x38, 0x00, 199 | 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 200 | 0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 201 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 202 | 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6C, 203 | 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00, 204 | 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 205 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 206 | 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 207 | 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 208 | 0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 209 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 210 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 211 | 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00, 212 | 0x00, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 213 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 214 | 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3C, 215 | 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 216 | 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 217 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 218 | 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xCC, 0xCC, 219 | 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00, 220 | 0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 221 | 0xD8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 222 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 223 | 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 224 | 0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 225 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 226 | 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 227 | 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 228 | 0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 229 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 230 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 231 | 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 232 | 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 233 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 234 | 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 235 | 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 236 | 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xDC, 0x86, 0x0C, 237 | 0x18, 0x3E, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 238 | 0x66, 0xCE, 0x9E, 0x3E, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 239 | 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 240 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6C, 0xD8, 0x6C, 0x36, 0x00, 0x00, 241 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x6C, 0x36, 242 | 0x6C, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, 243 | 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 244 | 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 245 | 0x55, 0xAA, 0x55, 0xAA, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 246 | 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0x18, 0x18, 0x18, 0x18, 247 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 248 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 249 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 250 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 251 | 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 252 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 253 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 254 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 255 | 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 256 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 257 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 258 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 259 | 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 260 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 261 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 262 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 263 | 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 264 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 265 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 267 | 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 268 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 269 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 270 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 271 | 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 272 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 273 | 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 274 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 275 | 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 276 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 277 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 278 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 279 | 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 280 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 281 | 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 282 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 283 | 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 284 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 285 | 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 286 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 287 | 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 288 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 289 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 290 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 291 | 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 293 | 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 294 | 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 295 | 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 296 | 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 297 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 298 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 299 | 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 300 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 301 | 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 302 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 303 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 304 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 305 | 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 306 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 307 | 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00, 308 | 0x00, 0x00, 0x78, 0xCC, 0xCC, 0xCC, 0xD8, 0xCC, 0xC6, 0xC6, 0xC6, 0xCC, 309 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 310 | 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 311 | 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 312 | 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 313 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 314 | 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 315 | 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00, 316 | 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 317 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 318 | 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 319 | 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 320 | 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 321 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 322 | 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 323 | 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 324 | 0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xDB, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 325 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 326 | 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 327 | 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 328 | 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 329 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 330 | 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 331 | 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 332 | 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 333 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 334 | 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 335 | 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, 336 | 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 337 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 338 | 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C, 339 | 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 340 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 341 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 342 | 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0C, 0x0C, 343 | 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00, 344 | 0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 345 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xD8, 0x30, 0x60, 0xC8, 0xF8, 0x00, 346 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 347 | 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 348 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 349 | 0x00, 0x00, 0x00, 0x00}; 350 | 351 | #endif 352 | 353 | -------------------------------------------------------------------------------- /img2c.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | import sys 4 | 5 | if __name__ == '__main__': 6 | img = plt.imread(sys.argv[1]) 7 | img = np.transpose(img, [2,0,1]) 8 | with open('image.c', 'w') as f: 9 | print('const unsigned char gImage_image[] __attribute__((aligned(128))) ={', file=f) 10 | print(', '.join([str(i) for i in img.flatten()]), file=f) 11 | print('};', file=f) -------------------------------------------------------------------------------- /lcd.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include 16 | #include 17 | #include "lcd.h" 18 | #include "nt35310.h" 19 | #include "font.h" 20 | #include "board_config.h" 21 | 22 | static lcd_ctl_t lcd_ctl; 23 | 24 | void lcd_polling_enable(void) 25 | { 26 | lcd_ctl.mode = 0; 27 | } 28 | 29 | void lcd_interrupt_enable(void) 30 | { 31 | lcd_ctl.mode = 1; 32 | } 33 | 34 | void lcd_init(void) 35 | { 36 | uint8_t data = 0; 37 | 38 | tft_hard_init(); 39 | /*soft reset*/ 40 | tft_write_command(SOFTWARE_RESET); 41 | usleep(100000); 42 | /*exit sleep*/ 43 | tft_write_command(SLEEP_OFF); 44 | usleep(100000); 45 | /*pixel format*/ 46 | tft_write_command(PIXEL_FORMAT_SET); 47 | data = 0x55; 48 | tft_write_byte(&data, 1); 49 | lcd_set_direction(DIR_XY_LRUD); 50 | 51 | /*display on*/ 52 | tft_write_command(DISPALY_ON); 53 | lcd_polling_enable(); 54 | } 55 | 56 | void lcd_set_direction(lcd_dir_t dir) 57 | { 58 | #if !BOARD_LICHEEDAN 59 | dir |= 0x08; 60 | #endif 61 | lcd_ctl.dir = dir; 62 | if (dir & DIR_XY_MASK) 63 | { 64 | lcd_ctl.width = LCD_Y_MAX - 1; 65 | lcd_ctl.height = LCD_X_MAX - 1; 66 | } 67 | else 68 | { 69 | lcd_ctl.width = LCD_X_MAX - 1; 70 | lcd_ctl.height = LCD_Y_MAX - 1; 71 | } 72 | 73 | tft_write_command(MEMORY_ACCESS_CTL); 74 | tft_write_byte((uint8_t *)&dir, 1); 75 | } 76 | 77 | void lcd_set_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) 78 | { 79 | uint8_t data[4] = {0}; 80 | 81 | data[0] = (uint8_t)(x1 >> 8); 82 | data[1] = (uint8_t)(x1); 83 | data[2] = (uint8_t)(x2 >> 8); 84 | data[3] = (uint8_t)(x2); 85 | tft_write_command(HORIZONTAL_ADDRESS_SET); 86 | tft_write_byte(data, 4); 87 | 88 | data[0] = (uint8_t)(y1 >> 8); 89 | data[1] = (uint8_t)(y1); 90 | data[2] = (uint8_t)(y2 >> 8); 91 | data[3] = (uint8_t)(y2); 92 | tft_write_command(VERTICAL_ADDRESS_SET); 93 | tft_write_byte(data, 4); 94 | 95 | tft_write_command(MEMORY_WRITE); 96 | } 97 | 98 | void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color) 99 | { 100 | lcd_set_area(x, y, x, y); 101 | tft_write_half(&color, 1); 102 | } 103 | 104 | void lcd_draw_char(uint16_t x, uint16_t y, char c, uint16_t color) 105 | { 106 | uint8_t i = 0; 107 | uint8_t j = 0; 108 | uint8_t data = 0; 109 | 110 | for (i = 0; i < 16; i++) 111 | { 112 | data = ascii0816[c * 16 + i]; 113 | for (j = 0; j < 8; j++) 114 | { 115 | if (data & 0x80) 116 | lcd_draw_point(x + j, y, color); 117 | data <<= 1; 118 | } 119 | y++; 120 | } 121 | } 122 | 123 | void lcd_draw_string(uint16_t x, uint16_t y, char *str, uint16_t color) 124 | { 125 | while (*str) 126 | { 127 | lcd_draw_char(x, y, *str, color); 128 | str++; 129 | x += 8; 130 | } 131 | } 132 | 133 | void lcd_ram_draw_string(char *str, uint32_t *ptr, uint16_t font_color, uint16_t bg_color) 134 | { 135 | uint8_t i = 0; 136 | uint8_t j = 0; 137 | uint8_t data = 0; 138 | uint8_t *pdata = NULL; 139 | uint16_t width = 0; 140 | uint32_t *pixel = NULL; 141 | 142 | width = 4 * strlen(str); 143 | while (*str) 144 | { 145 | pdata = (uint8_t *)&ascii0816[(*str) * 16]; 146 | for (i = 0; i < 16; i++) 147 | { 148 | data = *pdata++; 149 | pixel = ptr + i * width; 150 | for (j = 0; j < 4; j++) 151 | { 152 | switch (data >> 6) 153 | { 154 | case 0: 155 | *pixel = ((uint32_t)bg_color << 16) | bg_color; 156 | break; 157 | case 1: 158 | *pixel = ((uint32_t)bg_color << 16) | font_color; 159 | break; 160 | case 2: 161 | *pixel = ((uint32_t)font_color << 16) | bg_color; 162 | break; 163 | case 3: 164 | *pixel = ((uint32_t)font_color << 16) | font_color; 165 | break; 166 | default: 167 | *pixel = 0; 168 | break; 169 | } 170 | data <<= 2; 171 | pixel++; 172 | } 173 | } 174 | str++; 175 | ptr += 4; 176 | } 177 | } 178 | 179 | void lcd_clear(uint16_t color) 180 | { 181 | uint32_t data = ((uint32_t)color << 16) | (uint32_t)color; 182 | 183 | lcd_set_area(0, 0, lcd_ctl.width, lcd_ctl.height); 184 | tft_fill_data(&data, LCD_X_MAX * LCD_Y_MAX / 2); 185 | } 186 | 187 | void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width, uint16_t color) 188 | { 189 | uint32_t data_buf[640] = {0}; 190 | uint32_t *p = data_buf; 191 | uint32_t data = color; 192 | uint32_t index = 0; 193 | 194 | data = (data << 16) | data; 195 | for (index = 0; index < 160 * width; index++) 196 | *p++ = data; 197 | 198 | lcd_set_area(x1, y1, x2, y1 + width - 1); 199 | tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0); 200 | lcd_set_area(x1, y2 - width + 1, x2, y2); 201 | tft_write_word(data_buf, ((x2 - x1 + 1) * width + 1) / 2, 0); 202 | lcd_set_area(x1, y1, x1 + width - 1, y2); 203 | tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0); 204 | lcd_set_area(x2 - width + 1, y1, x2, y2); 205 | tft_write_word(data_buf, ((y2 - y1 + 1) * width + 1) / 2, 0); 206 | } 207 | 208 | void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t *ptr) 209 | { 210 | lcd_set_area(x1, y1, x1 + width - 1, y1 + height - 1); 211 | tft_write_word(ptr, width * height / 2, lcd_ctl.mode ? 2 : 0); 212 | } 213 | 214 | -------------------------------------------------------------------------------- /lcd.h: -------------------------------------------------------------------------------- 1 | #ifndef _LCD_H_ 2 | #define _LCD_H_ 3 | 4 | #include 5 | 6 | /* clang-format off */ 7 | #define LCD_X_MAX (240) 8 | #define LCD_Y_MAX (320) 9 | 10 | #define BLACK 0x0000 11 | #define NAVY 0x000F 12 | #define DARKGREEN 0x03E0 13 | #define DARKCYAN 0x03EF 14 | #define MAROON 0x7800 15 | #define PURPLE 0x780F 16 | #define OLIVE 0x7BE0 17 | #define LIGHTGREY 0xC618 18 | #define DARKGREY 0x7BEF 19 | #define BLUE 0x001F 20 | #define GREEN 0x07E0 21 | #define CYAN 0x07FF 22 | #define RED 0xF800 23 | #define MAGENTA 0xF81F 24 | #define YELLOW 0xFFE0 25 | #define WHITE 0xFFFF 26 | #define ORANGE 0xFD20 27 | #define GREENYELLOW 0xAFE5 28 | #define PINK 0xF81F 29 | #define USER_COLOR 0xAA55 30 | /* clang-format on */ 31 | 32 | typedef enum _lcd_dir 33 | { 34 | DIR_XY_RLUD = 0x00, 35 | DIR_YX_RLUD = 0x20, 36 | DIR_XY_LRUD = 0x40, 37 | DIR_YX_LRUD = 0x60, 38 | DIR_XY_RLDU = 0x80, 39 | DIR_YX_RLDU = 0xA0, 40 | DIR_XY_LRDU = 0xC0, 41 | DIR_YX_LRDU = 0xE0, 42 | DIR_XY_MASK = 0x20, 43 | DIR_MASK = 0xE0, 44 | } lcd_dir_t; 45 | 46 | typedef struct _lcd_ctl 47 | { 48 | uint8_t mode; 49 | uint8_t dir; 50 | uint16_t width; 51 | uint16_t height; 52 | } lcd_ctl_t; 53 | 54 | void lcd_polling_enable(void); 55 | void lcd_interrupt_enable(void); 56 | void lcd_init(void); 57 | void lcd_clear(uint16_t color); 58 | void lcd_set_direction(lcd_dir_t dir); 59 | void lcd_set_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); 60 | void lcd_draw_point(uint16_t x, uint16_t y, uint16_t color); 61 | void lcd_draw_string(uint16_t x, uint16_t y, char *str, uint16_t color); 62 | void lcd_draw_picture(uint16_t x1, uint16_t y1, uint16_t width, uint16_t height, uint32_t *ptr); 63 | void lcd_draw_rectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t width, uint16_t color); 64 | void lcd_ram_draw_string(char *str, uint32_t *ptr, uint16_t font_color, uint16_t bg_color); 65 | 66 | #endif 67 | 68 | -------------------------------------------------------------------------------- /lpbox.c: -------------------------------------------------------------------------------- 1 | /* 2 | * LPbox 模型程序,用于LPbox模型的结果解析。 3 | */ 4 | 5 | #include "config.h" 6 | 7 | #include 8 | 9 | #include "kpu.h" 10 | #include "lpbox.h" 11 | 12 | 13 | bbox_t *new_bbox(float x1, float y1, float x2, float y2, float score, bbox_t *next) 14 | { 15 | bbox_t *new; 16 | new = (bbox_t *)malloc(sizeof(bbox_t)); 17 | new->x1 = x1; 18 | new->x2 = x2; 19 | new->y1 = y1; 20 | new->y2 = y2; 21 | new->score = score; 22 | new->next = next; 23 | return new; 24 | } 25 | 26 | void free_bbox(bbox_t *bbox) 27 | { 28 | free(bbox); 29 | } 30 | 31 | void push_bbox(bbox_head_t *bboxes, bbox_t *next) 32 | { 33 | bbox_t *tmp = bboxes->box; 34 | 35 | bboxes->num += 1; 36 | 37 | if (tmp == NULL || tmp->score <= next->score) { 38 | next->next = bboxes->box; 39 | bboxes->box = next; 40 | return; 41 | } 42 | 43 | while (tmp->next != NULL) { 44 | if (tmp->next->score <= next->score) 45 | break; 46 | tmp = tmp->next; 47 | } 48 | 49 | next->next = tmp->next; 50 | tmp->next = next; 51 | } 52 | 53 | void delete_bbox(bbox_head_t *bboxes, bbox_t *node) 54 | { 55 | bbox_t *tmp = bboxes->box; 56 | 57 | if (tmp == node) { 58 | bboxes->box = tmp->next; 59 | free_bbox(node); 60 | bboxes->num -= 1; 61 | node = NULL; 62 | } else { 63 | while (tmp->next != NULL) { 64 | if (tmp->next == node) { 65 | tmp->next = node->next; 66 | free_bbox(node); 67 | bboxes->num -= 1; 68 | node = NULL; 69 | break; 70 | } 71 | tmp = tmp->next; 72 | } 73 | } 74 | } 75 | 76 | void free_all_bboxes(bbox_head_t *bboxes) 77 | { 78 | for (bbox_t* tmp = bboxes->box; tmp != NULL; tmp = tmp->next) 79 | free_bbox(tmp); 80 | bboxes->box = NULL; 81 | bboxes->num = 0; 82 | } 83 | 84 | /* 85 | * 提取预测框 86 | */ 87 | uint get_bbox(kpu_output_t *kpu_output, 88 | float score_threshold, 89 | bbox_head_t *bboxes) 90 | { 91 | float score, x1, x2, y1, y2; 92 | uint layer_size = kpu_output->w * kpu_output->h; 93 | 94 | for (uint h = 0; h < kpu_output->h; h++) { 95 | for (uint w=0; w < kpu_output->w; w++) { 96 | score = *(kpu_output->score_layer + h * kpu_output->w + w); 97 | if (score > score_threshold) { 98 | x1 = (kpu_output->rf_start + w * kpu_output->rf_stride) - (*(kpu_output->bbox_layer + 0 * layer_size + h * kpu_output->w + w)) * kpu_output->rf_size/2.0f; 99 | y1 = (kpu_output->rf_start + h * kpu_output->rf_stride) - (*(kpu_output->bbox_layer + 1 * layer_size + h * kpu_output->w + w)) * kpu_output->rf_size/2.0f; 100 | x2 = (kpu_output->rf_start + w * kpu_output->rf_stride) - (*(kpu_output->bbox_layer + 2 * layer_size + h * kpu_output->w + w)) * kpu_output->rf_size/2.0f; 101 | y2 = (kpu_output->rf_start + h * kpu_output->rf_stride) - (*(kpu_output->bbox_layer + 3 * layer_size + h * kpu_output->w + w)) * kpu_output->rf_size/2.0f; 102 | 103 | bbox_t *next = new_bbox(x1, y1, x2, y2, score, NULL); 104 | push_bbox(bboxes, next); 105 | } 106 | } 107 | } 108 | return 0; 109 | } 110 | 111 | 112 | /** 113 | * NMS 114 | */ 115 | 116 | float IoU(bbox_t *bbox1, bbox_t *bbox2) 117 | { 118 | float w = fmin(bbox1->x1, bbox2->x1) - fmax(bbox1->x2, bbox2->x2); 119 | float h = fmin(bbox1->y1, bbox2->y1) - fmax(bbox1->y2, bbox2->y2); 120 | float inter = (w > 0 || h > 0)? 0 : w * h; 121 | return inter / ((bbox1->x2 - bbox1->x1)*(bbox1->y2 - bbox1->y1) 122 | + (bbox2->x2 - bbox2->x1)*(bbox2->y2 - bbox2->y1) 123 | - inter); 124 | } 125 | 126 | void NMS(bbox_head_t *bboxes, float nms_value) 127 | { 128 | bbox_t *next, *tmp1, *tmp2; 129 | for (tmp1=bboxes->box; tmp1 != NULL && tmp1->next != NULL; tmp1=tmp1->next) { 130 | for (tmp2=tmp1->next; tmp2 != NULL; tmp2=next) { 131 | next = tmp2->next; 132 | if (IoU(tmp1, tmp2) > nms_value) { 133 | delete_bbox(bboxes, tmp2); 134 | } 135 | } 136 | } 137 | } 138 | 139 | /** 140 | * 提取 KPU 运算结果 141 | * 说明: 142 | * 理论上这段可以用循环替代,但ncc生成的模型的输出顺序不确定,无法用循环代替 143 | * 请通过输出大小判断输出结果。 144 | */ 145 | int get_lpbox_kpu_output(kpu_model_context_t *ctx, lpbox_t *lpbox) 146 | { 147 | float *score_layer0, *score_layer1, *bbox_layer0, *bbox_layer1; 148 | 149 | size_t score_layer0_size; 150 | kpu_get_output(ctx, 0, &score_layer0, &score_layer0_size); 151 | #if KPU_DEBUG 152 | score_layer0_size /= 4; 153 | LOGD("\nscore_layer0_size: %ld\n", score_layer0_size); 154 | PRINTF_KPU_OUTPUT((score_layer0), (score_layer0_size)); 155 | #endif 156 | (lpbox->kpu_output)[0].score_layer = score_layer0; 157 | 158 | size_t bbox_layer0_size; 159 | kpu_get_output(ctx, 1, &bbox_layer0, &bbox_layer0_size); 160 | #if KPU_DEBUG 161 | bbox_layer0_size /= 4; 162 | LOGD("bbox_layer0_size: %ld\n", bbox_layer0_size); 163 | PRINTF_KPU_OUTPUT((bbox_layer0), (bbox_layer0_size)); 164 | #endif 165 | (lpbox->kpu_output)[0].bbox_layer = bbox_layer0; 166 | 167 | return 0; 168 | } 169 | 170 | int get_lpbox( 171 | lpbox_t *lpbox, 172 | float score_threshold, 173 | float nms_value) 174 | { 175 | free_all_bboxes(lpbox->bboxes); 176 | 177 | // 提取预测框 178 | for (size_t i=0; i < lpbox->output_branch; i++) { 179 | get_bbox((lpbox->kpu_output+i), score_threshold, lpbox->bboxes); 180 | } 181 | if (nms_value > 0) { 182 | LOGD("no nms bboxes num: %d", lpbox->bboxes->num); 183 | NMS(lpbox->bboxes, nms_value); 184 | } 185 | return 0; 186 | } 187 | 188 | int lpbox_new(lpbox_t *lpbox, size_t output_branch) 189 | { 190 | lpbox->output_branch = output_branch; 191 | lpbox->kpu_output = (kpu_output_t *)malloc(lpbox->output_branch*sizeof(kpu_output_t)); 192 | if (lpbox->kpu_output == NULL) { 193 | return -1; 194 | } 195 | lpbox->bboxes = (bbox_head_t *)malloc(sizeof(bbox_head_t)); 196 | if (lpbox->bboxes == NULL) { 197 | return -1; 198 | } 199 | return 0; 200 | } 201 | 202 | void lpbox_free(lpbox_t *lpbox) 203 | { 204 | lpbox->output_branch = 0; 205 | free(lpbox->kpu_output); 206 | free_all_bboxes(lpbox->bboxes); 207 | free(lpbox->bboxes); 208 | } -------------------------------------------------------------------------------- /lpbox.h: -------------------------------------------------------------------------------- 1 | /** 2 | * 19/11/20 重新设计 API 3 | * TODO: 4 | * [x] 重构 API 添加 lpbox_t 类。 5 | * [x] 测试程序 6 | * 注意: 7 | * 由于未知原因,模型输出指针无法正常传入函数,请参考 Dome 重构代码。 8 | */ 9 | 10 | #ifndef _LPBOX_H_ 11 | #define _LPBOX_H_ 12 | 13 | typedef struct BBOX { 14 | float x1; 15 | float y1; 16 | float x2; 17 | float y2; 18 | float score; 19 | struct BBOX *next; 20 | } bbox_t; // 预测框 21 | 22 | typedef struct { 23 | uint num; // 预测框数量 24 | struct BBOX *box; // 预测框 25 | } bbox_head_t; // 预测框头部 26 | 27 | typedef struct { 28 | size_t w; 29 | size_t h; 30 | size_t rf_stride; 31 | size_t rf_start; 32 | size_t rf_size; 33 | float *score_layer; 34 | float *bbox_layer; 35 | } kpu_output_t; 36 | 37 | typedef struct { 38 | size_t output_branch; 39 | kpu_output_t *kpu_output; 40 | bbox_head_t *bboxes; 41 | } lpbox_t; 42 | 43 | bbox_t* new_bbox(float x1, float y1, float x2, float y2, float score, bbox_t* next); 44 | void free_bbox(bbox_t *bbox); 45 | void push_bbox(bbox_head_t *bboxes, bbox_t* next); 46 | void delete_bbox(bbox_head_t *bboxes, bbox_t* node); 47 | void free_all_bboxes(bbox_head_t *bboxes); 48 | 49 | int get_lpbox_kpu_output(kpu_model_context_t *ctx, lpbox_t *lpbox); 50 | int get_lpbox( 51 | lpbox_t *lpbox, 52 | float score_threshold, 53 | float nms_value); 54 | 55 | int lpbox_new(lpbox_t* lpbox, size_t output_branch); 56 | void lpbox_free(lpbox_t* lpbox); 57 | 58 | #endif /*_LPBOX_H_*/ -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include "config.h" 2 | #include "fpioa.h" 3 | #include "plic.h" 4 | #include "sysctl.h" 5 | #include "uarths.h" 6 | #include "utils.h" 7 | #include "kpu.h" 8 | #include "w25qxx.h" 9 | #include "lpbox.h" 10 | #include "nt35310.h" 11 | #include "lcd.h" 12 | 13 | const size_t layer0_w = 19, layer0_h = 14; 14 | const size_t layer1_w = 9 , layer1_h = 6; 15 | 16 | const size_t rf_stride0 = 16 , rf_stride1 = 32; 17 | const size_t rf_start0 = 15 , rf_start1 = 31; 18 | const size_t rf_size0 = 128, rf_size1 = 256; 19 | 20 | #define PLL0_OUTPUT_FREQ 800000000UL 21 | #define PLL1_OUTPUT_FREQ 400000000UL 22 | 23 | extern const unsigned char gImage_image[] __attribute__((aligned(128))); 24 | 25 | static uint16_t lcd_gram[320 * 240] __attribute__((aligned(32))); 26 | 27 | #define LPBOX_KMODEL_SIZE (394280) 28 | uint8_t* lpbox_model_data; 29 | 30 | kpu_model_context_t task; 31 | 32 | uint8_t lpimage[24 * 94 * 3] __attribute__((aligned(32))); 33 | 34 | volatile uint8_t g_ai_done_flag; 35 | 36 | static void ai_done(void* arg) 37 | { 38 | g_ai_done_flag = 1; 39 | } 40 | 41 | static void io_mux_init(void) 42 | { 43 | /* Init DVP IO map and function settings */ 44 | fpioa_set_function(42, FUNC_CMOS_RST); 45 | fpioa_set_function(44, FUNC_CMOS_PWDN); 46 | fpioa_set_function(46, FUNC_CMOS_XCLK); 47 | fpioa_set_function(43, FUNC_CMOS_VSYNC); 48 | fpioa_set_function(45, FUNC_CMOS_HREF); 49 | fpioa_set_function(47, FUNC_CMOS_PCLK); 50 | fpioa_set_function(41, FUNC_SCCB_SCLK); 51 | fpioa_set_function(40, FUNC_SCCB_SDA); 52 | 53 | /* Init SPI IO map and function settings */ 54 | fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM); 55 | fpioa_set_function(36, FUNC_SPI0_SS3); 56 | fpioa_set_function(39, FUNC_SPI0_SCLK); 57 | fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM); 58 | 59 | sysctl_set_spi0_dvp_data(1); 60 | } 61 | 62 | static void io_set_power(void) 63 | { 64 | /* Set dvp and spi pin to 1.8V */ 65 | sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18); 66 | sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18); 67 | } 68 | 69 | void rgb888_to_lcd(uint8_t* src, uint16_t* dest, size_t width, size_t height) 70 | { 71 | size_t chn_size = width * height; 72 | for (size_t i = 0; i < width * height; i++) { 73 | uint8_t r = src[i]; 74 | uint8_t g = src[chn_size + i]; 75 | uint8_t b = src[chn_size * 2 + i]; 76 | 77 | uint16_t rgb = ((r & 0b11111000) << 8) | ((g & 0b11111100) << 3) | (b >> 3); 78 | size_t d_i = i % 2 ? (i - 1) : (i + 1); 79 | dest[d_i] = rgb; 80 | } 81 | } 82 | 83 | int main() 84 | { 85 | // 配置时钟 86 | uint32_t pll0 = sysctl_pll_set_freq(SYSCTL_PLL0, PLL0_OUTPUT_FREQ); 87 | uint32_t pll1 = sysctl_pll_set_freq(SYSCTL_PLL1, PLL1_OUTPUT_FREQ); 88 | LOGI("PLL0 = %ld PLL1 = %ld", pll0, pll1); 89 | uarths_init(); 90 | 91 | io_mux_init(); 92 | io_set_power(); 93 | 94 | plic_init(); 95 | 96 | // LCD init 97 | LOGI("LCD init"); 98 | lcd_init(); 99 | lcd_set_direction(DIR_YX_RLDU); 100 | LOGI("LCD end"); 101 | 102 | // 加载模型 103 | LOGI("flash init"); 104 | w25qxx_init(3, 0); 105 | w25qxx_enable_quad_mode(); 106 | lpbox_model_data = (uint8_t*)malloc(LPBOX_KMODEL_SIZE); 107 | w25qxx_read_data(0xA00000, lpbox_model_data, LPBOX_KMODEL_SIZE, W25QXX_QUAD_FAST); 108 | LOGI("flash end") 109 | 110 | sysctl_enable_irq(); 111 | 112 | // 加载模型 113 | LOGI("model init start"); 114 | if (kpu_load_kmodel(&task, lpbox_model_data) != 0) { 115 | LOGE("model init error"); 116 | while (1) 117 | ; 118 | } 119 | LOGI("model init OK"); 120 | 121 | /*********************************************************************/ 122 | LOGI("lpbox init"); 123 | lpbox_t lpbox; 124 | if (lpbox_new(&lpbox, 1) != 0) { 125 | LOGE("lpbox new error"); 126 | while (1) 127 | ; 128 | } 129 | (lpbox.kpu_output)[0].w = layer0_w; 130 | (lpbox.kpu_output)[0].h = layer0_h; 131 | (lpbox.kpu_output)[0].rf_size = rf_size0; 132 | (lpbox.kpu_output)[0].rf_start = rf_start0; 133 | (lpbox.kpu_output)[0].rf_stride = rf_stride0; 134 | 135 | LOGI("lpbox init end"); 136 | /********************************************************************/ 137 | 138 | // 运行模型 139 | g_ai_done_flag = 0; 140 | kpu_run_kmodel(&task, gImage_image, DMAC_CHANNEL5, ai_done, NULL); 141 | LOGI("model run start"); 142 | while (!g_ai_done_flag) 143 | ; 144 | LOGI("model run OK"); 145 | 146 | // 提取模型推理结果 147 | get_lpbox_kpu_output(&task, &lpbox); 148 | 149 | // 提取预测框 150 | 151 | LOGI("LPbox run start"); 152 | get_lpbox(&lpbox, 0.8, 0.2); 153 | LOGI("LPbox run OK"); 154 | 155 | LOGI("bbox num:%d", lpbox.bboxes->num); 156 | 157 | // 显示图片 158 | rgb888_to_lcd(gImage_image, lcd_gram, 320, 240); 159 | lcd_draw_picture(0, 0, 320, 240, lcd_gram); 160 | 161 | for (bbox_t* bbox = lpbox.bboxes->box; bbox != NULL; bbox = bbox->next) { 162 | LOGI("x1: %f, y1: %f, x2: %f, y2: %f, score: %f", bbox->x1, bbox->y1, bbox->x2, bbox->y2, bbox->score); 163 | lcd_draw_rectangle(bbox->x1, bbox->y1, bbox->x2, bbox->y2, 2, GREEN); 164 | } 165 | 166 | LOGW("end"); 167 | 168 | while (1) 169 | ; 170 | } -------------------------------------------------------------------------------- /model/LPbox_1_branch.kmodel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zp-jump/LFFD-LP-K210/a94030e67c64056ed0653029e14d5d8e04945f54/model/LPbox_1_branch.kmodel -------------------------------------------------------------------------------- /model/LPbox_1_branch.tflite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zp-jump/LFFD-LP-K210/a94030e67c64056ed0653029e14d5d8e04945f54/model/LPbox_1_branch.tflite -------------------------------------------------------------------------------- /model/README.md: -------------------------------------------------------------------------------- 1 | # Kmodel 模型的生成与测试 2 | 3 | 使用 ncc 对模型进行转换,生成 `*.kmodel` 文件 4 | 5 | ## 命令 6 | ```cmd 7 | .\ncc.exe compile .\LPbox.tflite .\LPbox.kmodel -i tflite --dataset .\dataset\ --input-std 0.0039215686274509803921568627451 8 | .\ncc.exe infer .\LPbox.kmodel .\out\ --dataset .\dataset\ --input-std 0.0039215686274509803921568627451 9 | ``` 10 | 11 | ## 注意事项 12 | 13 | ncc 的默认模型输入范围为 0 ~ 1 其本质是将标准8位像素除以255,可以通过更改选项 `--input-std` 与 `--input-mean` 选项进行更改。ncc 在处理输入时会将输入 in 进行以下处理:$\frac{input - mean}{std}$ 。所以对于输入模型范围是 0 ~ 255 的模型要将 `--input-mean` 设置为 $\frac{1}{250}$ 即 0.0039215686274509803921568627451。 -------------------------------------------------------------------------------- /nt35310.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include "nt35310.h" 16 | #include "gpiohs.h" 17 | #include "spi.h" 18 | #include "unistd.h" 19 | #include "board_config.h" 20 | 21 | static void init_dcx(void) 22 | { 23 | gpiohs_set_drive_mode(DCX_GPIONUM, GPIO_DM_OUTPUT); 24 | gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH); 25 | } 26 | 27 | static void set_dcx_control(void) 28 | { 29 | gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_LOW); 30 | } 31 | 32 | static void set_dcx_data(void) 33 | { 34 | gpiohs_set_pin(DCX_GPIONUM, GPIO_PV_HIGH); 35 | } 36 | 37 | #if BOARD_LICHEEDAN 38 | static void init_rst(void) 39 | { 40 | gpiohs_set_drive_mode(RST_GPIONUM, GPIO_DM_OUTPUT); 41 | gpiohs_set_pin(RST_GPIONUM, GPIO_PV_LOW); 42 | usleep(100000); 43 | gpiohs_set_pin(RST_GPIONUM, GPIO_PV_HIGH); 44 | usleep(100000); 45 | } 46 | #endif 47 | 48 | void tft_hard_init(void) 49 | { 50 | init_dcx(); 51 | #if BOARD_LICHEEDAN 52 | init_rst(); 53 | #endif 54 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); 55 | spi_set_clk_rate(SPI_CHANNEL, 20000000); 56 | } 57 | 58 | void tft_write_command(uint8_t cmd) 59 | { 60 | set_dcx_control(); 61 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); 62 | spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, 63 | SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); 64 | spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, (uint8_t *)(&cmd), 1,SPI_TRANS_CHAR); 65 | } 66 | 67 | void tft_write_byte(uint8_t *data_buf, uint32_t length) 68 | { 69 | set_dcx_data(); 70 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0); 71 | spi_init_non_standard(SPI_CHANNEL, 8/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, 72 | SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); 73 | spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT, data_buf, length, SPI_TRANS_CHAR); 74 | } 75 | 76 | void tft_write_half(uint16_t *data_buf, uint32_t length) 77 | { 78 | set_dcx_data(); 79 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0); 80 | spi_init_non_standard(SPI_CHANNEL, 16/*instrction length*/, 0/*address length*/, 0/*wait cycles*/, 81 | SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); 82 | spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_SHORT); 83 | } 84 | 85 | void tft_write_word(uint32_t *data_buf, uint32_t length, uint32_t flag) 86 | { 87 | set_dcx_data(); 88 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); 89 | 90 | spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/, 91 | SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); 92 | spi_send_data_normal_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length, SPI_TRANS_INT); 93 | } 94 | 95 | void tft_fill_data(uint32_t *data_buf, uint32_t length) 96 | { 97 | set_dcx_data(); 98 | spi_init(SPI_CHANNEL, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0); 99 | spi_init_non_standard(SPI_CHANNEL, 0/*instrction length*/, 32/*address length*/, 0/*wait cycles*/, 100 | SPI_AITM_AS_FRAME_FORMAT/*spi address trans mode*/); 101 | spi_fill_data_dma(DMAC_CHANNEL0, SPI_CHANNEL, SPI_SLAVE_SELECT,data_buf, length); 102 | } 103 | 104 | -------------------------------------------------------------------------------- /nt35310.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #ifndef _NT35310_H_ 16 | #define _NT35310_H_ 17 | 18 | #include 19 | 20 | /* clang-format off */ 21 | #define NO_OPERATION 0x00 22 | #define SOFTWARE_RESET 0x01 23 | #define READ_ID 0x04 24 | #define READ_STATUS 0x09 25 | #define READ_POWER_MODE 0x0A 26 | #define READ_MADCTL 0x0B 27 | #define READ_PIXEL_FORMAT 0x0C 28 | #define READ_IMAGE_FORMAT 0x0D 29 | #define READ_SIGNAL_MODE 0x0E 30 | #define READ_SELT_DIAG_RESULT 0x0F 31 | #define SLEEP_ON 0x10 32 | #define SLEEP_OFF 0x11 33 | #define PARTIAL_DISPALY_ON 0x12 34 | #define NORMAL_DISPALY_ON 0x13 35 | #define INVERSION_DISPALY_OFF 0x20 36 | #define INVERSION_DISPALY_ON 0x21 37 | #define GAMMA_SET 0x26 38 | #define DISPALY_OFF 0x28 39 | #define DISPALY_ON 0x29 40 | #define HORIZONTAL_ADDRESS_SET 0x2A 41 | #define VERTICAL_ADDRESS_SET 0x2B 42 | #define MEMORY_WRITE 0x2C 43 | #define COLOR_SET 0x2D 44 | #define MEMORY_READ 0x2E 45 | #define PARTIAL_AREA 0x30 46 | #define VERTICAL_SCROL_DEFINE 0x33 47 | #define TEAR_EFFECT_LINE_OFF 0x34 48 | #define TEAR_EFFECT_LINE_ON 0x35 49 | #define MEMORY_ACCESS_CTL 0x36 50 | #define VERTICAL_SCROL_S_ADD 0x37 51 | #define IDLE_MODE_OFF 0x38 52 | #define IDLE_MODE_ON 0x39 53 | #define PIXEL_FORMAT_SET 0x3A 54 | #define WRITE_MEMORY_CONTINUE 0x3C 55 | #define READ_MEMORY_CONTINUE 0x3E 56 | #define SET_TEAR_SCANLINE 0x44 57 | #define GET_SCANLINE 0x45 58 | #define WRITE_BRIGHTNESS 0x51 59 | #define READ_BRIGHTNESS 0x52 60 | #define WRITE_CTRL_DISPALY 0x53 61 | #define READ_CTRL_DISPALY 0x54 62 | #define WRITE_BRIGHTNESS_CTL 0x55 63 | #define READ_BRIGHTNESS_CTL 0x56 64 | #define WRITE_MIN_BRIGHTNESS 0x5E 65 | #define READ_MIN_BRIGHTNESS 0x5F 66 | #define READ_ID1 0xDA 67 | #define READ_ID2 0xDB 68 | #define READ_ID3 0xDC 69 | #define RGB_IF_SIGNAL_CTL 0xB0 70 | #define NORMAL_FRAME_CTL 0xB1 71 | #define IDLE_FRAME_CTL 0xB2 72 | #define PARTIAL_FRAME_CTL 0xB3 73 | #define INVERSION_CTL 0xB4 74 | #define BLANK_PORCH_CTL 0xB5 75 | #define DISPALY_FUNCTION_CTL 0xB6 76 | #define ENTRY_MODE_SET 0xB7 77 | #define BACKLIGHT_CTL1 0xB8 78 | #define BACKLIGHT_CTL2 0xB9 79 | #define BACKLIGHT_CTL3 0xBA 80 | #define BACKLIGHT_CTL4 0xBB 81 | #define BACKLIGHT_CTL5 0xBC 82 | #define BACKLIGHT_CTL7 0xBE 83 | #define BACKLIGHT_CTL8 0xBF 84 | #define POWER_CTL1 0xC0 85 | #define POWER_CTL2 0xC1 86 | #define VCOM_CTL1 0xC5 87 | #define VCOM_CTL2 0xC7 88 | #define NV_MEMORY_WRITE 0xD0 89 | #define NV_MEMORY_PROTECT_KEY 0xD1 90 | #define NV_MEMORY_STATUS_READ 0xD2 91 | #define READ_ID4 0xD3 92 | #define POSITIVE_GAMMA_CORRECT 0xE0 93 | #define NEGATIVE_GAMMA_CORRECT 0xE1 94 | #define DIGITAL_GAMMA_CTL1 0xE2 95 | #define DIGITAL_GAMMA_CTL2 0xE3 96 | #define INTERFACE_CTL 0xF6 97 | 98 | #define DCX_GPIONUM (2) 99 | #define RST_GPIONUM (0) 100 | 101 | #define SPI_CHANNEL 0 102 | #define SPI_SLAVE_SELECT 3 103 | /* clang-format on */ 104 | 105 | void tft_hard_init(void); 106 | void tft_write_command(uint8_t cmd); 107 | void tft_write_byte(uint8_t *data_buf, uint32_t length); 108 | void tft_write_half(uint16_t *data_buf, uint32_t length); 109 | void tft_write_word(uint32_t *data_buf, uint32_t length, uint32_t flag); 110 | void tft_fill_data(uint32_t *data_buf, uint32_t length); 111 | 112 | #endif 113 | 114 | -------------------------------------------------------------------------------- /ov2640.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include 16 | #include "ov2640.h" 17 | #include "dvp.h" 18 | #include "plic.h" 19 | #include "board_config.h" 20 | 21 | const uint8_t ov2640_config[][2]= 22 | { 23 | {0xff, 0x01}, 24 | {0x12, 0x80}, 25 | {0xff, 0x00}, 26 | {0x2c, 0xff}, 27 | {0x2e, 0xdf}, 28 | {0xff, 0x01}, 29 | {0x3c, 0x32}, 30 | {0x11, 0x00}, 31 | {0x09, 0x02}, 32 | #if BOARD_LICHEEDAN 33 | {0x04, 0x88}, 34 | #else 35 | {0x04, 0xD8}, 36 | #endif 37 | {0x13, 0xe5}, 38 | {0x14, 0x48}, 39 | {0x2c, 0x0c}, 40 | {0x33, 0x78}, 41 | {0x3a, 0x33}, 42 | {0x3b, 0xfb}, 43 | {0x3e, 0x00}, 44 | {0x43, 0x11}, 45 | {0x16, 0x10}, 46 | {0x39, 0x92}, 47 | {0x35, 0xda}, 48 | {0x22, 0x1a}, 49 | {0x37, 0xc3}, 50 | {0x23, 0x00}, 51 | {0x34, 0xc0}, 52 | {0x36, 0x1a}, 53 | {0x06, 0x88}, 54 | {0x07, 0xc0}, 55 | {0x0d, 0x87}, 56 | {0x0e, 0x41}, 57 | {0x4c, 0x00}, 58 | {0x48, 0x00}, 59 | {0x5b, 0x00}, 60 | {0x42, 0x03}, 61 | {0x4a, 0x81}, 62 | {0x21, 0x99}, 63 | {0x24, 0x40}, 64 | {0x25, 0x38}, 65 | {0x26, 0x82}, 66 | {0x5c, 0x00}, 67 | {0x63, 0x00}, 68 | {0x46, 0x22}, 69 | {0x0c, 0x3c}, 70 | {0x61, 0x70}, 71 | {0x62, 0x80}, 72 | {0x7c, 0x05}, 73 | {0x20, 0x80}, 74 | {0x28, 0x30}, 75 | {0x6c, 0x00}, 76 | {0x6d, 0x80}, 77 | {0x6e, 0x00}, 78 | {0x70, 0x02}, 79 | {0x71, 0x94}, 80 | {0x73, 0xc1}, 81 | {0x3d, 0x34}, 82 | {0x5a, 0x57}, 83 | {0x12, 0x40}, 84 | {0x17, 0x11}, 85 | {0x18, 0x43}, 86 | {0x19, 0x00}, 87 | {0x1a, 0x4b}, 88 | {0x32, 0x09}, 89 | {0x37, 0xc0}, 90 | {0x4f, 0xca}, 91 | {0x50, 0xa8}, 92 | {0x5a, 0x23}, 93 | {0x6d, 0x00}, 94 | {0x3d, 0x38}, 95 | {0xff, 0x00}, 96 | {0xe5, 0x7f}, 97 | {0xf9, 0xc0}, 98 | {0x41, 0x24}, 99 | {0xe0, 0x14}, 100 | {0x76, 0xff}, 101 | {0x33, 0xa0}, 102 | {0x42, 0x20}, 103 | {0x43, 0x18}, 104 | {0x4c, 0x00}, 105 | {0x87, 0xd5}, 106 | {0x88, 0x3f}, 107 | {0xd7, 0x03}, 108 | {0xd9, 0x10}, 109 | {0xd3, 0x82}, 110 | {0xc8, 0x08}, 111 | {0xc9, 0x80}, 112 | {0x7c, 0x00}, 113 | {0x7d, 0x00}, 114 | {0x7c, 0x03}, 115 | {0x7d, 0x48}, 116 | {0x7d, 0x48}, 117 | {0x7c, 0x08}, 118 | {0x7d, 0x20}, 119 | {0x7d, 0x10}, 120 | {0x7d, 0x0e}, 121 | {0x90, 0x00}, 122 | {0x91, 0x0e}, 123 | {0x91, 0x1a}, 124 | {0x91, 0x31}, 125 | {0x91, 0x5a}, 126 | {0x91, 0x69}, 127 | {0x91, 0x75}, 128 | {0x91, 0x7e}, 129 | {0x91, 0x88}, 130 | {0x91, 0x8f}, 131 | {0x91, 0x96}, 132 | {0x91, 0xa3}, 133 | {0x91, 0xaf}, 134 | {0x91, 0xc4}, 135 | {0x91, 0xd7}, 136 | {0x91, 0xe8}, 137 | {0x91, 0x20}, 138 | {0x92, 0x00}, 139 | {0x93, 0x06}, 140 | {0x93, 0xe3}, 141 | {0x93, 0x05}, 142 | {0x93, 0x05}, 143 | {0x93, 0x00}, 144 | {0x93, 0x04}, 145 | {0x93, 0x00}, 146 | {0x93, 0x00}, 147 | {0x93, 0x00}, 148 | {0x93, 0x00}, 149 | {0x93, 0x00}, 150 | {0x93, 0x00}, 151 | {0x93, 0x00}, 152 | {0x96, 0x00}, 153 | {0x97, 0x08}, 154 | {0x97, 0x19}, 155 | {0x97, 0x02}, 156 | {0x97, 0x0c}, 157 | {0x97, 0x24}, 158 | {0x97, 0x30}, 159 | {0x97, 0x28}, 160 | {0x97, 0x26}, 161 | {0x97, 0x02}, 162 | {0x97, 0x98}, 163 | {0x97, 0x80}, 164 | {0x97, 0x00}, 165 | {0x97, 0x00}, 166 | {0xc3, 0xed}, 167 | {0xa4, 0x00}, 168 | {0xa8, 0x00}, 169 | {0xc5, 0x11}, 170 | {0xc6, 0x51}, 171 | {0xbf, 0x80}, 172 | {0xc7, 0x10}, 173 | {0xb6, 0x66}, 174 | {0xb8, 0xa5}, 175 | {0xb7, 0x64}, 176 | {0xb9, 0x7c}, 177 | {0xb3, 0xaf}, 178 | {0xb4, 0x97}, 179 | {0xb5, 0xff}, 180 | {0xb0, 0xc5}, 181 | {0xb1, 0x94}, 182 | {0xb2, 0x0f}, 183 | {0xc4, 0x5c}, 184 | {0xc0, 0x64}, 185 | {0xc1, 0x4b}, 186 | {0x8c, 0x00}, 187 | {0x86, 0x3d}, 188 | {0x50, 0x00}, 189 | {0x51, 0xc8}, 190 | {0x52, 0x96}, 191 | {0x53, 0x00}, 192 | {0x54, 0x00}, 193 | {0x55, 0x00}, 194 | {0x5a, 0xc8}, 195 | {0x5b, 0x96}, 196 | {0x5c, 0x00}, 197 | {0xd3, 0x02}, 198 | {0xc2, 0x0c}, 199 | {0xc3, 0xed}, 200 | {0x7f, 0x00}, 201 | {0xda, 0x08}, 202 | {0xe5, 0x1f}, 203 | {0xe1, 0x67}, 204 | {0xe0, 0x00}, 205 | {0xdd, 0x7f}, 206 | {0x05, 0x00}, 207 | {0xff, 0x00}, 208 | {0xe0, 0x04}, 209 | {0x5a, 0x50}, 210 | {0x5b, 0x3c}, 211 | {0x5c, 0x00}, 212 | {0xe0, 0x00}, 213 | {0x00, 0x00} 214 | }; 215 | 216 | int ov2640_init(void) 217 | { 218 | uint16_t v_manuf_id; 219 | uint16_t v_device_id; 220 | ov2640_read_id(&v_manuf_id, &v_device_id); 221 | printf("manuf_id:0x%04x,device_id:0x%04x\n", v_manuf_id, v_device_id); 222 | uint16_t index = 0; 223 | for (index = 0; ov2640_config[index][0]; index++) 224 | dvp_sccb_send_data(OV2640_ADDR, ov2640_config[index][0], ov2640_config[index][1]); 225 | return 0; 226 | } 227 | 228 | int ov2640_read_id(uint16_t *manuf_id, uint16_t *device_id) 229 | { 230 | dvp_sccb_send_data(OV2640_ADDR, 0xFF, 0x01); 231 | *manuf_id = (dvp_sccb_receive_data(OV2640_ADDR, 0x1C) << 8) | dvp_sccb_receive_data(OV2640_ADDR, 0x1D); 232 | *device_id = (dvp_sccb_receive_data(OV2640_ADDR, 0x0A) << 8) | dvp_sccb_receive_data(OV2640_ADDR, 0x0B); 233 | return 0; 234 | } 235 | 236 | -------------------------------------------------------------------------------- /ov2640.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #ifndef _OV2640_H 16 | #define _OV2640_H 17 | 18 | #include 19 | 20 | #define OV2640_ADDR 0x60 21 | 22 | int ov2640_init(void); 23 | int ov2640_read_id(uint16_t *manuf_id, uint16_t *device_id); 24 | 25 | #endif /* _OV2640_H */ 26 | 27 | -------------------------------------------------------------------------------- /w25qxx.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include "w25qxx.h" 16 | #include "fpioa.h" 17 | #include "spi.h" 18 | #include "sysctl.h" 19 | #include "dmac.h" 20 | 21 | uint32_t spi_bus_no = 0; 22 | uint32_t spi_chip_select = 0; 23 | 24 | w25qxx_status_t (*w25qxx_page_program_fun)(uint32_t addr, uint8_t *data_buf, uint32_t length); 25 | w25qxx_status_t (*w25qxx_read_fun)(uint32_t addr, uint8_t *data_buf, uint32_t length); 26 | static w25qxx_status_t w25qxx_stand_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length); 27 | static w25qxx_status_t w25qxx_quad_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length); 28 | 29 | static w25qxx_status_t w25qxx_page_program(uint32_t addr, uint8_t *data_buf, uint32_t length); 30 | static w25qxx_status_t w25qxx_quad_page_program(uint32_t addr, uint8_t *data_buf, uint32_t length); 31 | 32 | static w25qxx_status_t w25qxx_receive_data(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *rx_buff, uint32_t rx_len) 33 | { 34 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0); 35 | spi_receive_data_standard(spi_bus_no, spi_chip_select, cmd_buff, cmd_len, rx_buff, rx_len); 36 | return W25QXX_OK; 37 | } 38 | 39 | static w25qxx_status_t w25qxx_receive_data_dma(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *rx_buff, uint32_t rx_len) 40 | { 41 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0); 42 | spi_receive_data_standard_dma(DMAC_CHANNEL0, DMAC_CHANNEL1, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, rx_buff, rx_len); 43 | return W25QXX_OK; 44 | } 45 | 46 | static w25qxx_status_t w25qxx_send_data(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *tx_buff, uint32_t tx_len) 47 | { 48 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0); 49 | spi_send_data_standard(spi_bus_no, spi_chip_select, cmd_buff, cmd_len, tx_buff, tx_len); 50 | return W25QXX_OK; 51 | } 52 | 53 | static w25qxx_status_t w25qxx_send_data_dma(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *tx_buff, uint32_t tx_len) 54 | { 55 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0); 56 | spi_send_data_standard_dma(DMAC_CHANNEL0, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, tx_buff, tx_len); 57 | return W25QXX_OK; 58 | } 59 | 60 | static w25qxx_status_t w25qxx_receive_data_enhanced_dma(uint32_t *cmd_buff, uint8_t cmd_len, uint8_t *rx_buff, uint32_t rx_len) 61 | { 62 | spi_receive_data_multiple_dma(DMAC_CHANNEL0, DMAC_CHANNEL1, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, rx_buff, rx_len); 63 | return W25QXX_OK; 64 | } 65 | 66 | static w25qxx_status_t w25qxx_send_data_enhanced_dma(uint32_t *cmd_buff, uint8_t cmd_len, uint8_t *tx_buff, uint32_t tx_len) 67 | { 68 | spi_send_data_multiple_dma(DMAC_CHANNEL0, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, tx_buff, tx_len); 69 | return W25QXX_OK; 70 | } 71 | 72 | w25qxx_status_t w25qxx_init(uint8_t spi_index, uint8_t spi_ss) 73 | { 74 | spi_bus_no = spi_index; 75 | spi_chip_select = spi_ss; 76 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0); 77 | spi_set_clk_rate(spi_bus_no, 25000000); 78 | w25qxx_page_program_fun = w25qxx_page_program; 79 | w25qxx_read_fun = w25qxx_stand_read_data; 80 | return W25QXX_OK; 81 | } 82 | 83 | w25qxx_status_t w25qxx_read_id(uint8_t *manuf_id, uint8_t *device_id) 84 | { 85 | uint8_t cmd[4] = {READ_ID, 0x00, 0x00, 0x00}; 86 | uint8_t data[2] = {0}; 87 | 88 | w25qxx_receive_data(cmd, 4, data, 2); 89 | *manuf_id = data[0]; 90 | *device_id = data[1]; 91 | return W25QXX_OK; 92 | } 93 | 94 | static w25qxx_status_t w25qxx_write_enable(void) 95 | { 96 | uint8_t cmd[1] = {WRITE_ENABLE}; 97 | 98 | w25qxx_send_data(cmd, 1, 0, 0); 99 | return W25QXX_OK; 100 | } 101 | 102 | w25qxx_status_t w25qxx_write_status_reg(uint8_t reg1_data, uint8_t reg2_data) 103 | { 104 | uint8_t cmd[3] = {WRITE_REG1, reg1_data, reg2_data}; 105 | 106 | w25qxx_write_enable(); 107 | w25qxx_send_data(cmd, 3, 0, 0); 108 | return W25QXX_OK; 109 | } 110 | 111 | w25qxx_status_t w25qxx_read_status_reg1(uint8_t *reg_data) 112 | { 113 | uint8_t cmd[1] = {READ_REG1}; 114 | uint8_t data[1] = {0}; 115 | 116 | w25qxx_receive_data(cmd, 1, data, 1); 117 | *reg_data = data[0]; 118 | return W25QXX_OK; 119 | } 120 | 121 | w25qxx_status_t w25qxx_read_status_reg2(uint8_t *reg_data) 122 | { 123 | uint8_t cmd[1] = {READ_REG2}; 124 | uint8_t data[1] = {0}; 125 | 126 | w25qxx_receive_data(cmd, 1, data, 1); 127 | *reg_data = data[0]; 128 | return W25QXX_OK; 129 | } 130 | 131 | w25qxx_status_t w25qxx_is_busy(void) 132 | { 133 | uint8_t status = 0; 134 | 135 | w25qxx_read_status_reg1(&status); 136 | if (status & REG1_BUSY_MASK) 137 | return W25QXX_BUSY; 138 | return W25QXX_OK; 139 | } 140 | 141 | w25qxx_status_t w25qxx_sector_erase(uint32_t addr) 142 | { 143 | uint8_t cmd[4] = {SECTOR_ERASE}; 144 | 145 | cmd[1] = (uint8_t)(addr >> 16); 146 | cmd[2] = (uint8_t)(addr >> 8); 147 | cmd[3] = (uint8_t)(addr); 148 | w25qxx_write_enable(); 149 | w25qxx_send_data(cmd, 4, 0, 0); 150 | return W25QXX_OK; 151 | } 152 | 153 | w25qxx_status_t w25qxx_32k_block_erase(uint32_t addr) 154 | { 155 | uint8_t cmd[4] = {BLOCK_32K_ERASE}; 156 | 157 | cmd[1] = (uint8_t)(addr >> 16); 158 | cmd[2] = (uint8_t)(addr >> 8); 159 | cmd[3] = (uint8_t)(addr); 160 | w25qxx_write_enable(); 161 | w25qxx_send_data(cmd, 4, 0, 0); 162 | return W25QXX_OK; 163 | } 164 | 165 | w25qxx_status_t w25qxx_64k_block_erase(uint32_t addr) 166 | { 167 | uint8_t cmd[4] = {BLOCK_64K_ERASE}; 168 | 169 | cmd[1] = (uint8_t)(addr >> 16); 170 | cmd[2] = (uint8_t)(addr >> 8); 171 | cmd[3] = (uint8_t)(addr); 172 | w25qxx_write_enable(); 173 | w25qxx_send_data(cmd, 4, 0, 0); 174 | return W25QXX_OK; 175 | } 176 | 177 | w25qxx_status_t w25qxx_chip_erase(void) 178 | { 179 | uint8_t cmd[1] = {CHIP_ERASE}; 180 | 181 | w25qxx_write_enable(); 182 | w25qxx_send_data(cmd, 1, 0, 0); 183 | return W25QXX_OK; 184 | } 185 | 186 | w25qxx_status_t w25qxx_enable_quad_mode(void) 187 | { 188 | uint8_t reg_data = 0; 189 | 190 | w25qxx_read_status_reg2(®_data); 191 | if (!(reg_data & REG2_QUAL_MASK)) 192 | { 193 | reg_data |= REG2_QUAL_MASK; 194 | w25qxx_write_status_reg(0x00, reg_data); 195 | } 196 | w25qxx_page_program_fun = w25qxx_quad_page_program; 197 | w25qxx_read_fun = w25qxx_quad_read_data; 198 | return W25QXX_OK; 199 | } 200 | 201 | w25qxx_status_t w25qxx_disable_quad_mode(void) 202 | { 203 | uint8_t reg_data = 0; 204 | 205 | w25qxx_read_status_reg2(®_data); 206 | if (reg_data & REG2_QUAL_MASK) 207 | { 208 | reg_data &= (~REG2_QUAL_MASK); 209 | w25qxx_write_status_reg(0x00, reg_data); 210 | } 211 | w25qxx_page_program_fun = w25qxx_page_program; 212 | w25qxx_read_fun = w25qxx_stand_read_data; 213 | return W25QXX_OK; 214 | } 215 | 216 | static w25qxx_status_t w25qxx_page_program(uint32_t addr, uint8_t *data_buf, uint32_t length) 217 | { 218 | uint8_t cmd[4] = {PAGE_PROGRAM}; 219 | 220 | cmd[1] = (uint8_t)(addr >> 16); 221 | cmd[2] = (uint8_t)(addr >> 8); 222 | cmd[3] = (uint8_t)(addr); 223 | w25qxx_write_enable(); 224 | w25qxx_send_data_dma(cmd, 4, data_buf, length); 225 | while (w25qxx_is_busy() == W25QXX_BUSY) 226 | ; 227 | return W25QXX_OK; 228 | } 229 | 230 | static w25qxx_status_t w25qxx_quad_page_program(uint32_t addr, uint8_t *data_buf, uint32_t length) 231 | { 232 | uint32_t cmd[2] = {0}; 233 | 234 | cmd[0] = QUAD_PAGE_PROGRAM; 235 | cmd[1] = addr; 236 | w25qxx_write_enable(); 237 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_QUAD, DATALENGTH, 0); 238 | spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 24/*address length*/, 0/*wait cycles*/, 239 | SPI_AITM_STANDARD/*spi address trans mode*/); 240 | w25qxx_send_data_enhanced_dma(cmd, 2, data_buf, length); 241 | while (w25qxx_is_busy() == W25QXX_BUSY) 242 | ; 243 | return W25QXX_OK; 244 | } 245 | 246 | static w25qxx_status_t w25qxx_sector_program(uint32_t addr, uint8_t *data_buf) 247 | { 248 | uint8_t index = 0; 249 | 250 | for (index = 0; index < w25qxx_FLASH_PAGE_NUM_PER_SECTOR; index++) 251 | { 252 | w25qxx_page_program_fun(addr, data_buf, w25qxx_FLASH_PAGE_SIZE); 253 | addr += w25qxx_FLASH_PAGE_SIZE; 254 | data_buf += w25qxx_FLASH_PAGE_SIZE; 255 | } 256 | return W25QXX_OK; 257 | } 258 | 259 | w25qxx_status_t w25qxx_write_data(uint32_t addr, uint8_t *data_buf, uint32_t length) 260 | { 261 | uint32_t sector_addr = 0; 262 | uint32_t sector_offset = 0; 263 | uint32_t sector_remain = 0; 264 | uint32_t write_len = 0; 265 | uint32_t index = 0; 266 | uint8_t *pread = NULL; 267 | uint8_t *pwrite = NULL; 268 | uint8_t swap_buf[w25qxx_FLASH_SECTOR_SIZE] = {0}; 269 | 270 | while (length) 271 | { 272 | sector_addr = addr & (~(w25qxx_FLASH_SECTOR_SIZE - 1)); 273 | sector_offset = addr & (w25qxx_FLASH_SECTOR_SIZE - 1); 274 | sector_remain = w25qxx_FLASH_SECTOR_SIZE - sector_offset; 275 | write_len = ((length < sector_remain) ? length : sector_remain); 276 | w25qxx_read_fun(sector_addr, swap_buf, w25qxx_FLASH_SECTOR_SIZE); 277 | pread = swap_buf + sector_offset; 278 | pwrite = data_buf; 279 | for (index = 0; index < write_len; index++) 280 | { 281 | if ((*pwrite) != ((*pwrite) & (*pread))) 282 | { 283 | w25qxx_sector_erase(sector_addr); 284 | while (w25qxx_is_busy() == W25QXX_BUSY) 285 | ; 286 | break; 287 | } 288 | pwrite++; 289 | pread++; 290 | } 291 | if (write_len == w25qxx_FLASH_SECTOR_SIZE) 292 | { 293 | w25qxx_sector_program(sector_addr, data_buf); 294 | } 295 | else 296 | { 297 | pread = swap_buf + sector_offset; 298 | pwrite = data_buf; 299 | for (index = 0; index < write_len; index++) 300 | *pread++ = *pwrite++; 301 | w25qxx_sector_program(sector_addr, swap_buf); 302 | } 303 | length -= write_len; 304 | addr += write_len; 305 | data_buf += write_len; 306 | } 307 | return W25QXX_OK; 308 | } 309 | 310 | w25qxx_status_t w25qxx_write_data_direct(uint32_t addr, uint8_t *data_buf, uint32_t length) 311 | { 312 | uint32_t page_remain = 0; 313 | uint32_t write_len = 0; 314 | 315 | while (length) 316 | { 317 | page_remain = w25qxx_FLASH_PAGE_SIZE - (addr & (w25qxx_FLASH_PAGE_SIZE - 1)); 318 | write_len = ((length < page_remain) ? length : page_remain); 319 | w25qxx_page_program_fun(addr, data_buf, write_len); 320 | length -= write_len; 321 | addr += write_len; 322 | data_buf += write_len; 323 | } 324 | return W25QXX_OK; 325 | } 326 | 327 | static w25qxx_status_t _w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length, w25qxx_read_t mode) 328 | { 329 | uint32_t cmd[2] = {0}; 330 | 331 | switch (mode) { 332 | case W25QXX_STANDARD: 333 | *(((uint8_t *)cmd) + 0) = READ_DATA; 334 | *(((uint8_t *)cmd) + 1) = (uint8_t)(addr >> 16); 335 | *(((uint8_t *)cmd) + 2) = (uint8_t)(addr >> 8); 336 | *(((uint8_t *)cmd) + 3) = (uint8_t)(addr >> 0); 337 | w25qxx_receive_data_dma((uint8_t *)cmd, 4, data_buf, length); 338 | break; 339 | case W25QXX_STANDARD_FAST: 340 | *(((uint8_t *)cmd) + 0) = FAST_READ; 341 | *(((uint8_t *)cmd) + 1) = (uint8_t)(addr >> 16); 342 | *(((uint8_t *)cmd) + 2) = (uint8_t)(addr >> 8); 343 | *(((uint8_t *)cmd) + 3) = (uint8_t)(addr >> 0); 344 | *(((uint8_t *)cmd) + 4) = 0xFF; 345 | w25qxx_receive_data_dma((uint8_t *)cmd, 5, data_buf, length); 346 | break; 347 | case W25QXX_DUAL: 348 | cmd[0] = FAST_READ_DUAL_OUTPUT; 349 | cmd[1] = addr; 350 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_DUAL, DATALENGTH, 0); 351 | spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 24/*address length*/, 8/*wait cycles*/, 352 | SPI_AITM_STANDARD/*spi address trans mode*/); 353 | w25qxx_receive_data_enhanced_dma(cmd, 2, data_buf, length); 354 | break; 355 | case W25QXX_DUAL_FAST: 356 | cmd[0] = FAST_READ_DUAL_IO; 357 | cmd[1] = addr << 8; 358 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_DUAL, DATALENGTH, 0); 359 | spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 32/*address length*/, 0/*wait cycles*/, 360 | SPI_AITM_ADDR_STANDARD/*spi address trans mode*/); 361 | w25qxx_receive_data_enhanced_dma(cmd, 2, data_buf, length); 362 | break; 363 | case W25QXX_QUAD: 364 | cmd[0] = FAST_READ_QUAL_OUTPUT; 365 | cmd[1] = addr; 366 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_QUAD, DATALENGTH, 0); 367 | spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 24/*address length*/, 8/*wait cycles*/, 368 | SPI_AITM_STANDARD/*spi address trans mode*/); 369 | w25qxx_receive_data_enhanced_dma(cmd, 2, data_buf, length); 370 | break; 371 | case W25QXX_QUAD_FAST: 372 | cmd[0] = FAST_READ_QUAL_IO; 373 | cmd[1] = addr << 8; 374 | spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_QUAD, DATALENGTH, 0); 375 | spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 32/*address length*/, 4/*wait cycles*/, 376 | SPI_AITM_ADDR_STANDARD/*spi address trans mode*/); 377 | w25qxx_receive_data_enhanced_dma(cmd, 2, data_buf, length); 378 | break; 379 | } 380 | return W25QXX_OK; 381 | } 382 | 383 | w25qxx_status_t w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length, w25qxx_read_t mode) 384 | { 385 | uint32_t len = 0; 386 | 387 | while (length) 388 | { 389 | len = ((length >= 0x010000) ? 0x010000 : length); 390 | _w25qxx_read_data(addr, data_buf, len, mode); 391 | addr += len; 392 | data_buf += len; 393 | length -= len; 394 | } 395 | return W25QXX_OK; 396 | } 397 | 398 | static w25qxx_status_t w25qxx_stand_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length) 399 | { 400 | return w25qxx_read_data(addr, data_buf, length, W25QXX_STANDARD_FAST); 401 | } 402 | 403 | static w25qxx_status_t w25qxx_quad_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length) 404 | { 405 | return w25qxx_read_data(addr, data_buf, length, W25QXX_QUAD_FAST); 406 | } 407 | 408 | -------------------------------------------------------------------------------- /w25qxx.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2018 Canaan Inc. 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #ifndef _W25QXX_H 16 | #define _W25QXX_H 17 | 18 | #include 19 | 20 | /* clang-format off */ 21 | #define DATALENGTH 8 22 | 23 | #define w25qxx_FLASH_PAGE_SIZE 256 24 | #define w25qxx_FLASH_SECTOR_SIZE 4096 25 | #define w25qxx_FLASH_PAGE_NUM_PER_SECTOR 16 26 | #define w25qxx_FLASH_CHIP_SIZE (16777216 UL) 27 | 28 | #define WRITE_ENABLE 0x06 29 | #define WRITE_DISABLE 0x04 30 | #define READ_REG1 0x05 31 | #define READ_REG2 0x35 32 | #define READ_REG3 0x15 33 | #define WRITE_REG1 0x01 34 | #define WRITE_REG2 0x31 35 | #define WRITE_REG3 0x11 36 | #define READ_DATA 0x03 37 | #define FAST_READ 0x0B 38 | #define FAST_READ_DUAL_OUTPUT 0x3B 39 | #define FAST_READ_QUAL_OUTPUT 0x6B 40 | #define FAST_READ_DUAL_IO 0xBB 41 | #define FAST_READ_QUAL_IO 0xEB 42 | #define DUAL_READ_RESET 0xFFFF 43 | #define QUAL_READ_RESET 0xFF 44 | #define PAGE_PROGRAM 0x02 45 | #define QUAD_PAGE_PROGRAM 0x32 46 | #define SECTOR_ERASE 0x20 47 | #define BLOCK_32K_ERASE 0x52 48 | #define BLOCK_64K_ERASE 0xD8 49 | #define CHIP_ERASE 0x60 50 | #define READ_ID 0x90 51 | #define ENABLE_QPI 0x38 52 | #define EXIT_QPI 0xFF 53 | #define ENABLE_RESET 0x66 54 | #define RESET_DEVICE 0x99 55 | 56 | #define REG1_BUSY_MASK 0x01 57 | #define REG2_QUAL_MASK 0x02 58 | 59 | #define LETOBE(x) ((x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24)) 60 | /* clang-format on */ 61 | 62 | /** 63 | * @brief w25qxx operating status enumerate 64 | */ 65 | typedef enum _w25qxx_status 66 | { 67 | W25QXX_OK = 0, 68 | W25QXX_BUSY, 69 | W25QXX_ERROR, 70 | } w25qxx_status_t; 71 | 72 | /** 73 | * @brief w25qxx read operating enumerate 74 | */ 75 | typedef enum _w25qxx_read 76 | { 77 | W25QXX_STANDARD = 0, 78 | W25QXX_STANDARD_FAST, 79 | W25QXX_DUAL, 80 | W25QXX_DUAL_FAST, 81 | W25QXX_QUAD, 82 | W25QXX_QUAD_FAST, 83 | } w25qxx_read_t; 84 | 85 | w25qxx_status_t w25qxx_init(uint8_t spi_index, uint8_t spi_ss); 86 | w25qxx_status_t w25qxx_is_busy(void); 87 | w25qxx_status_t w25qxx_chip_erase(void); 88 | w25qxx_status_t w25qxx_enable_quad_mode(void); 89 | w25qxx_status_t w25qxx_disable_quad_mode(void); 90 | w25qxx_status_t w25qxx_sector_erase(uint32_t addr); 91 | w25qxx_status_t w25qxx_32k_block_erase(uint32_t addr); 92 | w25qxx_status_t w25qxx_64k_block_erase(uint32_t addr); 93 | w25qxx_status_t w25qxx_read_status_reg1(uint8_t *reg_data); 94 | w25qxx_status_t w25qxx_read_status_reg2(uint8_t *reg_data); 95 | w25qxx_status_t w25qxx_write_status_reg(uint8_t reg1_data, uint8_t reg2_data); 96 | w25qxx_status_t w25qxx_read_id(uint8_t *manuf_id, uint8_t *device_id); 97 | w25qxx_status_t w25qxx_write_data(uint32_t addr, uint8_t *data_buf, uint32_t length); 98 | w25qxx_status_t w25qxx_write_data_direct(uint32_t addr, uint8_t *data_buf, uint32_t length); 99 | w25qxx_status_t w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length, w25qxx_read_t mode); 100 | w25qxx_status_t w25qxx_enable_xip_mode(void); 101 | w25qxx_status_t w25qxx_disable_xip_mode(void); 102 | w25qxx_status_t w25qxx_read_id_dma(uint8_t *manuf_id, uint8_t *device_id); 103 | w25qxx_status_t w25qxx_sector_erase_dma(uint32_t addr); 104 | w25qxx_status_t w25qxx_init_dma(uint8_t spi_index, uint8_t spi_ss); 105 | w25qxx_status_t w25qxx_write_data_dma(uint32_t addr, uint8_t *data_buf, uint32_t length); 106 | w25qxx_status_t w25qxx_write_data_direct_dma(uint32_t addr, uint8_t *data_buf, uint32_t length); 107 | w25qxx_status_t w25qxx_read_data_dma(uint32_t addr, uint8_t *data_buf, uint32_t length, w25qxx_read_t mode); 108 | w25qxx_status_t w25qxx_is_busy_dma(void); 109 | w25qxx_status_t w25qxx_enable_quad_mode_dma(void); 110 | 111 | #endif 112 | 113 | --------------------------------------------------------------------------------