From b80413052b11515935d4f4251bf1892ebf9e88eb Mon Sep 17 00:00:00 2001 From: Wulu Date: Tue, 20 Oct 2026 14:41:14 +0800 Subject: [PATCH] chore: remove bundled XiaoZhi source and link upstream board --- README.md | 2 +- README_ZH.md | 2 +- .../xiaozhi/XiaoZhiCode_V2.1.0/.gitignore | 19 - .../xiaozhi/XiaoZhiCode_V2.1.0/CMakeLists.txt | 14 - examples/xiaozhi/XiaoZhiCode_V2.1.0/LICENSE | 22 - examples/xiaozhi/XiaoZhiCode_V2.1.0/README.md | 172 -- .../xiaozhi/XiaoZhiCode_V2.1.0/README_ja.md | 168 -- .../xiaozhi/XiaoZhiCode_V2.1.0/README_zh.md | 168 -- .../XiaoZhiCode_V2.1.0/main/CMakeLists.txt | 940 ----------- .../XiaoZhiCode_V2.1.0/main/Kconfig.projbuild | 820 ---------- .../XiaoZhiCode_V2.1.0/main/application.cc | 1055 ------------ .../XiaoZhiCode_V2.1.0/main/application.h | 186 --- .../xiaozhi/XiaoZhiCode_V2.1.0/main/assets.cc | 532 ------ .../xiaozhi/XiaoZhiCode_V2.1.0/main/assets.h | 52 - .../main/assets/common/exclamation.ogg | Bin 1663 -> 0 bytes .../main/assets/common/low_battery.ogg | Bin 2269 -> 0 bytes .../main/assets/common/popup.ogg | Bin 1148 -> 0 bytes .../main/assets/common/success.ogg | Bin 2012 -> 0 bytes .../main/assets/common/vibration.ogg | Bin 1574 -> 0 bytes .../main/assets/locales/ar-SA/0.ogg | Bin 1940 -> 0 bytes .../main/assets/locales/ar-SA/1.ogg | Bin 1658 -> 0 bytes .../main/assets/locales/ar-SA/2.ogg | Bin 1938 -> 0 bytes .../main/assets/locales/ar-SA/3.ogg | Bin 1861 -> 0 bytes .../main/assets/locales/ar-SA/4.ogg | Bin 1949 -> 0 bytes .../main/assets/locales/ar-SA/5.ogg | Bin 1755 -> 0 bytes .../main/assets/locales/ar-SA/6.ogg | Bin 1825 -> 0 bytes .../main/assets/locales/ar-SA/7.ogg | Bin 1721 -> 0 bytes .../main/assets/locales/ar-SA/8.ogg | Bin 1977 -> 0 bytes .../main/assets/locales/ar-SA/9.ogg | Bin 2063 -> 0 bytes .../main/assets/locales/ar-SA/activation.ogg | Bin 13539 -> 0 bytes .../main/assets/locales/ar-SA/err_pin.ogg | Bin 4416 -> 0 bytes .../main/assets/locales/ar-SA/err_reg.ogg | Bin 9211 -> 0 bytes .../main/assets/locales/ar-SA/language.json | 55 - .../main/assets/locales/ar-SA/upgrade.ogg | Bin 4104 -> 0 bytes .../main/assets/locales/ar-SA/welcome.ogg | Bin 2971 -> 0 bytes .../main/assets/locales/ar-SA/wificonfig.ogg | Bin 5461 -> 0 bytes .../main/assets/locales/bg-BG/0.ogg | Bin 2369 -> 0 bytes .../main/assets/locales/bg-BG/1.ogg | Bin 1867 -> 0 bytes .../main/assets/locales/bg-BG/2.ogg | Bin 2356 -> 0 bytes .../main/assets/locales/bg-BG/3.ogg | Bin 2245 -> 0 bytes .../main/assets/locales/bg-BG/4.ogg | Bin 2611 -> 0 bytes .../main/assets/locales/bg-BG/5.ogg | Bin 2015 -> 0 bytes .../main/assets/locales/bg-BG/6.ogg | Bin 2231 -> 0 bytes .../main/assets/locales/bg-BG/7.ogg | Bin 2276 -> 0 bytes .../main/assets/locales/bg-BG/8.ogg | Bin 2133 -> 0 bytes .../main/assets/locales/bg-BG/9.ogg | Bin 1770 -> 0 bytes .../main/assets/locales/bg-BG/activation.ogg | Bin 14501 -> 0 bytes .../main/assets/locales/bg-BG/err_pin.ogg | Bin 4716 -> 0 bytes .../main/assets/locales/bg-BG/err_reg.ogg | Bin 10755 -> 0 bytes .../main/assets/locales/bg-BG/language.json | 57 - .../main/assets/locales/bg-BG/upgrade.ogg | Bin 6374 -> 0 bytes .../main/assets/locales/bg-BG/welcome.ogg | Bin 3502 -> 0 bytes .../main/assets/locales/bg-BG/wificonfig.ogg | Bin 7569 -> 0 bytes .../main/assets/locales/ca-ES/0.ogg | Bin 1790 -> 0 bytes .../main/assets/locales/ca-ES/1.ogg | Bin 2616 -> 0 bytes .../main/assets/locales/ca-ES/2.ogg | Bin 1737 -> 0 bytes .../main/assets/locales/ca-ES/3.ogg | Bin 2088 -> 0 bytes .../main/assets/locales/ca-ES/4.ogg | Bin 1897 -> 0 bytes .../main/assets/locales/ca-ES/5.ogg | Bin 1733 -> 0 bytes .../main/assets/locales/ca-ES/6.ogg | Bin 1923 -> 0 bytes .../main/assets/locales/ca-ES/7.ogg | Bin 1674 -> 0 bytes .../main/assets/locales/ca-ES/8.ogg | Bin 1892 -> 0 bytes .../main/assets/locales/ca-ES/9.ogg | Bin 1986 -> 0 bytes .../main/assets/locales/ca-ES/activation.ogg | Bin 11679 -> 0 bytes .../main/assets/locales/ca-ES/err_pin.ogg | Bin 5439 -> 0 bytes .../main/assets/locales/ca-ES/err_reg.ogg | Bin 8509 -> 0 bytes .../main/assets/locales/ca-ES/language.json | 57 - .../main/assets/locales/ca-ES/upgrade.ogg | Bin 3717 -> 0 bytes .../main/assets/locales/ca-ES/welcome.ogg | Bin 2876 -> 0 bytes .../main/assets/locales/ca-ES/wificonfig.ogg | Bin 5347 -> 0 bytes .../main/assets/locales/cs-CZ/0.ogg | Bin 1781 -> 0 bytes .../main/assets/locales/cs-CZ/1.ogg | Bin 2000 -> 0 bytes .../main/assets/locales/cs-CZ/2.ogg | Bin 1788 -> 0 bytes .../main/assets/locales/cs-CZ/3.ogg | Bin 1531 -> 0 bytes .../main/assets/locales/cs-CZ/4.ogg | Bin 1880 -> 0 bytes .../main/assets/locales/cs-CZ/5.ogg | Bin 1857 -> 0 bytes .../main/assets/locales/cs-CZ/6.ogg | Bin 1871 -> 0 bytes .../main/assets/locales/cs-CZ/7.ogg | Bin 2052 -> 0 bytes .../main/assets/locales/cs-CZ/8.ogg | Bin 2057 -> 0 bytes .../main/assets/locales/cs-CZ/9.ogg | Bin 1876 -> 0 bytes .../main/assets/locales/cs-CZ/activation.ogg | Bin 9954 -> 0 bytes .../main/assets/locales/cs-CZ/err_pin.ogg | Bin 4045 -> 0 bytes .../main/assets/locales/cs-CZ/err_reg.ogg | Bin 7830 -> 0 bytes .../main/assets/locales/cs-CZ/language.json | 55 - .../main/assets/locales/cs-CZ/upgrade.ogg | Bin 4499 -> 0 bytes .../main/assets/locales/cs-CZ/welcome.ogg | Bin 2672 -> 0 bytes .../main/assets/locales/cs-CZ/wificonfig.ogg | Bin 5169 -> 0 bytes .../main/assets/locales/da-DK/0.ogg | Bin 1986 -> 0 bytes .../main/assets/locales/da-DK/1.ogg | Bin 1916 -> 0 bytes .../main/assets/locales/da-DK/2.ogg | Bin 2185 -> 0 bytes .../main/assets/locales/da-DK/3.ogg | Bin 2178 -> 0 bytes .../main/assets/locales/da-DK/4.ogg | Bin 2143 -> 0 bytes .../main/assets/locales/da-DK/5.ogg | Bin 1974 -> 0 bytes .../main/assets/locales/da-DK/6.ogg | Bin 1874 -> 0 bytes .../main/assets/locales/da-DK/7.ogg | Bin 2125 -> 0 bytes .../main/assets/locales/da-DK/8.ogg | Bin 1519 -> 0 bytes .../main/assets/locales/da-DK/9.ogg | Bin 1790 -> 0 bytes .../main/assets/locales/da-DK/activation.ogg | Bin 11373 -> 0 bytes .../main/assets/locales/da-DK/err_pin.ogg | Bin 3600 -> 0 bytes .../main/assets/locales/da-DK/err_reg.ogg | Bin 9516 -> 0 bytes .../main/assets/locales/da-DK/language.json | 57 - .../main/assets/locales/da-DK/upgrade.ogg | Bin 3074 -> 0 bytes .../main/assets/locales/da-DK/welcome.ogg | Bin 2849 -> 0 bytes .../main/assets/locales/da-DK/wificonfig.ogg | Bin 5526 -> 0 bytes .../main/assets/locales/de-DE/0.ogg | Bin 1829 -> 0 bytes .../main/assets/locales/de-DE/1.ogg | Bin 1801 -> 0 bytes .../main/assets/locales/de-DE/2.ogg | Bin 2010 -> 0 bytes .../main/assets/locales/de-DE/3.ogg | Bin 1756 -> 0 bytes .../main/assets/locales/de-DE/4.ogg | Bin 1868 -> 0 bytes .../main/assets/locales/de-DE/5.ogg | Bin 1979 -> 0 bytes .../main/assets/locales/de-DE/6.ogg | Bin 1943 -> 0 bytes .../main/assets/locales/de-DE/7.ogg | Bin 2139 -> 0 bytes .../main/assets/locales/de-DE/8.ogg | Bin 1751 -> 0 bytes .../main/assets/locales/de-DE/9.ogg | Bin 1835 -> 0 bytes .../main/assets/locales/de-DE/activation.ogg | Bin 14512 -> 0 bytes .../main/assets/locales/de-DE/err_pin.ogg | Bin 4396 -> 0 bytes .../main/assets/locales/de-DE/err_reg.ogg | Bin 11221 -> 0 bytes .../main/assets/locales/de-DE/language.json | 55 - .../main/assets/locales/de-DE/upgrade.ogg | Bin 4370 -> 0 bytes .../main/assets/locales/de-DE/welcome.ogg | Bin 2814 -> 0 bytes .../main/assets/locales/de-DE/wificonfig.ogg | Bin 6587 -> 0 bytes .../main/assets/locales/el-GR/0.ogg | Bin 2138 -> 0 bytes .../main/assets/locales/el-GR/1.ogg | Bin 1744 -> 0 bytes .../main/assets/locales/el-GR/2.ogg | Bin 2003 -> 0 bytes .../main/assets/locales/el-GR/3.ogg | Bin 1767 -> 0 bytes .../main/assets/locales/el-GR/4.ogg | Bin 2010 -> 0 bytes .../main/assets/locales/el-GR/5.ogg | Bin 1882 -> 0 bytes .../main/assets/locales/el-GR/6.ogg | Bin 1717 -> 0 bytes .../main/assets/locales/el-GR/7.ogg | Bin 1795 -> 0 bytes .../main/assets/locales/el-GR/8.ogg | Bin 1788 -> 0 bytes .../main/assets/locales/el-GR/9.ogg | Bin 1561 -> 0 bytes .../main/assets/locales/el-GR/activation.ogg | Bin 14003 -> 0 bytes .../main/assets/locales/el-GR/err_pin.ogg | Bin 4867 -> 0 bytes .../main/assets/locales/el-GR/err_reg.ogg | Bin 9306 -> 0 bytes .../main/assets/locales/el-GR/language.json | 57 - .../main/assets/locales/el-GR/upgrade.ogg | Bin 4139 -> 0 bytes .../main/assets/locales/el-GR/welcome.ogg | Bin 2936 -> 0 bytes .../main/assets/locales/el-GR/wificonfig.ogg | Bin 6031 -> 0 bytes .../main/assets/locales/en-US/0.ogg | Bin 1924 -> 0 bytes .../main/assets/locales/en-US/1.ogg | Bin 1569 -> 0 bytes .../main/assets/locales/en-US/2.ogg | Bin 1532 -> 0 bytes .../main/assets/locales/en-US/3.ogg | Bin 1445 -> 0 bytes .../main/assets/locales/en-US/4.ogg | Bin 1944 -> 0 bytes .../main/assets/locales/en-US/5.ogg | Bin 1586 -> 0 bytes .../main/assets/locales/en-US/6.ogg | Bin 1764 -> 0 bytes .../main/assets/locales/en-US/7.ogg | Bin 2110 -> 0 bytes .../main/assets/locales/en-US/8.ogg | Bin 1571 -> 0 bytes .../main/assets/locales/en-US/9.ogg | Bin 1653 -> 0 bytes .../main/assets/locales/en-US/activation.ogg | Bin 8855 -> 0 bytes .../main/assets/locales/en-US/err_pin.ogg | Bin 3805 -> 0 bytes .../main/assets/locales/en-US/err_reg.ogg | Bin 7780 -> 0 bytes .../main/assets/locales/en-US/language.json | 56 - .../main/assets/locales/en-US/upgrade.ogg | Bin 3112 -> 0 bytes .../main/assets/locales/en-US/welcome.ogg | Bin 2765 -> 0 bytes .../main/assets/locales/en-US/wificonfig.ogg | Bin 4634 -> 0 bytes .../main/assets/locales/es-ES/0.ogg | Bin 1841 -> 0 bytes .../main/assets/locales/es-ES/1.ogg | Bin 1519 -> 0 bytes .../main/assets/locales/es-ES/2.ogg | Bin 1880 -> 0 bytes .../main/assets/locales/es-ES/3.ogg | Bin 1747 -> 0 bytes .../main/assets/locales/es-ES/4.ogg | Bin 1871 -> 0 bytes .../main/assets/locales/es-ES/5.ogg | Bin 2111 -> 0 bytes .../main/assets/locales/es-ES/6.ogg | Bin 1960 -> 0 bytes .../main/assets/locales/es-ES/7.ogg | Bin 2157 -> 0 bytes .../main/assets/locales/es-ES/8.ogg | Bin 1863 -> 0 bytes .../main/assets/locales/es-ES/9.ogg | Bin 2020 -> 0 bytes .../main/assets/locales/es-ES/activation.ogg | Bin 14758 -> 0 bytes .../main/assets/locales/es-ES/err_pin.ogg | Bin 5458 -> 0 bytes .../main/assets/locales/es-ES/err_reg.ogg | Bin 10160 -> 0 bytes .../main/assets/locales/es-ES/language.json | 55 - .../main/assets/locales/es-ES/upgrade.ogg | Bin 3947 -> 0 bytes .../main/assets/locales/es-ES/welcome.ogg | Bin 2909 -> 0 bytes .../main/assets/locales/es-ES/wificonfig.ogg | Bin 6979 -> 0 bytes .../main/assets/locales/fa-IR/0.ogg | Bin 1975 -> 0 bytes .../main/assets/locales/fa-IR/1.ogg | Bin 2234 -> 0 bytes .../main/assets/locales/fa-IR/2.ogg | Bin 1626 -> 0 bytes .../main/assets/locales/fa-IR/3.ogg | Bin 1792 -> 0 bytes .../main/assets/locales/fa-IR/4.ogg | Bin 2043 -> 0 bytes .../main/assets/locales/fa-IR/5.ogg | Bin 3109 -> 0 bytes .../main/assets/locales/fa-IR/6.ogg | Bin 1909 -> 0 bytes .../main/assets/locales/fa-IR/7.ogg | Bin 2461 -> 0 bytes .../main/assets/locales/fa-IR/8.ogg | Bin 2679 -> 0 bytes .../main/assets/locales/fa-IR/9.ogg | Bin 2393 -> 0 bytes .../main/assets/locales/fa-IR/activation.ogg | Bin 12991 -> 0 bytes .../main/assets/locales/fa-IR/err_pin.ogg | Bin 4750 -> 0 bytes .../main/assets/locales/fa-IR/err_reg.ogg | Bin 11655 -> 0 bytes .../main/assets/locales/fa-IR/language.json | 57 - .../main/assets/locales/fa-IR/upgrade.ogg | Bin 3495 -> 0 bytes .../main/assets/locales/fa-IR/welcome.ogg | Bin 3309 -> 0 bytes .../main/assets/locales/fa-IR/wificonfig.ogg | Bin 4700 -> 0 bytes .../main/assets/locales/fi-FI/0.ogg | Bin 2108 -> 0 bytes .../main/assets/locales/fi-FI/1.ogg | Bin 2169 -> 0 bytes .../main/assets/locales/fi-FI/2.ogg | Bin 2158 -> 0 bytes .../main/assets/locales/fi-FI/3.ogg | Bin 2159 -> 0 bytes .../main/assets/locales/fi-FI/4.ogg | Bin 2233 -> 0 bytes .../main/assets/locales/fi-FI/5.ogg | Bin 2147 -> 0 bytes .../main/assets/locales/fi-FI/6.ogg | Bin 2133 -> 0 bytes .../main/assets/locales/fi-FI/7.ogg | Bin 2468 -> 0 bytes .../main/assets/locales/fi-FI/8.ogg | Bin 2240 -> 0 bytes .../main/assets/locales/fi-FI/9.ogg | Bin 2328 -> 0 bytes .../main/assets/locales/fi-FI/activation.ogg | Bin 10121 -> 0 bytes .../main/assets/locales/fi-FI/err_pin.ogg | Bin 3567 -> 0 bytes .../main/assets/locales/fi-FI/err_reg.ogg | Bin 8709 -> 0 bytes .../main/assets/locales/fi-FI/language.json | 55 - .../main/assets/locales/fi-FI/upgrade.ogg | Bin 4239 -> 0 bytes .../main/assets/locales/fi-FI/welcome.ogg | Bin 2828 -> 0 bytes .../main/assets/locales/fi-FI/wificonfig.ogg | Bin 5423 -> 0 bytes .../main/assets/locales/fil-PH/0.ogg | Bin 1571 -> 0 bytes .../main/assets/locales/fil-PH/1.ogg | Bin 1537 -> 0 bytes .../main/assets/locales/fil-PH/2.ogg | Bin 1628 -> 0 bytes .../main/assets/locales/fil-PH/3.ogg | Bin 1514 -> 0 bytes .../main/assets/locales/fil-PH/4.ogg | Bin 1395 -> 0 bytes .../main/assets/locales/fil-PH/5.ogg | Bin 1497 -> 0 bytes .../main/assets/locales/fil-PH/6.ogg | Bin 1480 -> 0 bytes .../main/assets/locales/fil-PH/7.ogg | Bin 1527 -> 0 bytes .../main/assets/locales/fil-PH/8.ogg | Bin 1647 -> 0 bytes .../main/assets/locales/fil-PH/9.ogg | Bin 1604 -> 0 bytes .../main/assets/locales/fil-PH/activation.ogg | Bin 12289 -> 0 bytes .../main/assets/locales/fil-PH/err_pin.ogg | Bin 4032 -> 0 bytes .../main/assets/locales/fil-PH/err_reg.ogg | Bin 7125 -> 0 bytes .../main/assets/locales/fil-PH/language.json | 57 - .../main/assets/locales/fil-PH/upgrade.ogg | Bin 3478 -> 0 bytes .../main/assets/locales/fil-PH/welcome.ogg | Bin 3754 -> 0 bytes .../main/assets/locales/fil-PH/wificonfig.ogg | Bin 6006 -> 0 bytes .../main/assets/locales/fr-FR/0.ogg | Bin 2291 -> 0 bytes .../main/assets/locales/fr-FR/1.ogg | Bin 2472 -> 0 bytes .../main/assets/locales/fr-FR/2.ogg | Bin 2555 -> 0 bytes .../main/assets/locales/fr-FR/3.ogg | Bin 2243 -> 0 bytes .../main/assets/locales/fr-FR/4.ogg | Bin 2326 -> 0 bytes .../main/assets/locales/fr-FR/5.ogg | Bin 2558 -> 0 bytes .../main/assets/locales/fr-FR/6.ogg | Bin 2377 -> 0 bytes .../main/assets/locales/fr-FR/7.ogg | Bin 2321 -> 0 bytes .../main/assets/locales/fr-FR/8.ogg | Bin 2362 -> 0 bytes .../main/assets/locales/fr-FR/9.ogg | Bin 2100 -> 0 bytes .../main/assets/locales/fr-FR/activation.ogg | Bin 17207 -> 0 bytes .../main/assets/locales/fr-FR/err_pin.ogg | Bin 6043 -> 0 bytes .../main/assets/locales/fr-FR/err_reg.ogg | Bin 9869 -> 0 bytes .../main/assets/locales/fr-FR/language.json | 55 - .../main/assets/locales/fr-FR/upgrade.ogg | Bin 3757 -> 0 bytes .../main/assets/locales/fr-FR/welcome.ogg | Bin 2927 -> 0 bytes .../main/assets/locales/fr-FR/wificonfig.ogg | Bin 5157 -> 0 bytes .../main/assets/locales/he-IL/0.ogg | Bin 1753 -> 0 bytes .../main/assets/locales/he-IL/1.ogg | Bin 1921 -> 0 bytes .../main/assets/locales/he-IL/2.ogg | Bin 2000 -> 0 bytes .../main/assets/locales/he-IL/3.ogg | Bin 1970 -> 0 bytes .../main/assets/locales/he-IL/4.ogg | Bin 2095 -> 0 bytes .../main/assets/locales/he-IL/5.ogg | Bin 2220 -> 0 bytes .../main/assets/locales/he-IL/6.ogg | Bin 3459 -> 0 bytes .../main/assets/locales/he-IL/7.ogg | Bin 2222 -> 0 bytes .../main/assets/locales/he-IL/8.ogg | Bin 3889 -> 0 bytes .../main/assets/locales/he-IL/9.ogg | Bin 3396 -> 0 bytes .../main/assets/locales/he-IL/activation.ogg | Bin 8528 -> 0 bytes .../main/assets/locales/he-IL/err_pin.ogg | Bin 5032 -> 0 bytes .../main/assets/locales/he-IL/err_reg.ogg | Bin 7378 -> 0 bytes .../main/assets/locales/he-IL/language.json | 57 - .../main/assets/locales/he-IL/upgrade.ogg | Bin 3648 -> 0 bytes .../main/assets/locales/he-IL/welcome.ogg | Bin 3037 -> 0 bytes .../main/assets/locales/he-IL/wificonfig.ogg | Bin 4292 -> 0 bytes .../main/assets/locales/hi-IN/0.ogg | Bin 2313 -> 0 bytes .../main/assets/locales/hi-IN/1.ogg | Bin 1490 -> 0 bytes .../main/assets/locales/hi-IN/2.ogg | Bin 1609 -> 0 bytes .../main/assets/locales/hi-IN/3.ogg | Bin 1530 -> 0 bytes .../main/assets/locales/hi-IN/4.ogg | Bin 1530 -> 0 bytes .../main/assets/locales/hi-IN/5.ogg | Bin 1837 -> 0 bytes .../main/assets/locales/hi-IN/6.ogg | Bin 1503 -> 0 bytes .../main/assets/locales/hi-IN/7.ogg | Bin 1803 -> 0 bytes .../main/assets/locales/hi-IN/8.ogg | Bin 1590 -> 0 bytes .../main/assets/locales/hi-IN/9.ogg | Bin 1550 -> 0 bytes .../main/assets/locales/hi-IN/activation.ogg | Bin 10626 -> 0 bytes .../main/assets/locales/hi-IN/err_pin.ogg | Bin 2949 -> 0 bytes .../main/assets/locales/hi-IN/err_reg.ogg | Bin 7548 -> 0 bytes .../main/assets/locales/hi-IN/language.json | 55 - .../main/assets/locales/hi-IN/upgrade.ogg | Bin 3315 -> 0 bytes .../main/assets/locales/hi-IN/welcome.ogg | Bin 2582 -> 0 bytes .../main/assets/locales/hi-IN/wificonfig.ogg | Bin 4698 -> 0 bytes .../main/assets/locales/hr-HR/0.ogg | Bin 2514 -> 0 bytes .../main/assets/locales/hr-HR/1.ogg | Bin 2662 -> 0 bytes .../main/assets/locales/hr-HR/2.ogg | Bin 2174 -> 0 bytes .../main/assets/locales/hr-HR/3.ogg | Bin 3902 -> 0 bytes .../main/assets/locales/hr-HR/4.ogg | Bin 1876 -> 0 bytes .../main/assets/locales/hr-HR/5.ogg | Bin 1996 -> 0 bytes .../main/assets/locales/hr-HR/6.ogg | Bin 2249 -> 0 bytes .../main/assets/locales/hr-HR/7.ogg | Bin 2586 -> 0 bytes .../main/assets/locales/hr-HR/8.ogg | Bin 2509 -> 0 bytes .../main/assets/locales/hr-HR/9.ogg | Bin 2187 -> 0 bytes .../main/assets/locales/hr-HR/activation.ogg | Bin 14451 -> 0 bytes .../main/assets/locales/hr-HR/err_pin.ogg | Bin 7108 -> 0 bytes .../main/assets/locales/hr-HR/err_reg.ogg | Bin 13477 -> 0 bytes .../main/assets/locales/hr-HR/language.json | 57 - .../main/assets/locales/hr-HR/upgrade.ogg | Bin 4241 -> 0 bytes .../main/assets/locales/hr-HR/welcome.ogg | Bin 5092 -> 0 bytes .../main/assets/locales/hr-HR/wificonfig.ogg | Bin 6223 -> 0 bytes .../main/assets/locales/hu-HU/0.ogg | Bin 1582 -> 0 bytes .../main/assets/locales/hu-HU/1.ogg | Bin 1963 -> 0 bytes .../main/assets/locales/hu-HU/2.ogg | Bin 2418 -> 0 bytes .../main/assets/locales/hu-HU/3.ogg | Bin 1966 -> 0 bytes .../main/assets/locales/hu-HU/4.ogg | Bin 2161 -> 0 bytes .../main/assets/locales/hu-HU/5.ogg | Bin 2173 -> 0 bytes .../main/assets/locales/hu-HU/6.ogg | Bin 2251 -> 0 bytes .../main/assets/locales/hu-HU/7.ogg | Bin 1531 -> 0 bytes .../main/assets/locales/hu-HU/8.ogg | Bin 2119 -> 0 bytes .../main/assets/locales/hu-HU/9.ogg | Bin 2049 -> 0 bytes .../main/assets/locales/hu-HU/activation.ogg | Bin 15641 -> 0 bytes .../main/assets/locales/hu-HU/err_pin.ogg | Bin 6545 -> 0 bytes .../main/assets/locales/hu-HU/err_reg.ogg | Bin 10408 -> 0 bytes .../main/assets/locales/hu-HU/language.json | 57 - .../main/assets/locales/hu-HU/upgrade.ogg | Bin 3811 -> 0 bytes .../main/assets/locales/hu-HU/welcome.ogg | Bin 3060 -> 0 bytes .../main/assets/locales/hu-HU/wificonfig.ogg | Bin 5701 -> 0 bytes .../main/assets/locales/id-ID/0.ogg | Bin 2025 -> 0 bytes .../main/assets/locales/id-ID/1.ogg | Bin 2633 -> 0 bytes .../main/assets/locales/id-ID/2.ogg | Bin 2273 -> 0 bytes .../main/assets/locales/id-ID/3.ogg | Bin 2252 -> 0 bytes .../main/assets/locales/id-ID/4.ogg | Bin 1806 -> 0 bytes .../main/assets/locales/id-ID/5.ogg | Bin 2342 -> 0 bytes .../main/assets/locales/id-ID/6.ogg | Bin 2178 -> 0 bytes .../main/assets/locales/id-ID/7.ogg | Bin 2101 -> 0 bytes .../main/assets/locales/id-ID/8.ogg | Bin 2409 -> 0 bytes .../main/assets/locales/id-ID/9.ogg | Bin 2484 -> 0 bytes .../main/assets/locales/id-ID/activation.ogg | Bin 17124 -> 0 bytes .../main/assets/locales/id-ID/err_pin.ogg | Bin 5087 -> 0 bytes .../main/assets/locales/id-ID/err_reg.ogg | Bin 7716 -> 0 bytes .../main/assets/locales/id-ID/language.json | 55 - .../main/assets/locales/id-ID/upgrade.ogg | Bin 3823 -> 0 bytes .../main/assets/locales/id-ID/welcome.ogg | Bin 2537 -> 0 bytes .../main/assets/locales/id-ID/wificonfig.ogg | Bin 8706 -> 0 bytes .../main/assets/locales/it-IT/0.ogg | Bin 1877 -> 0 bytes .../main/assets/locales/it-IT/1.ogg | Bin 1423 -> 0 bytes .../main/assets/locales/it-IT/2.ogg | Bin 1436 -> 0 bytes .../main/assets/locales/it-IT/3.ogg | Bin 1302 -> 0 bytes .../main/assets/locales/it-IT/4.ogg | Bin 1404 -> 0 bytes .../main/assets/locales/it-IT/5.ogg | Bin 1607 -> 0 bytes .../main/assets/locales/it-IT/6.ogg | Bin 1457 -> 0 bytes .../main/assets/locales/it-IT/7.ogg | Bin 1632 -> 0 bytes .../main/assets/locales/it-IT/8.ogg | Bin 1494 -> 0 bytes .../main/assets/locales/it-IT/9.ogg | Bin 1888 -> 0 bytes .../main/assets/locales/it-IT/activation.ogg | Bin 12274 -> 0 bytes .../main/assets/locales/it-IT/err_pin.ogg | Bin 3023 -> 0 bytes .../main/assets/locales/it-IT/err_reg.ogg | Bin 8416 -> 0 bytes .../main/assets/locales/it-IT/language.json | 55 - .../main/assets/locales/it-IT/upgrade.ogg | Bin 4059 -> 0 bytes .../main/assets/locales/it-IT/welcome.ogg | Bin 3063 -> 0 bytes .../main/assets/locales/it-IT/wificonfig.ogg | Bin 5995 -> 0 bytes .../main/assets/locales/ja-JP/0.ogg | Bin 1499 -> 0 bytes .../main/assets/locales/ja-JP/1.ogg | Bin 1459 -> 0 bytes .../main/assets/locales/ja-JP/2.ogg | Bin 1203 -> 0 bytes .../main/assets/locales/ja-JP/3.ogg | Bin 1312 -> 0 bytes .../main/assets/locales/ja-JP/4.ogg | Bin 1372 -> 0 bytes .../main/assets/locales/ja-JP/5.ogg | Bin 1085 -> 0 bytes .../main/assets/locales/ja-JP/6.ogg | Bin 1482 -> 0 bytes .../main/assets/locales/ja-JP/7.ogg | Bin 1503 -> 0 bytes .../main/assets/locales/ja-JP/8.ogg | Bin 1663 -> 0 bytes .../main/assets/locales/ja-JP/9.ogg | Bin 1565 -> 0 bytes .../main/assets/locales/ja-JP/activation.ogg | Bin 12162 -> 0 bytes .../main/assets/locales/ja-JP/err_pin.ogg | Bin 4547 -> 0 bytes .../main/assets/locales/ja-JP/err_reg.ogg | Bin 10168 -> 0 bytes .../main/assets/locales/ja-JP/language.json | 55 - .../main/assets/locales/ja-JP/upgrade.ogg | Bin 4754 -> 0 bytes .../main/assets/locales/ja-JP/welcome.ogg | Bin 3403 -> 0 bytes .../main/assets/locales/ja-JP/wificonfig.ogg | Bin 6770 -> 0 bytes .../main/assets/locales/ko-KR/0.ogg | Bin 1696 -> 0 bytes .../main/assets/locales/ko-KR/1.ogg | Bin 1687 -> 0 bytes .../main/assets/locales/ko-KR/2.ogg | Bin 1475 -> 0 bytes .../main/assets/locales/ko-KR/3.ogg | Bin 1588 -> 0 bytes .../main/assets/locales/ko-KR/4.ogg | Bin 1426 -> 0 bytes .../main/assets/locales/ko-KR/5.ogg | Bin 1490 -> 0 bytes .../main/assets/locales/ko-KR/6.ogg | Bin 1516 -> 0 bytes .../main/assets/locales/ko-KR/7.ogg | Bin 1734 -> 0 bytes .../main/assets/locales/ko-KR/8.ogg | Bin 1454 -> 0 bytes .../main/assets/locales/ko-KR/9.ogg | Bin 2430 -> 0 bytes .../main/assets/locales/ko-KR/activation.ogg | Bin 11193 -> 0 bytes .../main/assets/locales/ko-KR/err_pin.ogg | Bin 4725 -> 0 bytes .../main/assets/locales/ko-KR/err_reg.ogg | Bin 10954 -> 0 bytes .../main/assets/locales/ko-KR/language.json | 56 - .../main/assets/locales/ko-KR/upgrade.ogg | Bin 5335 -> 0 bytes .../main/assets/locales/ko-KR/welcome.ogg | Bin 4566 -> 0 bytes .../main/assets/locales/ko-KR/wificonfig.ogg | Bin 6474 -> 0 bytes .../main/assets/locales/ms-MY/0.ogg | Bin 2176 -> 0 bytes .../main/assets/locales/ms-MY/1.ogg | Bin 1639 -> 0 bytes .../main/assets/locales/ms-MY/2.ogg | Bin 2159 -> 0 bytes .../main/assets/locales/ms-MY/3.ogg | Bin 1571 -> 0 bytes .../main/assets/locales/ms-MY/4.ogg | Bin 1680 -> 0 bytes .../main/assets/locales/ms-MY/5.ogg | Bin 1565 -> 0 bytes .../main/assets/locales/ms-MY/6.ogg | Bin 1661 -> 0 bytes .../main/assets/locales/ms-MY/7.ogg | Bin 1486 -> 0 bytes .../main/assets/locales/ms-MY/8.ogg | Bin 2181 -> 0 bytes .../main/assets/locales/ms-MY/9.ogg | Bin 2479 -> 0 bytes .../main/assets/locales/ms-MY/activation.ogg | Bin 12883 -> 0 bytes .../main/assets/locales/ms-MY/err_pin.ogg | Bin 4105 -> 0 bytes .../main/assets/locales/ms-MY/err_reg.ogg | Bin 10706 -> 0 bytes .../main/assets/locales/ms-MY/language.json | 57 - .../main/assets/locales/ms-MY/upgrade.ogg | Bin 4065 -> 0 bytes .../main/assets/locales/ms-MY/welcome.ogg | Bin 5732 -> 0 bytes .../main/assets/locales/ms-MY/wificonfig.ogg | Bin 5042 -> 0 bytes .../main/assets/locales/nb-NO/0.ogg | Bin 1541 -> 0 bytes .../main/assets/locales/nb-NO/1.ogg | Bin 1448 -> 0 bytes .../main/assets/locales/nb-NO/2.ogg | Bin 2024 -> 0 bytes .../main/assets/locales/nb-NO/3.ogg | Bin 1767 -> 0 bytes .../main/assets/locales/nb-NO/4.ogg | Bin 1898 -> 0 bytes .../main/assets/locales/nb-NO/5.ogg | Bin 1778 -> 0 bytes .../main/assets/locales/nb-NO/6.ogg | Bin 1997 -> 0 bytes .../main/assets/locales/nb-NO/7.ogg | Bin 1647 -> 0 bytes .../main/assets/locales/nb-NO/8.ogg | Bin 1507 -> 0 bytes .../main/assets/locales/nb-NO/9.ogg | Bin 1782 -> 0 bytes .../main/assets/locales/nb-NO/activation.ogg | Bin 12110 -> 0 bytes .../main/assets/locales/nb-NO/err_pin.ogg | Bin 4175 -> 0 bytes .../main/assets/locales/nb-NO/err_reg.ogg | Bin 8992 -> 0 bytes .../main/assets/locales/nb-NO/language.json | 57 - .../main/assets/locales/nb-NO/upgrade.ogg | Bin 3155 -> 0 bytes .../main/assets/locales/nb-NO/welcome.ogg | Bin 2512 -> 0 bytes .../main/assets/locales/nb-NO/wificonfig.ogg | Bin 6131 -> 0 bytes .../main/assets/locales/nl-NL/0.ogg | Bin 1859 -> 0 bytes .../main/assets/locales/nl-NL/1.ogg | Bin 1553 -> 0 bytes .../main/assets/locales/nl-NL/2.ogg | Bin 1712 -> 0 bytes .../main/assets/locales/nl-NL/3.ogg | Bin 1547 -> 0 bytes .../main/assets/locales/nl-NL/4.ogg | Bin 1885 -> 0 bytes .../main/assets/locales/nl-NL/5.ogg | Bin 2010 -> 0 bytes .../main/assets/locales/nl-NL/6.ogg | Bin 1872 -> 0 bytes .../main/assets/locales/nl-NL/7.ogg | Bin 1981 -> 0 bytes .../main/assets/locales/nl-NL/8.ogg | Bin 1787 -> 0 bytes .../main/assets/locales/nl-NL/9.ogg | Bin 2154 -> 0 bytes .../main/assets/locales/nl-NL/activation.ogg | Bin 13132 -> 0 bytes .../main/assets/locales/nl-NL/err_pin.ogg | Bin 3190 -> 0 bytes .../main/assets/locales/nl-NL/err_reg.ogg | Bin 10114 -> 0 bytes .../main/assets/locales/nl-NL/language.json | 57 - .../main/assets/locales/nl-NL/upgrade.ogg | Bin 3529 -> 0 bytes .../main/assets/locales/nl-NL/welcome.ogg | Bin 2917 -> 0 bytes .../main/assets/locales/nl-NL/wificonfig.ogg | Bin 5759 -> 0 bytes .../main/assets/locales/pl-PL/0.ogg | Bin 2138 -> 0 bytes .../main/assets/locales/pl-PL/1.ogg | Bin 2152 -> 0 bytes .../main/assets/locales/pl-PL/2.ogg | Bin 1762 -> 0 bytes .../main/assets/locales/pl-PL/3.ogg | Bin 1821 -> 0 bytes .../main/assets/locales/pl-PL/4.ogg | Bin 1883 -> 0 bytes .../main/assets/locales/pl-PL/5.ogg | Bin 2067 -> 0 bytes .../main/assets/locales/pl-PL/6.ogg | Bin 2430 -> 0 bytes .../main/assets/locales/pl-PL/7.ogg | Bin 2142 -> 0 bytes .../main/assets/locales/pl-PL/8.ogg | Bin 1963 -> 0 bytes .../main/assets/locales/pl-PL/9.ogg | Bin 2386 -> 0 bytes .../main/assets/locales/pl-PL/activation.ogg | Bin 10689 -> 0 bytes .../main/assets/locales/pl-PL/err_pin.ogg | Bin 4294 -> 0 bytes .../main/assets/locales/pl-PL/err_reg.ogg | Bin 7341 -> 0 bytes .../main/assets/locales/pl-PL/language.json | 55 - .../main/assets/locales/pl-PL/upgrade.ogg | Bin 3937 -> 0 bytes .../main/assets/locales/pl-PL/welcome.ogg | Bin 3562 -> 0 bytes .../main/assets/locales/pl-PL/wificonfig.ogg | Bin 4551 -> 0 bytes .../main/assets/locales/pt-PT/0.ogg | Bin 1977 -> 0 bytes .../main/assets/locales/pt-PT/1.ogg | Bin 1496 -> 0 bytes .../main/assets/locales/pt-PT/2.ogg | Bin 1876 -> 0 bytes .../main/assets/locales/pt-PT/3.ogg | Bin 2119 -> 0 bytes .../main/assets/locales/pt-PT/4.ogg | Bin 1843 -> 0 bytes .../main/assets/locales/pt-PT/5.ogg | Bin 2197 -> 0 bytes .../main/assets/locales/pt-PT/6.ogg | Bin 1886 -> 0 bytes .../main/assets/locales/pt-PT/7.ogg | Bin 2094 -> 0 bytes .../main/assets/locales/pt-PT/8.ogg | Bin 1973 -> 0 bytes .../main/assets/locales/pt-PT/9.ogg | Bin 1809 -> 0 bytes .../main/assets/locales/pt-PT/activation.ogg | Bin 14660 -> 0 bytes .../main/assets/locales/pt-PT/err_pin.ogg | Bin 3457 -> 0 bytes .../main/assets/locales/pt-PT/err_reg.ogg | Bin 8363 -> 0 bytes .../main/assets/locales/pt-PT/language.json | 55 - .../main/assets/locales/pt-PT/upgrade.ogg | Bin 4051 -> 0 bytes .../main/assets/locales/pt-PT/welcome.ogg | Bin 3053 -> 0 bytes .../main/assets/locales/pt-PT/wificonfig.ogg | Bin 5471 -> 0 bytes .../main/assets/locales/ro-RO/0.ogg | Bin 1958 -> 0 bytes .../main/assets/locales/ro-RO/1.ogg | Bin 1870 -> 0 bytes .../main/assets/locales/ro-RO/2.ogg | Bin 1839 -> 0 bytes .../main/assets/locales/ro-RO/3.ogg | Bin 1566 -> 0 bytes .../main/assets/locales/ro-RO/4.ogg | Bin 2149 -> 0 bytes .../main/assets/locales/ro-RO/5.ogg | Bin 1766 -> 0 bytes .../main/assets/locales/ro-RO/6.ogg | Bin 1947 -> 0 bytes .../main/assets/locales/ro-RO/7.ogg | Bin 2318 -> 0 bytes .../main/assets/locales/ro-RO/8.ogg | Bin 2000 -> 0 bytes .../main/assets/locales/ro-RO/9.ogg | Bin 2279 -> 0 bytes .../main/assets/locales/ro-RO/activation.ogg | Bin 15258 -> 0 bytes .../main/assets/locales/ro-RO/err_pin.ogg | Bin 5609 -> 0 bytes .../main/assets/locales/ro-RO/err_reg.ogg | Bin 9224 -> 0 bytes .../main/assets/locales/ro-RO/language.json | 55 - .../main/assets/locales/ro-RO/upgrade.ogg | Bin 4479 -> 0 bytes .../main/assets/locales/ro-RO/welcome.ogg | Bin 2592 -> 0 bytes .../main/assets/locales/ro-RO/wificonfig.ogg | Bin 5552 -> 0 bytes .../main/assets/locales/ru-RU/0.ogg | Bin 1661 -> 0 bytes .../main/assets/locales/ru-RU/1.ogg | Bin 1847 -> 0 bytes .../main/assets/locales/ru-RU/2.ogg | Bin 1215 -> 0 bytes .../main/assets/locales/ru-RU/3.ogg | Bin 854 -> 0 bytes .../main/assets/locales/ru-RU/4.ogg | Bin 2328 -> 0 bytes .../main/assets/locales/ru-RU/5.ogg | Bin 2106 -> 0 bytes .../main/assets/locales/ru-RU/6.ogg | Bin 1091 -> 0 bytes .../main/assets/locales/ru-RU/7.ogg | Bin 1103 -> 0 bytes .../main/assets/locales/ru-RU/8.ogg | Bin 2557 -> 0 bytes .../main/assets/locales/ru-RU/9.ogg | Bin 1986 -> 0 bytes .../main/assets/locales/ru-RU/activation.ogg | Bin 12285 -> 0 bytes .../main/assets/locales/ru-RU/err_pin.ogg | Bin 5773 -> 0 bytes .../main/assets/locales/ru-RU/err_reg.ogg | Bin 9221 -> 0 bytes .../main/assets/locales/ru-RU/language.json | 55 - .../main/assets/locales/ru-RU/upgrade.ogg | Bin 3396 -> 0 bytes .../main/assets/locales/ru-RU/welcome.ogg | Bin 2327 -> 0 bytes .../main/assets/locales/ru-RU/wificonfig.ogg | Bin 7563 -> 0 bytes .../main/assets/locales/sk-SK/0.ogg | Bin 1640 -> 0 bytes .../main/assets/locales/sk-SK/1.ogg | Bin 1940 -> 0 bytes .../main/assets/locales/sk-SK/2.ogg | Bin 1620 -> 0 bytes .../main/assets/locales/sk-SK/3.ogg | Bin 2105 -> 0 bytes .../main/assets/locales/sk-SK/4.ogg | Bin 1893 -> 0 bytes .../main/assets/locales/sk-SK/5.ogg | Bin 1815 -> 0 bytes .../main/assets/locales/sk-SK/6.ogg | Bin 1924 -> 0 bytes .../main/assets/locales/sk-SK/7.ogg | Bin 1886 -> 0 bytes .../main/assets/locales/sk-SK/8.ogg | Bin 2521 -> 0 bytes .../main/assets/locales/sk-SK/9.ogg | Bin 1858 -> 0 bytes .../main/assets/locales/sk-SK/activation.ogg | Bin 10223 -> 0 bytes .../main/assets/locales/sk-SK/err_pin.ogg | Bin 3467 -> 0 bytes .../main/assets/locales/sk-SK/err_reg.ogg | Bin 8656 -> 0 bytes .../main/assets/locales/sk-SK/language.json | 57 - .../main/assets/locales/sk-SK/upgrade.ogg | Bin 3417 -> 0 bytes .../main/assets/locales/sk-SK/welcome.ogg | Bin 2630 -> 0 bytes .../main/assets/locales/sk-SK/wificonfig.ogg | Bin 5506 -> 0 bytes .../main/assets/locales/sl-SI/0.ogg | Bin 1907 -> 0 bytes .../main/assets/locales/sl-SI/1.ogg | Bin 1324 -> 0 bytes .../main/assets/locales/sl-SI/2.ogg | Bin 1552 -> 0 bytes .../main/assets/locales/sl-SI/3.ogg | Bin 1385 -> 0 bytes .../main/assets/locales/sl-SI/4.ogg | Bin 1638 -> 0 bytes .../main/assets/locales/sl-SI/5.ogg | Bin 1308 -> 0 bytes .../main/assets/locales/sl-SI/6.ogg | Bin 1913 -> 0 bytes .../main/assets/locales/sl-SI/7.ogg | Bin 1623 -> 0 bytes .../main/assets/locales/sl-SI/8.ogg | Bin 1652 -> 0 bytes .../main/assets/locales/sl-SI/9.ogg | Bin 1522 -> 0 bytes .../main/assets/locales/sl-SI/activation.ogg | Bin 14764 -> 0 bytes .../main/assets/locales/sl-SI/err_pin.ogg | Bin 5445 -> 0 bytes .../main/assets/locales/sl-SI/err_reg.ogg | Bin 9313 -> 0 bytes .../main/assets/locales/sl-SI/language.json | 57 - .../main/assets/locales/sl-SI/upgrade.ogg | Bin 3282 -> 0 bytes .../main/assets/locales/sl-SI/welcome.ogg | Bin 3786 -> 0 bytes .../main/assets/locales/sl-SI/wificonfig.ogg | Bin 7214 -> 0 bytes .../main/assets/locales/sr-RS/language.json | 57 - .../main/assets/locales/sv-SE/0.ogg | Bin 2303 -> 0 bytes .../main/assets/locales/sv-SE/1.ogg | Bin 2228 -> 0 bytes .../main/assets/locales/sv-SE/2.ogg | Bin 1995 -> 0 bytes .../main/assets/locales/sv-SE/3.ogg | Bin 2018 -> 0 bytes .../main/assets/locales/sv-SE/4.ogg | Bin 2010 -> 0 bytes .../main/assets/locales/sv-SE/5.ogg | Bin 1938 -> 0 bytes .../main/assets/locales/sv-SE/6.ogg | Bin 1900 -> 0 bytes .../main/assets/locales/sv-SE/7.ogg | Bin 1894 -> 0 bytes .../main/assets/locales/sv-SE/8.ogg | Bin 2028 -> 0 bytes .../main/assets/locales/sv-SE/9.ogg | Bin 2597 -> 0 bytes .../main/assets/locales/sv-SE/activation.ogg | Bin 14059 -> 0 bytes .../main/assets/locales/sv-SE/err_pin.ogg | Bin 5779 -> 0 bytes .../main/assets/locales/sv-SE/err_reg.ogg | Bin 8675 -> 0 bytes .../main/assets/locales/sv-SE/language.json | 57 - .../main/assets/locales/sv-SE/upgrade.ogg | Bin 4643 -> 0 bytes .../main/assets/locales/sv-SE/welcome.ogg | Bin 2490 -> 0 bytes .../main/assets/locales/sv-SE/wificonfig.ogg | Bin 6484 -> 0 bytes .../main/assets/locales/th-TH/0.ogg | Bin 2279 -> 0 bytes .../main/assets/locales/th-TH/1.ogg | Bin 2055 -> 0 bytes .../main/assets/locales/th-TH/2.ogg | Bin 2086 -> 0 bytes .../main/assets/locales/th-TH/3.ogg | Bin 2251 -> 0 bytes .../main/assets/locales/th-TH/4.ogg | Bin 1919 -> 0 bytes .../main/assets/locales/th-TH/5.ogg | Bin 1961 -> 0 bytes .../main/assets/locales/th-TH/6.ogg | Bin 1889 -> 0 bytes .../main/assets/locales/th-TH/7.ogg | Bin 1590 -> 0 bytes .../main/assets/locales/th-TH/8.ogg | Bin 1560 -> 0 bytes .../main/assets/locales/th-TH/9.ogg | Bin 1646 -> 0 bytes .../main/assets/locales/th-TH/activation.ogg | Bin 9627 -> 0 bytes .../main/assets/locales/th-TH/err_pin.ogg | Bin 3382 -> 0 bytes .../main/assets/locales/th-TH/err_reg.ogg | Bin 9745 -> 0 bytes .../main/assets/locales/th-TH/language.json | 56 - .../main/assets/locales/th-TH/upgrade.ogg | Bin 3404 -> 0 bytes .../main/assets/locales/th-TH/welcome.ogg | Bin 3788 -> 0 bytes .../main/assets/locales/th-TH/wificonfig.ogg | Bin 5596 -> 0 bytes .../main/assets/locales/tr-TR/0.ogg | Bin 1972 -> 0 bytes .../main/assets/locales/tr-TR/1.ogg | Bin 1983 -> 0 bytes .../main/assets/locales/tr-TR/2.ogg | Bin 1699 -> 0 bytes .../main/assets/locales/tr-TR/3.ogg | Bin 1767 -> 0 bytes .../main/assets/locales/tr-TR/4.ogg | Bin 1972 -> 0 bytes .../main/assets/locales/tr-TR/5.ogg | Bin 1868 -> 0 bytes .../main/assets/locales/tr-TR/6.ogg | Bin 2014 -> 0 bytes .../main/assets/locales/tr-TR/7.ogg | Bin 1818 -> 0 bytes .../main/assets/locales/tr-TR/8.ogg | Bin 2196 -> 0 bytes .../main/assets/locales/tr-TR/9.ogg | Bin 2002 -> 0 bytes .../main/assets/locales/tr-TR/activation.ogg | Bin 10808 -> 0 bytes .../main/assets/locales/tr-TR/err_pin.ogg | Bin 4456 -> 0 bytes .../main/assets/locales/tr-TR/err_reg.ogg | Bin 9495 -> 0 bytes .../main/assets/locales/tr-TR/language.json | 55 - .../main/assets/locales/tr-TR/upgrade.ogg | Bin 4021 -> 0 bytes .../main/assets/locales/tr-TR/welcome.ogg | Bin 3010 -> 0 bytes .../main/assets/locales/tr-TR/wificonfig.ogg | Bin 5432 -> 0 bytes .../main/assets/locales/uk-UA/0.ogg | Bin 2003 -> 0 bytes .../main/assets/locales/uk-UA/1.ogg | Bin 1902 -> 0 bytes .../main/assets/locales/uk-UA/2.ogg | Bin 2026 -> 0 bytes .../main/assets/locales/uk-UA/3.ogg | Bin 1765 -> 0 bytes .../main/assets/locales/uk-UA/4.ogg | Bin 2327 -> 0 bytes .../main/assets/locales/uk-UA/5.ogg | Bin 1989 -> 0 bytes .../main/assets/locales/uk-UA/6.ogg | Bin 1975 -> 0 bytes .../main/assets/locales/uk-UA/7.ogg | Bin 1678 -> 0 bytes .../main/assets/locales/uk-UA/8.ogg | Bin 2279 -> 0 bytes .../main/assets/locales/uk-UA/9.ogg | Bin 2146 -> 0 bytes .../main/assets/locales/uk-UA/activation.ogg | Bin 14195 -> 0 bytes .../main/assets/locales/uk-UA/err_pin.ogg | Bin 4537 -> 0 bytes .../main/assets/locales/uk-UA/err_reg.ogg | Bin 9545 -> 0 bytes .../main/assets/locales/uk-UA/language.json | 55 - .../main/assets/locales/uk-UA/upgrade.ogg | Bin 3642 -> 0 bytes .../main/assets/locales/uk-UA/welcome.ogg | Bin 2803 -> 0 bytes .../main/assets/locales/uk-UA/wificonfig.ogg | Bin 5981 -> 0 bytes .../main/assets/locales/vi-VN/0.ogg | Bin 1446 -> 0 bytes .../main/assets/locales/vi-VN/1.ogg | Bin 1635 -> 0 bytes .../main/assets/locales/vi-VN/2.ogg | Bin 1857 -> 0 bytes .../main/assets/locales/vi-VN/3.ogg | Bin 1656 -> 0 bytes .../main/assets/locales/vi-VN/4.ogg | Bin 1649 -> 0 bytes .../main/assets/locales/vi-VN/5.ogg | Bin 1443 -> 0 bytes .../main/assets/locales/vi-VN/6.ogg | Bin 1786 -> 0 bytes .../main/assets/locales/vi-VN/7.ogg | Bin 1967 -> 0 bytes .../main/assets/locales/vi-VN/8.ogg | Bin 1494 -> 0 bytes .../main/assets/locales/vi-VN/9.ogg | Bin 1733 -> 0 bytes .../main/assets/locales/vi-VN/activation.ogg | Bin 9747 -> 0 bytes .../main/assets/locales/vi-VN/err_pin.ogg | Bin 3806 -> 0 bytes .../main/assets/locales/vi-VN/err_reg.ogg | Bin 8213 -> 0 bytes .../main/assets/locales/vi-VN/language.json | 56 - .../main/assets/locales/vi-VN/upgrade.ogg | Bin 4162 -> 0 bytes .../main/assets/locales/vi-VN/welcome.ogg | Bin 2929 -> 0 bytes .../main/assets/locales/vi-VN/wificonfig.ogg | Bin 5203 -> 0 bytes .../main/assets/locales/zh-CN/0.ogg | Bin 1438 -> 0 bytes .../main/assets/locales/zh-CN/1.ogg | Bin 1485 -> 0 bytes .../main/assets/locales/zh-CN/2.ogg | Bin 1250 -> 0 bytes .../main/assets/locales/zh-CN/3.ogg | Bin 1503 -> 0 bytes .../main/assets/locales/zh-CN/4.ogg | Bin 1634 -> 0 bytes .../main/assets/locales/zh-CN/5.ogg | Bin 1512 -> 0 bytes .../main/assets/locales/zh-CN/6.ogg | Bin 1496 -> 0 bytes .../main/assets/locales/zh-CN/7.ogg | Bin 1652 -> 0 bytes .../main/assets/locales/zh-CN/8.ogg | Bin 1473 -> 0 bytes .../main/assets/locales/zh-CN/9.ogg | Bin 1421 -> 0 bytes .../main/assets/locales/zh-CN/activation.ogg | Bin 8402 -> 0 bytes .../main/assets/locales/zh-CN/err_pin.ogg | Bin 3538 -> 0 bytes .../main/assets/locales/zh-CN/err_reg.ogg | Bin 6747 -> 0 bytes .../main/assets/locales/zh-CN/language.json | 55 - .../main/assets/locales/zh-CN/upgrade.ogg | Bin 2847 -> 0 bytes .../main/assets/locales/zh-CN/welcome.ogg | Bin 3493 -> 0 bytes .../main/assets/locales/zh-CN/wificonfig.ogg | Bin 3155 -> 0 bytes .../main/assets/locales/zh-TW/0.ogg | Bin 1438 -> 0 bytes .../main/assets/locales/zh-TW/1.ogg | Bin 1485 -> 0 bytes .../main/assets/locales/zh-TW/2.ogg | Bin 1250 -> 0 bytes .../main/assets/locales/zh-TW/3.ogg | Bin 1503 -> 0 bytes .../main/assets/locales/zh-TW/4.ogg | Bin 1634 -> 0 bytes .../main/assets/locales/zh-TW/5.ogg | Bin 1512 -> 0 bytes .../main/assets/locales/zh-TW/6.ogg | Bin 1496 -> 0 bytes .../main/assets/locales/zh-TW/7.ogg | Bin 1652 -> 0 bytes .../main/assets/locales/zh-TW/8.ogg | Bin 1473 -> 0 bytes .../main/assets/locales/zh-TW/9.ogg | Bin 1421 -> 0 bytes .../main/assets/locales/zh-TW/activation.ogg | Bin 8402 -> 0 bytes .../main/assets/locales/zh-TW/err_pin.ogg | Bin 3538 -> 0 bytes .../main/assets/locales/zh-TW/err_reg.ogg | Bin 6747 -> 0 bytes .../main/assets/locales/zh-TW/language.json | 55 - .../main/assets/locales/zh-TW/upgrade.ogg | Bin 2847 -> 0 bytes .../main/assets/locales/zh-TW/welcome.ogg | Bin 3493 -> 0 bytes .../main/assets/locales/zh-TW/wificonfig.ogg | Bin 3155 -> 0 bytes .../XiaoZhiCode_V2.1.0/main/audio/README.md | 88 - .../main/audio/audio_codec.cc | 77 - .../main/audio/audio_codec.h | 61 - .../main/audio/audio_processor.h | 26 - .../main/audio/audio_service.cc | 686 -------- .../main/audio/audio_service.h | 161 -- .../main/audio/codecs/box_audio_codec.cc | 245 --- .../main/audio/codecs/box_audio_codec.h | 40 - .../main/audio/codecs/dummy_audio_codec.cc | 20 - .../main/audio/codecs/dummy_audio_codec.h | 16 - .../main/audio/codecs/es8311_audio_codec.cc | 197 --- .../main/audio/codecs/es8311_audio_codec.h | 42 - .../main/audio/codecs/es8374_audio_codec.cc | 198 --- .../main/audio/codecs/es8374_audio_codec.h | 41 - .../main/audio/codecs/es8388_audio_codec.cc | 221 --- .../main/audio/codecs/es8388_audio_codec.h | 40 - .../main/audio/codecs/es8389_audio_codec.cc | 204 --- .../main/audio/codecs/es8389_audio_codec.h | 40 - .../main/audio/codecs/no_audio_codec.cc | 359 ----- .../main/audio/codecs/no_audio_codec.h | 39 - .../audio/processors/afe_audio_processor.cc | 187 --- .../audio/processors/afe_audio_processor.h | 45 - .../main/audio/processors/audio_debugger.cc | 68 - .../main/audio/processors/audio_debugger.h | 22 - .../audio/processors/no_audio_processor.cc | 59 - .../audio/processors/no_audio_processor.h | 33 - .../XiaoZhiCode_V2.1.0/main/audio/wake_word.h | 26 - .../main/audio/wake_words/afe_wake_word.cc | 208 --- .../main/audio/wake_words/afe_wake_word.h | 60 - .../main/audio/wake_words/custom_wake_word.cc | 254 --- .../main/audio/wake_words/custom_wake_word.h | 69 - .../main/audio/wake_words/esp_wake_word.cc | 87 - .../main/audio/wake_words/esp_wake_word.h | 42 - .../main/boards/aipi-lite/README.md | 41 - .../main/boards/aipi-lite/README_en.md | 40 - .../main/boards/aipi-lite/aipi-lite.cc | 246 --- .../main/boards/aipi-lite/config.h | 53 - .../main/boards/aipi-lite/config.json | 12 - .../main/boards/aipi-lite/config_en.json | 17 - .../main/boards/aipi-lite/power_manager.h | 187 --- .../atk-dnesp32s3-box/atk_dnesp32s3_box.cc | 299 ---- .../main/boards/atk-dnesp32s3-box/config.h | 46 - .../main/boards/atk-dnesp32s3-box/config.json | 11 - .../atk-dnesp32s3-box0/atk_dnesp32s3_box0.cc | 388 ----- .../main/boards/atk-dnesp32s3-box0/config.h | 84 - .../boards/atk-dnesp32s3-box0/config.json | 9 - .../boards/atk-dnesp32s3-box0/power_manager.h | 193 --- .../atk_dnesp32s3_box2.cc | 477 ------ .../boards/atk-dnesp32s3-box2-4g/config.h | 80 - .../boards/atk-dnesp32s3-box2-4g/config.json | 9 - .../atk-dnesp32s3-box2-4g/power_manager.h | 195 --- .../atk_dnesp32s3_box2.cc | 456 ------ .../boards/atk-dnesp32s3-box2-wifi/config.h | 71 - .../atk-dnesp32s3-box2-wifi/config.json | 9 - .../atk-dnesp32s3-box2-wifi/power_manager.h | 195 --- .../boards/atk-dnesp32s3/atk_dnesp32s3.cc | 225 --- .../main/boards/atk-dnesp32s3/config.h | 64 - .../main/boards/atk-dnesp32s3/config.json | 13 - .../atk-dnesp32s3m-4g/atk_dnesp32s3m.cc | 220 --- .../main/boards/atk-dnesp32s3m-4g/config.h | 53 - .../atk-dnesp32s3m-wifi/atk_dnesp32s3m.cc | 230 --- .../main/boards/atk-dnesp32s3m-wifi/config.h | 52 - .../main/boards/atom-echos3r/README.md | 45 - .../main/boards/atom-echos3r/atom_echos3r.cc | 91 -- .../main/boards/atom-echos3r/config.h | 29 - .../main/boards/atom-echos3r/config.json | 12 - .../boards/atommatrix-echo-base/README.md | 25 - .../atommatrix_echo_base.cc | 133 -- .../main/boards/atommatrix-echo-base/config.h | 29 - .../boards/atommatrix-echo-base/config.json | 10 - .../main/boards/atoms3-echo-base/README.md | 49 - .../atoms3-echo-base/atoms3_echo_base.cc | 228 --- .../main/boards/atoms3-echo-base/config.h | 43 - .../main/boards/atoms3-echo-base/config.json | 13 - .../atoms3r-cam-m12-echo-base/README.md | 60 - .../atoms3r_cam_m12_echo_base.cc | 204 --- .../boards/atoms3r-cam-m12-echo-base/config.h | 49 - .../atoms3r-cam-m12-echo-base/config.json | 15 - .../main/boards/atoms3r-echo-base/README.md | 43 - .../atoms3r-echo-base/atoms3r_echo_base.cc | 308 ---- .../main/boards/atoms3r-echo-base/config.h | 43 - .../main/boards/atoms3r-echo-base/config.json | 12 - .../boards/bread-compact-esp32-lcd/config.h | 278 ---- .../bread-compact-esp32-lcd/config.json | 11 - .../esp32_bread_board_lcd.cc | 213 --- .../main/boards/bread-compact-esp32/README.md | 25 - .../main/boards/bread-compact-esp32/config.h | 58 - .../boards/bread-compact-esp32/config.json | 17 - .../bread-compact-esp32/esp32_bread_board.cc | 174 -- .../compact_ml307_board.cc | 191 --- .../main/boards/bread-compact-ml307/config.h | 59 - .../boards/bread-compact-ml307/config.json | 17 - .../compact_wifi_board_lcd.cc | 183 --- .../boards/bread-compact-wifi-lcd/config.h | 289 ---- .../boards/bread-compact-wifi-s3cam/README.md | 51 - .../compact_wifi_board_s3cam.cc | 229 --- .../boards/bread-compact-wifi-s3cam/config.h | 308 ---- .../bread-compact-wifi/compact_wifi_board.cc | 188 --- .../main/boards/bread-compact-wifi/config.h | 59 - .../boards/bread-compact-wifi/config.json | 17 - .../main/boards/common/adc_battery_monitor.cc | 116 -- .../main/boards/common/adc_battery_monitor.h | 30 - .../main/boards/common/afsk_demod.cc | 375 ----- .../main/boards/common/afsk_demod.h | 177 -- .../main/boards/common/axp2101.cc | 41 - .../main/boards/common/axp2101.h | 20 - .../main/boards/common/backlight.cc | 121 -- .../main/boards/common/backlight.h | 36 - .../main/boards/common/blufi.cpp | 777 --------- .../main/boards/common/blufi.h | 123 -- .../main/boards/common/board.cc | 178 -- .../main/boards/common/board.h | 92 -- .../main/boards/common/button.cc | 125 -- .../main/boards/common/button.h | 49 - .../main/boards/common/camera.h | 15 - .../main/boards/common/dual_network_board.cc | 98 -- .../main/boards/common/dual_network_board.h | 60 - .../main/boards/common/esp32_camera.cc | 1039 ------------ .../main/boards/common/esp32_camera.h | 56 - .../main/boards/common/i2c_device.cc | 35 - .../main/boards/common/i2c_device.h | 18 - .../main/boards/common/knob.cc | 52 - .../main/boards/common/knob.h | 25 - .../main/boards/common/lamp_controller.h | 44 - .../main/boards/common/ml307_board.cc | 274 ---- .../main/boards/common/ml307_board.h | 38 - .../main/boards/common/power_save_timer.cc | 132 -- .../main/boards/common/power_save_timer.h | 34 - .../boards/common/press_to_talk_mcp_tool.cc | 57 - .../boards/common/press_to_talk_mcp_tool.h | 29 - .../main/boards/common/sleep_timer.cc | 133 -- .../main/boards/common/sleep_timer.h | 32 - .../main/boards/common/sy6970.cc | 65 - .../main/boards/common/sy6970.h | 21 - .../main/boards/common/system_reset.cc | 72 - .../main/boards/common/system_reset.h | 21 - .../main/boards/common/wifi_board.cc | 359 ----- .../main/boards/common/wifi_board.h | 69 - .../main/boards/df-k10/README.md | 37 - .../main/boards/df-k10/config.h | 76 - .../main/boards/df-k10/config.json | 11 - .../main/boards/df-k10/df_k10_board.cc | 294 ---- .../main/boards/df-k10/k10_audio_codec.cc | 225 --- .../main/boards/df-k10/k10_audio_codec.h | 37 - .../main/boards/df-k10/led_control.cc | 124 -- .../main/boards/df-k10/led_control.h | 18 - .../main/boards/df-s3-ai-cam/README.md | 54 - .../main/boards/df-s3-ai-cam/config.h | 63 - .../main/boards/df-s3-ai-cam/config.json | 13 - .../main/boards/df-s3-ai-cam/df_s3_ai_cam.cc | 103 -- .../main/boards/doit-s3-aibox/README.md | 42 - .../main/boards/doit-s3-aibox/config.h | 29 - .../main/boards/doit-s3-aibox/config.json | 10 - .../boards/doit-s3-aibox/doit_s3_aibox.cc | 137 -- .../main/boards/du-chatx/config.h | 40 - .../main/boards/du-chatx/config.json | 9 - .../main/boards/du-chatx/du-chatx-wifi.cc | 164 -- .../main/boards/du-chatx/power_manager.h | 186 --- .../main/boards/echoear/EchoEar.cc | 666 -------- .../main/boards/echoear/README.md | 82 - .../main/boards/echoear/config.h | 88 - .../main/boards/echoear/config.json | 13 - .../main/boards/echoear/emote.json | 22 - .../main/boards/echoear/layout.json | 37 - .../main/boards/echoear/touch.h | 51 - .../main/boards/electron-bot/README.md | 75 - .../main/boards/electron-bot/config.h | 51 - .../main/boards/electron-bot/config.json | 9 - .../main/boards/electron-bot/electron_bot.cc | 123 -- .../electron-bot/electron_bot_controller.cc | 376 ----- .../electron-bot/electron_emoji_display.cc | 139 -- .../electron-bot/electron_emoji_display.h | 22 - .../main/boards/electron-bot/movements.cc | 470 ------ .../main/boards/electron-bot/movements.h | 89 - .../main/boards/electron-bot/oscillator.cc | 149 -- .../main/boards/electron-bot/oscillator.h | 83 - .../main/boards/electron-bot/otto_icon_font.c | 121 -- .../main/boards/electron-bot/power_manager.h | 128 -- .../main/boards/esp-box-3/README.md | 132 -- .../main/boards/esp-box-3/config.h | 41 - .../main/boards/esp-box-3/config.json | 14 - .../main/boards/esp-box-3/emote.json | 22 - .../main/boards/esp-box-3/esp_box3_board.cc | 175 -- .../main/boards/esp-box-3/layout.json | 37 - .../esp-box-lite/box_audio_codec_lite.cc | 272 ---- .../esp-box-lite/box_audio_codec_lite.h | 41 - .../main/boards/esp-box-lite/config.h | 39 - .../main/boards/esp-box-lite/config.json | 11 - .../boards/esp-box-lite/esp_box_lite_board.cc | 237 --- .../main/boards/esp-box/config.h | 41 - .../main/boards/esp-box/config.json | 9 - .../main/boards/esp-box/esp_box_board.cc | 168 -- .../main/boards/esp-hi/README.md | 51 - .../main/boards/esp-hi/adc_pdm_audio_codec.cc | 249 --- .../main/boards/esp-hi/adc_pdm_audio_codec.h | 37 - .../main/boards/esp-hi/config.h | 47 - .../main/boards/esp-hi/config.json | 33 - .../main/boards/esp-hi/emoji_display.cc | 178 -- .../main/boards/esp-hi/emoji_display.h | 55 - .../main/boards/esp-hi/esp_hi.cc | 421 ----- .../boards/esp-p4-function-ev-board/README.md | 41 - .../boards/esp-p4-function-ev-board/config.h | 11 - .../esp-p4-function-ev-board/config.json | 16 - .../esp-p4-function-ev-board.cc | 233 --- .../boards/esp-s3-lcd-ev-board-2/README.md | 10 - .../boards/esp-s3-lcd-ev-board-2/config.h | 42 - .../boards/esp-s3-lcd-ev-board-2/config.json | 9 - .../esp-s3-lcd-ev-board-2.cc | 271 ---- .../esp-s3-lcd-ev-board-2/esp_lcd_gc9503.c | 504 ------ .../esp-s3-lcd-ev-board-2/esp_lcd_gc9503.h | 146 -- .../boards/esp-s3-lcd-ev-board-2/pin_config.h | 52 - .../main/boards/esp-s3-lcd-ev-board/README.md | 11 - .../main/boards/esp-s3-lcd-ev-board/config.h | 53 - .../boards/esp-s3-lcd-ev-board/config.json | 17 - .../esp-s3-lcd-ev-board.cc | 240 --- .../esp_io_expander_tca9554.c | 154 -- .../esp_io_expander_tca9554.h | 90 -- .../esp-s3-lcd-ev-board/esp_lcd_gc9503.c | 504 ------ .../esp-s3-lcd-ev-board/esp_lcd_gc9503.h | 167 -- .../boards/esp-s3-lcd-ev-board/pin_config.h | 62 - .../main/boards/esp-sensairshuttle/README.md | 39 - .../esp-sensairshuttle/adc_pdm_audio_codec.cc | 249 --- .../esp-sensairshuttle/adc_pdm_audio_codec.h | 37 - .../main/boards/esp-sensairshuttle/config.h | 40 - .../boards/esp-sensairshuttle/config.json | 28 - .../esp-sensairshuttle/esp-sensairshuttle.cc | 315 ---- .../main/boards/esp-sparkbot/config.h | 99 -- .../main/boards/esp-sparkbot/config.json | 13 - .../boards/esp-sparkbot/esp_sparkbot_board.cc | 302 ---- .../main/boards/esp-spot/README.md | 63 - .../main/boards/esp-spot/config.h | 79 - .../main/boards/esp-spot/config.json | 14 - .../main/boards/esp-spot/esp_spot_board.cc | 436 ----- .../main/boards/esp32-cgc-144/README.md | 30 - .../main/boards/esp32-cgc-144/config.h | 73 - .../main/boards/esp32-cgc-144/config.json | 10 - .../esp32-cgc-144/esp32_cgc_144_board.cc | 192 --- .../main/boards/esp32-cgc-144/power_manager.h | 186 --- .../boards/esp32-cgc-144/power_manager_lite.h | 185 --- .../main/boards/esp32-cgc/README.md | 36 - .../main/boards/esp32-cgc/config.h | 271 ---- .../main/boards/esp32-cgc/config.json | 11 - .../main/boards/esp32-cgc/esp32_cgc_board.cc | 180 --- .../boards/esp32-s3-touch-amoled-1.8/config.h | 41 - .../esp32-s3-touch-amoled-1.8/config.json | 11 - .../esp32-s3-touch-amoled-1.8.cc | 335 ---- .../boards/esp32-s3-touch-lcd-1.46/README.md | 4 - .../boards/esp32-s3-touch-lcd-1.46/config.h | 70 - .../esp32-s3-touch-lcd-1.46/config.json | 9 - .../esp32-s3-touch-lcd-1.46.cc | 237 --- .../boards/esp32-s3-touch-lcd-1.85/README.md | 3 - .../boards/esp32-s3-touch-lcd-1.85/config.h | 69 - .../esp32-s3-touch-lcd-1.85/config.json | 9 - .../esp32-s3-touch-lcd-1.85.cc | 447 ------ .../boards/esp32-s3-touch-lcd-1.85c/README.md | 3 - .../boards/esp32-s3-touch-lcd-1.85c/config.h | 67 - .../esp32-s3-touch-lcd-1.85c/config.json | 9 - .../esp32-s3-touch-lcd-1.85c.cc | 396 ----- .../boards/esp32-s3-touch-lcd-3.5/README.md | 3 - .../boards/esp32-s3-touch-lcd-3.5/config.h | 69 - .../boards/esp32-s3-touch-lcd-3.5/config.json | 19 - .../esp32-s3-touch-lcd-3.5.cc | 373 ----- .../main/boards/esp32s3-korvo2-v3/config.h | 81 - .../main/boards/esp32s3-korvo2-v3/config.json | 17 - .../esp32s3_korvo2_v3_board.cc | 456 ------ .../boards/esp32s3-korvo2-v3/power_manager.h | 250 --- .../main/boards/genjutech-s3-1.54tft/config.h | 43 - .../boards/genjutech-s3-1.54tft/config.json | 9 - .../genjutech-s3-1.54tft.cc | 259 --- .../genjutech-s3-1.54tft/power_manager.h | 186 --- .../main/boards/hu-087/README.md | 7 - .../main/boards/hu-087/config.h | 28 - .../main/boards/hu-087/config.json | 9 - .../main/boards/hu-087/hu_087_board.cc | 151 -- .../main/boards/jiuchuan-s3/README.md | 24 - .../main/boards/jiuchuan-s3/config.h | 52 - .../main/boards/jiuchuan-s3/config.json | 9 - .../boards/jiuchuan-s3/esp_lcd_panel_gc9301.c | 384 ----- .../boards/jiuchuan-s3/esp_lcd_panel_gc9301.h | 31 - .../main/boards/jiuchuan-s3/gpio_manager.h | 62 - .../boards/jiuchuan-s3/jiuchuan_dev_board.cc | 382 ----- .../boards/jiuchuan-s3/power_controller.h | 58 - .../main/boards/jiuchuan-s3/power_manager.h | 201 --- .../main/boards/kevin-box-2/config.h | 41 - .../main/boards/kevin-box-2/config.json | 9 - .../boards/kevin-box-2/kevin_box_board.cc | 270 ---- .../main/boards/kevin-c3/config.h | 24 - .../main/boards/kevin-c3/config.json | 13 - .../main/boards/kevin-c3/kevin_c3_board.cc | 90 -- .../main/boards/kevin-c3/led_strip_control.cc | 129 -- .../main/boards/kevin-c3/led_strip_control.h | 18 - .../main/boards/kevin-sp-v3-dev/config.h | 64 - .../kevin-sp-v3-dev/kevin-sp-v3_board.cc | 165 -- .../main/boards/kevin-sp-v4-dev/config.h | 66 - .../main/boards/kevin-sp-v4-dev/config.json | 17 - .../kevin-sp-v4-dev/kevin-sp-v4_board.cc | 177 -- .../main/boards/kevin-yuying-313lcd/config.h | 35 - .../boards/kevin-yuying-313lcd/config.json | 9 - .../kevin-yuying-313lcd/esp_lcd_gc9503.c | 478 ------ .../kevin-yuying-313lcd/esp_lcd_gc9503.h | 145 -- .../kevin_yuying_313lcd.cc | 163 -- .../boards/kevin-yuying-313lcd/pin_config.h | 47 - .../main/boards/labplus-ledong-v2/README.md | 62 - .../main/boards/labplus-ledong-v2/config.h | 44 - .../main/boards/labplus-ledong-v2/config.json | 9 - .../labplus-ledong-v2/labplus_ledong_v2.cc | 163 -- .../main/boards/labplus-mpython-v3/README.md | 61 - .../main/boards/labplus-mpython-v3/config.h | 44 - .../boards/labplus-mpython-v3/config.json | 9 - .../boards/labplus-mpython-v3/mpython_pro.cc | 143 -- .../main/boards/lichuang-c3-dev/README.md | 11 - .../main/boards/lichuang-c3-dev/config.h | 45 - .../main/boards/lichuang-c3-dev/config.json | 14 - .../lichuang-c3-dev/lichuang_c3_dev_board.cc | 129 -- .../main/boards/lichuang-dev/config.h | 62 - .../main/boards/lichuang-dev/config.json | 14 - .../main/boards/lichuang-dev/emote.json | 22 - .../main/boards/lichuang-dev/layout.json | 37 - .../boards/lichuang-dev/lichuang_dev_board.cc | 295 ---- .../boards/lilygo-t-cameraplus-s3/README.md | 47 - .../boards/lilygo-t-cameraplus-s3/config.h | 57 - .../boards/lilygo-t-cameraplus-s3/config.json | 23 - .../ir_filter_controller.h | 44 - .../lilygo-t-cameraplus-s3.cc | 350 ---- .../lilygo-t-cameraplus-s3/pin_config.h | 154 -- .../tcamerapluss3_audio_codec.cc | 169 -- .../tcamerapluss3_audio_codec.h | 37 - .../main/boards/lilygo-t-circle-s3/README.md | 28 - .../main/boards/lilygo-t-circle-s3/config.h | 46 - .../boards/lilygo-t-circle-s3/config.json | 9 - .../lilygo-t-circle-s3/esp_lcd_gc9d01n.c | 353 ---- .../lilygo-t-circle-s3/esp_lcd_gc9d01n.h | 99 -- .../lilygo-t-circle-s3/lilygo-t-circle-s3.cc | 258 --- .../boards/lilygo-t-circle-s3/pin_config.h | 47 - .../tcircles3_audio_codec.cc | 147 -- .../tcircles3_audio_codec.h | 37 - .../main/boards/lilygo-t-display-p4/README.md | 42 - .../main/boards/lilygo-t-display-p4/config.h | 76 - .../lilygo-t-display-p4/hi8561_driver.cc | 404 ----- .../lilygo-t-display-p4/hi8561_driver.h | 66 - .../lilygo-t-display-p4.cc | 397 ----- .../lilygo-t-display-p4/rm69a10_driver.cc | 377 ----- .../lilygo-t-display-p4/rm69a10_driver.h | 68 - .../lilygo-t-display-p4/t_display_p4_config.h | 233 --- .../README.md | 32 - .../lilygo-t-display-s3-pro-mvsrlora/config.h | 47 - .../config.json | 9 - .../lilygo-t-display-s3-pro-mvsrlora.cc | 283 ---- .../pin_config.h | 80 - .../tdisplays3promvsrlora_audio_codec.cc | 150 -- .../tdisplays3promvsrlora_audio_codec.h | 37 - .../main/boards/m5stack-core-s3/README.md | 22 - .../main/boards/m5stack-core-s3/config.h | 66 - .../main/boards/m5stack-core-s3/config.json | 14 - .../m5stack-core-s3/cores3_audio_codec.cc | 244 --- .../m5stack-core-s3/cores3_audio_codec.h | 37 - .../boards/m5stack-core-s3/m5stack_core_s3.cc | 396 ----- .../main/boards/m5stack-tab5/README.md | 57 - .../main/boards/m5stack-tab5/config.h | 325 ---- .../main/boards/m5stack-tab5/config.json | 19 - .../main/boards/m5stack-tab5/esp_lcd_st7123.c | 381 ----- .../main/boards/m5stack-tab5/esp_lcd_st7123.h | 125 -- .../main/boards/m5stack-tab5/m5stack_tab5.cc | 565 ------- .../main/boards/m5stack-tab5/sdkconfig.tab5 | 14 - .../boards/m5stack-tab5/tab5_audio_codec.cc | 243 --- .../boards/m5stack-tab5/tab5_audio_codec.h | 37 - .../main/boards/magiclick-2p4/config.h | 50 - .../main/boards/magiclick-2p4/config.json | 9 - .../magiclick-2p4/magiclick_2p4_board.cc | 271 ---- .../main/boards/magiclick-2p5/config.h | 55 - .../main/boards/magiclick-2p5/config.json | 12 - .../magiclick-2p5/magiclick_2p5_board.cc | 319 ---- .../main/boards/magiclick-2p5/power_manager.h | 195 --- .../main/boards/magiclick-c3-v2/config.h | 47 - .../main/boards/magiclick-c3-v2/config.json | 13 - .../magiclick-c3-v2/magiclick_c3_v2_board.cc | 232 --- .../main/boards/magiclick-c3/config.h | 47 - .../main/boards/magiclick-c3/config.json | 13 - .../boards/magiclick-c3/magiclick_c3_board.cc | 190 --- .../main/boards/minsi-k08-dual/README.md | 36 - .../main/boards/minsi-k08-dual/config.h | 47 - .../main/boards/minsi-k08-dual/config.json | 9 - .../boards/minsi-k08-dual/minsi_k08_dual.cc | 246 --- .../boards/minsi-k08-dual/power_manager.h | 187 --- .../main/boards/mixgo-nova/README.md | 72 - .../main/boards/mixgo-nova/config.h | 42 - .../main/boards/mixgo-nova/config.json | 14 - .../main/boards/mixgo-nova/mixgo-nova.cc | 168 -- .../boards/movecall-cuican-esp32s3/README.md | 44 - .../boards/movecall-cuican-esp32s3/config.h | 45 - .../movecall-cuican-esp32s3/config.json | 13 - .../movecall_cuican_esp32s3.cc | 123 -- .../boards/movecall-moji-esp32s3/README.md | 26 - .../boards/movecall-moji-esp32s3/config.h | 45 - .../boards/movecall-moji-esp32s3/config.json | 9 - .../movecall_moji_esp32s3.cc | 143 -- .../boards/movecall-moji2-esp32c5/README.md | 57 - .../movecall-moji2-esp32c5/README_zh.md | 57 - .../boards/movecall-moji2-esp32c5/config.h | 68 - .../boards/movecall-moji2-esp32c5/config.json | 18 - .../movecall_moji2_esp32s3.cc | 390 ----- .../main/boards/otto-robot/README.md | 207 --- .../main/boards/otto-robot/config.h | 157 -- .../main/boards/otto-robot/config.json | 14 - .../main/boards/otto-robot/oscillator.cc | 161 -- .../main/boards/otto-robot/oscillator.h | 91 -- .../main/boards/otto-robot/otto_controller.cc | 849 ---------- .../boards/otto-robot/otto_emoji_display.cc | 165 -- .../boards/otto-robot/otto_emoji_display.h | 23 - .../main/boards/otto-robot/otto_icon_font.c | 121 -- .../main/boards/otto-robot/otto_movements.cc | 964 ----------- .../main/boards/otto-robot/otto_movements.h | 117 -- .../main/boards/otto-robot/otto_robot.cc | 343 ---- .../main/boards/otto-robot/power_manager.h | 151 -- .../otto-robot/websocket_control_server.cc | 191 --- .../otto-robot/websocket_control_server.h | 33 - .../main/boards/sensecap-watcher/README.md | 52 - .../main/boards/sensecap-watcher/README_en.md | 53 - .../main/boards/sensecap-watcher/config.h | 152 -- .../main/boards/sensecap-watcher/config.json | 16 - .../boards/sensecap-watcher/config_en.json | 20 - .../sensecap-watcher/sensecap_audio_codec.cc | 214 --- .../sensecap-watcher/sensecap_audio_codec.h | 38 - .../sensecap-watcher/sensecap_watcher.cc | 661 -------- .../boards/sensecap-watcher/sscma_camera.cc | 743 --------- .../boards/sensecap-watcher/sscma_camera.h | 75 - .../boards/sp-esp32-s3-1.28-box/README.md | 31 - .../main/boards/sp-esp32-s3-1.28-box/config.h | 56 - .../boards/sp-esp32-s3-1.28-box/config.json | 9 - .../sp-esp32-s3-1.28-box/power_manager.h | 189 --- .../sp-esp32-s3-1.28-box.cc | 484 ------ .../boards/sp-esp32-s3-1.54-muma/README.md | 34 - .../boards/sp-esp32-s3-1.54-muma/config.h | 58 - .../boards/sp-esp32-s3-1.54-muma/config.json | 9 - .../sp-esp32-s3-1.54-muma/power_manager.h | 186 --- .../sp-esp32-s3-1.54-muma.cc | 325 ---- .../main/boards/surfer-c3-1.14tft/README.md | 5 - .../main/boards/surfer-c3-1.14tft/config.h | 45 - .../main/boards/surfer-c3-1.14tft/config.json | 14 - .../boards/surfer-c3-1.14tft/power_manager.h | 201 --- .../surfer-c3-1.14tft/surfer-c3-1.14tft.cc | 210 --- .../main/boards/taiji-pi-s3/README.md | 45 - .../main/boards/taiji-pi-s3/config.h | 66 - .../main/boards/taiji-pi-s3/config.json | 19 - .../main/boards/taiji-pi-s3/taiji_pi_s3.cc | 663 -------- .../main/boards/tudouzi/config.h | 41 - .../main/boards/tudouzi/config.json | 13 - .../main/boards/tudouzi/kevin_box_board.cc | 255 --- .../boards/waveshare-c6-lcd-1.69/README.md | 56 - .../boards/waveshare-c6-lcd-1.69/config.h | 54 - .../boards/waveshare-c6-lcd-1.69/config.json | 11 - .../esp32-c6-lcd-1.69.cc | 254 --- .../waveshare-c6-lcd-1.69/power_manager.h | 174 -- .../waveshare-c6-touch-amoled-1.32/README.md | 48 - .../waveshare-c6-touch-amoled-1.32/config.h | 44 - .../config.json | 11 - .../esp32-c6-touch-amoled-1.32.cc | 215 --- .../waveshare-c6-touch-amoled-1.43/README.md | 49 - .../waveshare-c6-touch-amoled-1.43/config.h | 49 - .../config.json | 11 - .../esp32-c6-touch-amoled-1.43.cc | 284 ---- .../waveshare-c6-touch-amoled-2.06/README.md | 4 - .../waveshare-c6-touch-amoled-2.06/config.h | 46 - .../config.json | 11 - .../esp32-c6-touch-amoled-2.06.cc | 314 ---- .../waveshare-c6-touch-lcd-1.83/README.md | 49 - .../waveshare-c6-touch-lcd-1.83/config.h | 50 - .../waveshare-c6-touch-lcd-1.83/config.json | 12 - .../esp32-c6-touch-lcd-1.83.cc | 261 --- .../main/boards/waveshare-p4-nano/README.md | 43 - .../main/boards/waveshare-p4-nano/config.h | 44 - .../main/boards/waveshare-p4-nano/config.json | 16 - .../boards/waveshare-p4-nano/esp32-p4-nano.cc | 263 --- .../waveshare-p4-wifi6-touch-lcd-4b/README.md | 12 - .../waveshare-p4-wifi6-touch-lcd-4b/config.h | 47 - .../config.json | 16 - .../esp32-p4-wifi6-touch-lcd-4b.cc | 228 --- .../waveshare-p4-wifi6-touch-lcd-7b/README.md | 12 - .../waveshare-p4-wifi6-touch-lcd-7b/config.h | 47 - .../config.json | 16 - .../esp32-p4-wifi6-touch-lcd-7b.cc | 249 --- .../waveshare-p4-wifi6-touch-lcd-xc/README.md | 22 - .../waveshare-p4-wifi6-touch-lcd-xc/config.h | 490 ------ .../config.json | 29 - .../esp32-p4-wifi6-touch-lcd-xc.cc | 229 --- .../boards/waveshare-s3-audio-board/README.md | 3 - .../boards/waveshare-s3-audio-board/config.h | 95 -- .../waveshare-s3-audio-board/config.json | 19 - .../esp32-s3-audio_board.cc | 239 --- .../waveshare-s3-audio-board/esp_lcd_jd9853.c | 460 ------ .../waveshare-s3-audio-board/esp_lcd_jd9853.h | 102 -- .../boards/waveshare-s3-epaper-1.54/README.md | 48 - .../board_power_bsp.cc | 59 - .../board_power_bsp.h | 23 - .../boards/waveshare-s3-epaper-1.54/config.h | 50 - .../waveshare-s3-epaper-1.54/config.json | 12 - .../custom_lcd_display.cc | 404 ----- .../custom_lcd_display.h | 75 - .../waveshare-s3-epaper-1.54.cc | 172 -- .../boards/waveshare-s3-rlcd-4.2/README.md | 0 .../boards/waveshare-s3-rlcd-4.2/config.h | 46 - .../boards/waveshare-s3-rlcd-4.2/config.json | 9 - .../custom_lcd_display.cc | 339 ---- .../custom_lcd_display.h | 57 - .../waveshare-s3-rlcd-4.2.cc | 100 -- .../waveshare-s3-touch-amoled-1.32/README.md | 48 - .../waveshare-s3-touch-amoled-1.32/config.h | 47 - .../config.json | 12 - .../esp32-s3-touch-amoled-1.32.cc | 215 --- .../waveshare-s3-touch-amoled-1.75/README.md | 15 - .../waveshare-s3-touch-amoled-1.75/config.h | 44 - .../config.json | 12 - .../esp32-s3-touch-amoled-1.75.cc | 360 ----- .../waveshare-s3-touch-amoled-2.06/README.md | 11 - .../waveshare-s3-touch-amoled-2.06/config.h | 43 - .../config.json | 12 - .../esp32-s3-touch-amoled-2.06.cc | 346 ---- .../waveshare-s3-touch-lcd-1.83/README.md | 4 - .../waveshare-s3-touch-lcd-1.83/config.h | 47 - .../waveshare-s3-touch-lcd-1.83/config.json | 12 - .../esp32-s3-touch-lcd-1.83.cc | 261 --- .../waveshare-s3-touch-lcd-3.49/README.md | 3 - .../waveshare-s3-touch-lcd-3.49/config.h | 62 - .../waveshare-s3-touch-lcd-3.49/config.json | 12 - .../custom_lcd_display.cc | 145 -- .../custom_lcd_display.h | 17 - .../waveshare-s3-touch-lcd-3.49.cc | 253 --- .../waveshare-s3-touch-lcd-3.5b/README.md | 3 - .../waveshare-s3-touch-lcd-3.5b/config.h | 78 - .../waveshare-s3-touch-lcd-3.5b/config.json | 19 - .../custom_lcd_display.cc | 286 ---- .../custom_lcd_display.h | 19 - .../waveshare-s3-touch-lcd-3.5b.cc | 365 ----- .../waveshare-s3-touch-lcd-4b/README.md | 12 - .../boards/waveshare-s3-touch-lcd-4b/config.h | 65 - .../waveshare-s3-touch-lcd-4b/config.json | 12 - .../esp32-s3-touch-lcd-4b.cc | 431 ----- .../boards/wireless-tag-wtp4c5mp07s/README.md | 45 - .../boards/wireless-tag-wtp4c5mp07s/config.h | 104 -- .../wireless-tag-wtp4c5mp07s/config.json | 16 - .../wireless-tag-wtp4c5mp07s.cc | 297 ---- .../xingzhi-cube-0.85tft-ml307/config.h | 40 - .../xingzhi-cube-0.85tft-ml307/config.json | 9 - .../xingzhi-cube-0.85tft-ml307.cc | 239 --- .../boards/xingzhi-cube-0.85tft-wifi/config.h | 37 - .../xingzhi-cube-0.85tft-wifi/config.json | 9 - .../xingzhi-cube-0.85tft-wifi.cc | 244 --- .../xingzhi-cube-0.96oled-ml307/config.h | 30 - .../xingzhi-cube-0.96oled-ml307/config.json | 9 - .../xingzhi-cube-0.96oled-ml307.cc | 234 --- .../xingzhi-cube-0.96oled-wifi/config.h | 27 - .../xingzhi-cube-0.96oled-wifi/config.json | 9 - .../xingzhi-cube-0.96oled-wifi.cc | 225 --- .../xingzhi-cube-1.54tft-ml307/config.h | 40 - .../xingzhi-cube-1.54tft-ml307/config.json | 15 - .../xingzhi-cube-1.54tft-ml307.cc | 212 --- .../boards/xingzhi-cube-1.54tft-wifi/config.h | 36 - .../xingzhi-cube-1.54tft-wifi/config.json | 9 - .../xingzhi-cube-1.54tft-wifi/power_manager.h | 186 --- .../xingzhi-cube-1.54tft-wifi.cc | 201 --- .../boards/xingzhi-metal-1.54-wifi/README.md | 61 - .../boards/xingzhi-metal-1.54-wifi/config.h | 53 - .../xingzhi-metal-1.54-wifi/config.json | 10 - .../boards/xingzhi-metal-1.54-wifi/cst816x.cc | 213 --- .../boards/xingzhi-metal-1.54-wifi/cst816x.h | 90 -- .../xingzhi-metal-1.54-wifi/power_manager.h | 314 ---- .../xingzhi-metal-1.54-wifi.cc | 201 --- .../main/boards/xmini-c3-4g/README.md | 4 - .../main/boards/xmini-c3-4g/config.h | 32 - .../main/boards/xmini-c3-4g/config.json | 15 - .../boards/xmini-c3-4g/xmini_c3_4g_board.cc | 203 --- .../main/boards/xmini-c3-v3/README.md | 4 - .../main/boards/xmini-c3-v3/config.h | 28 - .../main/boards/xmini-c3-v3/config.json | 14 - .../main/boards/xmini-c3-v3/xmini_c3_board.cc | 201 --- .../main/boards/xmini-c3/config.h | 28 - .../main/boards/xmini-c3/config.json | 14 - .../main/boards/xmini-c3/xmini_c3_board.cc | 182 --- .../main/boards/yunliao-s3/README.md | 97 -- .../main/boards/yunliao-s3/config.h | 59 - .../main/boards/yunliao-s3/config.json | 11 - .../main/boards/yunliao-s3/power_manager.cc | 203 --- .../main/boards/yunliao-s3/power_manager.h | 37 - .../main/boards/yunliao-s3/yunliao_s3.cc | 255 --- .../boards/zhengchen-1.54tft-ml307/README.md | 45 - .../boards/zhengchen-1.54tft-ml307/config.h | 42 - .../zhengchen-1.54tft-ml307/config.json | 9 - .../zhengchen-1.54tft-ml307.cc | 211 --- .../boards/zhengchen-1.54tft-wifi/README.md | 45 - .../boards/zhengchen-1.54tft-wifi/config.h | 39 - .../boards/zhengchen-1.54tft-wifi/config.json | 9 - .../zhengchen-1.54tft-wifi/power_manager.h | 238 --- .../zhengchen-1.54tft-wifi.cc | 228 --- .../zhengchen_lcd_display.h | 66 - .../XiaoZhiCode_V2.1.0/main/device_state.h | 18 - .../main/device_state_machine.cc | 161 -- .../main/device_state_machine.h | 83 - .../main/display/display.cc | 56 - .../XiaoZhiCode_V2.1.0/main/display/display.h | 81 - .../main/display/emote_display.cc | 658 -------- .../main/display/emote_display.h | 102 -- .../main/display/lcd_display.cc | 1196 -------------- .../main/display/lcd_display.h | 85 - .../display/lvgl_display/emoji_collection.cc | 123 -- .../display/lvgl_display/emoji_collection.h | 34 - .../main/display/lvgl_display/gif/LICENSE.txt | 2 - .../main/display/lvgl_display/gif/README.md | 17 - .../main/display/lvgl_display/gif/gifdec.c | 821 ---------- .../main/display/lvgl_display/gif/gifdec.h | 68 - .../display/lvgl_display/gif/gifdec_mve.h | 140 -- .../main/display/lvgl_display/gif/lvgl_gif.cc | 208 --- .../main/display/lvgl_display/gif/lvgl_gif.h | 101 -- .../lvgl_display/jpg/image_to_jpeg.cpp | 467 ------ .../display/lvgl_display/jpg/image_to_jpeg.h | 70 - .../display/lvgl_display/jpg/jpeg_to_image.c | 264 --- .../display/lvgl_display/jpg/jpeg_to_image.h | 62 - .../main/display/lvgl_display/lvgl_display.cc | 258 --- .../main/display/lvgl_display/lvgl_display.h | 53 - .../main/display/lvgl_display/lvgl_font.cc | 13 - .../main/display/lvgl_display/lvgl_font.h | 31 - .../main/display/lvgl_display/lvgl_image.cc | 64 - .../main/display/lvgl_display/lvgl_image.h | 53 - .../main/display/lvgl_display/lvgl_theme.cc | 30 - .../main/display/lvgl_display/lvgl_theme.h | 94 -- .../main/display/oled_display.cc | 396 ----- .../main/display/oled_display.h | 40 - .../XiaoZhiCode_V2.1.0/main/idf_component.yml | 110 -- .../main/led/circular_strip.cc | 233 --- .../main/led/circular_strip.h | 51 - .../XiaoZhiCode_V2.1.0/main/led/gpio_led.cc | 263 --- .../XiaoZhiCode_V2.1.0/main/led/gpio_led.h | 49 - .../xiaozhi/XiaoZhiCode_V2.1.0/main/led/led.h | 17 - .../XiaoZhiCode_V2.1.0/main/led/single_led.cc | 163 -- .../XiaoZhiCode_V2.1.0/main/led/single_led.h | 38 - .../xiaozhi/XiaoZhiCode_V2.1.0/main/main.cc | 30 - .../XiaoZhiCode_V2.1.0/main/mcp_server.cc | 563 ------- .../XiaoZhiCode_V2.1.0/main/mcp_server.h | 344 ---- .../xiaozhi/XiaoZhiCode_V2.1.0/main/ota.cc | 473 ------ .../xiaozhi/XiaoZhiCode_V2.1.0/main/ota.h | 58 - .../main/protocols/mqtt_protocol.cc | 382 ----- .../main/protocols/mqtt_protocol.h | 65 - .../main/protocols/protocol.cc | 90 -- .../main/protocols/protocol.h | 98 -- .../main/protocols/websocket_protocol.cc | 253 --- .../main/protocols/websocket_protocol.h | 34 - .../XiaoZhiCode_V2.1.0/main/settings.cc | 108 -- .../XiaoZhiCode_V2.1.0/main/settings.h | 28 - .../XiaoZhiCode_V2.1.0/main/system_info.cc | 151 -- .../XiaoZhiCode_V2.1.0/main/system_info.h | 22 - .../XiaoZhiCode_V2.1.0/partitions/v1/16m.csv | 8 - .../partitions/v1/16m_custom_wakeword.csv | 8 - .../partitions/v1/16m_echoear.csv | 9 - .../XiaoZhiCode_V2.1.0/partitions/v1/32m.csv | 10 - .../XiaoZhiCode_V2.1.0/partitions/v1/4m.csv | 7 - .../partitions/v1/4m_esp-hi.csv | 8 - .../XiaoZhiCode_V2.1.0/partitions/v1/8m.csv | 8 - .../XiaoZhiCode_V2.1.0/partitions/v2/16m.csv | 8 - .../partitions/v2/16m_c3.csv | 8 - .../XiaoZhiCode_V2.1.0/partitions/v2/32m.csv | 9 - .../XiaoZhiCode_V2.1.0/partitions/v2/4m.csv | 7 - .../XiaoZhiCode_V2.1.0/partitions/v2/8m.csv | 8 - .../partitions/v2/README.md | 107 -- .../scripts/Image_Converter/LVGLImage.py | 1426 ----------------- .../scripts/Image_Converter/README.md | 45 - .../scripts/Image_Converter/lvgl_tools_gui.py | 253 --- .../scripts/Image_Converter/requirements.txt | 3 - .../scripts/acoustic_check/demod.py | 280 ---- .../scripts/acoustic_check/graphic.py | 444 ----- .../scripts/acoustic_check/main.py | 18 - .../scripts/acoustic_check/readme.md | 23 - .../scripts/acoustic_check/requirements.txt | 4 - .../scripts/audio_debug_server.py | 54 - .../scripts/build_default_assets.py | 882 ---------- .../scripts/download_github_runs.py | 264 --- .../XiaoZhiCode_V2.1.0/scripts/gen_lang.py | 187 --- .../XiaoZhiCode_V2.1.0/scripts/mp3_to_ogg.sh | 3 - .../scripts/ogg_converter/README.md | 36 - .../ogg_converter/xiaozhi_ogg_converter.py | 230 --- .../scripts/p3_tools/README.md | 95 -- .../scripts/p3_tools/batch_convert_gui.py | 221 --- .../scripts/p3_tools/convert_audio_to_p3.py | 62 - .../scripts/p3_tools/convert_p3_to_audio.py | 51 - .../scripts/p3_tools/img/img.png | Bin 144945 -> 0 bytes .../scripts/p3_tools/p3_gui_player.py | 241 --- .../scripts/p3_tools/play_p3.py | 71 - .../scripts/p3_tools/requirements.txt | 7 - .../XiaoZhiCode_V2.1.0/scripts/release.py | 305 ---- .../scripts/sonic_wifi_config.html | 208 --- .../scripts/spiffs_assets/README.md | 110 -- .../scripts/spiffs_assets/build.py | 400 ----- .../scripts/spiffs_assets/build_all.py | 187 --- .../scripts/spiffs_assets/pack_model.py | 123 -- .../spiffs_assets/spiffs_assets_gen.py | 647 -------- .../XiaoZhiCode_V2.1.0/scripts/versions.py | 250 --- .../XiaoZhiCode_V2.1.0/sdkconfig.defaults | 78 - .../sdkconfig.defaults.esp32 | 6 - .../sdkconfig.defaults.esp32c3 | 15 - .../sdkconfig.defaults.esp32c5 | 14 - .../sdkconfig.defaults.esp32c6 | 5 - .../sdkconfig.defaults.esp32p4 | 31 - .../sdkconfig.defaults.esp32s3 | 31 - 1350 files changed, 2 insertions(+), 93858 deletions(-) delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/.gitignore delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/CMakeLists.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/LICENSE delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/README_ja.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/README_zh.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/CMakeLists.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/Kconfig.projbuild delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/exclamation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/low_battery.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/popup.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/success.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/vibration.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sr-RS/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/0.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/1.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/2.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/3.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/4.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/5.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/6.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/7.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/8.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/9.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/activation.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_pin.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_reg.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/language.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/upgrade.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/welcome.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/wificonfig.ogg delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_processor.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_word.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README_en.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/aipi-lite.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config_en.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/atk_dnesp32s3_box.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/atk_dnesp32s3_box0.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/atk_dnesp32s3_box2.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/atk_dnesp32s3_box2.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/atk_dnesp32s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/atk_dnesp32s3m.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/atk_dnesp32s3m.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/atom_echos3r.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/atommatrix_echo_base.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/atoms3_echo_base.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/atoms3r_cam_m12_echo_base.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/atoms3r_echo_base.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/esp32_bread_board_lcd.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/esp32_bread_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/compact_ml307_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/compact_wifi_board_lcd.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/compact_wifi_board_s3cam.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/compact_wifi_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.cpp delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/camera.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/lamp_controller.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/df_k10_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/df_s3_ai_cam.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/doit_s3_aibox.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/du-chatx-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/EchoEar.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/emote.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/layout.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/touch.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot_controller.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/otto_icon_font.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/emote.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/esp_box3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/layout.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/esp_box_lite_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/esp_box_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/esp_hi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/esp-p4-function-ev-board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp-s3-lcd-ev-board-2.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp-s3-lcd-ev-board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/esp-sensairshuttle.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/esp_sparkbot_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/esp_spot_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/esp32_cgc_144_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager_lite.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/esp32_cgc_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/esp32-s3-touch-lcd-1.46.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/esp32-s3-touch-lcd-1.85.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/esp32-s3-touch-lcd-1.85c.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/esp32-s3-touch-lcd-3.5.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/esp32s3_korvo2_v3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/genjutech-s3-1.54tft.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/hu_087_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/gpio_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/jiuchuan_dev_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_controller.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/kevin_box_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/kevin_c3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/kevin-sp-v3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/kevin-sp-v4_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/kevin_yuying_313lcd.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/mpython_pro.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/lichuang_c3_dev_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/emote.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/layout.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/lichuang_dev_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/ir_filter_controller.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/lilygo-t-circle-s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/lilygo-t-display-p4.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/t_display_p4_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/lilygo-t-display-s3-pro-mvsrlora.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/pin_config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/m5stack_core_s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/m5stack_tab5.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/sdkconfig.tab5 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/magiclick_2p4_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/magiclick_2p5_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/magiclick_c3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/minsi_k08_dual.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/mixgo-nova.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/movecall_cuican_esp32s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README_zh.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/movecall_moji2_esp32s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_controller.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_icon_font.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_robot.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README_en.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config_en.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_watcher.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/sp-esp32-s3-1.28-box.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/sp-esp32-s3-1.54-muma.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/surfer-c3-1.14tft.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/taiji_pi_s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/kevin_box_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/esp32-c6-lcd-1.69.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/esp32-c6-touch-amoled-1.32.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/esp32-c6-touch-amoled-1.43.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/esp32-c6-touch-amoled-2.06.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/esp32-c6-touch-lcd-1.83.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/esp32-p4-nano.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/esp32-p4-wifi6-touch-lcd-4b.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/esp32-p4-wifi6-touch-lcd-7b.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/esp32-p4-wifi6-touch-lcd-xc.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp32-s3-audio_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/waveshare-s3-rlcd-4.2.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/esp32-s3-touch-amoled-1.32.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/esp32-s3-touch-amoled-1.75.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/esp32-s3-touch-amoled-2.06.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/esp32-s3-touch-lcd-1.83.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/custom_lcd_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/custom_lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/waveshare-s3-touch-lcd-3.49.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/waveshare-s3-touch-lcd-3.5b.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/esp32-s3-touch-lcd-4b.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/wireless-tag-wtp4c5mp07s.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/xingzhi-cube-0.85tft-ml307.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/xingzhi-cube-0.85tft-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/xingzhi-cube-0.96oled-ml307.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/xingzhi-cube-0.96oled-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/xingzhi-cube-1.54tft-ml307.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/xingzhi-cube-1.54tft-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/xingzhi-metal-1.54-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/xmini_c3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/xmini_c3_board.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/yunliao_s3.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/zhengchen-1.54tft-ml307.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.json delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/power_manager.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen-1.54tft-wifi.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen_lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/LICENSE.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec_mve.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.cpp delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.c delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/idf_component.yml delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/led.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/main.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.cc delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.h delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_custom_wakeword.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_echoear.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/32m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m_esp-hi.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/8m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m_c3.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/32m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/4m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/8m.csv delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/LVGLImage.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/lvgl_tools_gui.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/requirements.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/demod.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/graphic.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/main.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/readme.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/requirements.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/audio_debug_server.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/build_default_assets.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/download_github_runs.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/gen_lang.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/mp3_to_ogg.sh delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/xiaozhi_ogg_converter.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/batch_convert_gui.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_audio_to_p3.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_p3_to_audio.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/img/img.png delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/p3_gui_player.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/play_p3.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/requirements.txt delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/release.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/sonic_wifi_config.html delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/README.md delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build_all.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/pack_model.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/spiffs_assets_gen.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/versions.py delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32c3 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32c5 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32c6 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32p4 delete mode 100644 examples/xiaozhi/XiaoZhiCode_V2.1.0/sdkconfig.defaults.esp32s3 diff --git a/README.md b/README.md index 419b48c2..d8abbd8e 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ Factory firmware (restores the out-of-box demo): download the file whose name co | [10_U8G2_Test](examples/arduino/examples/10_U8G2_Test/) | U8g2 | Libraries used by the sketches are bundled in [`examples/arduino/libraries`](examples/arduino/libraries/). -ESPHome configurations are in [`examples/esphome`](examples/esphome/README.md) and the XiaoZhi AI firmware source in [`examples/xiaozhi`](examples/xiaozhi/). +ESPHome configurations are in [`examples/esphome`](examples/esphome/README.md). The XiaoZhi AI firmware source for this board is in the upstream [xiaozhi-esp32](https://github.com/78/xiaozhi-esp32/tree/main/main/boards/waveshare/esp32-s3-rlcd-4.2) repository. ## 🛠️ Development Environment diff --git a/README_ZH.md b/README_ZH.md index 497d427f..1c9dfa69 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -79,7 +79,7 @@ ESP32-S3-RLCD-4.2 是一块 AIoT 开发板,采用 ESP32-S3-WROOM-1-N16R8 模 | [10_U8G2_Test](examples/arduino/examples/10_U8G2_Test/README_ZH.md) | U8g2 | 草图使用的库随仓库提供,位于 [`examples/arduino/libraries`](examples/arduino/libraries/)。 -ESPHome 配置位于 [`examples/esphome`](examples/esphome/README_ZH.md),小智 AI 固件源码位于 [`examples/xiaozhi`](examples/xiaozhi/)。 +ESPHome 配置位于 [`examples/esphome`](examples/esphome/README_ZH.md)。本产品的小智 AI 固件源码在上游 [xiaozhi-esp32](https://github.com/78/xiaozhi-esp32/tree/main/main/boards/waveshare/esp32-s3-rlcd-4.2) 仓库。 ## 🛠️ 开发环境 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/.gitignore b/examples/xiaozhi/XiaoZhiCode_V2.1.0/.gitignore deleted file mode 100644 index a1b5d8e6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -tmp/ -components/ -managed_components/ -build/ -.vscode/ -.devcontainer/ -sdkconfig.old -sdkconfig -dependencies.lock -.env -releases/ -main/assets/lang_config.h -main/mmap_generate_emoji.h -.DS_Store -.cache -*.pyc -*.bin -mmap_generate_*.h -.clangd diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/CMakeLists.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/CMakeLists.txt deleted file mode 100644 index 8dcd6df0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# For more information about build system see -# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html -# The following five lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.16) - -set(PROJECT_VER "2.1.0") - -# Add this line to disable the specific warning -add_compile_options(-Wno-missing-field-initializers) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(xiaozhi) - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/LICENSE b/examples/xiaozhi/XiaoZhiCode_V2.1.0/LICENSE deleted file mode 100644 index e90b5545..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -Copyright (c) 2025 Shenzhen Xinzhi Future Technology Co., Ltd. -Copyright (c) 2025 Project Contributors - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/README.md deleted file mode 100644 index 9e8c70d6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README.md +++ /dev/null @@ -1,172 +0,0 @@ -# An MCP-based Chatbot - -(English | [中文](README_zh.md) | [日本語](README_ja.md)) - -## Introduction - -👉 [Human: Give AI a camera vs AI: Instantly finds out the owner hasn't washed hair for three days【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/) - -👉 [Handcraft your AI girlfriend, beginner's guide【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/) - -As a voice interaction entry, the XiaoZhi AI chatbot leverages the AI capabilities of large models like Qwen / DeepSeek, and achieves multi-terminal control via the MCP protocol. - -Control everything via MCP - -## Version Notes - -The current v2 version is incompatible with the v1 partition table, so it is not possible to upgrade from v1 to v2 via OTA. For partition table details, see [partitions/v2/README.md](partitions/v2/README.md). - -All hardware running v1 can be upgraded to v2 by manually flashing the firmware. - -The stable version of v1 is 1.9.2. You can switch to v1 by running `git checkout v1`. The v1 branch will be maintained until February 2026. - -### Features Implemented - -- Wi-Fi / ML307 Cat.1 4G -- Offline voice wake-up [ESP-SR](https://github.com/espressif/esp-sr) -- Supports two communication protocols ([Websocket](docs/websocket.md) or MQTT+UDP) -- Uses OPUS audio codec -- Voice interaction based on streaming ASR + LLM + TTS architecture -- Speaker recognition, identifies the current speaker [3D Speaker](https://github.com/modelscope/3D-Speaker) -- OLED / LCD display, supports emoji display -- Battery display and power management -- Multi-language support (Chinese, English, Japanese) -- Supports ESP32-C3, ESP32-S3, ESP32-P4 chip platforms -- Device-side MCP for device control (Speaker, LED, Servo, GPIO, etc.) -- Cloud-side MCP to extend large model capabilities (smart home control, PC desktop operation, knowledge search, email, etc.) -- Customizable wake words, fonts, emojis, and chat backgrounds with online web-based editing ([Custom Assets Generator](https://github.com/78/xiaozhi-assets-generator)) - -## Hardware - -### Breadboard DIY Practice - -See the Feishu document tutorial: - -👉 ["XiaoZhi AI Chatbot Encyclopedia"](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink) - -Breadboard demo: - -![Breadboard Demo](docs/v1/wiring2.jpg) - -### Supports 70+ Open Source Hardware (Partial List) - -- LiChuang ESP32-S3 Development Board -- Espressif ESP32-S3-BOX3 -- M5Stack CoreS3 -- M5Stack AtomS3R + Echo Base -- Magic Button 2.4 -- Waveshare ESP32-S3-Touch-AMOLED-1.8 -- LILYGO T-Circle-S3 -- XiaGe Mini C3 -- CuiCan AI Pendant -- WMnologo-Xingzhi-1.54TFT -- SenseCAP Watcher -- ESP-HI Low Cost Robot Dog - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -## Software - -### Firmware Flashing - -For beginners, it is recommended to use the firmware that can be flashed without setting up a development environment. - -The firmware connects to the official [xiaozhi.me](https://xiaozhi.me) server by default. Personal users can register an account to use the Qwen real-time model for free. - -👉 [Beginner's Firmware Flashing Guide](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS) - -### Development Environment - -- Cursor or VSCode -- Install ESP-IDF plugin, select SDK version 5.4 or above -- Linux is better than Windows for faster compilation and fewer driver issues -- This project uses Google C++ code style, please ensure compliance when submitting code - -### Developer Documentation - -- [Custom Board Guide](docs/custom-board.md) - Learn how to create custom boards for XiaoZhi AI -- [MCP Protocol IoT Control Usage](docs/mcp-usage.md) - Learn how to control IoT devices via MCP protocol -- [MCP Protocol Interaction Flow](docs/mcp-protocol.md) - Device-side MCP protocol implementation -- [MQTT + UDP Hybrid Communication Protocol Document](docs/mqtt-udp.md) -- [A detailed WebSocket communication protocol document](docs/websocket.md) - -## Large Model Configuration - -If you already have a XiaoZhi AI chatbot device and have connected to the official server, you can log in to the [xiaozhi.me](https://xiaozhi.me) console for configuration. - -👉 [Backend Operation Video Tutorial (Old Interface)](https://www.bilibili.com/video/BV1jUCUY2EKM/) - -## Related Open Source Projects - -For server deployment on personal computers, refer to the following open-source projects: - -- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python server -- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java server -- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang server - -Other client projects using the XiaoZhi communication protocol: - -- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python client -- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android client -- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) Linux client by 100ask -- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) Bluetooth chip firmware by Sichuan -- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) QuecPython firmware by Quectel - -Custom Assets Tools: - -- [78/xiaozhi-assets-generator](https://github.com/78/xiaozhi-assets-generator) Custom Assets Generator (Wake words, fonts, emojis, backgrounds) - -## About the Project - -This is an open-source ESP32 project, released under the MIT license, allowing anyone to use it for free, including for commercial purposes. - -We hope this project helps everyone understand AI hardware development and apply rapidly evolving large language models to real hardware devices. - -If you have any ideas or suggestions, please feel free to raise Issues or join the QQ group: 1011329060 - -## Star History - - - - - - Star History Chart - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_ja.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_ja.md deleted file mode 100644 index ea7f70f0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_ja.md +++ /dev/null @@ -1,168 +0,0 @@ -# MCP ベースのチャットボット - -(日本語 | [中文](README_zh.md) | [English](README.md)) - -## はじめに - -👉 [人間:AIにカメラを装着 vs AI:その場で飼い主が3日間髪を洗っていないことを発見【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/) - -👉 [手作りでAIガールフレンドを作る、初心者入門チュートリアル【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/) - -シャオジーAIチャットボットは音声インタラクションの入口として、Qwen / DeepSeekなどの大規模モデルのAI能力を活用し、MCPプロトコルを通じてマルチエンド制御を実現します。 - -MCPであらゆるものを制御 - -## バージョンノート - -現在のv2バージョンはv1パーティションテーブルと互換性がないため、v1からv2へOTAでアップグレードすることはできません。パーティションテーブルの詳細については、[partitions/v2/README.md](partitions/v2/README.md)をご参照ください。 - -v1を実行しているすべてのハードウェアは、ファームウェアを手動で書き込むことでv2にアップグレードできます。 - -v1の安定版は1.9.2です。`git checkout v1`でv1に切り替えることができます。v1ブランチは2026年2月まで継続的にメンテナンスされます。 - -### 実装済み機能 - -- Wi-Fi / ML307 Cat.1 4G -- オフライン音声ウェイクアップ [ESP-SR](https://github.com/espressif/esp-sr) -- 2種類の通信プロトコルに対応([Websocket](docs/websocket.md) または MQTT+UDP) -- OPUSオーディオコーデックを採用 -- ストリーミングASR + LLM + TTSアーキテクチャに基づく音声インタラクション -- 話者認識、現在話している人を識別 [3D Speaker](https://github.com/modelscope/3D-Speaker) -- OLED / LCDディスプレイ、表情表示対応 -- バッテリー表示と電源管理 -- 多言語対応(中国語、英語、日本語) -- ESP32-C3、ESP32-S3、ESP32-P4チッププラットフォーム対応 -- デバイス側MCPによるデバイス制御(音量・明るさ調整、アクション制御など) -- クラウド側MCPで大規模モデル能力を拡張(スマートホーム制御、PCデスクトップ操作、知識検索、メール送受信など) -- カスタマイズ可能なウェイクワード、フォント、絵文字、チャット背景、オンラインWeb編集に対応 ([カスタムアセットジェネレーター](https://github.com/78/xiaozhi-assets-generator)) - -## ハードウェア - -### ブレッドボード手作り実践 - -Feishuドキュメントチュートリアルをご覧ください: - -👉 [「シャオジーAIチャットボット百科事典」](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink) - -ブレッドボードのデモ: - -![ブレッドボードデモ](docs/v1/wiring2.jpg) - -### 70種類以上のオープンソースハードウェアに対応(一部のみ表示) - -- 立創・実戦派 ESP32-S3 開発ボード -- 楽鑫 ESP32-S3-BOX3 -- M5Stack CoreS3 -- M5Stack AtomS3R + Echo Base -- マジックボタン2.4 -- 微雪電子 ESP32-S3-Touch-AMOLED-1.8 -- LILYGO T-Circle-S3 -- エビ兄さん Mini C3 -- CuiCan AIペンダント -- 無名科技Nologo-星智-1.54TFT -- SenseCAP Watcher -- ESP-HI 超低コストロボット犬 - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -## ソフトウェア - -### ファームウェア書き込み - -初心者の方は、まず開発環境を構築せずに書き込み可能なファームウェアを使用することをおすすめします。 - -ファームウェアはデフォルトで公式 [xiaozhi.me](https://xiaozhi.me) サーバーに接続します。個人ユーザーはアカウント登録でQwenリアルタイムモデルを無料で利用できます。 - -👉 [初心者向けファームウェア書き込みガイド](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS) - -### 開発環境 - -- Cursor または VSCode -- ESP-IDFプラグインをインストールし、SDKバージョン5.4以上を選択 -- LinuxはWindowsよりも優れており、コンパイルが速く、ドライバの問題も少ない -- 本プロジェクトはGoogle C++コードスタイルを採用、コード提出時は準拠を確認してください - -### 開発者ドキュメント - -- [カスタム開発ボードガイド](docs/custom-board.md) - シャオジーAI用のカスタム開発ボード作成方法 -- [MCPプロトコルIoT制御使用法](docs/mcp-usage.md) - MCPプロトコルでIoTデバイスを制御する方法 -- [MCPプロトコルインタラクションフロー](docs/mcp-protocol.md) - デバイス側MCPプロトコルの実装方法 -- [MQTT + UDP ハイブリッド通信プロトコルドキュメント](docs/mqtt-udp.md) -- [詳細なWebSocket通信プロトコルドキュメント](docs/websocket.md) - -## 大規模モデル設定 - -すでにシャオジーAIチャットボットデバイスをお持ちで、公式サーバーに接続済みの場合は、[xiaozhi.me](https://xiaozhi.me) コンソールで設定できます。 - -👉 [バックエンド操作ビデオチュートリアル(旧インターフェース)](https://www.bilibili.com/video/BV1jUCUY2EKM/) - -## 関連オープンソースプロジェクト - -個人PCでサーバーをデプロイする場合は、以下のオープンソースプロジェクトを参照してください: - -- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Pythonサーバー -- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Javaサーバー -- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golangサーバー - -シャオジー通信プロトコルを利用した他のクライアントプロジェクト: - -- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Pythonクライアント -- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Androidクライアント -- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百問科技提供のLinuxクライアント -- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技のBluetoothチップファームウェア -- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移遠提供のQuecPythonファームウェア - -## プロジェクトについて - -これはエビ兄さんがオープンソースで公開しているESP32プロジェクトで、MITライセンスのもと、誰でも無料で、商用利用も可能です。 - -このプロジェクトを通じて、AIハードウェア開発を理解し、急速に進化する大規模言語モデルを実際のハードウェアデバイスに応用できるようになることを目指しています。 - -ご意見やご提案があれば、いつでもIssueを提出するか、QQグループ:1011329060 にご参加ください。 - -## スター履歴 - - - - - - Star History Chart - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_zh.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_zh.md deleted file mode 100644 index e7ad1fad..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/README_zh.md +++ /dev/null @@ -1,168 +0,0 @@ -# An MCP-based Chatbot - -(中文 | [English](README.md) | [日本語](README_ja.md)) - -## 介绍 - -👉 [人类:给 AI 装摄像头 vs AI:当场发现主人三天没洗头【bilibili】](https://www.bilibili.com/video/BV1bpjgzKEhd/) - -👉 [手工打造你的 AI 女友,新手入门教程【bilibili】](https://www.bilibili.com/video/BV1XnmFYLEJN/) - -小智 AI 聊天机器人作为一个语音交互入口,利用 Qwen / DeepSeek 等大模型的 AI 能力,通过 MCP 协议实现多端控制。 - -通过MCP控制万物 - -### 版本说明 - -当前 v2 版本与 v1 版本分区表不兼容,所以无法从 v1 版本通过 OTA 升级到 v2 版本。分区表说明参见 [partitions/v2/README.md](partitions/v2/README.md)。 - -使用 v1 版本的所有硬件,可以通过手动烧录固件来升级到 v2 版本。 - -v1 的稳定版本为 1.9.2,可以通过 `git checkout v1` 来切换到 v1 版本,该分支会持续维护到 2026 年 2 月。 - -### 已实现功能 - -- Wi-Fi / ML307 Cat.1 4G -- 离线语音唤醒 [ESP-SR](https://github.com/espressif/esp-sr) -- 支持两种通信协议([Websocket](docs/websocket.md) 或 MQTT+UDP) -- 采用 OPUS 音频编解码 -- 基于流式 ASR + LLM + TTS 架构的语音交互 -- 声纹识别,识别当前说话人的身份 [3D Speaker](https://github.com/modelscope/3D-Speaker) -- OLED / LCD 显示屏,支持表情显示 -- 电量显示与电源管理 -- 支持多语言(中文、英文、日文) -- 支持 ESP32-C3、ESP32-S3、ESP32-P4 芯片平台 -- 通过设备端 MCP 实现设备控制(音量、灯光、电机、GPIO 等) -- 通过云端 MCP 扩展大模型能力(智能家居控制、PC桌面操作、知识搜索、邮件收发等) -- 自定义唤醒词、字体、表情与聊天背景,支持网页端在线修改 ([自定义Assets生成器](https://github.com/78/xiaozhi-assets-generator)) - -## 硬件 - -### 面包板手工制作实践 - -详见飞书文档教程: - -👉 [《小智 AI 聊天机器人百科全书》](https://ccnphfhqs21z.feishu.cn/wiki/F5krwD16viZoF0kKkvDcrZNYnhb?from=from_copylink) - -面包板效果图如下: - -![面包板效果图](docs/v1/wiring2.jpg) - -### 支持 70 多个开源硬件(仅展示部分) - -- 立创·实战派 ESP32-S3 开发板 -- 乐鑫 ESP32-S3-BOX3 -- M5Stack CoreS3 -- M5Stack AtomS3R + Echo Base -- 神奇按钮 2.4 -- 微雪电子 ESP32-S3-Touch-AMOLED-1.8 -- LILYGO T-Circle-S3 -- 虾哥 Mini C3 -- 璀璨·AI 吊坠 -- 无名科技 Nologo-星智-1.54TFT -- SenseCAP Watcher -- ESP-HI 超低成本机器狗 - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -## 软件 - -### 固件烧录 - -新手第一次操作建议先不要搭建开发环境,直接使用免开发环境烧录的固件。 - -固件默认接入 [xiaozhi.me](https://xiaozhi.me) 官方服务器,个人用户注册账号可以免费使用 Qwen 实时模型。 - -👉 [新手烧录固件教程](https://ccnphfhqs21z.feishu.cn/wiki/Zpz4wXBtdimBrLk25WdcXzxcnNS) - -### 开发环境 - -- Cursor 或 VSCode -- 安装 ESP-IDF 插件,选择 SDK 版本 5.4 或以上 -- Linux 比 Windows 更好,编译速度快,也免去驱动问题的困扰 -- 本项目使用 Google C++ 代码风格,提交代码时请确保符合规范 - -### 开发者文档 - -- [自定义开发板指南](docs/custom-board.md) - 学习如何为小智 AI 创建自定义开发板 -- [MCP 协议物联网控制用法说明](docs/mcp-usage.md) - 了解如何通过 MCP 协议控制物联网设备 -- [MCP 协议交互流程](docs/mcp-protocol.md) - 设备端 MCP 协议的实现方式 -- [MQTT + UDP 混合通信协议文档](docs/mqtt-udp.md) -- [一份详细的 WebSocket 通信协议文档](docs/websocket.md) - -## 大模型配置 - -如果你已经拥有一个小智 AI 聊天机器人设备,并且已接入官方服务器,可以登录 [xiaozhi.me](https://xiaozhi.me) 控制台进行配置。 - -👉 [后台操作视频教程(旧版界面)](https://www.bilibili.com/video/BV1jUCUY2EKM/) - -## 相关开源项目 - -在个人电脑上部署服务器,可以参考以下第三方开源的项目: - -- [xinnan-tech/xiaozhi-esp32-server](https://github.com/xinnan-tech/xiaozhi-esp32-server) Python 服务器 -- [joey-zhou/xiaozhi-esp32-server-java](https://github.com/joey-zhou/xiaozhi-esp32-server-java) Java 服务器 -- [AnimeAIChat/xiaozhi-server-go](https://github.com/AnimeAIChat/xiaozhi-server-go) Golang 服务器 - -使用小智通信协议的第三方客户端项目: - -- [huangjunsen0406/py-xiaozhi](https://github.com/huangjunsen0406/py-xiaozhi) Python 客户端 -- [TOM88812/xiaozhi-android-client](https://github.com/TOM88812/xiaozhi-android-client) Android 客户端 -- [100askTeam/xiaozhi-linux](http://github.com/100askTeam/xiaozhi-linux) 百问科技提供的 Linux 客户端 -- [78/xiaozhi-sf32](https://github.com/78/xiaozhi-sf32) 思澈科技的蓝牙芯片固件 -- [QuecPython/solution-xiaozhiAI](https://github.com/QuecPython/solution-xiaozhiAI) 移远提供的 QuecPython 固件 - -## 关于项目 - -这是一个由虾哥开源的 ESP32 项目,以 MIT 许可证发布,允许任何人免费使用,修改或用于商业用途。 - -我们希望通过这个项目,能够帮助大家了解 AI 硬件开发,将当下飞速发展的大语言模型应用到实际的硬件设备中。 - -如果你有任何想法或建议,请随时提出 Issues 或加入 QQ 群:1011329060 - -## Star History - - - - - - Star History Chart - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/CMakeLists.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/CMakeLists.txt deleted file mode 100644 index e9927b0f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/CMakeLists.txt +++ /dev/null @@ -1,940 +0,0 @@ -# Define source files -set(SOURCES "audio/audio_codec.cc" - "audio/audio_service.cc" - "audio/codecs/no_audio_codec.cc" - "audio/codecs/box_audio_codec.cc" - "audio/codecs/es8311_audio_codec.cc" - "audio/codecs/es8374_audio_codec.cc" - "audio/codecs/es8388_audio_codec.cc" - "audio/codecs/es8389_audio_codec.cc" - "audio/codecs/dummy_audio_codec.cc" - "audio/processors/audio_debugger.cc" - "led/single_led.cc" - "led/circular_strip.cc" - "led/gpio_led.cc" - "display/display.cc" - "display/lcd_display.cc" - "display/oled_display.cc" - "display/lvgl_display/lvgl_display.cc" - "display/emote_display.cc" - "display/lvgl_display/emoji_collection.cc" - "display/lvgl_display/lvgl_theme.cc" - "display/lvgl_display/lvgl_font.cc" - "display/lvgl_display/lvgl_image.cc" - "display/lvgl_display/gif/lvgl_gif.cc" - "display/lvgl_display/gif/gifdec.c" - "display/lvgl_display/jpg/image_to_jpeg.cpp" - "display/lvgl_display/jpg/jpeg_to_image.c" - "protocols/protocol.cc" - "protocols/mqtt_protocol.cc" - "protocols/websocket_protocol.cc" - "mcp_server.cc" - "system_info.cc" - "application.cc" - "ota.cc" - "settings.cc" - "device_state_machine.cc" - "assets.cc" - "main.cc" - ) - -set(INCLUDE_DIRS "." "display" "display/lvgl_display" "display/lvgl_display/jpg" "audio" "protocols") - -# Add board common files -file(GLOB BOARD_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/common/*.cc) -list(APPEND SOURCES ${BOARD_COMMON_SOURCES}) -list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/boards/common) - -idf_build_get_property(build_components BUILD_COMPONENTS) -# Function to find component dynamically by pattern -function(find_component_by_pattern PATTERN COMPONENT_VAR PATH_VAR) - foreach(COMPONENT ${build_components}) - if(COMPONENT MATCHES "${PATTERN}") - set(${COMPONENT_VAR} ${COMPONENT} PARENT_SCOPE) - idf_component_get_property(COMPONENT_PATH ${COMPONENT} COMPONENT_DIR) - set(${PATH_VAR} "${COMPONENT_PATH}" PARENT_SCOPE) - break() - endif() - endforeach() -endfunction() - -# Set default BUILTIN_TEXT_FONT and BUILTIN_ICON_FONT -set(BUILTIN_TEXT_FONT font_puhui_14_1) -set(BUILTIN_ICON_FONT font_awesome_14_1) - -# Add board files according to BOARD_TYPE -# Set default assets if the board uses partition table V2 -if(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI) - set(BOARD_TYPE "bread-compact-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307) - set(BOARD_TYPE "bread-compact-ml307") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32) - set(BOARD_TYPE "bread-compact-esp32") -elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32_LCD) - set(BOARD_TYPE "bread-compact-esp32-lcd") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_DF_K10) - set(BOARD_TYPE "df-k10") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_DF_S3_AI_CAM) - set(BOARD_TYPE "df-s3-ai-cam") -elseif(CONFIG_BOARD_TYPE_ESP_BOX_3) - set(BOARD_TYPE "esp-box-3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_BOX) - set(BOARD_TYPE "esp-box") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_BOX_LITE) - set(BOARD_TYPE "esp-box-lite") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_2) - set(BOARD_TYPE "kevin-box-2") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_KEVIN_C3) - set(BOARD_TYPE "kevin-c3") -elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V3_DEV) - set(BOARD_TYPE "kevin-sp-v3-dev") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V4_DEV) - set(BOARD_TYPE "kevin-sp-v4-dev") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_KEVIN_YUYING_313LCD) - set(BOARD_TYPE "kevin-yuying-313lcd") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV_S3) - set(BOARD_TYPE "lichuang-dev") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV_C3) - set(BOARD_TYPE "lichuang-c3-dev") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_MAGICLICK_S3_2P4) - set(BOARD_TYPE "magiclick-2p4") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_MAGICLICK_S3_2P5) - set(BOARD_TYPE "magiclick-2p5") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3) - set(BOARD_TYPE "magiclick-c3") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3_V2) - set(BOARD_TYPE "magiclick-c3-v2") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_S3) - set(BOARD_TYPE "m5stack-core-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5) - set(BOARD_TYPE "m5stack-tab5") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_M5STACK_ATOM_S3_ECHO_BASE) - set(BOARD_TYPE "atoms3-echo-base") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_M5STACK_ATOM_S3R_ECHO_BASE) - set(BOARD_TYPE "atoms3r-echo-base") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_M5STACK_ATOM_S3R_CAM_M12_ECHO_BASE) - set(BOARD_TYPE "atoms3r-cam-m12-echo-base") -elseif(CONFIG_BOARD_TYPE_M5STACK_ATOM_ECHOS3R) - set(BOARD_TYPE "atom-echos3r") -elseif(CONFIG_BOARD_TYPE_M5STACK_ATOM_MATRIX_ECHO_BASE) - set(BOARD_TYPE "atommatrix-echo-base") -elseif(CONFIG_BOARD_TYPE_XMINI_C3_V3) - set(BOARD_TYPE "xmini-c3-v3") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_XMINI_C3_4G) - set(BOARD_TYPE "xmini-c3-4g") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_XMINI_C3) - set(BOARD_TYPE "xmini-c3") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_ESP_KORVO2_V3) - set(BOARD_TYPE "esp32s3-korvo2-v3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_SPARKBOT) - set(BOARD_TYPE "esp-sparkbot") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_SPOT_S3) - set(BOARD_TYPE "esp-spot") -elseif(CONFIG_BOARD_TYPE_ESP_SPOT_C5) - set(BOARD_TYPE "esp-spot") -elseif(CONFIG_BOARD_TYPE_ESP_HI) - set(BOARD_TYPE "esp-hi") - # Set ESP_HI emoji directory for DEFAULT_ASSETS_EXTRA_FILES - set(DEFAULT_ASSETS_EXTRA_FILES "${CMAKE_BINARY_DIR}/emoji") -elseif(CONFIG_BOARD_TYPE_ECHOEAR) - set(BOARD_TYPE "echoear") - set(BUILTIN_TEXT_FONT font_puhui_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_SENSAIRSHUTTLE) - set(BOARD_TYPE "esp-sensairshuttle") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_AUDIO_BOARD) - set(BOARD_TYPE "waveshare-s3-audio-board") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_8) - set(BOARD_TYPE "esp32-s3-touch-amoled-1.8") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_2_06) - set(BOARD_TYPE "waveshare-s3-touch-amoled-2.06") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_2_06) - set(BOARD_TYPE "waveshare-c6-touch-amoled-2.06") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_4B) - set(BOARD_TYPE "waveshare-s3-touch-lcd-4b") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_75) - set(BOARD_TYPE "waveshare-s3-touch-amoled-1.75") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_83) - set(BOARD_TYPE "waveshare-s3-touch-lcd-1.83") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85C) - set(BOARD_TYPE "esp32-s3-touch-lcd-1.85c") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85) - set(BOARD_TYPE "esp32-s3-touch-lcd-1.85") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_46) - set(BOARD_TYPE "esp32-s3-touch-lcd-1.46") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5) - set(BOARD_TYPE "esp32-s3-touch-lcd-3.5") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5B) - set(BOARD_TYPE "waveshare-s3-touch-lcd-3.5b") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_ePaper_1_54) - set(BOARD_TYPE "waveshare-s3-epaper-1.54") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_RLCD_4_2) - set(BOARD_TYPE "waveshare-s3-rlcd-4.2") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49) - set(BOARD_TYPE "waveshare-s3-touch-lcd-3.49") - set(LVGL_TEXT_FONT font_puhui_basic_30_4) - set(LVGL_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_C6_LCD_1_69) - set(BOARD_TYPE "waveshare-c6-lcd-1.69") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_C6_TOUCH_LCD_1_83) - set(BOARD_TYPE "waveshare-c6-touch-lcd-1.83") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_43) - set(BOARD_TYPE "waveshare-c6-touch-amoled-1.43") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_32) - set(BOARD_TYPE "waveshare-c6-touch-amoled-1.32") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_32) - set(BOARD_TYPE "waveshare-s3-touch-amoled-1.32") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_P4_NANO) - set(BOARD_TYPE "waveshare-p4-nano") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_4B) - set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-4b") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_7B) - set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-7b") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC) - set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-xc") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_P4_FUNCTION_EV_BOARD) - set(BOARD_TYPE "esp-p4-function-ev-board") -elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD) - set(BOARD_TYPE "bread-compact-wifi-lcd") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_TUDOUZI) - set(BOARD_TYPE "tudouzi") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3) - set(BOARD_TYPE "lilygo-t-circle-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1) - set(BOARD_TYPE "lilygo-t-cameraplus-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2) - set(BOARD_TYPE "lilygo-t-cameraplus-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA) - set(BOARD_TYPE "lilygo-t-display-s3-pro-mvsrlora") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY) - set(BOARD_TYPE "lilygo-t-display-s3-pro-mvsrlora") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_P4) - set(BOARD_TYPE "lilygo-t-display-p4") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3) - set(BOARD_TYPE "movecall-moji-esp32s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI2_ESP32C5) - set(BOARD_TYPE "movecall-moji2-esp32c5") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_MOVECALL_CUICAN_ESP32S3) - set(BOARD_TYPE "movecall-cuican-esp32s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3) - set(BOARD_TYPE "atk-dnesp32s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX) - set(BOARD_TYPE "atk-dnesp32s3-box") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX0) - set(BOARD_TYPE "atk-dnesp32s3-box0") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI) - set(BOARD_TYPE "atk-dnesp32s3-box2-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_4G) - set(BOARD_TYPE "atk-dnesp32s3-box2-4g") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_WIFI) - set(BOARD_TYPE "atk-dnesp32s3m-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_4G) - set(BOARD_TYPE "atk-dnesp32s3m-4g") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_DU_CHATX) - set(BOARD_TYPE "du-chatx") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_TAIJI_PI_S3) - set(BOARD_TYPE "taiji-pi-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_0_85TFT_WIFI) - set(BOARD_TYPE "xingzhi-cube-0.85tft-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_0_85TFT_ML307) - set(BOARD_TYPE "xingzhi-cube-0.85tft-ml307") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_0_96OLED_WIFI) - set(BOARD_TYPE "xingzhi-cube-0.96oled-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_0_96OLED_ML307) - set(BOARD_TYPE "xingzhi-cube-0.96oled-ml307") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_1_54TFT_WIFI) - set(BOARD_TYPE "xingzhi-cube-1.54tft-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_XINGZHI_CUBE_1_54TFT_ML307) - set(BOARD_TYPE "xingzhi-cube-1.54tft-ml307") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_XINGZHI_METAL_1_54_WIFI) - set(BOARD_TYPE "xingzhi-metal-1.54-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER) - set(BOARD_TYPE "sensecap-watcher") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_DOIT_S3_AIBOX) - set(BOARD_TYPE "doit-s3-aibox") -elseif(CONFIG_BOARD_TYPE_MIXGO_NOVA) - set(BOARD_TYPE "mixgo-nova") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_GENJUTECH_S3_1_54TFT) - set(BOARD_TYPE "genjutech-s3-1.54tft") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_CGC) - set(BOARD_TYPE "esp32-cgc") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_CGC_144) - set(BOARD_TYPE "esp32-cgc-144") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board) - set(BOARD_TYPE "esp-s3-lcd-ev-board") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board_2) - set(BOARD_TYPE "esp-s3-lcd-ev-board-2") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI) - set(BOARD_TYPE "zhengchen-1.54tft-wifi") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_MINSI_K08_DUAL) - set(BOARD_TYPE "minsi-k08-dual") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307) - set(BOARD_TYPE "zhengchen-1.54tft-ml307") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_SPOTPEAR_ESP32_S3_1_54_MUMA) - set(BOARD_TYPE "sp-esp32-s3-1.54-muma") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_SPOTPEAR_ESP32_S3_1_28_BOX) - set(BOARD_TYPE "sp-esp32-s3-1.28-box") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_OTTO_ROBOT) - set(BOARD_TYPE "otto-robot") - set(BUILTIN_TEXT_FONT font_puhui_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) -elseif(CONFIG_BOARD_TYPE_ELECTRON_BOT) - set(BOARD_TYPE "electron-bot") - set(BUILTIN_TEXT_FONT font_puhui_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) -elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM) - set(BOARD_TYPE "bread-compact-wifi-s3cam") - set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) - set(BUILTIN_ICON_FONT font_awesome_16_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_JIUCHUAN) - set(BOARD_TYPE "jiuchuan-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LABPLUS_MPYTHON_V3) - set(BOARD_TYPE "labplus-mpython-v3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2) - set(BOARD_TYPE "labplus-ledong-v2") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_SURFER_C3_1_14TFT) - set(BOARD_TYPE "surfer-c3-1.14tft") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_YUNLIAO_S3) - set(BOARD_TYPE "yunliao-s3") - set(BUILTIN_TEXT_FONT font_puhui_basic_20_4) - set(BUILTIN_ICON_FONT font_awesome_20_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_WIRELESS_TAG_WTP4C5MP07S) - set(BOARD_TYPE "wireless-tag-wtp4c5mp07s") - set(BUILTIN_TEXT_FONT font_puhui_basic_30_4) - set(BUILTIN_ICON_FONT font_awesome_30_4) - set(DEFAULT_EMOJI_COLLECTION twemoji_64) -elseif(CONFIG_BOARD_TYPE_AIPI_LITE) - set(BOARD_TYPE "aipi-lite") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) - set(DEFAULT_EMOJI_COLLECTION twemoji_32) -elseif(CONFIG_BOARD_TYPE_HU_087) - set(BOARD_TYPE "hu-087") - set(BUILTIN_TEXT_FONT font_puhui_basic_14_1) - set(BUILTIN_ICON_FONT font_awesome_14_1) -endif() - -file(GLOB BOARD_SOURCES - ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc - ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.c -) -list(APPEND SOURCES ${BOARD_SOURCES}) - -# Select audio processor according to Kconfig -if(CONFIG_USE_AUDIO_PROCESSOR) - list(APPEND SOURCES "audio/processors/afe_audio_processor.cc") -else() - list(APPEND SOURCES "audio/processors/no_audio_processor.cc") -endif() -if(CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32P4) - list(APPEND SOURCES "audio/wake_words/afe_wake_word.cc") - list(APPEND SOURCES "audio/wake_words/custom_wake_word.cc") -else() - list(APPEND SOURCES "audio/wake_words/esp_wake_word.cc") -endif() - -# Auto Select Additional Sources -if (CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING) - list(APPEND SOURCES "boards/common/blufi.cpp") -endif () -# Select language directory according to Kconfig -if(CONFIG_LANGUAGE_ZH_CN) - set(LANG_DIR "zh-CN") -elseif(CONFIG_LANGUAGE_ZH_TW) - set(LANG_DIR "zh-TW") -elseif(CONFIG_LANGUAGE_EN_US) - set(LANG_DIR "en-US") -elseif(CONFIG_LANGUAGE_JA_JP) - set(LANG_DIR "ja-JP") -elseif(CONFIG_LANGUAGE_KO_KR) - set(LANG_DIR "ko-KR") -elseif(CONFIG_LANGUAGE_VI_VN) - set(LANG_DIR "vi-VN") -elseif(CONFIG_LANGUAGE_TH_TH) - set(LANG_DIR "th-TH") -elseif(CONFIG_LANGUAGE_DE_DE) - set(LANG_DIR "de-DE") -elseif(CONFIG_LANGUAGE_FR_FR) - set(LANG_DIR "fr-FR") -elseif(CONFIG_LANGUAGE_ES_ES) - set(LANG_DIR "es-ES") -elseif(CONFIG_LANGUAGE_IT_IT) - set(LANG_DIR "it-IT") -elseif(CONFIG_LANGUAGE_RU_RU) - set(LANG_DIR "ru-RU") -elseif(CONFIG_LANGUAGE_AR_SA) - set(LANG_DIR "ar-SA") -elseif(CONFIG_LANGUAGE_HI_IN) - set(LANG_DIR "hi-IN") -elseif(CONFIG_LANGUAGE_PT_PT) - set(LANG_DIR "pt-PT") -elseif(CONFIG_LANGUAGE_PL_PL) - set(LANG_DIR "pl-PL") -elseif(CONFIG_LANGUAGE_CS_CZ) - set(LANG_DIR "cs-CZ") -elseif(CONFIG_LANGUAGE_FI_FI) - set(LANG_DIR "fi-FI") -elseif(CONFIG_LANGUAGE_TR_TR) - set(LANG_DIR "tr-TR") -elseif(CONFIG_LANGUAGE_ID_ID) - set(LANG_DIR "id-ID") -elseif(CONFIG_LANGUAGE_UK_UA) - set(LANG_DIR "uk-UA") -elseif(CONFIG_LANGUAGE_RO_RO) - set(LANG_DIR "ro-RO") -elseif(CONFIG_LANGUAGE_BG_BG) - set(LANG_DIR "bg-BG") -elseif(CONFIG_LANGUAGE_CA_ES) - set(LANG_DIR "ca-ES") -elseif(CONFIG_LANGUAGE_DA_DK) - set(LANG_DIR "da-DK") -elseif(CONFIG_LANGUAGE_EL_GR) - set(LANG_DIR "el-GR") -elseif(CONFIG_LANGUAGE_FA_IR) - set(LANG_DIR "fa-IR") -elseif(CONFIG_LANGUAGE_FIL_PH) - set(LANG_DIR "fil-PH") -elseif(CONFIG_LANGUAGE_HE_IL) - set(LANG_DIR "he-IL") -elseif(CONFIG_LANGUAGE_HR_HR) - set(LANG_DIR "hr-HR") -elseif(CONFIG_LANGUAGE_HU_HU) - set(LANG_DIR "hu-HU") -elseif(CONFIG_LANGUAGE_MS_MY) - set(LANG_DIR "ms-MY") -elseif(CONFIG_LANGUAGE_NB_NO) - set(LANG_DIR "nb-NO") -elseif(CONFIG_LANGUAGE_NL_NL) - set(LANG_DIR "nl-NL") -elseif(CONFIG_LANGUAGE_SK_SK) - set(LANG_DIR "sk-SK") -elseif(CONFIG_LANGUAGE_SL_SI) - set(LANG_DIR "sl-SI") -elseif(CONFIG_LANGUAGE_SV_SE) - set(LANG_DIR "sv-SE") -elseif(CONFIG_LANGUAGE_SR_RS) - set(LANG_DIR "sr-RS") -endif() - -# Define generation path -set(LANG_JSON "${CMAKE_CURRENT_SOURCE_DIR}/assets/locales/${LANG_DIR}/language.json") -set(LANG_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/assets/lang_config.h") - -# Collect current language audio files -file(GLOB LANG_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/locales/${LANG_DIR}/*.ogg) - -# If not en-US, collect en-US audio files as fallback for missing files -if(NOT LANG_DIR STREQUAL "en-US") - file(GLOB EN_US_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/locales/en-US/*.ogg) - - # Extract filenames (without path) from current language - set(EXISTING_NAMES "") - foreach(SOUND_FILE ${LANG_SOUNDS}) - get_filename_component(FILENAME ${SOUND_FILE} NAME) - list(APPEND EXISTING_NAMES ${FILENAME}) - endforeach() - - # Only add en-US audio files that are missing in current language - foreach(EN_SOUND ${EN_US_SOUNDS}) - get_filename_component(FILENAME ${EN_SOUND} NAME) - if(NOT ${FILENAME} IN_LIST EXISTING_NAMES) - list(APPEND LANG_SOUNDS ${EN_SOUND}) - message(STATUS "Using en-US fallback for missing audio: ${FILENAME}") - endif() - endforeach() -endif() - -file(GLOB COMMON_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/common/*.ogg) - -# If target chip is ESP32, exclude specific files to avoid build errors -if(CONFIG_IDF_TARGET_ESP32) - list(REMOVE_ITEM SOURCES "audio/codecs/box_audio_codec.cc" - "audio/codecs/es8388_audio_codec.cc" - "audio/codecs/es8389_audio_codec.cc" - "led/gpio_led.cc" - "${CMAKE_CURRENT_SOURCE_DIR}/boards/common/esp32_camera.cc" - "display/lvgl_display/jpg/image_to_jpeg.cpp" - "display/lvgl_display/jpg/jpeg_to_image.c" - ) -endif() - -idf_component_register(SRCS ${SOURCES} - EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS} - INCLUDE_DIRS ${INCLUDE_DIRS} - WHOLE_ARCHIVE - ) - -# Use target_compile_definitions to define BOARD_TYPE, BOARD_NAME -# If BOARD_NAME is empty, use BOARD_TYPE -if(NOT BOARD_NAME) - set(BOARD_NAME ${BOARD_TYPE}) -endif() -target_compile_definitions(${COMPONENT_LIB} - PRIVATE BOARD_TYPE=\"${BOARD_TYPE}\" BOARD_NAME=\"${BOARD_NAME}\" - PRIVATE BUILTIN_TEXT_FONT=${BUILTIN_TEXT_FONT} BUILTIN_ICON_FONT=${BUILTIN_ICON_FONT} - ) - -# Add generation rules -add_custom_command( - OUTPUT ${LANG_HEADER} - COMMAND python ${PROJECT_DIR}/scripts/gen_lang.py - --language "${LANG_DIR}" - --output "${LANG_HEADER}" - DEPENDS - ${LANG_JSON} - ${PROJECT_DIR}/scripts/gen_lang.py - COMMENT "Generating ${LANG_DIR} language config" -) - -# Force build generation dependencies -add_custom_target(lang_header ALL - DEPENDS ${LANG_HEADER} -) - -# Find ESP-SR component dynamically -find_component_by_pattern("espressif__esp-sr" ESP_SR_COMPONENT ESP_SR_COMPONENT_PATH) -if(ESP_SR_COMPONENT_PATH) - set(ESP_SR_MODEL_PATH "${ESP_SR_COMPONENT_PATH}/model") -endif() - -# Find xiaozhi-fonts component dynamically -find_component_by_pattern("xiaozhi-fonts" XIAOZHI_FONTS_COMPONENT XIAOZHI_FONTS_COMPONENT_PATH) -if(XIAOZHI_FONTS_COMPONENT_PATH) - set(XIAOZHI_FONTS_PATH "${XIAOZHI_FONTS_COMPONENT_PATH}") -endif() - -if(CONFIG_BOARD_TYPE_ESP_HI) -set(URL "https://github.com/espressif2022/image_player/raw/main/test_apps/test_8bit") -set(EMOJI_DIR "${CMAKE_BINARY_DIR}/emoji") -file(MAKE_DIRECTORY ${EMOJI_DIR}) - -# List all files to download -set(FILES_TO_DOWNLOAD "") -list(APPEND FILES_TO_DOWNLOAD "Anger_enter.aaf" "Anger_loop.aaf" "Anger_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "happy_enter.aaf" "happy_loop.aaf" "happ_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "sad_enter.aaf" "sad_loop.aaf" "sad_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "scorn_enter.aaf" "scorn_loop.aaf" "scorn_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "left_enter.aaf" "left_loop.aaf" "left_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "right_enter.aaf" "right_loop.aaf" "right_return.aaf") -list(APPEND FILES_TO_DOWNLOAD "asking.aaf" "blink_once.aaf" "blink_quick.aaf") -list(APPEND FILES_TO_DOWNLOAD "connecting.aaf" "panic_enter.aaf" "panic_loop.aaf") -list(APPEND FILES_TO_DOWNLOAD "panic_return.aaf" "wake.aaf") - -foreach(FILENAME IN LISTS FILES_TO_DOWNLOAD) - set(REMOTE_FILE "${URL}/${FILENAME}") - set(LOCAL_FILE "${EMOJI_DIR}/${FILENAME}") - - # Check if local file exists - if(EXISTS ${LOCAL_FILE}) - message(STATUS "File ${FILENAME} already exists, skipping download") - else() - message(STATUS "Downloading ${FILENAME}") - file(DOWNLOAD ${REMOTE_FILE} ${LOCAL_FILE} - STATUS DOWNLOAD_STATUS) - list(GET DOWNLOAD_STATUS 0 STATUS_CODE) - if(NOT STATUS_CODE EQUAL 0) - message(FATAL_ERROR "Failed to download ${FILENAME} from ${URL}") - endif() - endif() -endforeach() - -endif() - - -# Function to build default assets based on configuration -function(build_default_assets_bin) - # Set output path for generated assets.bin - set(GENERATED_ASSETS_BIN "${CMAKE_BINARY_DIR}/generated_assets.bin") - - # Prepare arguments for build script - set(BUILD_ARGS - "--sdkconfig" "${SDKCONFIG}" - "--output" "${GENERATED_ASSETS_BIN}" - ) - - # Add builtin text font if defined - if(BUILTIN_TEXT_FONT) - list(APPEND BUILD_ARGS "--builtin_text_font" "${BUILTIN_TEXT_FONT}") - endif() - - # Add default emoji collection if defined - if(DEFAULT_EMOJI_COLLECTION) - list(APPEND BUILD_ARGS "--emoji_collection" "${DEFAULT_EMOJI_COLLECTION}") - endif() - - # Add default assets extra files if defined - if(DEFAULT_ASSETS_EXTRA_FILES) - list(APPEND BUILD_ARGS "--extra_files" "${DEFAULT_ASSETS_EXTRA_FILES}") - endif() - - list(APPEND BUILD_ARGS "--esp_sr_model_path" "${ESP_SR_MODEL_PATH}") - list(APPEND BUILD_ARGS "--xiaozhi_fonts_path" "${XIAOZHI_FONTS_PATH}") - - # Create custom command to build assets - add_custom_command( - OUTPUT ${GENERATED_ASSETS_BIN} - COMMAND python ${PROJECT_DIR}/scripts/build_default_assets.py ${BUILD_ARGS} - DEPENDS - ${SDKCONFIG} - ${PROJECT_DIR}/scripts/build_default_assets.py - COMMENT "Building default assets.bin based on configuration" - VERBATIM - ) - - # Create target for generated assets - add_custom_target(generated_default_assets ALL - DEPENDS ${GENERATED_ASSETS_BIN} - ) - - # Set the generated file path in parent scope - set(GENERATED_ASSETS_LOCAL_FILE ${GENERATED_ASSETS_BIN} PARENT_SCOPE) - - message(STATUS "Default assets build configured: ${GENERATED_ASSETS_BIN}") -endfunction() - - -# Function to get local assets file path (handles both URL and local file) -function(get_assets_local_file assets_source assets_local_file_var) - # Check if it's a URL (starts with http:// or https://) - if(assets_source MATCHES "^https?://") - # It's a URL, download it - get_filename_component(ASSETS_FILENAME "${assets_source}" NAME) - set(ASSETS_LOCAL_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}") - set(ASSETS_TEMP_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}.tmp") - - # Check if local file exists - if(EXISTS ${ASSETS_LOCAL_FILE}) - message(STATUS "Assets file ${ASSETS_FILENAME} already exists, skipping download") - else() - message(STATUS "Downloading ${ASSETS_FILENAME}") - - # Clean up any existing temp file - if(EXISTS ${ASSETS_TEMP_FILE}) - file(REMOVE ${ASSETS_TEMP_FILE}) - endif() - - # Download to temporary file first - file(DOWNLOAD ${assets_source} ${ASSETS_TEMP_FILE} - STATUS DOWNLOAD_STATUS) - list(GET DOWNLOAD_STATUS 0 STATUS_CODE) - if(NOT STATUS_CODE EQUAL 0) - # Clean up temp file on failure - if(EXISTS ${ASSETS_TEMP_FILE}) - file(REMOVE ${ASSETS_TEMP_FILE}) - endif() - message(FATAL_ERROR "Failed to download ${ASSETS_FILENAME} from ${assets_source}") - endif() - - # Move temp file to final location (atomic operation) - file(RENAME ${ASSETS_TEMP_FILE} ${ASSETS_LOCAL_FILE}) - message(STATUS "Successfully downloaded ${ASSETS_FILENAME}") - endif() - else() - # It's a local file path - if(IS_ABSOLUTE "${assets_source}") - set(ASSETS_LOCAL_FILE "${assets_source}") - else() - set(ASSETS_LOCAL_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${assets_source}") - endif() - - # Check if local file exists - if(NOT EXISTS ${ASSETS_LOCAL_FILE}) - message(FATAL_ERROR "Assets file not found: ${ASSETS_LOCAL_FILE}") - endif() - - message(STATUS "Using assets file: ${ASSETS_LOCAL_FILE}") - endif() - - set(${assets_local_file_var} ${ASSETS_LOCAL_FILE} PARENT_SCOPE) -endfunction() - - -partition_table_get_partition_info(size "--partition-name assets" "size") -partition_table_get_partition_info(offset "--partition-name assets" "offset") -if ("${size}" AND "${offset}") - # Flash assets based on configuration - if(CONFIG_FLASH_DEFAULT_ASSETS) - # Build default assets based on configuration - build_default_assets_bin() - esptool_py_flash_to_partition(flash "assets" "${GENERATED_ASSETS_LOCAL_FILE}") - message(STATUS "Generated default assets flash configured: ${GENERATED_ASSETS_LOCAL_FILE} -> assets partition") - elseif(CONFIG_FLASH_CUSTOM_ASSETS) - # Flash custom assets - get_assets_local_file("${CONFIG_CUSTOM_ASSETS_FILE}" ASSETS_LOCAL_FILE) - esptool_py_flash_to_partition(flash "assets" "${ASSETS_LOCAL_FILE}") - message(STATUS "Custom assets flash configured: ${ASSETS_LOCAL_FILE} -> assets partition") - elseif(CONFIG_FLASH_NONE_ASSETS) - message(STATUS "Assets flashing disabled (FLASH_NONE_ASSETS)") - endif() -else() - message(STATUS "Assets partition not found, using v1 partition table") -endif() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/Kconfig.projbuild b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/Kconfig.projbuild deleted file mode 100644 index e271fe55..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/Kconfig.projbuild +++ /dev/null @@ -1,820 +0,0 @@ -menu "Xiaozhi Assistant" - -config OTA_URL - string "Default OTA URL" - default "https://api.tenclass.net/xiaozhi/ota/" - help - The application will access this URL to check for new firmwares and server address. - -choice - prompt "Flash Assets" - default FLASH_DEFAULT_ASSETS - help - Select the assets to flash. - - config FLASH_NONE_ASSETS - bool "Do not flash assets" - config FLASH_DEFAULT_ASSETS - bool "Flash Default Assets" - config FLASH_CUSTOM_ASSETS - bool "Flash Custom Assets" -endchoice - -config CUSTOM_ASSETS_FILE - depends on FLASH_CUSTOM_ASSETS - string "Custom Assets File" - default "assets.bin" - help - The custom assets file to flash. - It can be a local file relative to the project directory or a remote url. - -choice - prompt "Default Language" - default LANGUAGE_ZH_CN - help - Select device display language - - config LANGUAGE_ZH_CN - bool "Chinese" - config LANGUAGE_ZH_TW - bool "Chinese Traditional" - config LANGUAGE_EN_US - bool "English" - config LANGUAGE_JA_JP - bool "Japanese" - config LANGUAGE_KO_KR - bool "Korean" - config LANGUAGE_VI_VN - bool "Vietnamese" - config LANGUAGE_TH_TH - bool "Thai" - config LANGUAGE_DE_DE - bool "German" - config LANGUAGE_FR_FR - bool "French" - config LANGUAGE_ES_ES - bool "Spanish" - config LANGUAGE_IT_IT - bool "Italian" - config LANGUAGE_RU_RU - bool "Russian" - config LANGUAGE_AR_SA - bool "Arabic" - config LANGUAGE_HI_IN - bool "Hindi" - config LANGUAGE_PT_PT - bool "Portuguese" - config LANGUAGE_PL_PL - bool "Polish" - config LANGUAGE_CS_CZ - bool "Czech" - config LANGUAGE_FI_FI - bool "Finnish" - config LANGUAGE_TR_TR - bool "Turkish" - config LANGUAGE_ID_ID - bool "Indonesian" - config LANGUAGE_UK_UA - bool "Ukrainian" - config LANGUAGE_RO_RO - bool "Romanian" - config LANGUAGE_BG_BG - bool "Bulgarian" - config LANGUAGE_CA_ES - bool "Catalan" - config LANGUAGE_DA_DK - bool "Danish" - config LANGUAGE_EL_GR - bool "Greek" - config LANGUAGE_FA_IR - bool "Persian" - config LANGUAGE_FIL_PH - bool "Filipino" - config LANGUAGE_HE_IL - bool "Hebrew" - config LANGUAGE_HR_HR - bool "Croatian" - config LANGUAGE_HU_HU - bool "Hungarian" - config LANGUAGE_MS_MY - bool "Malay" - config LANGUAGE_NB_NO - bool "Norwegian" - config LANGUAGE_NL_NL - bool "Dutch" - config LANGUAGE_SK_SK - bool "Slovak" - config LANGUAGE_SL_SI - bool "Slovenian" - config LANGUAGE_SV_SE - bool "Swedish" - config LANGUAGE_SR_RS - bool "Serbian" -endchoice - -choice BOARD_TYPE - prompt "Board Type" - default BOARD_TYPE_BREAD_COMPACT_WIFI - help - Board type. 开发板类型 - config BOARD_TYPE_BREAD_COMPACT_WIFI - bool "Bread Compact WiFi (面包板)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_BREAD_COMPACT_WIFI_LCD - bool "Bread Compact WiFi + LCD (面包板)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_BREAD_COMPACT_WIFI_CAM - bool "Bread Compact WiFi + LCD + Camera (面包板)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_BREAD_COMPACT_ML307 - bool "Bread Compact ML307/EC801E (面包板 4G)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_BREAD_COMPACT_ESP32 - bool "Bread Compact ESP32 DevKit (面包板)" - depends on IDF_TARGET_ESP32 - config BOARD_TYPE_BREAD_COMPACT_ESP32_LCD - bool "Bread Compact ESP32 DevKit + LCD (面包板)" - depends on IDF_TARGET_ESP32 - config BOARD_TYPE_XMINI_C3_V3 - bool "Xmini C3 V3" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_XMINI_C3_4G - bool "Xmini C3 4G" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_XMINI_C3 - bool "Xmini C3" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_ESP_KORVO2_V3 - bool "Espressif Korvo2 V3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_SPARKBOT - bool "Espressif SparkBot" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_SENSAIRSHUTTLE - bool "Espressif ESP-SensairShuttle" - depends on IDF_TARGET_ESP32C5 - config BOARD_TYPE_ESP_SPOT_S3 - bool "Espressif Spot-S3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_SPOT_C5 - bool "Espressif Spot-C5" - depends on IDF_TARGET_ESP32C5 - config BOARD_TYPE_ESP_HI - bool "Espressif ESP-HI" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_ESP_BOX_3 - bool "Espressif ESP-BOX-3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_BOX - bool "Espressif ESP-BOX" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_BOX_LITE - bool "Espressif ESP-BOX-Lite" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_P4_FUNCTION_EV_BOARD - bool "Espressif ESP-P4-Function-EV-Board" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_ECHOEAR - bool "EchoEar" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_KEVIN_BOX_2 - bool "Kevin Box 2" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_KEVIN_C3 - bool "Kevin C3" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_KEVIN_SP_V3_DEV - bool "Kevin SP V3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_KEVIN_SP_V4_DEV - bool "Kevin SP V4" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_KEVIN_YUYING_313LCD - bool "鱼鹰科技 3.13LCD" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_CGC - bool "CGC" - depends on IDF_TARGET_ESP32 - config BOARD_TYPE_CGC_144 - bool "CGC 144" - depends on IDF_TARGET_ESP32 - config BOARD_TYPE_LICHUANG_DEV_S3 - bool "立创·实战派 ESP32-S3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LICHUANG_DEV_C3 - bool "立创·实战派 ESP32-C3" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_DF_K10 - bool "DFRobot 行空板 k10" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_DF_S3_AI_CAM - bool "DFRobot ESP32-S3 AI智能摄像头模块" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MAGICLICK_S3_2P4 - bool "神奇按钮 Magiclick_2.4" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MAGICLICK_S3_2P5 - bool "神奇按钮 Magiclick_2.5" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MAGICLICK_C3 - bool "神奇按钮 Magiclick_C3" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_MAGICLICK_C3_V2 - bool "神奇按钮 Magiclick_C3_v2" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_M5STACK_CORE_S3 - bool "M5Stack CoreS3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_M5STACK_CORE_TAB5 - bool "M5Stack Tab5" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_M5STACK_ATOM_S3_ECHO_BASE - bool "M5Stack AtomS3 + Echo Base" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_M5STACK_ATOM_S3R_ECHO_BASE - bool "M5Stack AtomS3R + Echo Base" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_M5STACK_ATOM_S3R_CAM_M12_ECHO_BASE - bool "M5Stack AtomS3R CAM/M12 + Echo Base" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_M5STACK_ATOM_ECHOS3R - bool "M5Stack AtomEchoS3R" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_M5STACK_ATOM_MATRIX_ECHO_BASE - bool "M5Stack AtomMatrix + Echo Base" - depends on IDF_TARGET_ESP32 - config BOARD_TYPE_WAVESHARE_S3_AUDIO_BOARD - bool "Waveshare ESP32-S3-Audio-Board" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_8 - bool "Waveshare ESP32-S3-Touch-AMOLED-1.8" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_2_06 - bool "Waveshare ESP32-S3-Touch-AMOLED-2.06" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_2_06 - bool "Waveshare ESP32-C6-Touch-AMOLED-2.06" - depends on IDF_TARGET_ESP32C6 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_75 - bool "Waveshare ESP32-S3-Touch-AMOLED-1.75" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_83 - bool "Waveshare ESP32-S3-Touch-LCD-1.83" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_4B - bool "Waveshare ESP32-S3-Touch-LCD-4B" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85C - bool "Waveshare ESP32-S3-Touch-LCD-1.85C" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_85 - bool "Waveshare ESP32-S3-Touch-LCD-1.85" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_46 - bool "Waveshare ESP32-S3-Touch-LCD-1.46" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_C6_LCD_1_69 - bool "Waveshare ESP32-C6-LCD-1.69" - depends on IDF_TARGET_ESP32C6 - config BOARD_TYPE_WAVESHARE_C6_TOUCH_LCD_1_83 - bool "Waveshare ESP32-C6-Touch-LCD-1.83" - depends on IDF_TARGET_ESP32C6 - config BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_43 - bool "Waveshare ESP32-C6-Touch-AMOLOED-1.43" - depends on IDF_TARGET_ESP32C6 - config BOARD_TYPE_WAVESHARE_C6_TOUCH_AMOLED_1_32 - bool "Waveshare ESP32-C6-Touch-AMOLOED-1.32" - depends on IDF_TARGET_ESP32C6 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_32 - bool "Waveshare ESP32-S3-Touch-AMOLOED-1.32" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49 - bool "Waveshare ESP32-S3-Touch-LCD-3.49" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5 - bool "Waveshare ESP32-S3-Touch-LCD-3.5" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_ePaper_1_54 - bool "Waveshare ESP32-S3-ePaper-1.54" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_RLCD_4_2 - bool "Waveshare ESP32-S3-RLCD-4.2" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_5B - bool "Waveshare ESP32-S3-Touch-LCD-3.5B" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WAVESHARE_P4_NANO - bool "Waveshare ESP32-P4-NANO" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_4B - bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4B" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_7B - bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-7B" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC - bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C or ESP32-P4-WIFI6-Touch-LCD-4C" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_TUDOUZI - bool "土豆子" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_CIRCLE_S3 - bool "LILYGO T-Circle-S3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1 - bool "LILYGO T-CameraPlus-S3_V1_0_V1_1" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 - bool "LILYGO T-CameraPlus-S3_V1_2" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA - bool "LILYGO T-Display-S3-Pro-MVSRLora" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY - bool "LILYGO T-Display-S3-Pro-MVSRLora_No_Battery" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LILYGO_T_DISPLAY_P4 - bool "LILYGO T-Display-P4" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_MOVECALL_MOJI_ESP32S3 - bool "Movecall Moji 小智AI衍生版" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MOVECALL_MOJI2_ESP32C5 - bool "Movecall Moji2.0 小智AI衍生版" - depends on IDF_TARGET_ESP32C5 - config BOARD_TYPE_MOVECALL_CUICAN_ESP32S3 - bool "Movecall CuiCan 璀璨·AI吊坠" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3 - bool "正点原子DNESP32S3开发板" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3_BOX - bool "正点原子DNESP32S3-BOX" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3_BOX0 - bool "正点原子DNESP32S3-BOX0" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI - bool "正点原子DNESP32S3-BOX2-WIFI" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3_BOX2_4G - bool "正点原子DNESP32S3-BOX2-4G" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3M_WIFI - bool "正点原子DNESP32S3M-WIFI" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ATK_DNESP32S3M_4G - bool "正点原子DNESP32S3M-4G" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_DU_CHATX - bool "嘟嘟开发板CHATX(wifi)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_TAIJI_PI_S3 - bool "太极小派esp32s3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_0_85TFT_WIFI - bool "无名科技星智0.85(WIFI)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_0_85TFT_ML307 - bool "无名科技星智0.85(ML307)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_0_96OLED_WIFI - bool "无名科技星智0.96(WIFI)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_0_96OLED_ML307 - bool "无名科技星智0.96(ML307)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_1_54TFT_WIFI - bool "无名科技星智1.54(WIFI)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_CUBE_1_54TFT_ML307 - bool "无名科技星智1.54(ML307)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_XINGZHI_METAL_1_54_WIFI - bool "无名科技星智1.54 METAL(wifi)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER - bool "Seeed Studio SenseCAP Watcher" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_DOIT_S3_AIBOX - bool "四博智联AI陪伴盒子" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MIXGO_NOVA - bool "元控·青春" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_GENJUTECH_S3_1_54TFT - bool "亘具科技1.54(s3)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_S3_LCD_EV_Board - bool "乐鑫ESP S3 LCD EV Board开发板" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ESP_S3_LCD_EV_Board_2 - bool "乐鑫ESP S3 LCD EV Board 2开发板" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI - bool "征辰科技1.54(WIFI)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307 - bool "征辰科技1.54(ML307)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_MINSI_K08_DUAL - bool "敏思科技K08(DUAL)" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_SPOTPEAR_ESP32_S3_1_54_MUMA - bool "Spotpear ESP32-S3-1.54-MUMA" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_SPOTPEAR_ESP32_S3_1_28_BOX - bool "Spotpear ESP32-S3-1.28-BOX" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_OTTO_ROBOT - bool "ottoRobot" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_ELECTRON_BOT - bool "electronBot" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_JIUCHUAN - bool "九川智能" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LABPLUS_MPYTHON_V3 - bool "labplus mpython_v3 board" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_LABPLUS_LEDONG_V2 - bool "labplus ledong_v2 board" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_SURFER_C3_1_14TFT - bool "Surfer-C3-1.14TFT" - depends on IDF_TARGET_ESP32C3 - config BOARD_TYPE_YUNLIAO_S3 - bool "小智云聊-S3" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_WIRELESS_TAG_WTP4C5MP07S - bool "Wireless-Tag WTP4C5MP07S" - depends on IDF_TARGET_ESP32P4 - config BOARD_TYPE_AIPI_LITE - bool "AIPI-Lite" - depends on IDF_TARGET_ESP32S3 - config BOARD_TYPE_HU_087 - bool "HU-087" - depends on IDF_TARGET_ESP32S3 -endchoice - -choice - depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4 - prompt "Select the screen type" - default SCREEN_TYPE_HI8561 - config SCREEN_TYPE_HI8561 - bool "HI8561" - config SCREEN_TYPE_RM69A10 - bool "RM69A10" -endchoice - -choice - depends on BOARD_TYPE_LILYGO_T_DISPLAY_P4 - prompt "Select the color format of the screen" - default SCREEN_PIXEL_FORMAT_RGB565 - config SCREEN_PIXEL_FORMAT_RGB565 - bool "RGB565" - config SCREEN_PIXEL_FORMAT_RGB888 - bool "RGB888" -endchoice - -choice ESP_S3_LCD_EV_Board_Version_TYPE - depends on BOARD_TYPE_ESP_S3_LCD_EV_Board - prompt "EV_BOARD Type" - default ESP_S3_LCD_EV_Board_1p4 - config ESP_S3_LCD_EV_Board_1p4 - bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.4" - config ESP_S3_LCD_EV_Board_1p5 - bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.5" -endchoice - -choice DISPLAY_OLED_TYPE - depends on BOARD_TYPE_BREAD_COMPACT_WIFI || BOARD_TYPE_BREAD_COMPACT_ML307 || BOARD_TYPE_BREAD_COMPACT_ESP32 || BOARD_TYPE_HU_087 - prompt "OLED Type" - default OLED_SSD1306_128X32 - help - OLED Monochrome Display Type - config OLED_SSD1306_128X32 - bool "SSD1306 128*32" - config OLED_SSD1306_128X64 - bool "SSD1306 128*64" - config OLED_SH1106_128X64 - bool "SH1106 128*64" -endchoice - -choice DISPLAY_LCD_TYPE - depends on BOARD_TYPE_BREAD_COMPACT_WIFI_LCD || BOARD_TYPE_BREAD_COMPACT_ESP32_LCD || BOARD_TYPE_CGC || BOARD_TYPE_WAVESHARE_P4_NANO || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC || BOARD_TYPE_BREAD_COMPACT_WIFI_CAM - prompt "LCD Type" - default LCD_ST7789_240X320 - help - LCD Display Type - config LCD_ST7789_240X320 - bool "ST7789 240*320, IPS" - config LCD_ST7789_240X320_NO_IPS - bool "ST7789 240*320, Non-IPS" - config LCD_ST7789_170X320 - bool "ST7789 170*320" - config LCD_ST7789_172X320 - bool "ST7789 172*320" - config LCD_ST7789_240X280 - bool "ST7789 240*280" - config LCD_ST7789_240X240 - bool "ST7789 240*240" - config LCD_ST7789_240X240_7PIN - bool "ST7789 240*240, 7PIN" - config LCD_ST7789_240X135 - bool "ST7789 240*135" - config LCD_ST7735_128X160 - bool "ST7735 128*160" - config LCD_ST7735_128X128 - bool "ST7735 128*128" - config LCD_ST7796_320X480 - bool "ST7796 320*480 IPS" - config LCD_ST7796_320X480_NO_IPS - bool "ST7796 320*480, Non-IPS" - config LCD_ILI9341_240X320 - bool "ILI9341 240*320" - config LCD_ILI9341_240X320_NO_IPS - bool "ILI9341 240*320, Non-IPS" - config LCD_GC9A01_240X240 - bool "GC9A01 240*240 Circle" - config LCD_TYPE_800_1280_10_1_INCH - bool "Waveshare 101M-8001280-IPS-CT-K Display" - config LCD_TYPE_800_1280_10_1_INCH_A - bool "Waveshare 10.1-DSI-TOUCH-A Display" - config LCD_TYPE_800_800_3_4_INCH - bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C with 800*800 3.4inch round display" - config LCD_TYPE_720_720_4_INCH - bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4C with 720*720 4inch round display" - config LCD_CUSTOM - bool "Custom LCD (自定义屏幕参数)" -endchoice - -choice DISPLAY_ESP32S3_KORVO2_V3 - depends on BOARD_TYPE_ESP_KORVO2_V3 - prompt "ESP32S3_KORVO2_V3 LCD Type" - default ESP32S3_KORVO2_V3_LCD_ST7789 - help - LCD Display Type - config ESP32S3_KORVO2_V3_LCD_ST7789 - bool "ST7789 240*280" - config ESP32S3_KORVO2_V3_LCD_ILI9341 - bool "ILI9341 240*320" -endchoice - -choice DISPLAY_ESP32S3_AUDIO_BOARD - depends on BOARD_TYPE_WAVESHARE_S3_AUDIO_BOARD - prompt "ESP32S3_AUDIO_BOARD LCD Type" - default AUDIO_BOARD_LCD_JD9853 - help - LCD Display Type - config AUDIO_BOARD_LCD_JD9853 - bool "JD9853 320*172" - config AUDIO_BOARD_LCD_ST7789 - bool "ST7789 240*320" -endchoice - -choice DISPLAY_STYLE - prompt "Select display style" - default USE_DEFAULT_MESSAGE_STYLE - help - Select display style for Xiaozhi device - - config USE_DEFAULT_MESSAGE_STYLE - bool "Enable default message style" - - config USE_WECHAT_MESSAGE_STYLE - bool "Enable WeChat Message Style" - - config USE_EMOTE_MESSAGE_STYLE - bool "Emote animation style" - depends on BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ECHOEAR || BOARD_TYPE_LICHUANG_DEV_S3 || BOARD_TYPE_ESP_SENSAIRSHUTTLE -endchoice - -choice WAKE_WORD_TYPE - prompt "Wake Word Implementation Type" - default USE_AFE_WAKE_WORD if (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM - default WAKE_WORD_DISABLED - help - Choose the type of wake word implementation to use - - config WAKE_WORD_DISABLED - bool "Disabled" - help - Disable wake word detection - - config USE_ESP_WAKE_WORD - bool "Wakenet model without AFE" - depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM) - help - Support ESP32 C3、ESP32 C5 与 ESP32 C6, and (ESP32 with PSRAM) - - config USE_AFE_WAKE_WORD - bool "Wakenet model with AFE" - depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM - help - Support AEC if available, requires ESP32 S3 and PSRAM - - config USE_CUSTOM_WAKE_WORD - bool "Multinet model (Custom Wake Word)" - depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM - help - Requires ESP32 S3 and PSRAM - -endchoice - -config CUSTOM_WAKE_WORD - string "Custom Wake Word" - default "xiao tu dou" - depends on USE_CUSTOM_WAKE_WORD - help - Custom Wake Word, use pinyin for Chinese, separated by spaces - -config CUSTOM_WAKE_WORD_DISPLAY - string "Custom Wake Word Display" - default "小土豆" - depends on USE_CUSTOM_WAKE_WORD - help - Greeting sent to the server after wake word detection - -config CUSTOM_WAKE_WORD_THRESHOLD - int "Custom Wake Word Threshold (%)" - default 20 - range 1 99 - depends on USE_CUSTOM_WAKE_WORD - help - Custom Wake Word Threshold, range 1-99, the smaller the more sensitive, default 20 - -config SEND_WAKE_WORD_DATA - bool "Send Wake Word Data" - default y - depends on USE_AFE_WAKE_WORD || USE_CUSTOM_WAKE_WORD - help - Send wake word data to the server as the first message of the conversation and wait for response - -config USE_AUDIO_PROCESSOR - bool "Enable Audio Noise Reduction" - default y - depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM - help - Requires ESP32 S3 and PSRAM - -config USE_DEVICE_AEC - bool "Enable Device-Side AEC" - default n - depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE \ - || BOARD_TYPE_LICHUANG_DEV_S3 || BOARD_TYPE_ESP_KORVO2_V3 || BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_1_75 || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_1_83\ - || BOARD_TYPE_WAVESHARE_S3_TOUCH_AMOLED_2_06 || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_4B || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_7B \ - || BOARD_TYPE_WAVESHARE_P4_WIFI6_TOUCH_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 || BOARD_TYPE_YUNLIAO_S3 \ - || BOARD_TYPE_ECHOEAR || BOARD_TYPE_WAVESHARE_S3_TOUCH_LCD_3_49 || BOARD_TYPE_WAVESHARE_S3_RLCD_4_2) - help - To work properly, device-side AEC requires a clean output reference path from the speaker signal and physical acoustic isolation between the microphone and speaker. - -config USE_SERVER_AEC - bool "Enable Server-Side AEC (Unstable)" - default n - depends on USE_AUDIO_PROCESSOR - help - To work perperly, server-side AEC requires server support - -config USE_AUDIO_DEBUGGER - bool "Enable Audio Debugger" - default n - help - Enable audio debugger, send audio data through UDP to the host machine - -menu "WiFi Configuration Method" - help - WiFi Configuration Method Selection - config USE_HOTSPOT_WIFI_PROVISIONING - bool "Hotspot" - default y - help - Use WiFi Hotspot to transmit WiFi configuration data - config USE_ACOUSTIC_WIFI_PROVISIONING - bool "Acoustic" - help - Use audio signal to transmit WiFi configuration data - - config USE_ESP_BLUFI_WIFI_PROVISIONING - bool "Esp Blufi" - help - Use esp blufi protocol to transmit WiFi configuration data - select BT_ENABLED - select BT_BLE_42_FEATURES_SUPPORTED - select BT_BLE_BLUFI_ENABLE - select MBEDTLS_DHM_C -endmenu - -config AUDIO_DEBUG_UDP_SERVER - string "Audio Debug UDP Server Address" - default "192.168.2.100:8000" - depends on USE_AUDIO_DEBUGGER - help - UDP server address, format: IP:PORT, used to receive audio debugging data - -config RECEIVE_CUSTOM_MESSAGE - bool "Enable Custom Message Reception" - default n - help - Enable custom message reception, allow the device to receive custom messages from the server (preferably through the MQTT protocol) - -menu "Camera Configuration" - depends on !IDF_TARGET_ESP32 - - comment "Warning: Please read the help text before modifying these settings." - - config XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - bool "Allow JPEG Input" - default n - help - Allow JPEG Input format for the camera. - - This option may need to be enabled when using a USB camera. - - Not currently supported when used simultaneously with XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE. - - config XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - bool "Enable Hardware JPEG Encoder" - default y - depends on SOC_JPEG_ENCODE_SUPPORTED - help - Use hardware JPEG encoder on ESP32-P4 to encode image to JPEG. - See https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/jpeg.html for more details. - - config XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER - bool "Enable Hardware JPEG Decoder" - default n - depends on SOC_JPEG_DECODE_SUPPORTED && XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - help - Use hardware JPEG decoder on ESP32-P4 to decode JPEG to image. - See https://docs.espressif.com/projects/esp-idf/en/stable/esp32p4/api-reference/peripherals/jpeg.html for more details. - - config XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - bool "Enable Camera Debug Mode" - default n - help - Enable camera debug mode, print camera debug information to the console. - Only works on boards that support camera. - - config XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP - bool "Enable software camera buffer endianness swapping" - default n - depends on !CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER - help - This option treats the camera buffer as a uint16_t[] array and performs byte-swapping (endianness conversion) on each element. - - Should only be modified by development board integration engineers. - - **Incorrect usage may result in incorrect image colors!** - - ATTENTION: If the option CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER is available for your sensor, please use that instead. - - menuconfig XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - bool "Enable Camera Image Rotation" - default n - depends on !XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - help - Enable camera image rotation, rotate the camera image to the correct orientation. - - On ESP32-P4, rotation is handled by PPA hardware. - - On other chips, rotation is done in software with performance cost. - - For 180° rotation, use HFlip + VFlip instead of this option. - - Not currently supported when used simultaneously with XIAOZHI_CAMERA_ALLOW_JPEG_INPUT. - - if XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - choice XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE - prompt "Camera Image Rotation Angle (clockwise)" - default XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90 - help - Camera image rotation angle. - config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90 - bool "90°" - config XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_270 - bool "270°" - comment "For 180° rotation, use HFlip + VFlip instead of this option" - endchoice - endif -endmenu - -menu "TAIJIPAI_S3_CONFIG" - depends on BOARD_TYPE_TAIJI_PI_S3 - choice I2S_TYPE_TAIJIPI_S3 - prompt "taiji-pi-S3 I2S Type" - default TAIJIPAI_I2S_TYPE_STD - help - I2S 类型选择 - config TAIJIPAI_I2S_TYPE_STD - bool "I2S Type STD" - config TAIJIPAI_I2S_TYPE_PDM - bool "I2S Type PDM" - endchoice - - config I2S_USE_2SLOT - bool "Enable I2S 2 Slot" - default y - help - 启动双声道 -endmenu - -endmenu diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.cc deleted file mode 100644 index 09803862..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.cc +++ /dev/null @@ -1,1055 +0,0 @@ -#include "application.h" -#include "board.h" -#include "display.h" -#include "system_info.h" -#include "audio_codec.h" -#include "mqtt_protocol.h" -#include "websocket_protocol.h" -#include "assets/lang_config.h" -#include "mcp_server.h" -#include "assets.h" -#include "settings.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "Application" - - -Application::Application() { - event_group_ = xEventGroupCreate(); - -#if CONFIG_USE_DEVICE_AEC && CONFIG_USE_SERVER_AEC -#error "CONFIG_USE_DEVICE_AEC and CONFIG_USE_SERVER_AEC cannot be enabled at the same time" -#elif CONFIG_USE_DEVICE_AEC - aec_mode_ = kAecOnDeviceSide; -#elif CONFIG_USE_SERVER_AEC - aec_mode_ = kAecOnServerSide; -#else - aec_mode_ = kAecOff; -#endif - - esp_timer_create_args_t clock_timer_args = { - .callback = [](void* arg) { - Application* app = (Application*)arg; - xEventGroupSetBits(app->event_group_, MAIN_EVENT_CLOCK_TICK); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "clock_timer", - .skip_unhandled_events = true - }; - esp_timer_create(&clock_timer_args, &clock_timer_handle_); -} - -Application::~Application() { - if (clock_timer_handle_ != nullptr) { - esp_timer_stop(clock_timer_handle_); - esp_timer_delete(clock_timer_handle_); - } - vEventGroupDelete(event_group_); -} - -bool Application::SetDeviceState(DeviceState state) { - return state_machine_.TransitionTo(state); -} - -void Application::Initialize() { - auto& board = Board::GetInstance(); - SetDeviceState(kDeviceStateStarting); - - // Setup the display - auto display = board.GetDisplay(); - - // Print board name/version info - display->SetChatMessage("system", SystemInfo::GetUserAgent().c_str()); - - // Setup the audio service - auto codec = board.GetAudioCodec(); - audio_service_.Initialize(codec); - audio_service_.Start(); - - AudioServiceCallbacks callbacks; - callbacks.on_send_queue_available = [this]() { - xEventGroupSetBits(event_group_, MAIN_EVENT_SEND_AUDIO); - }; - callbacks.on_wake_word_detected = [this](const std::string& wake_word) { - xEventGroupSetBits(event_group_, MAIN_EVENT_WAKE_WORD_DETECTED); - }; - callbacks.on_vad_change = [this](bool speaking) { - xEventGroupSetBits(event_group_, MAIN_EVENT_VAD_CHANGE); - }; - audio_service_.SetCallbacks(callbacks); - - // Add state change listeners - state_machine_.AddStateChangeListener([this](DeviceState old_state, DeviceState new_state) { - xEventGroupSetBits(event_group_, MAIN_EVENT_STATE_CHANGED); - }); - - // Start the clock timer to update the status bar - esp_timer_start_periodic(clock_timer_handle_, 1000000); - - // Add MCP common tools (only once during initialization) - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddCommonTools(); - mcp_server.AddUserOnlyTools(); - - // Set network event callback for UI updates and network state handling - board.SetNetworkEventCallback([this](NetworkEvent event, const std::string& data) { - auto display = Board::GetInstance().GetDisplay(); - - switch (event) { - case NetworkEvent::Scanning: - display->ShowNotification(Lang::Strings::SCANNING_WIFI, 30000); - xEventGroupSetBits(event_group_, MAIN_EVENT_NETWORK_DISCONNECTED); - break; - case NetworkEvent::Connecting: { - if (data.empty()) { - // Cellular network - registering without carrier info yet - display->SetStatus(Lang::Strings::REGISTERING_NETWORK); - } else { - // WiFi or cellular with carrier info - std::string msg = Lang::Strings::CONNECT_TO; - msg += data; - msg += "..."; - display->ShowNotification(msg.c_str(), 30000); - } - break; - } - case NetworkEvent::Connected: { - std::string msg = Lang::Strings::CONNECTED_TO; - msg += data; - display->ShowNotification(msg.c_str(), 30000); - xEventGroupSetBits(event_group_, MAIN_EVENT_NETWORK_CONNECTED); - break; - } - case NetworkEvent::Disconnected: - xEventGroupSetBits(event_group_, MAIN_EVENT_NETWORK_DISCONNECTED); - break; - case NetworkEvent::WifiConfigModeEnter: - // WiFi config mode enter is handled by WifiBoard internally - break; - case NetworkEvent::WifiConfigModeExit: - // WiFi config mode exit is handled by WifiBoard internally - break; - // Cellular modem specific events - case NetworkEvent::ModemDetecting: - display->SetStatus(Lang::Strings::DETECTING_MODULE); - break; - case NetworkEvent::ModemErrorNoSim: - Alert(Lang::Strings::ERROR, Lang::Strings::PIN_ERROR, "triangle_exclamation", Lang::Sounds::OGG_ERR_PIN); - break; - case NetworkEvent::ModemErrorRegDenied: - Alert(Lang::Strings::ERROR, Lang::Strings::REG_ERROR, "triangle_exclamation", Lang::Sounds::OGG_ERR_REG); - break; - case NetworkEvent::ModemErrorInitFailed: - display->SetStatus(Lang::Strings::DETECTING_MODULE); - display->SetChatMessage("system", Lang::Strings::DETECTING_MODULE); - break; - case NetworkEvent::ModemErrorTimeout: - display->SetStatus(Lang::Strings::REGISTERING_NETWORK); - break; - } - }); - - // Start network asynchronously - board.StartNetwork(); - - // Update the status bar immediately to show the network state - display->UpdateStatusBar(true); -} - -void Application::Run() { - const EventBits_t ALL_EVENTS = - MAIN_EVENT_SCHEDULE | - MAIN_EVENT_SEND_AUDIO | - MAIN_EVENT_WAKE_WORD_DETECTED | - MAIN_EVENT_VAD_CHANGE | - MAIN_EVENT_CLOCK_TICK | - MAIN_EVENT_ERROR | - MAIN_EVENT_NETWORK_CONNECTED | - MAIN_EVENT_NETWORK_DISCONNECTED | - MAIN_EVENT_TOGGLE_CHAT | - MAIN_EVENT_START_LISTENING | - MAIN_EVENT_STOP_LISTENING | - MAIN_EVENT_ACTIVATION_DONE | - MAIN_EVENT_STATE_CHANGED; - - while (true) { - auto bits = xEventGroupWaitBits(event_group_, ALL_EVENTS, pdTRUE, pdFALSE, portMAX_DELAY); - - if (bits & MAIN_EVENT_ERROR) { - SetDeviceState(kDeviceStateIdle); - Alert(Lang::Strings::ERROR, last_error_message_.c_str(), "circle_xmark", Lang::Sounds::OGG_EXCLAMATION); - } - - if (bits & MAIN_EVENT_NETWORK_CONNECTED) { - HandleNetworkConnectedEvent(); - } - - if (bits & MAIN_EVENT_NETWORK_DISCONNECTED) { - HandleNetworkDisconnectedEvent(); - } - - if (bits & MAIN_EVENT_ACTIVATION_DONE) { - HandleActivationDoneEvent(); - } - - if (bits & MAIN_EVENT_STATE_CHANGED) { - HandleStateChangedEvent(); - } - - if (bits & MAIN_EVENT_TOGGLE_CHAT) { - HandleToggleChatEvent(); - } - - if (bits & MAIN_EVENT_START_LISTENING) { - HandleStartListeningEvent(); - } - - if (bits & MAIN_EVENT_STOP_LISTENING) { - HandleStopListeningEvent(); - } - - if (bits & MAIN_EVENT_SEND_AUDIO) { - while (auto packet = audio_service_.PopPacketFromSendQueue()) { - if (protocol_ && !protocol_->SendAudio(std::move(packet))) { - break; - } - } - } - - if (bits & MAIN_EVENT_WAKE_WORD_DETECTED) { - HandleWakeWordDetectedEvent(); - } - - if (bits & MAIN_EVENT_VAD_CHANGE) { - if (GetDeviceState() == kDeviceStateListening) { - auto led = Board::GetInstance().GetLed(); - led->OnStateChanged(); - } - } - - if (bits & MAIN_EVENT_SCHEDULE) { - std::unique_lock lock(mutex_); - auto tasks = std::move(main_tasks_); - lock.unlock(); - for (auto& task : tasks) { - task(); - } - } - - if (bits & MAIN_EVENT_CLOCK_TICK) { - clock_ticks_++; - auto display = Board::GetInstance().GetDisplay(); - display->UpdateStatusBar(); - - // Print debug info every 10 seconds - if (clock_ticks_ % 10 == 0) { - SystemInfo::PrintHeapStats(); - } - } - } -} - -void Application::HandleNetworkConnectedEvent() { - ESP_LOGI(TAG, "Network connected"); - auto state = GetDeviceState(); - - if (state == kDeviceStateStarting || state == kDeviceStateWifiConfiguring) { - // Network is ready, start activation - SetDeviceState(kDeviceStateActivating); - if (activation_task_handle_ != nullptr) { - ESP_LOGW(TAG, "Activation task already running"); - return; - } - - xTaskCreate([](void* arg) { - Application* app = static_cast(arg); - app->ActivationTask(); - app->activation_task_handle_ = nullptr; - vTaskDelete(NULL); - }, "activation", 4096 * 2, this, 2, &activation_task_handle_); - } - - // Update the status bar immediately to show the network state - auto display = Board::GetInstance().GetDisplay(); - display->UpdateStatusBar(true); -} - -void Application::HandleNetworkDisconnectedEvent() { - // Close current conversation when network disconnected - auto state = GetDeviceState(); - if (state == kDeviceStateConnecting || state == kDeviceStateListening || state == kDeviceStateSpeaking) { - ESP_LOGI(TAG, "Closing audio channel due to network disconnection"); - protocol_->CloseAudioChannel(); - } - - // Update the status bar immediately to show the network state - auto display = Board::GetInstance().GetDisplay(); - display->UpdateStatusBar(true); -} - -void Application::HandleActivationDoneEvent() { - ESP_LOGI(TAG, "Activation done"); - - SystemInfo::PrintHeapStats(); - SetDeviceState(kDeviceStateIdle); - - has_server_time_ = ota_->HasServerTime(); - - auto display = Board::GetInstance().GetDisplay(); - std::string message = std::string(Lang::Strings::VERSION) + ota_->GetCurrentVersion(); - display->ShowNotification(message.c_str()); - display->SetChatMessage("system", ""); - - // Play the success sound to indicate the device is ready - audio_service_.PlaySound(Lang::Sounds::OGG_SUCCESS); - - // Release OTA object after activation is complete - ota_.reset(); - auto& board = Board::GetInstance(); - board.SetPowerSaveLevel(PowerSaveLevel::LOW_POWER); -} - -void Application::ActivationTask() { - // Create OTA object for activation process - ota_ = std::make_unique(); - - // Check for new assets version - CheckAssetsVersion(); - - // Check for new firmware version - CheckNewVersion(); - - // Initialize the protocol - InitializeProtocol(); - - // Signal completion to main loop - xEventGroupSetBits(event_group_, MAIN_EVENT_ACTIVATION_DONE); -} - -void Application::CheckAssetsVersion() { - // Only allow CheckAssetsVersion to be called once - if (assets_version_checked_) { - return; - } - assets_version_checked_ = true; - - auto& board = Board::GetInstance(); - auto display = board.GetDisplay(); - auto& assets = Assets::GetInstance(); - - if (!assets.partition_valid()) { - ESP_LOGW(TAG, "Assets partition is disabled for board %s", BOARD_NAME); - return; - } - - Settings settings("assets", true); - // Check if there is a new assets need to be downloaded - std::string download_url = settings.GetString("download_url"); - - if (!download_url.empty()) { - settings.EraseKey("download_url"); - - char message[256]; - snprintf(message, sizeof(message), Lang::Strings::FOUND_NEW_ASSETS, download_url.c_str()); - Alert(Lang::Strings::LOADING_ASSETS, message, "cloud_arrow_down", Lang::Sounds::OGG_UPGRADE); - - // Wait for the audio service to be idle for 3 seconds - vTaskDelay(pdMS_TO_TICKS(3000)); - SetDeviceState(kDeviceStateUpgrading); - board.SetPowerSaveLevel(PowerSaveLevel::PERFORMANCE); - display->SetChatMessage("system", Lang::Strings::PLEASE_WAIT); - - bool success = assets.Download(download_url, [display](int progress, size_t speed) -> void { - std::thread([display, progress, speed]() { - char buffer[32]; - snprintf(buffer, sizeof(buffer), "%d%% %uKB/s", progress, speed / 1024); - display->SetChatMessage("system", buffer); - }).detach(); - }); - - board.SetPowerSaveLevel(PowerSaveLevel::LOW_POWER); - vTaskDelay(pdMS_TO_TICKS(1000)); - - if (!success) { - Alert(Lang::Strings::ERROR, Lang::Strings::DOWNLOAD_ASSETS_FAILED, "circle_xmark", Lang::Sounds::OGG_EXCLAMATION); - vTaskDelay(pdMS_TO_TICKS(2000)); - SetDeviceState(kDeviceStateActivating); - return; - } - } - - // Apply assets - assets.Apply(); - display->SetChatMessage("system", ""); - display->SetEmotion("microchip_ai"); -} - -void Application::CheckNewVersion() { - const int MAX_RETRY = 10; - int retry_count = 0; - int retry_delay = 10; // Initial retry delay in seconds - - auto& board = Board::GetInstance(); - while (true) { - auto display = board.GetDisplay(); - display->SetStatus(Lang::Strings::CHECKING_NEW_VERSION); - - esp_err_t err = ota_->CheckVersion(); - if (err != ESP_OK) { - retry_count++; - if (retry_count >= MAX_RETRY) { - ESP_LOGE(TAG, "Too many retries, exit version check"); - return; - } - - char error_message[128]; - snprintf(error_message, sizeof(error_message), "code=%d, url=%s", err, ota_->GetCheckVersionUrl().c_str()); - char buffer[256]; - snprintf(buffer, sizeof(buffer), Lang::Strings::CHECK_NEW_VERSION_FAILED, retry_delay, error_message); - Alert(Lang::Strings::ERROR, buffer, "cloud_slash", Lang::Sounds::OGG_EXCLAMATION); - - ESP_LOGW(TAG, "Check new version failed, retry in %d seconds (%d/%d)", retry_delay, retry_count, MAX_RETRY); - for (int i = 0; i < retry_delay; i++) { - vTaskDelay(pdMS_TO_TICKS(1000)); - if (GetDeviceState() == kDeviceStateIdle) { - break; - } - } - retry_delay *= 2; // Double the retry delay - continue; - } - retry_count = 0; - retry_delay = 10; // Reset retry delay - - if (ota_->HasNewVersion()) { - if (UpgradeFirmware(ota_->GetFirmwareUrl(), ota_->GetFirmwareVersion())) { - return; // This line will never be reached after reboot - } - // If upgrade failed, continue to normal operation - } - - // No new version, mark the current version as valid - ota_->MarkCurrentVersionValid(); - if (!ota_->HasActivationCode() && !ota_->HasActivationChallenge()) { - // Exit the loop if done checking new version - break; - } - - display->SetStatus(Lang::Strings::ACTIVATION); - // Activation code is shown to the user and waiting for the user to input - if (ota_->HasActivationCode()) { - ShowActivationCode(ota_->GetActivationCode(), ota_->GetActivationMessage()); - } - - // This will block the loop until the activation is done or timeout - for (int i = 0; i < 10; ++i) { - ESP_LOGI(TAG, "Activating... %d/%d", i + 1, 10); - esp_err_t err = ota_->Activate(); - if (err == ESP_OK) { - break; - } else if (err == ESP_ERR_TIMEOUT) { - vTaskDelay(pdMS_TO_TICKS(3000)); - } else { - vTaskDelay(pdMS_TO_TICKS(10000)); - } - if (GetDeviceState() == kDeviceStateIdle) { - break; - } - } - } -} - -void Application::InitializeProtocol() { - auto& board = Board::GetInstance(); - auto display = board.GetDisplay(); - auto codec = board.GetAudioCodec(); - - display->SetStatus(Lang::Strings::LOADING_PROTOCOL); - - if (ota_->HasMqttConfig()) { - protocol_ = std::make_unique(); - } else if (ota_->HasWebsocketConfig()) { - protocol_ = std::make_unique(); - } else { - ESP_LOGW(TAG, "No protocol specified in the OTA config, using MQTT"); - protocol_ = std::make_unique(); - } - - protocol_->OnConnected([this]() { - DismissAlert(); - }); - - protocol_->OnNetworkError([this](const std::string& message) { - last_error_message_ = message; - xEventGroupSetBits(event_group_, MAIN_EVENT_ERROR); - }); - - protocol_->OnIncomingAudio([this](std::unique_ptr packet) { - if (GetDeviceState() == kDeviceStateSpeaking) { - audio_service_.PushPacketToDecodeQueue(std::move(packet)); - } - }); - - protocol_->OnAudioChannelOpened([this, codec, &board]() { - board.SetPowerSaveLevel(PowerSaveLevel::PERFORMANCE); - if (protocol_->server_sample_rate() != codec->output_sample_rate()) { - ESP_LOGW(TAG, "Server sample rate %d does not match device output sample rate %d, resampling may cause distortion", - protocol_->server_sample_rate(), codec->output_sample_rate()); - } - }); - - protocol_->OnAudioChannelClosed([this, &board]() { - board.SetPowerSaveLevel(PowerSaveLevel::LOW_POWER); - Schedule([this]() { - auto display = Board::GetInstance().GetDisplay(); - display->SetChatMessage("system", ""); - SetDeviceState(kDeviceStateIdle); - }); - }); - - protocol_->OnIncomingJson([this, display](const cJSON* root) { - // Parse JSON data - auto type = cJSON_GetObjectItem(root, "type"); - if (strcmp(type->valuestring, "tts") == 0) { - auto state = cJSON_GetObjectItem(root, "state"); - if (strcmp(state->valuestring, "start") == 0) { - Schedule([this]() { - aborted_ = false; - SetDeviceState(kDeviceStateSpeaking); - }); - } else if (strcmp(state->valuestring, "stop") == 0) { - Schedule([this]() { - if (GetDeviceState() == kDeviceStateSpeaking) { - if (listening_mode_ == kListeningModeManualStop) { - SetDeviceState(kDeviceStateIdle); - } else { - SetDeviceState(kDeviceStateListening); - } - } - }); - } else if (strcmp(state->valuestring, "sentence_start") == 0) { - auto text = cJSON_GetObjectItem(root, "text"); - if (cJSON_IsString(text)) { - ESP_LOGI(TAG, "<< %s", text->valuestring); - Schedule([this, display, message = std::string(text->valuestring)]() { - display->SetChatMessage("assistant", message.c_str()); - }); - } - } - } else if (strcmp(type->valuestring, "stt") == 0) { - auto text = cJSON_GetObjectItem(root, "text"); - if (cJSON_IsString(text)) { - ESP_LOGI(TAG, ">> %s", text->valuestring); - Schedule([this, display, message = std::string(text->valuestring)]() { - display->SetChatMessage("user", message.c_str()); - }); - } - } else if (strcmp(type->valuestring, "llm") == 0) { - auto emotion = cJSON_GetObjectItem(root, "emotion"); - if (cJSON_IsString(emotion)) { - Schedule([this, display, emotion_str = std::string(emotion->valuestring)]() { - display->SetEmotion(emotion_str.c_str()); - }); - } - } else if (strcmp(type->valuestring, "mcp") == 0) { - auto payload = cJSON_GetObjectItem(root, "payload"); - if (cJSON_IsObject(payload)) { - McpServer::GetInstance().ParseMessage(payload); - } - } else if (strcmp(type->valuestring, "system") == 0) { - auto command = cJSON_GetObjectItem(root, "command"); - if (cJSON_IsString(command)) { - ESP_LOGI(TAG, "System command: %s", command->valuestring); - if (strcmp(command->valuestring, "reboot") == 0) { - // Do a reboot if user requests a OTA update - Schedule([this]() { - Reboot(); - }); - } else { - ESP_LOGW(TAG, "Unknown system command: %s", command->valuestring); - } - } - } else if (strcmp(type->valuestring, "alert") == 0) { - auto status = cJSON_GetObjectItem(root, "status"); - auto message = cJSON_GetObjectItem(root, "message"); - auto emotion = cJSON_GetObjectItem(root, "emotion"); - if (cJSON_IsString(status) && cJSON_IsString(message) && cJSON_IsString(emotion)) { - Alert(status->valuestring, message->valuestring, emotion->valuestring, Lang::Sounds::OGG_VIBRATION); - } else { - ESP_LOGW(TAG, "Alert command requires status, message and emotion"); - } -#if CONFIG_RECEIVE_CUSTOM_MESSAGE - } else if (strcmp(type->valuestring, "custom") == 0) { - auto payload = cJSON_GetObjectItem(root, "payload"); - ESP_LOGI(TAG, "Received custom message: %s", cJSON_PrintUnformatted(root)); - if (cJSON_IsObject(payload)) { - Schedule([this, display, payload_str = std::string(cJSON_PrintUnformatted(payload))]() { - display->SetChatMessage("system", payload_str.c_str()); - }); - } else { - ESP_LOGW(TAG, "Invalid custom message format: missing payload"); - } -#endif - } else { - ESP_LOGW(TAG, "Unknown message type: %s", type->valuestring); - } - }); - - protocol_->Start(); -} - -void Application::ShowActivationCode(const std::string& code, const std::string& message) { - struct digit_sound { - char digit; - const std::string_view& sound; - }; - static const std::array digit_sounds{{ - digit_sound{'0', Lang::Sounds::OGG_0}, - digit_sound{'1', Lang::Sounds::OGG_1}, - digit_sound{'2', Lang::Sounds::OGG_2}, - digit_sound{'3', Lang::Sounds::OGG_3}, - digit_sound{'4', Lang::Sounds::OGG_4}, - digit_sound{'5', Lang::Sounds::OGG_5}, - digit_sound{'6', Lang::Sounds::OGG_6}, - digit_sound{'7', Lang::Sounds::OGG_7}, - digit_sound{'8', Lang::Sounds::OGG_8}, - digit_sound{'9', Lang::Sounds::OGG_9} - }}; - - // This sentence uses 9KB of SRAM, so we need to wait for it to finish - Alert(Lang::Strings::ACTIVATION, message.c_str(), "link", Lang::Sounds::OGG_ACTIVATION); - - for (const auto& digit : code) { - auto it = std::find_if(digit_sounds.begin(), digit_sounds.end(), - [digit](const digit_sound& ds) { return ds.digit == digit; }); - if (it != digit_sounds.end()) { - audio_service_.PlaySound(it->sound); - } - } -} - -void Application::Alert(const char* status, const char* message, const char* emotion, const std::string_view& sound) { - ESP_LOGW(TAG, "Alert [%s] %s: %s", emotion, status, message); - auto display = Board::GetInstance().GetDisplay(); - display->SetStatus(status); - display->SetEmotion(emotion); - display->SetChatMessage("system", message); - if (!sound.empty()) { - audio_service_.PlaySound(sound); - } -} - -void Application::DismissAlert() { - if (GetDeviceState() == kDeviceStateIdle) { - auto display = Board::GetInstance().GetDisplay(); - display->SetStatus(Lang::Strings::STANDBY); - display->SetEmotion("neutral"); - display->SetChatMessage("system", ""); - } -} - -void Application::ToggleChatState() { - xEventGroupSetBits(event_group_, MAIN_EVENT_TOGGLE_CHAT); -} - -void Application::StartListening() { - xEventGroupSetBits(event_group_, MAIN_EVENT_START_LISTENING); -} - -void Application::StopListening() { - xEventGroupSetBits(event_group_, MAIN_EVENT_STOP_LISTENING); -} - -void Application::HandleToggleChatEvent() { - auto state = GetDeviceState(); - - if (state == kDeviceStateActivating) { - SetDeviceState(kDeviceStateIdle); - return; - } else if (state == kDeviceStateWifiConfiguring) { - audio_service_.EnableAudioTesting(true); - SetDeviceState(kDeviceStateAudioTesting); - return; - } else if (state == kDeviceStateAudioTesting) { - audio_service_.EnableAudioTesting(false); - SetDeviceState(kDeviceStateWifiConfiguring); - return; - } - - if (!protocol_) { - ESP_LOGE(TAG, "Protocol not initialized"); - return; - } - - if (state == kDeviceStateIdle) { - if (!protocol_->IsAudioChannelOpened()) { - SetDeviceState(kDeviceStateConnecting); - if (!protocol_->OpenAudioChannel()) { - return; - } - } - - SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime); - } else if (state == kDeviceStateSpeaking) { - AbortSpeaking(kAbortReasonNone); - } else if (state == kDeviceStateListening) { - protocol_->CloseAudioChannel(); - } -} - -void Application::HandleStartListeningEvent() { - auto state = GetDeviceState(); - - if (state == kDeviceStateActivating) { - SetDeviceState(kDeviceStateIdle); - return; - } else if (state == kDeviceStateWifiConfiguring) { - audio_service_.EnableAudioTesting(true); - SetDeviceState(kDeviceStateAudioTesting); - return; - } - - if (!protocol_) { - ESP_LOGE(TAG, "Protocol not initialized"); - return; - } - - if (state == kDeviceStateIdle) { - if (!protocol_->IsAudioChannelOpened()) { - SetDeviceState(kDeviceStateConnecting); - if (!protocol_->OpenAudioChannel()) { - return; - } - } - - SetListeningMode(kListeningModeManualStop); - } else if (state == kDeviceStateSpeaking) { - AbortSpeaking(kAbortReasonNone); - SetListeningMode(kListeningModeManualStop); - } -} - -void Application::HandleStopListeningEvent() { - auto state = GetDeviceState(); - - if (state == kDeviceStateAudioTesting) { - audio_service_.EnableAudioTesting(false); - SetDeviceState(kDeviceStateWifiConfiguring); - return; - } else if (state == kDeviceStateListening) { - if (protocol_) { - protocol_->SendStopListening(); - } - SetDeviceState(kDeviceStateIdle); - } -} - -void Application::HandleWakeWordDetectedEvent() { - if (!protocol_) { - return; - } - - auto state = GetDeviceState(); - - if (state == kDeviceStateIdle) { - audio_service_.EncodeWakeWord(); - - if (!protocol_->IsAudioChannelOpened()) { - SetDeviceState(kDeviceStateConnecting); - if (!protocol_->OpenAudioChannel()) { - audio_service_.EnableWakeWordDetection(true); - return; - } - } - - auto wake_word = audio_service_.GetLastWakeWord(); - ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str()); -#if CONFIG_SEND_WAKE_WORD_DATA - // Encode and send the wake word data to the server - while (auto packet = audio_service_.PopWakeWordPacket()) { - protocol_->SendAudio(std::move(packet)); - } - // Set the chat state to wake word detected - protocol_->SendWakeWordDetected(wake_word); - SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime); -#else - // Set flag to play popup sound after state changes to listening - // (PlaySound here would be cleared by ResetDecoder in EnableVoiceProcessing) - play_popup_on_listening_ = true; - SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime); -#endif - } else if (state == kDeviceStateSpeaking) { - AbortSpeaking(kAbortReasonWakeWordDetected); - } else if (state == kDeviceStateActivating) { - // Restart the activation check if the wake word is detected during activation - SetDeviceState(kDeviceStateIdle); - } -} - -void Application::HandleStateChangedEvent() { - DeviceState new_state = state_machine_.GetState(); - clock_ticks_ = 0; - - auto& board = Board::GetInstance(); - auto display = board.GetDisplay(); - auto led = board.GetLed(); - led->OnStateChanged(); - - switch (new_state) { - case kDeviceStateUnknown: - case kDeviceStateIdle: - display->SetStatus(Lang::Strings::STANDBY); - display->SetEmotion("neutral"); - audio_service_.EnableVoiceProcessing(false); - audio_service_.EnableWakeWordDetection(true); - break; - case kDeviceStateConnecting: - display->SetStatus(Lang::Strings::CONNECTING); - display->SetEmotion("neutral"); - display->SetChatMessage("system", ""); - break; - case kDeviceStateListening: - display->SetStatus(Lang::Strings::LISTENING); - display->SetEmotion("neutral"); - - // Make sure the audio processor is running - if (!audio_service_.IsAudioProcessorRunning()) { - // Send the start listening command - protocol_->SendStartListening(listening_mode_); - audio_service_.EnableVoiceProcessing(true); - audio_service_.EnableWakeWordDetection(false); - } - - // Play popup sound after ResetDecoder (in EnableVoiceProcessing) has been called - if (play_popup_on_listening_) { - play_popup_on_listening_ = false; - audio_service_.PlaySound(Lang::Sounds::OGG_POPUP); - } - break; - case kDeviceStateSpeaking: - display->SetStatus(Lang::Strings::SPEAKING); - - if (listening_mode_ != kListeningModeRealtime) { - audio_service_.EnableVoiceProcessing(false); - // Only AFE wake word can be detected in speaking mode - audio_service_.EnableWakeWordDetection(audio_service_.IsAfeWakeWord()); - } - audio_service_.ResetDecoder(); - break; - case kDeviceStateWifiConfiguring: - audio_service_.EnableVoiceProcessing(false); - audio_service_.EnableWakeWordDetection(false); - break; - default: - // Do nothing - break; - } -} - -void Application::Schedule(std::function&& callback) { - { - std::lock_guard lock(mutex_); - main_tasks_.push_back(std::move(callback)); - } - xEventGroupSetBits(event_group_, MAIN_EVENT_SCHEDULE); -} - -void Application::AbortSpeaking(AbortReason reason) { - ESP_LOGI(TAG, "Abort speaking"); - aborted_ = true; - if (protocol_) { - protocol_->SendAbortSpeaking(reason); - } -} - -void Application::SetListeningMode(ListeningMode mode) { - listening_mode_ = mode; - SetDeviceState(kDeviceStateListening); -} - -void Application::Reboot() { - ESP_LOGI(TAG, "Rebooting..."); - // Disconnect the audio channel - if (protocol_ && protocol_->IsAudioChannelOpened()) { - protocol_->CloseAudioChannel(); - } - protocol_.reset(); - audio_service_.Stop(); - - vTaskDelay(pdMS_TO_TICKS(1000)); - esp_restart(); -} - -bool Application::UpgradeFirmware(const std::string& url, const std::string& version) { - auto& board = Board::GetInstance(); - auto display = board.GetDisplay(); - - std::string upgrade_url = url; - std::string version_info = version.empty() ? "(Manual upgrade)" : version; - - // Close audio channel if it's open - if (protocol_ && protocol_->IsAudioChannelOpened()) { - ESP_LOGI(TAG, "Closing audio channel before firmware upgrade"); - protocol_->CloseAudioChannel(); - } - ESP_LOGI(TAG, "Starting firmware upgrade from URL: %s", upgrade_url.c_str()); - - Alert(Lang::Strings::OTA_UPGRADE, Lang::Strings::UPGRADING, "download", Lang::Sounds::OGG_UPGRADE); - vTaskDelay(pdMS_TO_TICKS(3000)); - - SetDeviceState(kDeviceStateUpgrading); - - std::string message = std::string(Lang::Strings::NEW_VERSION) + version_info; - display->SetChatMessage("system", message.c_str()); - - board.SetPowerSaveLevel(PowerSaveLevel::PERFORMANCE); - audio_service_.Stop(); - vTaskDelay(pdMS_TO_TICKS(1000)); - - bool upgrade_success = Ota::Upgrade(upgrade_url, [display](int progress, size_t speed) { - std::thread([display, progress, speed]() { - char buffer[32]; - snprintf(buffer, sizeof(buffer), "%d%% %uKB/s", progress, speed / 1024); - display->SetChatMessage("system", buffer); - }).detach(); - }); - - if (!upgrade_success) { - // Upgrade failed, restart audio service and continue running - ESP_LOGE(TAG, "Firmware upgrade failed, restarting audio service and continuing operation..."); - audio_service_.Start(); // Restart audio service - board.SetPowerSaveLevel(PowerSaveLevel::LOW_POWER); // Restore power save level - Alert(Lang::Strings::ERROR, Lang::Strings::UPGRADE_FAILED, "circle_xmark", Lang::Sounds::OGG_EXCLAMATION); - vTaskDelay(pdMS_TO_TICKS(3000)); - return false; - } else { - // Upgrade success, reboot immediately - ESP_LOGI(TAG, "Firmware upgrade successful, rebooting..."); - display->SetChatMessage("system", "Upgrade successful, rebooting..."); - vTaskDelay(pdMS_TO_TICKS(1000)); // Brief pause to show message - Reboot(); - return true; - } -} - -void Application::WakeWordInvoke(const std::string& wake_word) { - if (!protocol_) { - return; - } - - auto state = GetDeviceState(); - - if (state == kDeviceStateIdle) { - audio_service_.EncodeWakeWord(); - - if (!protocol_->IsAudioChannelOpened()) { - SetDeviceState(kDeviceStateConnecting); - if (!protocol_->OpenAudioChannel()) { - audio_service_.EnableWakeWordDetection(true); - return; - } - } - - ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str()); -#if CONFIG_USE_AFE_WAKE_WORD || CONFIG_USE_CUSTOM_WAKE_WORD - // Encode and send the wake word data to the server - while (auto packet = audio_service_.PopWakeWordPacket()) { - protocol_->SendAudio(std::move(packet)); - } - // Set the chat state to wake word detected - protocol_->SendWakeWordDetected(wake_word); - SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime); -#else - // Set flag to play popup sound after state changes to listening - // (PlaySound here would be cleared by ResetDecoder in EnableVoiceProcessing) - play_popup_on_listening_ = true; - SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime); -#endif - } else if (state == kDeviceStateSpeaking) { - Schedule([this]() { - AbortSpeaking(kAbortReasonNone); - }); - } else if (state == kDeviceStateListening) { - Schedule([this]() { - if (protocol_) { - protocol_->CloseAudioChannel(); - } - }); - } -} - -bool Application::CanEnterSleepMode() { - if (GetDeviceState() != kDeviceStateIdle) { - return false; - } - - if (protocol_ && protocol_->IsAudioChannelOpened()) { - return false; - } - - if (!audio_service_.IsIdle()) { - return false; - } - - // Now it is safe to enter sleep mode - return true; -} - -void Application::SendMcpMessage(const std::string& payload) { - // Always schedule to run in main task for thread safety - Schedule([this, payload = std::move(payload)]() { - if (protocol_) { - protocol_->SendMcpMessage(payload); - } - }); -} - -void Application::SetAecMode(AecMode mode) { - aec_mode_ = mode; - Schedule([this]() { - auto& board = Board::GetInstance(); - auto display = board.GetDisplay(); - switch (aec_mode_) { - case kAecOff: - audio_service_.EnableDeviceAec(false); - display->ShowNotification(Lang::Strings::RTC_MODE_OFF); - break; - case kAecOnServerSide: - audio_service_.EnableDeviceAec(false); - display->ShowNotification(Lang::Strings::RTC_MODE_ON); - break; - case kAecOnDeviceSide: - audio_service_.EnableDeviceAec(true); - display->ShowNotification(Lang::Strings::RTC_MODE_ON); - break; - } - - // If the AEC mode is changed, close the audio channel - if (protocol_ && protocol_->IsAudioChannelOpened()) { - protocol_->CloseAudioChannel(); - } - }); -} - -void Application::PlaySound(const std::string_view& sound) { - audio_service_.PlaySound(sound); -} - -void Application::ResetProtocol() { - Schedule([this]() { - // Close audio channel if opened - if (protocol_ && protocol_->IsAudioChannelOpened()) { - protocol_->CloseAudioChannel(); - } - // Reset protocol - protocol_.reset(); - }); -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.h deleted file mode 100644 index 33bda4cf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/application.h +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef _APPLICATION_H_ -#define _APPLICATION_H_ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "protocol.h" -#include "ota.h" -#include "audio_service.h" -#include "device_state.h" -#include "device_state_machine.h" - -// Main event bits -#define MAIN_EVENT_SCHEDULE (1 << 0) -#define MAIN_EVENT_SEND_AUDIO (1 << 1) -#define MAIN_EVENT_WAKE_WORD_DETECTED (1 << 2) -#define MAIN_EVENT_VAD_CHANGE (1 << 3) -#define MAIN_EVENT_ERROR (1 << 4) -#define MAIN_EVENT_ACTIVATION_DONE (1 << 5) -#define MAIN_EVENT_CLOCK_TICK (1 << 6) -#define MAIN_EVENT_NETWORK_CONNECTED (1 << 7) -#define MAIN_EVENT_NETWORK_DISCONNECTED (1 << 8) -#define MAIN_EVENT_TOGGLE_CHAT (1 << 9) -#define MAIN_EVENT_START_LISTENING (1 << 10) -#define MAIN_EVENT_STOP_LISTENING (1 << 11) -#define MAIN_EVENT_STATE_CHANGED (1 << 12) - - -enum AecMode { - kAecOff, - kAecOnDeviceSide, - kAecOnServerSide, -}; - -class Application { -public: - static Application& GetInstance() { - static Application instance; - return instance; - } - // Delete copy constructor and assignment operator - Application(const Application&) = delete; - Application& operator=(const Application&) = delete; - - /** - * Initialize the application - * This sets up display, audio, network callbacks, etc. - * Network connection starts asynchronously. - */ - void Initialize(); - - /** - * Run the main event loop - * This function runs in the main task and never returns. - * It handles all events including network, state changes, and user interactions. - */ - void Run(); - - DeviceState GetDeviceState() const { return state_machine_.GetState(); } - bool IsVoiceDetected() const { return audio_service_.IsVoiceDetected(); } - - /** - * Request state transition - * Returns true if transition was successful - */ - bool SetDeviceState(DeviceState state); - - /** - * Schedule a callback to be executed in the main task - */ - void Schedule(std::function&& callback); - - /** - * Alert with status, message, emotion and optional sound - */ - void Alert(const char* status, const char* message, const char* emotion = "", const std::string_view& sound = ""); - void DismissAlert(); - - void AbortSpeaking(AbortReason reason); - - /** - * Toggle chat state (event-based, thread-safe) - * Sends MAIN_EVENT_TOGGLE_CHAT to be handled in Run() - */ - void ToggleChatState(); - - /** - * Start listening (event-based, thread-safe) - * Sends MAIN_EVENT_START_LISTENING to be handled in Run() - */ - void StartListening(); - - /** - * Stop listening (event-based, thread-safe) - * Sends MAIN_EVENT_STOP_LISTENING to be handled in Run() - */ - void StopListening(); - - void Reboot(); - void WakeWordInvoke(const std::string& wake_word); - bool UpgradeFirmware(const std::string& url, const std::string& version = ""); - bool CanEnterSleepMode(); - void SendMcpMessage(const std::string& payload); - void SetAecMode(AecMode mode); - AecMode GetAecMode() const { return aec_mode_; } - void PlaySound(const std::string_view& sound); - AudioService& GetAudioService() { return audio_service_; } - - /** - * Reset protocol resources (thread-safe) - * Can be called from any task to release resources allocated after network connected - * This includes closing audio channel, resetting protocol and ota objects - */ - void ResetProtocol(); - -private: - Application(); - ~Application(); - - std::mutex mutex_; - std::deque> main_tasks_; - std::unique_ptr protocol_; - EventGroupHandle_t event_group_ = nullptr; - esp_timer_handle_t clock_timer_handle_ = nullptr; - DeviceStateMachine state_machine_; - ListeningMode listening_mode_ = kListeningModeAutoStop; - AecMode aec_mode_ = kAecOff; - std::string last_error_message_; - AudioService audio_service_; - std::unique_ptr ota_; - - bool has_server_time_ = false; - bool aborted_ = false; - bool assets_version_checked_ = false; - bool play_popup_on_listening_ = false; // Flag to play popup sound after state changes to listening - int clock_ticks_ = 0; - TaskHandle_t activation_task_handle_ = nullptr; - - - // Event handlers - void HandleStateChangedEvent(); - void HandleToggleChatEvent(); - void HandleStartListeningEvent(); - void HandleStopListeningEvent(); - void HandleNetworkConnectedEvent(); - void HandleNetworkDisconnectedEvent(); - void HandleActivationDoneEvent(); - void HandleWakeWordDetectedEvent(); - - // Activation task (runs in background) - void ActivationTask(); - - // Helper methods - void CheckAssetsVersion(); - void CheckNewVersion(); - void InitializeProtocol(); - void ShowActivationCode(const std::string& code, const std::string& message); - void SetListeningMode(ListeningMode mode); - - // State change handler called by state machine - void OnStateChanged(DeviceState old_state, DeviceState new_state); -}; - - -class TaskPriorityReset { -public: - TaskPriorityReset(BaseType_t priority) { - original_priority_ = uxTaskPriorityGet(NULL); - vTaskPrioritySet(NULL, priority); - } - ~TaskPriorityReset() { - vTaskPrioritySet(NULL, original_priority_); - } - -private: - BaseType_t original_priority_; -}; - -#endif // _APPLICATION_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.cc deleted file mode 100644 index 2d45bd36..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.cc +++ /dev/null @@ -1,532 +0,0 @@ -#include "assets.h" -#include "board.h" -#include "display.h" -#include "application.h" -#include "lvgl_theme.h" -#include "emote_display.h" -#ifdef HAVE_LVGL -#include "display/lcd_display.h" -#endif - -#include -#include -#include -#include - - -#define TAG "Assets" - -struct mmap_assets_table { - char asset_name[32]; /*!< Name of the asset */ - uint32_t asset_size; /*!< Size of the asset */ - uint32_t asset_offset; /*!< Offset of the asset */ - uint16_t asset_width; /*!< Width of the asset */ - uint16_t asset_height; /*!< Height of the asset */ -}; - - -Assets::Assets() { - // Initialize the partition - InitializePartition(); -} - -Assets::~Assets() { - if (mmap_handle_ != 0) { - esp_partition_munmap(mmap_handle_); - } -} - -uint32_t Assets::CalculateChecksum(const char* data, uint32_t length) { - uint32_t checksum = 0; - for (uint32_t i = 0; i < length; i++) { - checksum += data[i]; - } - return checksum & 0xFFFF; -} - -bool Assets::InitializePartition() { - partition_valid_ = false; - checksum_valid_ = false; - assets_.clear(); - - partition_ = esp_partition_find_first(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, "assets"); - if (partition_ == nullptr) { - ESP_LOGI(TAG, "No assets partition found"); - return false; - } - - int free_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA); - uint32_t storage_size = free_pages * 64 * 1024; - ESP_LOGI(TAG, "The storage free size is %ld KB", storage_size / 1024); - ESP_LOGI(TAG, "The partition size is %ld KB", partition_->size / 1024); - if (storage_size < partition_->size) { - ESP_LOGE(TAG, "The free size %ld KB is less than assets partition required %ld KB", storage_size / 1024, partition_->size / 1024); - return false; - } - - esp_err_t err = esp_partition_mmap(partition_, 0, partition_->size, ESP_PARTITION_MMAP_DATA, (const void**)&mmap_root_, &mmap_handle_); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to mmap assets partition: %s", esp_err_to_name(err)); - return false; - } - - partition_valid_ = true; - - uint32_t stored_files = *(uint32_t*)(mmap_root_ + 0); - uint32_t stored_chksum = *(uint32_t*)(mmap_root_ + 4); - uint32_t stored_len = *(uint32_t*)(mmap_root_ + 8); - - if (stored_len > partition_->size - 12) { - ESP_LOGD(TAG, "The stored_len (0x%lx) is greater than the partition size (0x%lx) - 12", stored_len, partition_->size); - return false; - } - - auto start_time = esp_timer_get_time(); - uint32_t calculated_checksum = CalculateChecksum(mmap_root_ + 12, stored_len); - auto end_time = esp_timer_get_time(); - ESP_LOGI(TAG, "The checksum calculation time is %d ms", int((end_time - start_time) / 1000)); - - if (calculated_checksum != stored_chksum) { - ESP_LOGE(TAG, "The calculated checksum (0x%lx) does not match the stored checksum (0x%lx)", calculated_checksum, stored_chksum); - return false; - } - - checksum_valid_ = true; - - for (uint32_t i = 0; i < stored_files; i++) { - auto item = (const mmap_assets_table*)(mmap_root_ + 12 + i * sizeof(mmap_assets_table)); - auto asset = Asset{ - .size = static_cast(item->asset_size), - .offset = static_cast(12 + sizeof(mmap_assets_table) * stored_files + item->asset_offset) - }; - assets_[item->asset_name] = asset; - } - return checksum_valid_; -} - -bool Assets::Apply() { - void* ptr = nullptr; - size_t size = 0; - if (!GetAssetData("index.json", ptr, size)) { - ESP_LOGE(TAG, "The index.json file is not found"); - return false; - } - - cJSON* root = cJSON_ParseWithLength(static_cast(ptr), size); - if (root == nullptr) { - ESP_LOGE(TAG, "The index.json file is not valid"); - return false; - } - - cJSON* version = cJSON_GetObjectItem(root, "version"); - if (cJSON_IsNumber(version)) { - if (version->valuedouble > 1) { - ESP_LOGE(TAG, "The assets version %d is not supported, please upgrade the firmware", version->valueint); - return false; - } - } - - cJSON* srmodels = cJSON_GetObjectItem(root, "srmodels"); - if (cJSON_IsString(srmodels)) { - std::string srmodels_file = srmodels->valuestring; - if (GetAssetData(srmodels_file, ptr, size)) { - if (models_list_ != nullptr) { - esp_srmodel_deinit(models_list_); - models_list_ = nullptr; - } - models_list_ = srmodel_load(static_cast(ptr)); - if (models_list_ != nullptr) { - auto& app = Application::GetInstance(); - app.GetAudioService().SetModelsList(models_list_); - } else { - ESP_LOGE(TAG, "Failed to load srmodels.bin"); - } - } else { - ESP_LOGE(TAG, "The srmodels file %s is not found", srmodels_file.c_str()); - } - } - -#ifdef HAVE_LVGL - auto& theme_manager = LvglThemeManager::GetInstance(); - auto light_theme = theme_manager.GetTheme("light"); - auto dark_theme = theme_manager.GetTheme("dark"); - - cJSON* font = cJSON_GetObjectItem(root, "text_font"); - if (cJSON_IsString(font)) { - std::string fonts_text_file = font->valuestring; - if (GetAssetData(fonts_text_file, ptr, size)) { - auto text_font = std::make_shared(ptr); - if (text_font->font() == nullptr) { - ESP_LOGE(TAG, "Failed to load fonts.bin"); - return false; - } - if (light_theme != nullptr) { - light_theme->set_text_font(text_font); - } - if (dark_theme != nullptr) { - dark_theme->set_text_font(text_font); - } - } else { - ESP_LOGE(TAG, "The font file %s is not found", fonts_text_file.c_str()); - } - } - - cJSON* emoji_collection = cJSON_GetObjectItem(root, "emoji_collection"); - if (cJSON_IsArray(emoji_collection)) { - auto custom_emoji_collection = std::make_shared(); - int emoji_count = cJSON_GetArraySize(emoji_collection); - for (int i = 0; i < emoji_count; i++) { - cJSON* emoji = cJSON_GetArrayItem(emoji_collection, i); - if (cJSON_IsObject(emoji)) { - cJSON* name = cJSON_GetObjectItem(emoji, "name"); - cJSON* file = cJSON_GetObjectItem(emoji, "file"); - cJSON* eaf = cJSON_GetObjectItem(emoji, "eaf"); - if (cJSON_IsString(name) && cJSON_IsString(file) && (NULL== eaf)) { - if (!GetAssetData(file->valuestring, ptr, size)) { - ESP_LOGE(TAG, "Emoji %s image file %s is not found", name->valuestring, file->valuestring); - continue; - } - custom_emoji_collection->AddEmoji(name->valuestring, new LvglRawImage(ptr, size)); - } - } - } - if (light_theme != nullptr) { - light_theme->set_emoji_collection(custom_emoji_collection); - } - if (dark_theme != nullptr) { - dark_theme->set_emoji_collection(custom_emoji_collection); - } - } - - cJSON* skin = cJSON_GetObjectItem(root, "skin"); - if (cJSON_IsObject(skin)) { - cJSON* light_skin = cJSON_GetObjectItem(skin, "light"); - if (cJSON_IsObject(light_skin) && light_theme != nullptr) { - cJSON* text_color = cJSON_GetObjectItem(light_skin, "text_color"); - cJSON* background_color = cJSON_GetObjectItem(light_skin, "background_color"); - cJSON* background_image = cJSON_GetObjectItem(light_skin, "background_image"); - if (cJSON_IsString(text_color)) { - light_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring)); - } - if (cJSON_IsString(background_color)) { - light_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring)); - light_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring)); - } - if (cJSON_IsString(background_image)) { - if (!GetAssetData(background_image->valuestring, ptr, size)) { - ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring); - return false; - } - auto background_image = std::make_shared(ptr); - light_theme->set_background_image(background_image); - } - } - cJSON* dark_skin = cJSON_GetObjectItem(skin, "dark"); - if (cJSON_IsObject(dark_skin) && dark_theme != nullptr) { - cJSON* text_color = cJSON_GetObjectItem(dark_skin, "text_color"); - cJSON* background_color = cJSON_GetObjectItem(dark_skin, "background_color"); - cJSON* background_image = cJSON_GetObjectItem(dark_skin, "background_image"); - if (cJSON_IsString(text_color)) { - dark_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring)); - } - if (cJSON_IsString(background_color)) { - dark_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring)); - dark_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring)); - } - if (cJSON_IsString(background_image)) { - if (!GetAssetData(background_image->valuestring, ptr, size)) { - ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring); - return false; - } - auto background_image = std::make_shared(ptr); - dark_theme->set_background_image(background_image); - } - } - } - - auto display = Board::GetInstance().GetDisplay(); - ESP_LOGI(TAG, "Refreshing display theme..."); - - auto current_theme = display->GetTheme(); - if (current_theme != nullptr) { - display->SetTheme(current_theme); - } - - // Parse hide_subtitle configuration - cJSON* hide_subtitle = cJSON_GetObjectItem(root, "hide_subtitle"); - if (cJSON_IsBool(hide_subtitle)) { - bool hide = cJSON_IsTrue(hide_subtitle); - auto lcd_display = dynamic_cast(display); - if (lcd_display != nullptr) { - lcd_display->SetHideSubtitle(hide); - ESP_LOGI(TAG, "Set hide_subtitle to %s", hide ? "true" : "false"); - } - } - -#elif defined(CONFIG_USE_EMOTE_MESSAGE_STYLE) - auto &board = Board::GetInstance(); - auto display = board.GetDisplay(); - auto emote_display = dynamic_cast(display); - - cJSON* font = cJSON_GetObjectItem(root, "text_font"); - if (cJSON_IsString(font)) { - std::string fonts_text_file = font->valuestring; - if (GetAssetData(fonts_text_file, ptr, size)) { - auto text_font = std::make_shared(ptr); - if (text_font->font() == nullptr) { - ESP_LOGE(TAG, "Failed to load fonts.bin"); - return false; - } - - if (emote_display) { - emote_display->AddTextFont(text_font); - } - } else { - ESP_LOGE(TAG, "The font file %s is not found", fonts_text_file.c_str()); - } - } - - cJSON* emoji_collection = cJSON_GetObjectItem(root, "emoji_collection"); - if (cJSON_IsArray(emoji_collection)) { - int emoji_count = cJSON_GetArraySize(emoji_collection); - if (emote_display) { - for (int i = 0; i < emoji_count; i++) { - cJSON* icon = cJSON_GetArrayItem(emoji_collection, i); - if (cJSON_IsObject(icon)) { - cJSON* name = cJSON_GetObjectItem(icon, "name"); - cJSON* file = cJSON_GetObjectItem(icon, "file"); - - if (cJSON_IsString(name) && cJSON_IsString(file)) { - if (GetAssetData(file->valuestring, ptr, size)) { - cJSON* eaf = cJSON_GetObjectItem(icon, "eaf"); - bool lack_value = false; - bool loop_value = false; - int fps_value = 0; - - if (cJSON_IsObject(eaf)) { - cJSON* lack = cJSON_GetObjectItem(eaf, "lack"); - cJSON* loop = cJSON_GetObjectItem(eaf, "loop"); - cJSON* fps = cJSON_GetObjectItem(eaf, "fps"); - - lack_value = lack ? cJSON_IsTrue(lack) : false; - loop_value = loop ? cJSON_IsTrue(loop) : false; - fps_value = fps ? fps->valueint : 0; - - emote_display->AddEmojiData(name->valuestring, ptr, size, - static_cast(fps_value), - loop_value, lack_value); - } - - } else { - ESP_LOGE(TAG, "Emoji \"%10s\" image file %s is not found", name->valuestring, file->valuestring); - } - } - } - } - } - } - - cJSON* icon_collection = cJSON_GetObjectItem(root, "icon_collection"); - if (cJSON_IsArray(icon_collection)) { - if (emote_display) { - int icon_count = cJSON_GetArraySize(icon_collection); - for (int i = 0; i < icon_count; i++) { - cJSON* icon = cJSON_GetArrayItem(icon_collection, i); - if (cJSON_IsObject(icon)) { - cJSON* name = cJSON_GetObjectItem(icon, "name"); - cJSON* file = cJSON_GetObjectItem(icon, "file"); - - if (cJSON_IsString(name) && cJSON_IsString(file)) { - if (GetAssetData(file->valuestring, ptr, size)) { - emote_display->AddIconData(name->valuestring, ptr, size); - } else { - ESP_LOGE(TAG, "Icon \"%10s\" image file %s is not found", name->valuestring, file->valuestring); - } - } - } - } - } - } - - cJSON* layout_json = cJSON_GetObjectItem(root, "layout"); - if (cJSON_IsArray(layout_json)) { - int layout_count = cJSON_GetArraySize(layout_json); - - for (int i = 0; i < layout_count; i++) { - cJSON* layout_item = cJSON_GetArrayItem(layout_json, i); - if (cJSON_IsObject(layout_item)) { - cJSON* name = cJSON_GetObjectItem(layout_item, "name"); - cJSON* align = cJSON_GetObjectItem(layout_item, "align"); - cJSON* x = cJSON_GetObjectItem(layout_item, "x"); - cJSON* y = cJSON_GetObjectItem(layout_item, "y"); - cJSON* width = cJSON_GetObjectItem(layout_item, "width"); - cJSON* height = cJSON_GetObjectItem(layout_item, "height"); - - if (cJSON_IsString(name) && cJSON_IsString(align) && cJSON_IsNumber(x) && cJSON_IsNumber(y)) { - int width_val = cJSON_IsNumber(width) ? width->valueint : 0; - int height_val = cJSON_IsNumber(height) ? height->valueint : 0; - - if (emote_display) { - emote_display->AddLayoutData(name->valuestring, align->valuestring, - x->valueint, y->valueint, width_val, height_val); - } - } else { - ESP_LOGW(TAG, "Invalid layout item %d: missing required fields", i); - } - } - } - } -#endif - - cJSON_Delete(root); - return true; -} - -bool Assets::Download(std::string url, std::function progress_callback) { - ESP_LOGI(TAG, "Downloading new version of assets from %s", url.c_str()); - - // 取消当前资源分区的内存映射 - if (mmap_handle_ != 0) { - esp_partition_munmap(mmap_handle_); - mmap_handle_ = 0; - mmap_root_ = nullptr; - } - checksum_valid_ = false; - assets_.clear(); - - // 下载新的资源文件 - auto network = Board::GetInstance().GetNetwork(); - auto http = network->CreateHttp(0); - - if (!http->Open("GET", url)) { - ESP_LOGE(TAG, "Failed to open HTTP connection"); - return false; - } - - if (http->GetStatusCode() != 200) { - ESP_LOGE(TAG, "Failed to get assets, status code: %d", http->GetStatusCode()); - return false; - } - - size_t content_length = http->GetBodyLength(); - if (content_length == 0) { - ESP_LOGE(TAG, "Failed to get content length"); - return false; - } - - if (content_length > partition_->size) { - ESP_LOGE(TAG, "Assets file size (%u) is larger than partition size (%lu)", content_length, partition_->size); - return false; - } - - // 定义扇区大小为4KB(ESP32的标准扇区大小) - const size_t SECTOR_SIZE = esp_partition_get_main_flash_sector_size(); - - // 计算需要擦除的扇区数量 - size_t sectors_to_erase = (content_length + SECTOR_SIZE - 1) / SECTOR_SIZE; // 向上取整 - size_t total_erase_size = sectors_to_erase * SECTOR_SIZE; - - ESP_LOGI(TAG, "Sector size: %u, content length: %u, sectors to erase: %u, total erase size: %u", - SECTOR_SIZE, content_length, sectors_to_erase, total_erase_size); - - // 写入新的资源文件到分区,一边erase一边写入 - char buffer[512]; - size_t total_written = 0; - size_t recent_written = 0; - size_t current_sector = 0; - auto last_calc_time = esp_timer_get_time(); - - while (true) { - int ret = http->Read(buffer, sizeof(buffer)); - if (ret < 0) { - ESP_LOGE(TAG, "Failed to read HTTP data: %s", esp_err_to_name(ret)); - return false; - } - - if (ret == 0) { - break; - } - - // 检查是否需要擦除新的扇区 - size_t write_end_offset = total_written + ret; - size_t needed_sectors = (write_end_offset + SECTOR_SIZE - 1) / SECTOR_SIZE; - - // 擦除需要的新扇区 - while (current_sector < needed_sectors) { - size_t sector_start = current_sector * SECTOR_SIZE; - size_t sector_end = (current_sector + 1) * SECTOR_SIZE; - - // 确保擦除范围不超过分区大小 - if (sector_end > partition_->size) { - ESP_LOGE(TAG, "Sector end (%u) exceeds partition size (%lu)", sector_end, partition_->size); - return false; - } - - ESP_LOGD(TAG, "Erasing sector %u (offset: %u, size: %u)", current_sector, sector_start, SECTOR_SIZE); - esp_err_t err = esp_partition_erase_range(partition_, sector_start, SECTOR_SIZE); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to erase sector %u at offset %u: %s", current_sector, sector_start, esp_err_to_name(err)); - return false; - } - - current_sector++; - } - - // 写入数据到分区 - esp_err_t err = esp_partition_write(partition_, total_written, buffer, ret); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to write to assets partition at offset %u: %s", total_written, esp_err_to_name(err)); - return false; - } - - total_written += ret; - recent_written += ret; - - // 计算进度和速度 - if (esp_timer_get_time() - last_calc_time >= 1000000 || total_written == content_length || ret == 0) { - size_t progress = total_written * 100 / content_length; - size_t speed = recent_written; // 每秒的字节数 - ESP_LOGI(TAG, "Progress: %u%% (%u/%u), Speed: %u B/s, Sectors erased: %u", - progress, total_written, content_length, speed, current_sector); - if (progress_callback) { - progress_callback(progress, speed); - } - last_calc_time = esp_timer_get_time(); - recent_written = 0; // 重置最近写入的字节数 - } - } - - http->Close(); - - if (total_written != content_length) { - ESP_LOGE(TAG, "Downloaded size (%u) does not match expected size (%u)", total_written, content_length); - return false; - } - - ESP_LOGI(TAG, "Assets download completed, total written: %u bytes, total sectors erased: %u", - total_written, current_sector); - - // 重新初始化资源分区 - if (!InitializePartition()) { - ESP_LOGE(TAG, "Failed to re-initialize assets partition"); - return false; - } - - return true; -} - -bool Assets::GetAssetData(const std::string& name, void*& ptr, size_t& size) { - auto asset = assets_.find(name); - if (asset == assets_.end()) { - return false; - } - auto data = (const char*)(mmap_root_ + asset->second.offset); - if (data[0] != 'Z' || data[1] != 'Z') { - ESP_LOGE(TAG, "The asset %s is not valid with magic %02x%02x", name.c_str(), data[0], data[1]); - return false; - } - - ptr = static_cast(const_cast(data + 2)); - size = asset->second.size; - return true; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.h deleted file mode 100644 index 016692ee..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef ASSETS_H -#define ASSETS_H - -#include -#include -#include - -#include -#include -#include - - -struct Asset { - size_t size; - size_t offset; -}; - -class Assets { -public: - static Assets& GetInstance() { - static Assets instance; - return instance; - } - ~Assets(); - - bool Download(std::string url, std::function progress_callback); - bool Apply(); - bool GetAssetData(const std::string& name, void*& ptr, size_t& size); - - inline bool partition_valid() const { return partition_valid_; } - inline bool checksum_valid() const { return checksum_valid_; } - inline std::string default_assets_url() const { return default_assets_url_; } - -private: - Assets(); - Assets(const Assets&) = delete; - Assets& operator=(const Assets&) = delete; - - bool InitializePartition(); - uint32_t CalculateChecksum(const char* data, uint32_t length); - - const esp_partition_t* partition_ = nullptr; - esp_partition_mmap_handle_t mmap_handle_ = 0; - const char* mmap_root_ = nullptr; - bool partition_valid_ = false; - bool checksum_valid_ = false; - std::string default_assets_url_; - srmodel_list_t* models_list_ = nullptr; - std::map assets_; -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/exclamation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/exclamation.ogg deleted file mode 100644 index 9a4cf5840d8a3dadaa013e9abfc97b12dfedb6f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1663 zcmV-_27vibXJ=CY0ssI2000000P!AvU;qFB0FgVdZvhieaCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000@g9C)0RR91SETuM0X|P~b#qiE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS00ir&00000 z008kGeqaIs008wz!ix_&HDYmlVo_ywWleU9XJ}Xh5p3sL(#zs3GVJfB0e9_A7#QZ- zWq5_|$n2C?OHEwiSw)$D84&E^Bn`@npima@k`BeTl)&zkSOXDn6uR#;;eDG5-T6^OWQZJo;t*M1Zm_e$ghRnpfixJ#V7K0$HOu&78UTA>dI6E4nN>reQ+W+;&*mfglDRVz@ustG=QG zRx|lq=4e|}V0jKd{QGgdP0H<=9)ZE8T(MaMi5Xbw?M?<3Nhy0nK|Q36>adKv4}6Wj z7gb+%8hKQ%V&-&CB>|^Y<@lq5RzGXy?zLFW)2kPbwW)KfLFZ*`cYUl_(JS||o76BRCcUaR>Y3~q1(YFQgz&8_+8$eV2BuYphEjm!nB#a-odpMT*RUyCaDGh3TFIN2 z1L1>@2d{0bDNxi{>SKn{g8pnvy@cQr!G-_+dBNE#oZOk4*A}&xD0&?C2@8ROQm_5* zk-`g0pH*6zQ5mXIKZePUh^|9tKh|d-;@TDJ@_?03V6gq+;V0e!oyPm|^;9dTzbPM( zQ+jjp6gW5zSQ&Q?>q#uQyiJ2RZvOEbuvqEiLfUxeprDZ4sc(85xVx?ompw4NOqJg{ zy@s){xn~IdO^G{)am2|to0wiNzv|TK@Lw*1@yq>R9Ybc2L)|i@eH5k>R`G`=lie~0 zX>J~6pD>YdiJ-L!zYF^zs^rN>b=LE;9yXqde!xDSWF}`cgvk5#7@X|_8`?KQ>@{m) z{F3JcVjn5_vHPO*Lw#~qP?R(VjXwm1=)`H3!`tC~R`2J5R5?mU>9It#L<$;qph zx5yi3>M&(NGU#dj-kJ;OMxQ)v4phM3>D9TBBvid{(*k7^hV0$g^FPO_-mG<1qm5&B z!y&QCeIZ!sfHAa;CjNuPNd`AzgYzb8ddz8rS@X&e47=?5%F878PA$&S6x6-f#^f~y zp!avj!PQDX0fgfg;wK7a3A-6h_m_zgaKAYB-`Ds=?th@qV18Mi3y7yb0CKs|v-Ql% J8A#NjeORrD6V3nt diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/low_battery.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/low_battery.ogg deleted file mode 100644 index 968b3ee104901e41394e4f1d68d86149b0d0ff73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2269 zcmV<32qO1SXJ=CY0ssI2000000PiFmA^-pY0Bnq}JpmI>aCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000?<5=|0RR91C^4dc0X|P~b#qiE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS002P000000 z008eK93lb$003oK9!wEXh z66;`-9D_S&dF`*`dD7Vax3vfGQn~3KpOSIHeCUGgdM{~L6VHx-Sm;oGqHIDE#bH|v zWZu^nP1|VnwHao4?#SP%_VkL;&TQ+Zd>fobmU7;qI+rp-m_2FJ5R_m}>$`R62j%(W ztN7=D#&i`I>j%aAe?iQhCQIIr&nW(Q!+y+)Y$RUz&Uc=l*TPVuiHH4c58pT=^vsM)=Gq9)*WiG+;G@nwHSb>&2(BAC9oa8b}P zk#3-ydWg#cDz11n9oW9Djvu@?3hhIK{cc$2tWKhG6A7(hz{W7taE1xB$nr{Te>GYu zJxq)zw<)Wyulj{V@SPtU_!;hnPOM{-%m%w+;J2h(z=S?0& zar#IhU?ku$eCiw!fLQ1LW|Eia;cxr$ysDs#mmlJ!y7yLjU`-z8T8|oioV`xFd*?k7oWMsj;}+Ln?$0GQD!i_E_jgr1;|kWl70f z*K1?W9dwWgrcwy4)A?+{{BM^d-c8}uGqstzIv)$eE-MI3GoJ`E-T?JQ-tE5j@nZAvA%Z`nng{t>0;b#)D6VnD3sNG3WLHN%3W{7P(3YG1nior_*uW* z5wGKggq$chVYa9UpjhXv&TYyuZXeG$4Q5K6GX(OFRvBs|k`>Qt-&K{9b?<3E9)Xy( zoRQVi+kxY%0#36vq^1Mc1Gm?q`- zhM1H457NK>AZ9(#LFx3knY^tMSffeApJr$h@$3Kbu}R+4kFed9jNk3zdOgW#r&{1x zhyG@wym3v!tf?zOfiUwI``D{Q)z2d6w$8hiQQQz!^Y*d(Zdm)-V&Fz)>S3#&yo~+H zP+J)M2tXjJ(hpTsZrvw_bMzBZKVsM{Tg90?v|(?8?|~X;!z%>s-iW~VAtPYfT^k3+tU`6`iv0hraAs#WEF2m+dG@fTl&a) z!JG`jZibT5=(?+QZyZ2a4gPdCYz4{XCMrLF_CEkQW643YcBMxs`Xu}{t1G6`oGXSoetZ5w2 zB@s5k+~3s{S)EyLS`9};= zwgJ?$V?5g^9~IYuU9aPiLK|I(JlYi)I|)Hk4MiYauL4`dB<|Pf4gu*zn*i^Y(3T`c zfrP%+byRlWGB9!j&HB)4tKJ#GB&O%-?G3oWg$00BL+>Ea<8oHl__vEK!XY)~RmI?d zSPhBdJ45-6h`&><3HB=R3@8)CYfqYA@zp`YrQIaR0JFE(c&}vUvGMWKlb{-VQ=mkw z&=CVlXW8JiEZYt4fyJoq-SPd;v zc}QO;XJY#~20nicl*X0))272?Ke@}xUEp8a;W1CTI6?XIV|*ob+cfvfVl*En^{_^; z8W5dd;+%)bGelo>-`SHu@1U#0OZ(h>L$K;-Cf8Gn@~Uz;^ur4KKv)S*5DENWjrRGU z=qB_fGr}?F8oD+Soai= z;6|UKjdHf8z+IVaN$aA%mHBs1XJ=CY1bDyz000000PiFmA_D*b05G(MzyU2-0Xi*e rz#lHLv}&)_W5g(p`&a4_=FzTaK-;6n?6SgpYQ?@t4(teO%{7wp__JF$ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/popup.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/popup.ogg deleted file mode 100644 index ea73b6f8a20ef9965644382b43e79e9495c8a029..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1148 zcmV-?1cUoeXJ=CY0ssI2000000ACmEz5oCK01j>h9sv_iaCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000Ul;7Y0RR91z480U0X|P~b#qiE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS00cN&00000 z003VX?7jj3007sY*rW+gQ&*9ihKgB3SOXqsn`gQJ^o9A{;}u)dk|E2{!X<5jBwA1U zJqBJkDm&{#)xT&?Fiy++F!E2+UAFBet>5keJOik(PgJMpaiX+S`pQkrriQ2gWLQ`R zUV8risWVt5ut)HQaSgg}Y)9OL)4h2Z? zg#GV$GHnkYigWWgSmDdgqd=W(SbPk1YRu3KT+lms$4}%^3wd5KSr`Pd*7&8GEc5<_ zTKEja=vM52FbCNMAz-lD_4tN}rEgAn_7(^OF4TJ%Uakt%cb6>gch_n$7`v4+{{f6! zGb2SrWp(yoV9|x6!_fVEPe!(?3WCs!PC*)1J@?3~y_;cazGp-vd+J)}i>!eP{aGBy8{tkHb=hOvcZ9Q2xS@K=| zCE_?e?Fv~+OZSzmBADf1iFqn!0U*!hW5g&YS$>ghnS1d?KVH;{lEM6`aw*R|xp(47eoEC7bc~bcH!B4Osb$U==lYcZ?;=8%4X|UrH}m46ydXAOT}6p*i=uSD@gO z_c)<|AcN6;FR9q*t*^+LOXhu_f$H9Gan0uHOH5;wtLGL;!d(&F{=ihY=e%E%WCkZc?D@;E*L?Q30&o zOnNm$hYU6$$BI<8Pa?FRS(`_CzvRoWimD%!Jq%TfLCH3mSBXKF34s|K;*KBt`TI~2 z=eaNSfCXj7@t1zy$OKA%F%jXK>OzEbnG(9xEvb@+Y{_QX8sE;YNvj5Zm%;wcyc8)1PA#NKGSnbKu$zBiUh`ovp&XG*;;601iLho%RjF0ZCx z%=)XaR{<*l@~V=zOhz?MtAu8Qs2w>n;L&gd+D;8kT(8^xj$tH-wGU7tE<%(HSODuV z5D)-yviF&1NszHR*xoHLGJ_d)XDRkQuAVYT@R0zy=Jf5pvj_H2nZ3N)!!a(-i_FAH OgC@`-{uMzPJoSLFO%H_t diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/success.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/success.ogg deleted file mode 100644 index ced190267fe4b1decfa16f0732deb4dad2b60175..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2012 zcmV<22P61TXJ=CY0ssI20000007#kimjD0&0P1yIU;z_PaCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000NSXAP0RR91?z{-x0X|P~b#qiE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS002P000000 z002mt^p^qv008=ABQg;?l7pC8u0W8nKn>Z=pC>0P4$ zNoSw<#>oHL4d8rrkQt)!V!1eJURrx|nzTBS_PH8eYw|AJe&_QWEWQ0V zYG9>#ljieX&pSK2D~dD5L}R%mfwlu|FA9J6kXY%vvSUZOD(tD!qchRZUDCeXn zRk6|^EGD}tKvt|=SokfvAe!qjB9OS6s^_uk1v?XjEt=PdlQx!Jj8=5sITqjE%`jN! zyl5ScT>G)KYCH!ZS# zu%5Rk5s`-o0rT8L&K!8#7 zz(E~0$L{01?)rc%mzO==8d4_2(_3usM#H^1!RxJ9hcm!f=7q35x}8x*gux+?Pj7KA zD!#}@muYt}vcz7WYO>bQu$Q<;IOX^CG1Wg&PwbmtyP18EFqppv6%W<{G=g-Ub-4;0 zW#++nV5W~@WM$TkM>mlkzKQ5Pm$HDo>jPo^%D9G1>z(hRB=N+y{_x&R73^Xtd`iez z;4opG*Ji|vrh!4BYQ$hYQLA2S78IEv#;@1s5cO4N^w^(HC%;6aYipLmVL@=lc-LBj zrR3P&h=y&*F%Um198u(VjHDuB%i-YIUmUE@C2q#sO?1o9SGhbd6OlVi3U`250G8bv z8E_8jiK+!&*#3-F^=d8IDV4KoMOLv4vevx~&0lFL8C+#zIGkWc_tdS2H=I;mxzDi) z&4Rv;q(}z`W@5`wV?5qvQ?udGo;S2Oa zGeB4XRAnm>p|T#M1dzwwBH=HqC)Le6S#DoGC7vhGl6M*Jma>15j z^0Z{aBsj$&Kn4`(7u_(_u9X}&q;ES$k9oz=SOkiKgh-rp6Y=_Voz~s*(GbkgcMcno z9H->o_7xNGY=s)=l(nUzv)$X4d~{^T+Vu&T((?l#0#1UnznJ%mdQa~vhJH6Yg+hDy zSOk{Fu3*jvJwmHhB%~|fG5>RZ33(;WXsZ#HQc4U_|44zI!HBGl@rv@!TW1|WZ{(tS z+t%Pw*`Mht*AF5%%{g4iN*NKt98IM{z09LFXDa8(mylQllr8AT_42NH-jBn)h1(#I~qq+F>BM`imxmNo|=x6?`h{;c+);g zD3h^I$+}nslAZcy3bV81nwV1^f!Zqp+Vj9XAqv@UU9~G_pO(Sjd>tqC9k$9#>*vNm z2@a}XPfLhOH|Vb+m-7(>f{SgIzFMdocvN|8OXWf}9(a{H59q{m+wdNsSOrk4+`Ljb zvPMEUE?jb9YMRg7YD_`(|}KBXHx(Kc)$Pv00000NSXAP0{{R3h&;pG u0V!Aj^&M)%Du+`ps% diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/vibration.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/common/vibration.ogg deleted file mode 100644 index 00764361318b711398ab3de98a27daee62fbb278..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1574 zcmV+>2HE*fXJ=CY0ssI20000007DE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS00g*|00000 z002WD*Hi)k001lLjkyj&Qfz=(fqQ~$f?rWXJy-x}B&-OH#Bh}59eW*#_L2zfE<*z#ek z4Rl`J=(L#=#wyIR$7hzZiO`Th4-^NoVrivsqIKT@h6R)g=4on8hCiup@;WUg4hD+J z28KSz=qk`i0rfiS5hU-G1SD0$U|8ZU3HUT@w^Dm3ei}0!T*=OgmRbQw(Uf`vi=UeN zvC~9thd$@(Xu|Ufo8z+JuWR8f8miJGKFb4ypHDciEBFcJ(tTv=%f`-Ro}9`9ag&yJ zq-LW}?^E|owpZk;a;UQ9*>j~|IGIvSMp)t@hzZyd0W>y#d1>bLhS2({(~wCsN4?DG zO{yPK5aZ2F)F|}3D~p}WyLX-c0sG`;YOn4AvUEJJ`%t|5(S@3;O!UiL5F{2+PJ0DO zRYN^Z5`%PXZ(;n{$8KA%AH?L<(Ex@NN>swEXwa@N;TOz28<#^PmS{gRZUTb-Gw@JxOt=3NHvea zbk_%Jo@C(ee6_6&?gM&_x2eFT0i(Q-*LR#OP^}Cca)4Osb%tjWU-;w>-nkqbPSy3( z$l#Lb9$y&NUKPqz%G*TAu(0GQAl0lc9vQPj?EZTIJkSMF4Y zTmH-y;Ad~C=?=jqq4n8%;8BdFvAhw6C^tSPxV&|$+GlxiC|X4oRKul^`UGTOTQ%3i z!J%iDzA!*o@0qvN-ju`iOvmELgFU&7UA*R9VY5wS{mU-ttwj($q|t3g|JQs&v52olaz_Tyi0T zh77eLBvjZD`bd!^%C^AyS)+0~v;SX9rN&D>uzKnGzpgDqHCflMzzuif!AnsSn@}>$pn6e>(+0 zSn2Th2UPSgvlVXId6Wt=vmOewgMkIWFYynFI|V%X?=GSQ?X_Hvx97qAwArH-V&EcW z^WrdH{G2L#p#%XqwF2LaFd-Naxg1xEvuU{k@ReO$NSxyXk{6xDATy%X|^d-Rxg ztFU0KZwP3#RrtvJKjqDwpI2^8<$yuPIrk`Z*=`M>&hgGd_dQH1BreWtK+2D=7>2n3 zg#bn4RbM4yScxfl^mq<4E*KChRVO=Y?+$sMkXXRFhHyAx_Jv~dIcct{4h*{5GPQKi zF7fCQ!AVCmX;WrCu8Gf=R3@2|ac74~Py1p$W_6BO2Z=yHA=7L}HRQf}6j|iyu<82J zA5d>S?0AMpl%MWR4%e-I?eaI;^8f$< diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/0.ogg deleted file mode 100644 index c656582724e673d543f5df7d340e5bf78f632a3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1940 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/1.ogg deleted file mode 100644 index dca3e06db9cc5cb8a4c16c267534f4ac2e676467..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1658 zcmY+Edpy&77{@KS4bzY*myB=_wG>mf=2W7~ku#E(Ga>E7!RZCs@jbax>GLT7o)>iFYBz~CQt+c=My;4ff_&+yvCBl2H6`p(@ zaDIRiP0RTHo}3BUDl{Xbj8ye3nm|?4P$CLWJf@e`@!9s663{k-6`#Z3%Dlr?6YnDrHJ7~-ku1_WIAQequ6%|Hye&S|9+ZPtHodj|LQ~+ ze^8B+BzFybX5hq>dvNC+1ga6d=F{w$dkWR86`Deh(x~g_oKay_4%J6lKBD&?FYJ_` z+n3$oP|GpgH@bc%PAymSc1AL6dUN;dp*Mw$XMi{P$3#y1`%d*#xSAF?-|!IW1S`6>)Cp@Hm$>j?Y5& ztHI9qiud=7$(f7y(Z#Ei=JAZRIHQ=G*^O&o>&0Q9^Y||A!J3RVBC04W1BXgh7vA;)%K_g&FHoLu{Qhdjt)FBq1RUkl3bc8msqEeYQo#_ zT{(FKDjZH%$r}5E%m7Y+ zWI16D1rF`wBan{Cv>Vm3$FD+aGgB*L99Tsbn($XRFz-S!7@TrV4>sKqKh1Mw9OC)S z7EThV`nsEah`lYF{I(v(G4%s~!CTNWQ5ojlz3a8}KDL=X*2|obu|f~pvI>mM1s@8h z)E%eYFOKydDi{m(R~gApB|E?|t3q_o+P{o+e<`4((g@U58enXzk4hdtj}icd&7lVs1hIU92e0(u!lmT91S$mb^`T7Nh$4E+ z|DkBJZ-w9BC(3XEi$GQV1_SPr*wxbPjFht&F(V|%{>TDaDtpa!=38B$XYGl%Ke2$8 zVwT11Mt`1^@s6 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/2.ogg deleted file mode 100644 index 6d1f4d7a422b926608f1e4d754c1d1e29481bf97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1938 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 Z72e)>OMk!gKXpO9q3+P)#y5bf`%l1iQbPa$ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/4.ogg deleted file mode 100644 index e12dd7a221698d5a1cf8f6e0269e45ebf59e3134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1949 zcmY*a2{ha378gQ7EwQGwO_|h$X%f=d6;ae$OLeBLrKOgHC>jx}wkM>hrJ2$a)G|Fr z$19C}4|6P`nLg2K2c>AsFj{}hQ?`@8p^^PPL$$Yf73ak2l| zRY&zN2iGk%-Cn?-PLBg5eccQKsn~Mm=kbzgMy>5U45GI31Wn6^(No%nUpwd}K7XukGWhOe9Kr z9x6YkN+`YWtXYwQ8hvcMRlrz~5Koq|x~Sdp5qU+R&C_ywEr^wsxU$mo#L2Aq$QN$+ zKfDWt>3PE)W1P>;@j};PN-C#*noGLshcLiZqzD}J+Ll7%jtQwu%@du9cA+U<2L8Ij zK9?8;o;5ky*K2sEfEW;dYipPz3v|RPJqx~VT#A`lK_ff2XRv)aJv649+|PZIc+#TR z@DI;^-s-5y#1sX4d~0slT*7)`1|-(++MU}9G(29$nH3AUPogrlv^zppE0K4jGG2=H zO$B5ap;_WH=*U+l-_1R0vMZNk*i5!BCg}g69h*6-A{KApHd^$ce~ok+Ks@Zm(ZdbS z?;SG2Y6Q2m%i&z_q0BbkBcvouWdts#1_}v7I)@PWyNFT#DmX~ zPwpYNmx$q;=mwc6ukH%A#FM!scva)z`mVY_A&^AY`-qYZ5%P@VtBBPNx~rcNBoZx* zwdw|D)Gp1rW*1jRKs@_+G=JcUPkZa;el0b9+!aAhFl-KL*odkPDH#Z&S^s*Bqa%FnLfhCCLjeDH7 z7re3h*P1>%4j=I4k9Sn6Eh%SO!Za#zu6(n!k=x4C#)&bV?oodI_wajX3~eXemFGXX zNzfW4RiC@#Yu`K8((PjH<4lR6eY#xYtD8y4tpL zxz1HaP<@`xmMb^?TqjAB4B_@T+m_t9Tz+%+vb8tgW^mNJJkl&UfpWEQN3JZ+0pmoV zGSTQpNlEA`(pFh=soBkdX5E-yZKCy(3TpEr5Q>vk9{wSiAPkC97R1!^PS>^&Lm zSkLw3i}kJp#xkU z$3orCyy^62b)|YnEbIP_g$duJ>24P>+98eXNjLk3UlO{KH~w{;=$-H&TA$p z>4P`-V2sMXf2)30?d+Hob`}Yg4Z}&G(ipv z`!TeIFRm(I6sSyPC3yGD{wuw*avc4NI1&|(We&GXC+l0ZsXAVo*x^NNE-ZMUp|HW5 z{K1Re6-wx2A;70f{Dm`DRt2I6;Qxj46#>E5EduSI{klZHZV?IaYDi}hpjgmEr9iq! ya47*05q|8kDiGy@ScF@DL$nAG{jJ1Kwy3w0Et+M33;azN#3H&vp=b>t;{OLYj(}4D diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/5.ogg deleted file mode 100644 index 7dae30dc6b8c87818e2d33df20131ada39c4d21d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1755 zcmeZIPY-5bVt|4}S}|8a%(|Od(-?*Q3rdSUQWH}c87&wO#DbOhgOtMoNI4^rmw9BC zB%>`zc}QYP*- zBg9~b{Xlg<05TZlsLP8&MFp*mgNm~AveJr*3qs8-&GdD$o5h57#Oi%pt` zTcGIM!ZTul{U_N^?Dl(Ms93_g=W=Y9&S8^q74{Rd0&4jW+wXy%x+V*gRS1YK>#9sG*T>?boWwQ)8{7mBZ1QOe@Bd2M#Hun7D6 z()<4>Z{rU#XZrjY<`}OFmjRi2W7jXEU)?skZDq z|LT0^^B&%<9!U#N&SY4s8Po8@EUbomV!>10>}GY9CPuYR-i!b36IiD{;5&VTHRN{Z zjWfIZ8hN{#j%EH8N*2-O&fck#J5|{JQMbpJuCEbuF3YXlS(YjyDOWGtlNz$fWa+8> z&)?j<#W`WRioo&%r@LmKIwr-jC(l#q@v{8~+%!ezsYuwFp1-+L|AS^|cC)JeBY55QpbC&Q)SmA&39|o6}`EW=^ysKM`hRKxGwEC`nAl5 zvYXYEcK_yZc-wdPT7TOvzs3S}i|~VsjAj(Sc69L((E8|ob@AfapYHzY-OZ!?(X@Hn z+;e|CCzbleGUos5dUkc+;@;A)pOQ|_JNNr`(Y7h7S7#Xrs~$Md@pNA4IrhRP;TvBs z{C_XL?uKZa`=u-e$?Rqog*CbJ-(S|6Rj1T0R?@StYkT|bm|b^LPNr-Vl>5zeoZ+S9 z*S#6*!VG3u?kU^I9wz7acJn!rd2?#ZOR@!S_Oab(UeUC^Wp$U*W#?6T8z1vb3EDFu zO=+@U{WXq<(gpgN)s|j6);OPBncb|Q)arX_sUmNpt%t(<@LldZOzUnqD^zBOpCPu}UeQNp7h>u6AKFg ztEx|7rRzA9I(ckuKN?1+8$V5IneSQo-9`F;GqW{UhIO3XJpD&3G1klEjYV#~NH=So zcY)J~Lo~u|&6%g!yCwD|WjD*o8bxHz7wzepTrydIU*@#^ebb)L(wl!&VL#iRqwMR0 z6gH`BH8bB5X2J9FSAAP!@%)9tOFQ1DSSh_)xMLn)qfz?ff5AG@Z=@fnxSvm*=IL`) zb}_J65a5>W$UAnWKi>ScNX)W#tirbHMVy^!ypEF3=5ozj^>B6lnMs^eW|?}}{5RZi z_uQ(EE5O1;NSL!@^7Y#F*`{`S%!@5{t;HNX$%qV;$wet->A*r2j_~8V&z-F<#11_(@1vWE~8EoxwhFM2P2ic^Rfynj% mc}V7NF8qLEE0B*QyLaLzB;N6js4fKZkz_AkM0O#NcLD%%Q5R$Y diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/6.ogg deleted file mode 100644 index 697278b388607f51168116cccccc92efa2229754..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1825 zcmY+E4LH+lAIB|XN11J;yv=5qx3P_fp%)IaFnTmXc4|X({ykVbk;qY-=0r}0&3TAO z2M7G`?{~|8yFL_Pi2G3 z|H|6(rQzDP;pz`4h)!U_aW*BI5e0#eA?@^aN#L6N|FtHEfb<*Ev+prM#qLIiql%>YnG`PhO+f?{m z^O{)GNr?N{{D|yW=rb=tJ|S4V`VhXG<2Ic!Z@(Ggcc}RD11qcQQ@&Dp$WC8?gEejQ zMI%x-OaMM%c#@#+;Wn6Iss9J;qm})Hk1&!dZc9!@CK67Rfu{`cM z`goX38{6Jib=}#^*#kSXpBg&-cg@$lm2zz7OqOOJiX~XE1+YLL{JN= zb1w-qInr8Ib)4w7pK$C|3vnbry(Ej6@u?;!G^ULo`kbdl4MnzQIWW(AogEz`S5uQ^ zn|*Vo8pygwH;B<0-3ss{u0?vQ!Q}u;24C zXXMAIZM@$XqJ$}0E2x+R5-$y6K*C)wjxVy_>oXk-bJcXz_cRk6~?u@Mm`FfJ8f?Jo=lflFRwcInQZ*pXYs^_w#-}-^=^`n9n6TJzT!J0Ig#jE24Unjvr=vn+fy93cJN5uNAS8t)L(L;HCe#kNC&eTr z#U)0cI&N>f*VNRMK+;lGTtw_dku8LWiOuxr%1_5s)uFCjg_sWIQeJ`$vpiUXHC5%M z5MiPM5{36Py*cBNJc>H>y1<@5QqzRcgmqaKJ-VHP*Re7DSnO^&Q4?BF$*s(;BLq{f zHJuQ%oeMIw11`oJ zu+kewzgBi~_g8@bU`|ji_-8I+OU}|wy8a}BOaVe)EZ?*@YPvodXYP>Y5FrH(v zo1whPs56da9`u-nfK*JPoH?@gkakXPM8#{Qg2o$VwCESc57PPTmUywwDO9bm2h}2l zK!U-kfpuwaVh22=EH2TRQ7*`VyL>cX?GAF+G9cHN&scOWrc;TIxaWH3urJ3-pM1;? zlXn=X5VfOhLGzE}Eqb^&`<`r2olJ|;qYZvgcim=rPjNWuW;i1|akb`d>Xl*drrm{z zZih7Gy^=59`8f<~i=N0SO@kaJC-bl2WsJk_8yJfOab#<#TEeu>!Q9OH&zP?HAmKB( ztKc*NwBwzr`(J0r0~wB(Ww$6n$k_C3aH*MNd6#(fBD>$pdmuGWWwEWbJ8w@Wm2vXV z<5A4&3oB0kdsbrfFhEDd?VqMtnlKZ{tEzrZ1QJO%uhI=*wML@zVCK%WBj}=8NYEhC zE33tgh%H%@$1K2b&Ma1+SWRe3^EODHduZZeIrk!va;KELGtg^M{}1#cpOr6MX8uzLtBzmIK(*#`aEYhwfS1%>8gE+rt{ zv3HAhAsrYqyLQ;E5`?U$tBlLmlFq1zsk?;Ot8ci;rr3qi` zlx2>xC|r14WNR^tv3_dJ>OJO4R3lz6-^lR%g+PKMI*%w6D0>cDVItR!$PZi(7z)24 z{hx1)8Hy+M$8)!ZPMRY*0cjmIVrZ1wR!`~@*qS$^5OmbA`OMyt&wS+iMzE9mozBaH z{_uFL-K`aySoRI2zS;)H7kivs;t>x7(_x$9V{&k_JvHN44v#`0L80x=gxGjN!p8B1 zLlIu#^%mUnDdn)C3cSY5!p(b)PlZ z_n;7YYtG#5kGsaH){WIScI^l(nECxI#2sw~GD$7NKtfy8nq!#LPbtyBK8=drd*fuI zk;V5X=f3=?+R8S&fv-D!)nVMGB)MJ-n|D?xzqk++kty!J+Ue4R7W__#w0sAma<6wE?tieX zv7Vw3nREi=oB5>pWh?PgsP+zu<5NgALGcFnLr71`17Zi&Q(Yi&D9BY=O>G7!6IOiP zPtR$B*R^W`>=2j3o8XJsgY*>}!{Kn=4^j53GF7ZFG39{dC_Tq=3?-2VNqN<6$ z(^jHHQd$5>X&bynL(+8tEXB6POLqYfd(*qO40AWFd(*pRf$N2$T~A~Hvz8k0Zh>?v YfTYR}wtV=mDS)L|K3{r-$wkr7KZblEpa1{> diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/8.ogg deleted file mode 100644 index bf3d2a1ec5f6026211f1a489223de17fe72a0abd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1977 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/activation.ogg deleted file mode 100644 index 17aa008177061d4cefc75151433825f1aa63648b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13539 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 M$dC8W*Z;r$Km9nzm;e9( diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/err_pin.ogg deleted file mode 100644 index 8c624f5c1fc48cdedd1ba26a930e7f779626ba02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4416 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 vTei;e-&_dwuaOOdW9w|~ zVq@zrjq_RKe8LZLPGL4jdn*@Q;QtcKwc&U;yH0#PsO-XOF$yVB6E|-cXPC3It2-QS zX6Xh;(om4>%1hQk0beUimQj6Mq<|u2wU#f$qEa#K)SW&{61Sp6|mC z1G_WW;Y)jyKO9qVBpo9NaPlI8Fg?BYVQC**4Y4$-PoM`D|1_MjO9rF0)zrrOe$GDp zb}RwaDn5E~a33)duA79KwQ1P2aUFM%-gRwd*+Fpr9&Rj9~-+=%VXtOi^6-!`J{=6XL&jPby&|MMSa?kD;=Wq zEV>K!7k=cC=E11tMR3$kfst*Ibl4(_6%j;UGJ4cJS+n$0?09jAT*g|xcl6P#rB%~c zwiJbC#ijCaBsX^}IJkFxRVhMuScG1${S$X$?yb@EE&rfeo=r{_23@E&(YAFQGXNZln?e10a7M))>Xo^QXvpb`m3?L!BM+S*%ZFH4v> z&&6|g&^9BCnhRbmJr;dI(Mwf(w9{}TJ5LKRD#L#(t+xc2F;`m~Ny8<}#7=6xhHVMH z+w$DImOzoUg?W-&Gu0NmoKrQ?7sjSFa5Rv2q^#a$8WLx@T05baKk>meF|Gh};W&B& zolpg^zfHl`7SkeA`|tylQf+eJd(TDFi4pyADjXm4W11jj%R-(-5Fd$}XjGgZr&{tO zM1ap!!{1To2JP(+!e$#O*?*$&c{{VK`OB#$(iqe6>=d5J#@eZM7u$MScVSe5n&uh{ z6<^m7M$UgZP*5Cu#8r7w@EBVv0OBd~ST7GNei}s>l+ufv99xrWXF(PEyJYo;wvE0n zqn8s?E!)59OJAEGeQDgpV{3C5s@v|@btaO1UBL!t`SnF8=Eadgx5|FRFP6{#i&~Eb zKGoe()nEx4ez(+XMa&!8&I;&JUSWK*nIj%k9B%#Xtv?30b(}Rb+K~98KRstxOvJ)# zgn}|^j0fz%Ju~fezk|%y_h;vZ`|EoPb(Xh3@eWmOt7%XhJWBpaX55&P?DgD`u*>-| z&&TCUE_w7FRQ&{1=pM1e&3?S^6~3~9uQrWIvuUsdgY}0Ks=aBgrf?(|TSL?9JH%*b zUYJrzU}$RsjmPRZ)fdaDBIRbO__B^c*}4=;K1_W=)Ehch%&_vHI7Jl5GtmwHA#y;N z{<0yoG3s$rqk4lygRcmK08Sbf?RBSEamXN!2 z9NQ{|nIxKa(Tr`{JQ{BqiLlO!Jo#2OnC5@khWEP3C@rfAO zd-Gyk-*KXu9tcJ6k;8AT0Mfb(*M_1*g|FI0z>+60hsl?E2Q0^vOF+Juq!3F0W65q+ z{0~clnX1`yr;k(pMCm;_KR!v#PK^s_9dg!`@$jh8iP|M~Z?S%INZq_uNqE~~J1#A< z<9%Mm;`qJ#pgCeJ>)3pCrOpgGDDO8J1&lPw z))+I4JB<{Q&P<*`vdx}w`Bf+_Xq2$I_~?6?hlRZlsZM4kzNr5;s0(OLtAJL9Y=eWT zNeWBlSo;THIdm}UADOe85IB;Py_xM6eqg;+V})n_!9ZfWRS((p%)VEo9&p>-%|LSK zlzh8hKEZZr%uwGkeLFG4pzfO)GCqdnx&2)jK*EDMFX?`AX`CDK5dflK)ixla+zLrd zO)sB10UN`S49xt+y7>yt0rDK}AoL6^Cy{SKqt`n^%+>YDq~Vox2G7%q$IV+AP` z^{hV*U}Qsmwal8#THh)LkFALCLg}9+E%QY}hK@Cx_^4Ykp?8_9QtizJf*axYzNT{H z4moGoAY}bOiZp(8n8)fKZ51>4QCcN&`69?nPvGo#2ADHq4ANW^c85mBl-1LtaW<^H zE>A=9OB#z~C2JW|5Af2YP-a)p?9~gB=FkndHbi&>l`6S47u{#`$c8kZ)q1_C4!>-r z02HmM>3Txu|8y=W;93;_r*rtY_q-*$F9jUoZR_al0fTwDI66DLuoA`f1V?k|h!ZHmtuIwRb1I(0l+{u{o%>*KFK00X=@{ED`l)yYr4ng)KMiqj$lVoM5RUZvhPzt08Y!{4 z5PEGlcKd*vU93Vix6*#TTaMxPS59tc1X3%TZD$ft9P2e@#PoglKX6=obAZWr3#~n+ z&`#;*$w43H|1q$Z%F!Xek)gia{Fw*4>Elfx3)N{)w*Kfkkq7hlV5uW5j?=8HxVfU+ z)(p#it4_?n*Q|6i$q+ zd`-_J^ibC^Bx0&;|Itm#d(XrWcnC+*v$w&5NCCv2>=_G!XJB#@(^eKLh;S$aN{q#7 zZ9>E{X?7?2cy(|dO>gRLA?#+6>J&*V_UX^%@5*E3z&k_1B{hoQ9HbM!0884?Y6;Pl z630_St_(ZZEN!qLFLCP=Ve0E1OfpkCXvj7|j)|Qo)gTv{3N4%!ylDaQclZ&)1$rmd z&0bYc)8A&P^y-E##oLCC+2Q>IO-6~V>MNjhwGt?y3eaO?@ z|6K>bHXSDqRLQ_w8%}dF74qe_`jeSKP&kr62k|bV+I8mBbuZ1VcD_ei@)wDQB8p?pln9Yuas06TC^KV zI19cGH5@lAi;;u4E|=;V7{hP?^;NPSR49@@6-fh)<@Fq{y7#4$9pbOXL) z5aw|ut5_>^h3O3A7t(Q~cT%`HwjDPJw#%SikkwjO_XN8Y zTfHSNP|k0Ake>k)%##M6 zSo+#8evUAnlk6ioYpshRTPMCcDloGe3V9VCZnfVjqIZ5!Hz0PUD7R2JCI@ugq49k+faRnpEYTa`Tb|?RE19zTYb%x zL*MJg&hp)Bf1ddPahABPAUl>tAaU41UnnsfUT_jU!>CeZTk>nBkpR%eOA}N84tOfk znrl7z%IL-xoC|kI*b6`~fmAMU+eFMd)3*%t5MuKXj`n}uT_ zMudQXMVOBLL;w1_XX@gW@*1jD$wR@mN%XaOb9NkyL{`E_8PPYMfnYt`MD>0!1iFb>pkz{!v1hChA9wEOsyr8t6I+O1le~nk4rgg+Y4T%f zeetfC!GQ%mZnL=cW4-}A`G{{07O8sQ8UQuY>ctMJ+sEEZ@q>=frJzxQLh=EzTFx){ zTe~xj?N^jPa#_$n=K|TpXY9NaHvMj45RZ>`p%bx#EHLzI@Kg5!w@$oDKLj>$v!_kD zosp)%kzg&i|4JpnWye2KNr00|6|-hdqK9Jq*9J$DQ-e@hQ0pIc8*)O2b7Jb%AocEnNuwQQ z%dgqhH#*Sm+A6zuZc;0+Wcg*Fw@I3P-#XQFE#riTk`fd}Wg|tV$C1e@Xgv*|^+!a2 zoFpd2IO%JuYJypeLu`?|R78Egy?uu5xs)71qrZFM`2XOj-QR=%p!XDe|3?4fW(oi8 z#i8DRB0uQt4gQ@MhyU`{xcwbjx zC=sOzNWi5jy;uN&fKn6%bi?kR|HpUEoS8fKzWcqIcfRkT+}zCAIN1IRt+mX%`;R4t z{+8@ul$W2+6&I(Q?Cfgn&+Y$_p!Vhei+wpe3+>hJ-DlU@mzz7e`S7#e7&-a7s=}2o zD8pf}eT4+;a=~K=H(hRPu{aEigR8ShxFpWQnZQc?*BJ4PrDMgu@qSTNf3+IWoDcPc)-`;Jw z2E1f9l9Fb<%oF?b+~ z)9^WRmpreNd5|~kKQO9Z`K&&dswe9~KI#5}B}vQG&eSMagib{b+oVvkgy;5n#+jf6 z0RbRD?9e@c6kR74JgZ34UEcg4rj*AK5bSM!XMoqfZu*DQ$odKD@Vm_xDj+%7y6Kjx z+z>qq+FZeaPg{=LMjDE|j>BQB3?HS`oG3h*?OUDi9_FQN_yJ3jk);Pu$cWVv;ttPz zB)qv-@3Q2D{&M)$SUw-J--uSJSQEF25Pe7YNV(X?HmxkRiEQ)^9DUly102=~BaQ?l zfhKuO5`Z+I6USR%qqX9Z?ukZNaQozS?%$JQ?pGFddO@Zh@=nPUjSQ+k@)**u%3caTG541j8Q=hHLD~U-gB%Otn z)(bUdCvQWwd8&iAkAv)o=c1dBmau-L2)Gxr8B99S4-=GsMCV zS6cF}h12m}%He9IZWFd|sYNyYP~8DqzizJKUxo7-5(U3m%#Cz>b+j$(%Ch-}=UYhB zAWnUUZcV-Nd%sAHM7c6R zcWY^PqGvh;-`82uR}ota`YFXcTkhf6S7>(8oIO1eO1l+OmoI4857{KXO)w8njV@K~ zzn~BaiweoS;~u6+el%>6g)M5>U+u}wFS(r~M3K|Tlm2>&XW9bJTU!>bhL9gsCxF@^ zkioXU8fTM?=gv^Z;{xB2-@wE43Kb47UK?ZNy2;pZ^uB;tfST{T&YV3YAD~XGN*6rs zrZ07Y{Yd91=QrI4exemiKF58rBq=EU=+~_W(?b1hW%#PY8hawn0r8tJJ%r(5==>j4 z>O;QL2Ge=2q6-0AZQs$bRi+DVP|axNeFa4#vURbgKwHgW=594{oUvkg;@&g`$KxPz zJFOoZI_&z`-(%}sDVmm}sjh?CU#My=sdERSFjS!Z#GuGo$b{m8ijv95;mdB^N!kq4 z{?1vS%ig$VN#bQx+}Na%4bBEOivO^jm6;BGe~)V0Up#5GSugb%B>XKyr`L4Y&jxP|LDs*6Hi*_P_{R`z20F@I14ZAqUZdC;l2ecZ9#&(O z;Wqhg2-~KRqB+#?H=*EDV;xa$l|yCm_mz8GD}80;mcmVtInZHZT~v5n%7B=B^Nb<}gK=a<1MViXyI z)oWH@EGbe`Oeb{BcY(l41s5Xh=3(L+A8E0o5sW0(?vjc8QI?4&zujQC0_0v0JyKt4-Y6k zbQ$H$m$s-_TJEg>j4L^%15#|hsFId!U?`)gXjsq}gv}h$-QWWRE%|(3p?erlMwHfh zu_Fo0riB{XvO;s2asbuYg#*Sk$Ej@ewRptTToNZgjL=ZGX@QOvksf_@c`$W^)j63a zzh{HoS8VJOjjyuJg)G&z*rde|+!7N1nqga_g1UjWzeI~hGm{qI^&|pA^cDC-MhC*D z^xms@P!ZdKe+H_AoA~0M!0*$V#TixC_NYiXKuGuT&Q_&ey&sxYnXX{Q$78+S=&SBY zNw|Mz;-PJ`{Q>&#Oyp$Ux$Pp60+?GkA3Q=wS>?=r?AJx>oNHnfPq+w26MIEYgk~-^ z7A?rXX;*oiFDgr`4O_5PP94fID4~SJ^%Ose1ZARW z8AY-i-V^<3(5v|;;kub3x2@vsZ;V$6S5{A{w@AIr zDJzTkI7a-=PAO#C?9I@GNlO+M>HNjaNurmvmTcW}m`RqWws$XVh-utHx~i$_xK>;y zRC8-rlP>9@-y~p1G_USVHx0T7v>|2cl2hAhm)|5XrwQ-zC3E^<)k+UtuS@3k5ZkritYH!P2)=NQh7VX<3#^^tWqxlm}EZnu~y^I;B z^P2zcb4r+xC$Z%of~$%M0FaID{*#+1GG+J3?caPQc{NZnV zqO8t?1%b?=vB{YS4v%8qRVW8`2c1UdaaULwY-Cp|Sbf4BLC2$5DXlW8U+!uLT#o6+ za{lK~06LWmUuXP+y8n+#P1hL*wJdyqt@S>b$wI&QK27>`z?X#%WOh}5`o))p53mCR W2Qw!=|5^hJAJEPV9jt+cy8i}zfP-KF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ar-SA/wificonfig.ogg deleted file mode 100644 index b82f7a8b52b7288f1177b6c28d667903fed841ac..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5461 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 C_&y>4 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/0.ogg deleted file mode 100644 index 0cf648372559cb1fb03010a4afde639dafb9683d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2369 zcmY*a2T&7A6DD+`h?ImTp@$BMJd#M02Zo|_=}1igB|wlWMG!-RB3-J|q=lmNCPqN% zMMM;&2%!o{KoNY1ApF6<%=|lZGy9d>yS=%YHS_Yi%D~9*pE&s9hd4>2D&M97c+LES z0}VagumAuG(CPHYVs>KxU!2$hbVQIdPXuV4*sa{W0#DN!W491b1Y8-Z42Qu^93u4P z;fKLvJp#1o8iuaHFVID}n9mJ&JbmN83+r^yee^gfd~zwAJ^nJcy@RcH2tG74z$XA7 z=;L|gI*xEolwp|TuZR+G_7+Ayb5JM7BD2|?Jqj7cX~#QuC~*Al(;9hv=aA*Yu8;=i1WbyPL*fLSl-2W`%x1O{vU%>v(QA%6Eo=i&|X z)02?w%GOzUNa?1kB2DB+YSNO*Go|+~=p(5c^3m&@5X001AndjRxC5Op9t;Y45iqjZ zDS_yXasHCV=yUGc7u5=~@Dl93I=1VX5t5U5c z4RTYKQ&(8++pl2MrkuveRYikwi^+L0BD! zG>nn5!1lq%s&E7;nTGe7M`e&-3>)b`da8a)H99}_HQkaWMXtDf`L0Zp#<(VNgw~%u z{@!)Oni~la8GnoXAm;uyG%G<`Z|=#}#*i{?Dq}y}g9ZNy_Ik0=_A$;u<>^Mx(4Tpw z-*?`>5~c1#sb_E#i$rgjqQ(4y$vd+g904j-ZtTbg90WHl~`gykZdeYiF$;`pcK(M!`AQNg+< zK)b@O2M)NVm7@%o;O9TTZ(fe;p8J_){B-_&WOb_h>4O&~1@v zX(a1z5S4zlB$a__&S!zM_=s=RiAF^x$Pdl4p$LSi=qWZd*O#6(l6o4D{Me?n4<3ea$`&HgXPxb0wI#I3c zXKF*XOF$@WJLRz~H=?C{Bti9IeV^d5MY4KR@m=0yT%GZLbXvLgQf)r--X$F}B^ayl zj#TCye9P_`HN9!Ll9ng^rWZEe{iwEp8lG*w`JDb)#VDqRPCsFi!DsJJD@1Z1vPoyK z#t$x)=FGe)1ZbcLsjHdhDI#Es4k_?**|-x~hY0KJUv=EQiLmyL0oMuiGM=vFkC|%I zDyd{ZS{dx5-8P*YIi{HKY`4Djx*0*?5$1a=Z`{wh4)vI(Hz?VP8A{^wJXSw*N(s*9 zsD79huUZIDs#Z^LdTHU{{a~nFyk_BUOR48jt428*M%G?_xgqyO7VR*68jGs_k zIiTa%{y9_Y3~bo7d^sOQ_+AiCsM91DpZ)wWVCt3-MXuazyR`CG$+%*s#}0l^4nh(04SrDJi@>#}~M3fg^~C%5j#Q z>)l0Px>T+!%ZL%b{XC3(fBdF>b>%F$N}+M5n`vJL>X5;FB-tGdssha^>4n>(bc~7{ zlA7%f{WToowhN%5=OuhEAomK~(E20C*3VlWdn)Z1)$Cww-@I4p{Z!!ZQcG_~{GMO5 ztDm~X_~YiiGsu3vlm+T;MeQDBz1t#*5tlNCU zcqWT5`hn}tkkG$p^5vrDj*6I!JEE|!e0&^=eO9yAs5crCw7A3=4-Z#vWd50>%;vj) z#^|3p%0y4gdSX3Tu4(I|6>$U!v3uAwBLln&BX8$?h>LTYsdrnAV`YeO3_I9rw;em0 z;=B;Un^cyT5lEAL_|8Smchdc@;B?JbH7$p(HLQ0>@3w9;6B$@)oSHwoFQ}H;Cn=!~ z9(2bFEaM3L+&~$Hx3(+Jyr6-^ukTwDgH!k6VHT6x?1f7{;z-Iod1zLic)Ex|gS{ZL zpFiW&EPy3PyzOE0|7D%m%dnUe|s4{1e(V&u?>Xv57>4V U@krkJfTGL)Me)1p|Bq1r0$J`-cmMzZ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/1.ogg deleted file mode 100644 index 68bc66b1a18514e72ea885d98d2ead0d76817839..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1867 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 U8v11qt-+^R8akCp&4uXw4HR)QNdN!< diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/3.ogg deleted file mode 100644 index 95aaceb0c4b3f72bb2ce62ff0412a5f816561320..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2245 zcmY+F2T)Vn7KTGddW#7~2)!dw2oXaGC}7}8Fa$&q6o|kLy@V&ygMcVSil9^}5d@_x zB^VS@ka7VL2$v$Fp@tHgBIO3(n|FC@=FIGW|KD1BpL6z}W$o^c0k8u88?Pd3Cl7~W z06skyQER{8KnvUrHx?E+OWU>Ii1i`sADoY?uNyAFfa$q1J?I&x359rhy7)2^|5MnQ!sM87Som;Lywihkg$cpe z9RvRD}jvIq;xvYdXD_ z3K7f@cDvGmKDnRh^`gjeykwHXf($H>j%P?g5@D@7oObbI>9=m7exzzzAu<>jMLYLsH6kqLN}7BS!bRLnjQE)n4UU%ON-`3QunE z6E}XNYqAezb7mNZE<_J89?Vv73=H?3%kN7foS0cgwlrQ;zx4Xn?v`q;|E9P;ucZ4{ zf8*J)0WRHm#2eow`YhHzOxsSNvjxct1l5OZUSHu5vyXT6_+8_+i7#uV1sTN1`L)UI*8ivSmo zF*K#~I|on;|!R5cY8) zmB-q&KWI|H8h0qk2QZ=P*DW|bOy8nf0DIK_+v5+ZO-gZtp!usXIrrUzep)ek+wb+P z`02|Dnoq>(4eR7|51i(GnNfRTtZNtBy@kpi<}XqvQz|zn{G9Txiabu0DTmvM*b1;m ziO#Axl)iU~3Z2jOO}-e;(?BLvMEkCV>u~^ci%GJi9H8sG&qry>G7ABF^{O zFMc{n%aAGoqxP{&?lR60a%Ze9x#Mgw;JS&kne5Avll0}D?zCb?_$%_0DuJa8*$ceu z%x?-IkA{yzsv~ZP32?(Q8FC@vc9cCg6UfcGCMTWU{nCw387a^I0+82@$hM@j62WVU z7@6G6XBxg3?^I3f*N{>Kea$wtjl6}F6dFx4Rg1ldl0~> zASuwa3s00)ApfXmtM8(oslD*Rt^z|Ltjf(n`*{lz`{P!>_?DUR{i{{7K|M(D!3Mdc zEIiZ4S@Jwb#W$C|_#XiG*!|a9B|J(SQtaeySC>;#udJe+fdO)7G;xC?lQ&3sNUe{m z-jhkR8;H4(B6<6c7$^=kw8h=kmR#X4f|eKPsmo3i#&)ChqkkpcULi9$Vye9F8GMlt zHyxTBLD61KUQXEB(orJSxhHSKmcb3jxg5#ll@I8YrEiaGn!4v(O@}oA(h?AV*f|s6 zKtj7lBd1k5?eHcv83bmz=u@K56!QtouACi1^PXszKlgM@@=PWRuK)jAvWMfT}&Q|iV9FDyh>EPUOR68tUQ3t%$OtK^wjPo-&ANd z?@9f<-jul=g+?*VOYC!&7OpYoDN!y0Hw}WSW*h%#92bm|7xQt@a)`Tqowk0}5b})? zI4m!sS2^TX&{7scP(Efe&WI2|Q4IDA2*afym$U+fA-7M#XMf@nc#J<+P;F1S)2nR< z<~Givw@A*@fe{psXJIPQI-fCLu9>R=N@JMo$!So>LP9sWR191n?oJEcZGXpSP`D4G zv11v3`EIY+4NV286abZ5kR}$!)bU44Kd#)_YyX5OWluAME?SLDY3$|c6^q|`r@-a- zC0YJ02)f??jo=%UW<;~|;zmAy@byx3B%TPAW-aN=AFJpXJWpg{n-{TIT($J(%98Y6 zIwcmlwi&?#|A@%=4n|7Ry#b}z?>ma8n}I=+67jiCQ^!1xzlE)P1Z@Clfo43WRTs+B zyzoRRDR2;N=h7MpJR{)ZlAS8bYjDtjGXiWjUgqz%1l>{Hd^nEg)Lo^W_SY@2>{*Wi zN7PaAOL;VNphlC9xav(O&bLBZHGE)oonjR5e4Kg5@|caSp(5Ll7{6-b!Vy^?o{L;Vy0%n1vvsxfn8b56{Ffbk)?zyX6p{m zniUuJN3@l V%yL`!|J7ycBW_*L(LFE~{BJ5)2)O_N diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/4.ogg deleted file mode 100644 index af31cf75a2199d9c4279c159dcae39db4ee81030..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2611 zcmY*a2RIvA8y4dxRS8k6#JWZrTw+wUc2TQ}8YL*Ti9Kr;q1389+Nx2#M)NPK{4D)s9&G21VJ1`}zk4 zgrdFeZOv?b{DRRKAs8T1qHsBRwrptxIH%OY3bH5-J@oAc=cxY2n+$<7_4F-oF9Y9> z`Kj6P?hW{xeA7y2*F4DSjn?*ngN7+RanuQ=r(O{nKh)%bLrZEGGFZRazP@IL#s~_E zz80;utgyT94ZVoX)ui4EkwF)y3dtR?iJk4W6+L^v$=_w~^IHtQ5j!8p>kC^C@=XZ2 zTqW41y~Vh1^ff>BW~cS`+vK>z3A|wVZx7z2dI|)74nt!k;iVcadS|#tA8AfeowJA6 zZS>Fi{ArQv{O;k??(WC&64B;6;l|0lN%i8NfUC1K&FULTch!xGt|rUqKy)R{F7)-- ze2ev>M6S4u5>Hl=w((FAedj}#s;=InHfN}2@N;W}!JTX6Y#%mdnewW^X=Qr(vS^IB za1!|p!9;L8UnYrEQ*Pd-t!kgrE?XW$$ql0VnX_*=_!~qiC-nh4kP)6ydpDWk8+Em; ziV_V}Yt}j>gQNn=d7M2dQHx*r+$%b_uFc!D@n*Y^*%)?5d0m@7BG*CK& z9b)qerqd~{<50x@?9&Qg+B09t8w_c#*n%WJzsyQ|GocY#q{rBtbZlE_#XU1xO_Trr z%^soeKR#wCxP|SM{NXuNuUb$Xb-Uv9fNhG=Srx&|zzWIZagFP1^3~2H3m6aD68h_2 zI|H}caKR|_m-TBVFK3MKXxJkQ>A~_t_1fzxv?EewFSj5E1GLA{T&#I4tGq`BX0h^e z231Zt>DLWe?V2oP9coxMWs@ffX@7-d^^k==MC7Y-eKbZy5=5 zNrm$H(Yp(`nH;r7BQ*%3_=EDhcArOI%bipRsbY2rPY^Q?j#&2U3YQ3xr7dxm#GI)5 z@$U9sPc7Qpdh)ZtNSte7TbpO%=uY~@reDGM#Ov_euuv&9=2vli-RhM;EVV&7$DAT4 z2mI5L;#Th{NM4-=bFr&oQI_CrHm>8*;)tqhd z;GHi>gU*}34eh_7CLqd$BA$exF#<4LM{(4>Mnc1bb!vPr&p<~_g!^(HL-j#kBNMJ8 z6(8u6#39!oX@qQNimf5qsqp_kkuL^rzfb3C+9{DO(u(;;$1Rp=dNE_d!4BF|=msM_ z?MO6z?xXVQ<0575;kL#UtcbbPJkCE=Z5(GcnP*pBN!k=DZMJku#4f)| zE>dZw@RyqiDzP*T_M*MD!^@o{hUBPiv)ANKU-o<}g|#ZmTCfnWAVhoEyVPxq;+~ zy6_228!dLr52wGQs5ovGM|QyUzgs-RFjd+R?1dPs@qNveSX6Tkl zz#W%TxzW) z_ZfG5TlewQk&45IBAw0#762<)Ic7Wj#YIGJ-Q<|n>dXaG=J}!Am$801DVr759_q?> z{jOQ%dAPXE=N;78;$H<_Wa3BzL!kO@Y*y5td64;))M?WEI}b9^TT_T*9cyra##Mc7 z5K>Nto=qfL#bLaFF&m~o>lC=A&MY;fU%pAOKg$tE{yv zAHpR+OD{Nnq=?7E`GyD?#JU0KCGOuD=L8?MnmX3U5rtE{5eor~o0U=dm;MftCxugAd8-k31a-s@LmXEGRAxlbatCE7S!3Vl*hPCH^7^}OA z!i0#&DlA&wjTVK0&3xyjj2B7T-Nu zWF#$_S=49Pmqgn3ffGrZ9AN99bbRL=8bN~m~5>SYCTxbyFb%U#ph41U6sNeQaOEEtt=tf-XUyL0I7 zv_PUMDo%HxP?ls27u@3QhF#FaS@zEyi-0boq+D@EiA!|vgz2L0p42{fFX!=BQXF;i zf=Dw`=D_V4l{TUzWJe2{-U0c|pU}umC$!Uo#&AH+u5>GJ^=G78Pxct+Ib@G}Awr R(6~GDf9PM@@$ub}zW_&B-<_~25a8)Hx@ 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 e!2iFD7<@nq`XLzN#aRwmUpp+qG!oL6kp6)RK diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/9.ogg deleted file mode 100644 index dd5a37f25aee9385f5f8a263ec9517d950592658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1770 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/err_reg.ogg deleted file mode 100644 index 992557cbe0967df2b03acc3f43f18abc2008977d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10755 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/bg-BG/welcome.ogg deleted file mode 100644 index 71e547b6685222ca5f67508dec8205a2456cac65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3502 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/0.ogg deleted file mode 100644 index 2934044c213f9b671605cfbb5a5c528a564f3ea9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1790 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/3.ogg deleted file mode 100644 index ce93833282d65653c3c9693c253967b37dfdeaaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2088 zcmY*a2{hFI7H=|^8Opv+yorqL{1YP@45DKn8nV@7nbFwSs5JZxLy{PSk@OamK`}h6F{xZ|3<+)<9 z8zUe|r|_64+W?$D2!sT6`s_)Zc=G=mPY&WnUa`6Lpp!hg8x9{O!bR+Hv4MvAIz~GB zdU`yCB6kIZ`i1!iM4seweq2u9m`m!zgM%)FaX0=uvH5eZj%&Qcyi48nVpNNxFGfa% zhKCWtf+B(fygkq;A|Ndxyv`50O&WdKQSG+?)isJ9I@0Gj+eWk(btT0El|iJEvhz8hdR%F-6{?_dTX&ZA>+4H&HbJD%ic_Ssxlk|c8U;2 zn2>9u>KshM6nu(n7rlIf&=iPFa=3|zwb^TA&IOhp!Eij02&f{STh9_3r>UE5kbC_Iv@H6Jt@iXtb4lYs^Xq1q;7Wqh1|W83ROvYX^#UiYT3>C)>%Q z(uzVSlHYKS1h!pSvq<@4krOBxqvZ*UjW&WFDvwLR2#srzI$C8^y;9~H4-$dHh_>D9 zrj-lDaf1xnLHeoNn6#Q6=IR2rDKk=TohBAooY;EtVnn;nOZ>Ny?>gmYH` zOd=c}Q`ODZ}S_LKp+0nj{-HEAD-4A z0?KNwR-A{f#5C`Wa;*+m6SU4$K=&ht=z(LDt6F&!bFxz9I^EnCtQwpr@JoOef{LLJ zxx9Kv|L z+fhT&8A$pm(rrmaH*BipMf)3mTOY&Lsj@ClcGjsQe-JIC@XTGA28B1-w$06xRdKX= zUG4g%q-1|e#<&2tjR-0Z7Og$DRaIfIaXPg{Wa0&CUMBvXhu>95FP)+0h!OijMP1HP zkSs5Jy%Wy1GxgsYTI4`A?(3Q0HAwDYyIVJpcQ2HO1XGU~DppYo?fk5_(>gP1b#3o# z>WehnoHHljW~3!jevxZ(xW}nbt#qoOS=dr{M1ok3yyQ_Ey9u;?sNYMRmqykPI`$xh zMHM`>+{xDzRoCkFbq3}ct^b%=AwQ82CgC$SeCTY`X8J^3Ub>>5=d#RFuWHG*lytOw z24b^%u3a6vP1&Vi$?x~){y5d!&*DZ`zXiy@x!MLssz=4CyS(d!}fX2&llbVZe5zE}<%Uz(17Tp8Yu=}h3i57Q^C*^ZQCXH0BB6g`+7?DdK zJTiA=efVtPntEtxP|3LDd|N}9T%rrNg~|p^!!yDlMdL38*`S8LNZVfARpr33nD1RU zg(i%Tk)tkH7azi|IK1iNp?*#{=Yu^y^j81$2;FkdAOt6(oQc{m->cKzGAt_)`D?pd zqr!!Kp+oud#MEkuF_@uOUk)Y$a&Ryq`Z1+J$LmxIW@*jLff+7rv(cvgG*LT|{-Ob@ zS+|>&o>U2!n(-J=8DmXBUa#aIXW^$frC^`Yjh1+noDIS84to~-dp5FPmhpuF2rfPa zAHdQzxdp&9@2nhnAYUty>wz>kcg4FW!s_4*k;#Pu7F-M{R@mw$fMJ>ZM&o^B$2H3= zJQ+8me`4J)Z~H1x8f6m1wmh>N91hYNO_xij)3dHTQd;jKEG`oPSqUf>=X>_l#~$>Q z)L?gtLiqhFZ$|_=;~}YYx(TEXLjQ725}$^}knnz?<_ApG(du$pdivBodDd^O!>t`C zA|DS{u{iSnU0-d6dQ6+w&oM0q44WA~^hj zsXnu1mA%QSUNg%RrH$Q8$FXL8gPA-Avo^`kOledJb=`MtViR(I)&t3X8W@jKQwCbpJ4m~OVTlKo#qKe*47($tddOy-^(Yc@`E8pU3^Bc qu8+cbO5sk=ZCMy3kx#HMzPHc4^S*=%>D>v_|BI0Si!wHlrvCyXdbjrg diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/4.ogg deleted file mode 100644 index 8a3b4a9ee7c4d1510debf35fcbb23c4675697d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1897 zcmY+Fc{CgN7RP1q5~5AfDz(KLDpiRRs)%LEQIesSnn&#=6C+YdD|TX!eL6-hZDTAA zTB41py)+uCMl44yRaMkl`|^tRMdzJYbI)-~Xz>4+8%SH2v)3 z!|Uj9%+CNxY%n>*+Rw`u05AZwxqq`@5AFYtLpy*^JLnG5(9K*R31+ z2yK)$LPzJ&A6#GY){*WAmVz@y6TA{*Y+h;B!9w$ z;1Lm{NWn2<5Uz&(pAX0gw?K$yg?y?H3Qv_h1Kb8=g@S`MC6ZbF*jTt!l;~EXcpW(A zme7X7)L-|L$`=nT@H!cKZs199L}J?RAnPGY$*xSXrYf~6W{nbA(45_7NSt!d_A?Zk zmL2a*przrdYOo|GS7w(Iw;ed%)vi{Ix6ra;&~g&PZ%Q3}gdu`8Una87XkucEb^{41 zwKgGwP?&@0z6_-^s`ng|!;OrQCwK9P+F$#Gcj5Qy;&n1gU${|*uAyH&m@Jx~>Um$< z0y+;LY%s7&V=brB$c-|dk$-^kR2b|xhcHsX>hrAxYm-aQ=ocSwT{$*%xf$10mzm2Q z;(Y}pmFF{ym}7NYqwPSHYeHLdI%l^B=#<+y`vzo`y(TxPVW62#Dl!2-E#X#@*qdVz zRYzWJct@OP$7(>!rvPX7J;`ns$*qpuL!X@I530-_v$wW8tJ}GsK!`46E;014yv~bx3o|DOCCh6jQ_E! zR&l24N)(}9@hgq|@Iq&G!@u`5jBd{+UpuQ|4>VkRSrDSl^o#pKvc6q~!#W>Ndy%Tymj2*}2tfEe#!7$HJWU{on^@=C3pyMEb< zUha#EpM>G5N-E7SXAT1P7v~6lkvG~>YRB2NRnHCHY>-=`x=V#PDG;3mqDg+dJ6qvn zph@xPxsSd@#kB%qJ`h&*Q*1eWKHO-YFqjZpG{^8D_Fz4%A=gPMSyY zcDD^Yz_)@OPt24==sxKcLKgF1KWMeS7GJ-r7vKuZTY5iT)h)_& z=#H$*yNs6_osS;3&HZ;S+7xH+(^9$8W54E?Y4&)dzpL(=m)k~x1+%HTH-nVZb&M&# zGgTauIxUJ$QaTvlAKzsNXZTP~YzIhV-qP_@W#yLrB~W12kR;7xfN0=JBcjf=S1w+t zz8pP-bGh;B!>T;lmc2)Y(KGT|ITe(M2DDAKR&wGi$15$$YOnKtAJED2#*&Oq8MeQe zy0dw0^8Tq#%c?MmpDYN{U>i$`Q@6Th=ZbsB@l+KkYG9@H)qbKgowr$i54Pz~%~_iE zR>X-dXWzX&kYqIiVeDTBS`D`hfMOHF4;~XXl4Q(8iIPjQL-@;{mgN6DyT$}!Ad&!F*Mnwc25CRm`{55{1dpF=q<0{q@kjKr$Xd_ zT@;?-34Ik~qv65jsy1Nj@JaT<`VZz~Z99(Aal~0QovdW3h)kjNCnbCLfUwMa5(&ErLnc6xqRY&uRANg d-gDH;=OgMW;%E=HG<7imY+sDw(1CD9W{fd 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 ba?LXf`2T0P-`Onq@2Vuj{nuHr6>t6z8QbY) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/8.ogg deleted file mode 100644 index c6cca34d8aad325e5d25a7c0d08bddac2b901471..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1892 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/activation.ogg deleted file mode 100644 index 082e561ce6aa9b1b7f42851be46e84136e5586fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11679 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 J!SQcM)+8=^)R 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 Uw`{(E$bWI+)PKEMp)VrwKMY6r?f?J) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/language.json deleted file mode 100644 index 02337e33..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "ca-ES" - }, - "strings": { - "WARNING": "Advertència", - "INFO": "Informació", - "ERROR": "Error", - "VERSION": "Versió ", - "LOADING_PROTOCOL": "Iniciant sessió...", - "INITIALIZING": "Inicialitzant...", - "PIN_ERROR": "Si us plau, inseriu la targeta SIM", - "REG_ERROR": "No es pot accedir a la xarxa, si us plau comproveu l'estat de la targeta SIM", - "DETECTING_MODULE": "Detectant mòdul...", - "REGISTERING_NETWORK": "Esperant la xarxa...", - "CHECKING_NEW_VERSION": "Comprovant nova versió...", - "CHECK_NEW_VERSION_FAILED": "La comprovació de nova versió ha fallat, es tornarà a intentar en %d segons: %s", - "SWITCH_TO_WIFI_NETWORK": "Canviant a Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Canviant a 4G...", - "STANDBY": "En espera", - "CONNECT_TO": "Connectar a ", - "CONNECTING": "Connectant...", - "CONNECTION_SUCCESSFUL": "Connexió exitosa", - "CONNECTED_TO": "Connectat a ", - "LISTENING": "Escoltant...", - "SPEAKING": "Parlant...", - "SERVER_NOT_FOUND": "Buscant servei disponible", - "SERVER_NOT_CONNECTED": "No es pot connectar al servei, si us plau intenteu-ho més tard", - "SERVER_TIMEOUT": "Temps d'espera de resposta exhaurit", - "SERVER_ERROR": "L'enviament ha fallat, si us plau comproveu la xarxa", - "CONNECT_TO_HOTSPOT": "Punt d'accés: ", - "ACCESS_VIA_BROWSER": " URL de configuració: ", - "WIFI_CONFIG_MODE": "Mode de configuració Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "Entrant en mode de configuració Wi-Fi...", - "SCANNING_WIFI": "Escanejant Wi-Fi...", - "NEW_VERSION": "Nova versió ", - "OTA_UPGRADE": "Actualització OTA", - "UPGRADING": "El sistema s'està actualitzant...", - "UPGRADE_FAILED": "L'actualització ha fallat", - "ACTIVATION": "Activació", - "BATTERY_LOW": "Bateria baixa", - "BATTERY_CHARGING": "Carregant", - "BATTERY_FULL": "Bateria plena", - "BATTERY_NEED_CHARGE": "Bateria baixa, si us plau carregueu", - "VOLUME": "Volum ", - "MUTED": "Silenciat", - "MAX_VOLUME": "Volum màxim", - "RTC_MODE_OFF": "AEC desactivat", - "RTC_MODE_ON": "AEC activat", - "PLEASE_WAIT": "Si us plau, espereu...", - "FOUND_NEW_ASSETS": "S'han trobat nous recursos: %s", - "DOWNLOAD_ASSETS_FAILED": "No s'han pogut descarregar els recursos", - "LOADING_ASSETS": "Carregant recursos...", - "HELLO_MY_FRIEND": "Hola, amic meu!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/upgrade.ogg deleted file mode 100644 index 1bb2f2809fb78667fb84924b73bdf120a4d9ad1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3717 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 c diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/welcome.ogg deleted file mode 100644 index 530d04eb1558e33cbf9d4a4c1e1d50bf65a18feb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2876 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 JRy!FO{Rd(gFq!}W diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ca-ES/wificonfig.ogg deleted file mode 100644 index a4b77cd69f15777ac96db611b5aec96b6c29bb1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5347 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/1.ogg deleted file mode 100644 index a12d638033a4c08703350361a65a9269d847612e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2000 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 b6>4TKt2GFq|7%dpS7*h1^%nZ?C}sZ!`h+N3 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/3.ogg deleted file mode 100644 index a2d9d3daffd80b3736dcc86775f4a2a660b96265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1531 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/6.ogg deleted file mode 100644 index 571ff305c3311e2fb5573e04dd12cb0a45c85349..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1871 zcmZ{lc{Cf?7smxHVqZF1#1bSzttnzDN(93oYM3&XL~Ko~sH(JzN)Z$ZYH7z>Rr?m@ z_Y)dwi=s6`Q`AzWS{=1?(4b6o=FHDOzkAL*=YHS)-23i(=bdw%0t3%;adZ7+)H?zx zhi=KX$#a0DQ|Ps;w*D9#0Du5=dVNQn4)K5O5C?G7`B*zL;OrspiV3_b#MyDcL zY8h(j>gXI2AkOj+@wpMx3Co;-z5h6;9&cg)QhDj$?;~51Z0^m2NKX z;o}t?fxjM(4f77fxR{1xOJxIbjBYx44at0wQ*Wbd6HrIh^PT@a+9kn*S1GC z_8Z@qmpbuT+AHJ1ZePy{<~0v@Z&53NBe%ALXXJl0vkEiRo%hQvi(wR7ivKdt0SoMs z$qvF3738(;SL7;Q&%qUJM2@Q@O;{cr%&UNK&sXIi*K2w9ztM(-2o?&7oNQ)zs&-}% zRHZy<8R9>d;ydFziOu*Sk1e$cEQEe7Y>dhZN4>oHNx>q8Q_CPK^>(rL0etkpN5u+UWg`|TQ z?UH)dtOfTS(E|1xYaGa6ej58Ihf3&h_i8n{sp z5bIVi%$s1P-uqoUdoEgm2kk@TgfgJzr03+09#tbqwGDm&{>)|Y%OH%epL^;nt@K3$ zR;{w`Tv~!oZ)2!r;>l{)i`_W_4Uu(A0tFVlTV{XAy@G63p4#Dbg6YnaOdFTU!BUUT;R3?|noOe{E zow|)KYF2uuULZECZ>d&x&49t18CEEH2NN!+A3gnQ^lJSc*Nj!0V>nszW;t%d{P(GS z@6B!;$X6!*_2m#?;go)6BG%oz(npKy-u(5Yo?FlI{G@ufu^KCwcXi29?E_B;>V23S zD92gFZ{soS*oQPcQAH)YC&Ddy40(lYz!dN9F(XFkt&+Ul2(d|Ey5tLV9>lR2W0tv{ z-!zhXW8GJ~S*iKj2gNOB$vxR5Lki(bvS|rea%*v0=@R8bP^-?o!%78!nQvT`o)f=N zqLV_SgKUm3Qjg;x8{BB}Nmwc8qVh!PTqC8ZzHAYM`(mtp+iQCP-CE3TXBo-Y++O9uNZ?F>Ql9fYQoAaeM+|iCb?5)cx?L}&lX3CKe!E|Qv>^Nq+CepDH=?2{e&R6AmcK*Offr6)*ZNedRKsUY1(dr zI}@`U`~%AcZWKsbx;=O004Z8y%=soDJ?#ED5xP{qPdTesYGBUIe(G1}%a@|wzr2;- z6&TYx<5vT#J4@an^1(o8acUGUBCLK%O*D`0ET7LL>L}Zb2|DO<$LNN1+?cGPNIr zWu!g6KGK)4+f9>2^W}!;nS^$J9tJdBe;RtcDOfcLM&W&D%BUf9RB3FY((f}$KP7_M zef`Ztx?^&9qPzku(=m8_7RYrKt=lF#k#*|xZpQN}_?cI@tTqHF5SHn5caN-`FHCRYiB!;I}Kdqj>ORK!zG8rj`IAghw zCn`xps}{CEqqOy3=}2CRx&#|z69kOPLY0%O)9J8teSb#q)Cw1cmovK7v;)E^K7CO( za|&+E`D)=Y8?h0eJy|8VQ%^;=$&4pl;_j6$#iwME<@C^_c1MZ!r63TJEuQC3g zN?BhUI?8hN5%!+=#t~JdyD{{AqVSTK-v`R~iNeEig^X)lxj7@`$e|qgNNOc|W9WY^ Wa1`SxOAT8)66L5PnH`k1p}zpa(_h*E diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/7.ogg deleted file mode 100644 index e8f0f94e75cc6719af6399428841933ea36cf161..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2052 zcmY+F2{hZ;9>*K8CyhpxQc9AF+Wp(~Y3UYK%UGhe63bXZLP#tVMHSOj(ORZYfvJ1N^AmJVIcujapHdppYIZL;@By?b11t+ zYX`WmcOWgA77|G%(Siw1E*AhYT?-)re2Lf`2VFdobSuOEXoSe;EhC}*Dc<~`!s7cv z-!u%M-t2l594L*r;%{o;An;V4Ri8$H#zwMG}Hf z9VE&eNK)fL7~2qY=XB0kv$4HtLp)T+zp#OUxkBf^GybXc6`*4MmDkobaYL?3PCn?q>(o#>l8;Qv2Y}; ze8yHQ<*n6esn(>=WEUmIiv`?3>dig-m&ets$8*uDe)@QqW1DZf;a_W#0}ZH&zbSp# zbA(JsYcn!#{7!n&I54G;)19BbOK1K`?wUpR4^mADP$xBq7_6uQE-+(wDFN4NTP1K; zOJ%!0RbH!z5S_P5%ukIcDsQd&H_0oZJe`{u$OOHyz=Aj;rHlrtc*sK@SeiW4jTlb; zAt)~4R~_370R50mKcd5gE_QL7WEf^|XL+R|pC3Y-ORugiko#PjG6 zcE^7Aj#nCN5i{{(1stNL7@Z7#WkIGRHQRW!%=S@vYlBU~%VBv)7Mg$FI9FcxW54l6F;ruuZNslkfShbHLG}0_N-wKR z`orW&{G&tBzVLG?exL4Y&ydl%Pvl*~=3`Rw zYs{6*;;QhBnP*QP%VjAY)2(DuaLQC0ozBM6lg964Q@32lOTi*J4Ss-QR$M!7UdmIY z)pFR&nik$+n*GMH7Pj4EeM{MW{rvY!!hW~&D%&`Xp0g}U5n^WC220|?^wAvZ&i|C1 zaU{;g>4kK=E9dD}Uu*Ao1la|5{i`|ntnLrO9+n_-Elrxv>_@#{@8+=g`8P)lt<;2Lx>#h-yMM zL@nMb%QRomVQ9B$oy$jIVY6uD1&2mxodq)NvOcBlXpMtUdsq3TR z^1cZc*sRztmkDcOlYU(P-CEhQz3usUEt#8$do$gYQpZ;Xg|;8`69@t=5!lj`_eDdK zi!u(#Eb(cRY^s2#VZj$ zzw#ie1+xU|d=)jng1ESxKhY*n$qP_l-S-%Cy~Z)#U5CR{MOn-%L_ZZWX7D^sk7cC+kDyIrx`m02IT U_P4rXz02*mvwN4pI>G3_0dCd71poj5 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/8.ogg deleted file mode 100644 index 0f72a5810397e94253bbf6bf48d718c7b2691bbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2057 zcmY+F2{e@b9>+~XmSnBO#F()SN5hniUNe@Y?8MlObr_6&$UCEZD-&Z&QDbdVUi-dN zWTxzyNJuF}+_q6j$THnW_nv#bzjOZQ{J+ol^ZTCX|3Bw>ezruS1K&Qr|CU75xdXe~ z4vowgAZgo(7_yna4*>+y1F`YH5!+q-f3=H)0F{f4K!dQmIL?Pi76qPI`CJUpMIq5h zl(zORArCD7Fu!nue-sw*`~VMi8Zc3cAwj<3K;wUcjaUE&)Nb(ZOO=l_u1I=$6Qje! z$l(zIBmN!=Atkr@Nn>h*Y#$7 zu7B?Aqw2jpS&a;y7)lXwR1&IcMfmy{{ zTD{GSe^#1i+=+mbAiAb09aEOrvgfIYb6H&y_XAcGFG1Ls;EM+v&DiGc-@|LPGCjTc z)ClbDD;0Pq_eLb?RTYtyT|8c3=&6lwAv#em=x!J^{dFT0p&!%G$^J>Asi{0%Al<#6 zRG9Mht>>?N1wud9)%?@xfYKIpo!PLr=q7Gv#+%>s*H{PEBND#R`=<7MU}=#;T!l2V z%RtyXak}OWy<~!pt8N!b))Z^2lI73ywQZFXD}*J68-LK^vlw2B{yI;&wGidz`mN=2 zjzBz#rV48d!87F_%m+gtAG@AXVi9-fZ8;o<5e|;^=p)vmr?NM{r(q->Mle!?TtX5E zI0`bjx_Td733gtOd(5hDr&|3YzxrJV4yVFEJMvPzes+%$!7uX*986=AF#Wk0G?peNvg`|edP2O; zn-chf;rN+;|DOEdIA3>RnL6X7YJPQ~NHN+iJyGgrzu@e8OinfU`EBl+*Xbih>D75f z8g?h!bVev+)#B*Kc3k)2?J!lU&X!dnarZtMu1qV*JZhFc!dh6iOf8<^VjpjYpTx6* zD(xj?i|JA2fk^n>toCC);>zctsWf&v7m*%I&SDuj**M#?SkBhqdYX}5hy!-%)@B$~2HgO*6S#z+k46}nik!cJ#um?x-4GK;uz?!{c~WmSAEL zwtgPnChg>~wCaDj5CaGdl2qd(VGG4jKo954kozut$zBFia*g;O#+^JtFikNaw|iBH%hx`NG|GZ_?FK8pI)J#@!M&YBXU~6!Ibt3Lpa>h z*>461O%FQ*W-cIDzyshlCTmx4%%^yLJ+DlmUb)c-FqTNWHINkVpsiEZ`m=B2k zmPr&=qi=#PO5n7p${1<{#D7*M8}YIT|Kw(u`q8om^37a-`@T{x@FRh0Uyl39L6Fs9 zGts2fS4KXBtu2n%n~S_559)F8pDRqnJDw-w(d{QsRvoWrxSt>HZ8IMDN_R{ARjE!* zVCYb^ATB4yYx-KhtjfIhn^W-^?PS|TduNT3XmU{X3?UZ_#`~SesU7n5xn7Qq|I~w| z*a+TsXjP{cCTAM|iYkz5_=s@p;3b7aTTMP@TSl7=oCvc(t7ka!=a&ut>Z{6*xp*Ma zGO8AKReOwDqPkD;3?nIbokWvW1g{OkI94+^5F3K$ooX7_G0^4)#zYRrUaibr+I*T& zYHxteZ&!}n^a);cd>U{AvfS68!y0IR4{mBKy5m$Au^`jq5tWoMcgtueM7aZql$Q8J zStO%)%|fq{$RVvXGokA~_5>nbg&{(DpyKHM-8SQ9I{igY#qbBxoCt2{T`=#SX5xWB zyxGodn;wZKAub%*ht=Q{&p0-2dT^)JWk+y;(xbDq_@*6)c02Da|nxNd$;ph)2V<0;E4oWH3(Q4Gly&R!PKd)xxl-cCUE?`6v` cEbYk!)Sk}9$fdvK0(y`8C}VGDU;PT_-%YWz761SM diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/9.ogg deleted file mode 100644 index c1026671e1f64ae78516f03fa76788c36a6360a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1876 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 GP5cY8L}9`J diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/err_reg.ogg deleted file mode 100644 index 6d4752e4cd51365f07253d893a3b09248ff44ca8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7830 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 H(7=BHXw7UM diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/welcome.ogg deleted file mode 100644 index 7a0625e46d64c591e8bd876bdcb7283958c0f2d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2672 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 P&#^7Z=QCT9H}U@gzw-U@ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/cs-CZ/wificonfig.ogg deleted file mode 100644 index bc945a95ead3167d4969017f7c8d30bd5e08dc15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5169 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/0.ogg deleted file mode 100644 index b27207c0c40fedbf5f1fbb0a414fe767f6fdb9de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1986 zcmY+F2{hYT8^#e8O9Vk8*5u?S7K=;f}v{p{(N)3G4DC|ocrA8ckg-cz305Im9MWI6ARPd;o%KUJ)K4- z+IlhbTLp%Nn0jNqn3*-1J6z8Yt5f{{af&ko3h@xO&#ZTf+hcu0Ai&Chu;D%^6{H4I z<=VAVLL3<0c+UVY?_fQ^^8`EYr%6SbemdsUHc<8S z3A`5&h!6Akb+Izm!Vv{wTx%;t%j}^l7$RkCEWdkbks4{c$6o!Tl;gJW;|KjCHB$jj zDebS>i$5W_C!Phm(GB+k?vgGOae_bm2g zO$zOHQ8`=eMnjMQ_#L75onuEaOg4Ii-V3Cv0N%b?iTz&Whc3I^mwDlpd*WopC^*{O zCwP&fDRiyQYH#Q0?pj6d46SU-<%j{Y(@C!v%3N8VYJ5>?QTye)25+wU(qD3k$j!mV zbfiJ%vTuDW;)1K`Go8aD@SVJI98pTP(Y8zLoriUV@2qBI{{m(s4RbBk-cmS^71BL; zYg6>XAI;iMtn{A_oj=qR+d|VUIDXk6rog=tR=r}Dx>W8bg8eoc*Ze16_H_AsYCGd4 z=ueW>K6ScI54_TS8xRTl8;r4n}3+tMaHb*_jJnjbi9$zU+^J5;rv z^(F|+9>&SI^D^P{+;_}TQh0ZMiIK5~EKgZ)*jh;afo6zVx)PQ_X*Zt!8CB5zObq*C zWdUujaob(#&vibYUMaz?5>bQbvz&0sHpPTA@RZGoBKm}p(^ju%Qq6JhN89A zxq~?!K4tfe(BCGqD5YP9eLjQqK59QM6>ix@prU&$NEJqQNFMWB7?QWku2O;RI7h@A z);(B@>ve6)It=#}gfMW>%aqdh^jF%y4rd5SgA|U^dh4r%>i8YSVyS&i z#zzRH=HB>yE^<);b-HI>fQf;-b3MnJPrf`?{j-quu%@C6FVzemqAtA33$F!!PJtXK zC)$c8FN4-EF-ExF$L@-66enVq9Mn-q>vYK-b+*;p+rCW?OgZen_>EPra@6a7kz9~y zZt{C7(6V?xnIf5xXF|r;r>*MVAT)kVl-bUqy8Pgf;!z#a5-P%l4tLD1GZu40OOjA! z8JhFf$1K1PDm1R&)VkO0QYzKNGIt{OXKn6QzkNTQz_w7av+3FKZNHv?|CRH@{A%U< zny@#MX#EHlEpNa89;TLGSfZ9=W|-2s|O+hTMf z$*OA-V#q?AH3Tjwo^lwdoi3l&exLK}ym@M=>u&XQhG=4EqMt$eB~x_ET#TbQM*fR<{FDs=LroYg^c+{oo}X;WTy{8H7_g3eEvC=uvf zvUA+F_{a}(chysB1!wPqGL8{4ig%GtbN8X{L*@@XQ0XWi zNONCEp)-lQ`=c_ArQr#e8(A@d_5qtSe*`HBO-72aBK;I`L_U5_zYrQ%kg|h~@PtvW ze4*JkM;t?I6o0bT+YePHDe?-A>`!yt>lYRaHSL2Vw&bn&VZyJ^8V9TO&RO3$YaAe8 z>YfA{zo4QF1dhlJ`MV|;jUQy+s5ujrO_rg8u?yf1|NXFXgh}53>_j`p2dvG`pM(Sb zyM+Ivp7AjT&MTn2pJNME=;vHO_5Q<_+t3Hjvw%M5)(0`psn&GHzgR$@b9?H}=K!eQ F{{jn#pmP8K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/1.ogg deleted file mode 100644 index 5fd2fce7b5d7445959642462863bd88dad0a7b46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1916 zcmZ{lcQ_l`8^=YAm^D(PVuZAcYZF!1EQ+>vY_Y4FiY+!3d(~F7b*+nA^P*;q*qd5y zV$~?Mu4rkE@{8Nw^ZW1jeV%jPbI$kkzR&xde_jJuR}%_KivJ2JXc2jJT)9!F3t%_! z^z+eiac~9z?f|-M|3wV0@c-!w2as>^$zVx<@)d6C;OfIjetGEN{}?VUp&%hGC3Qvc zl9vnG$-~*jTbb-Rkv(ZevMDX_%+1k*ocOD-S|^z!>#FcoQ(}gBcvdBOc^$O1rIXKN zTSpAW_<;@z3ua^3UUS-zKg{u=p7P3L&(9EFbcE7*bAI=$6lESW7mAHfCR|6CfQn%y zx!kN8(#rwuW8raZJ}4|ZGpNWTMAPcpc%jpJHGO5*vBo6+kXU?lqQt##lQ6< zOx_Ti+=vlee}E7f&NjN8D;}|7&_0&-Mo&d?qGi`Asyh{h6^2DewvUtviZE`fJ#tT< zz5Sti!6JUuJqr~a$gr68F=9BoQ`g+<;4w}&TYYSM0$t&oGzA73)AIwO$|bar+I9n( z=QUQ^cP2N?ws3cK!a&kX)UOYWs~62@2f$kAutwnu`0^aRgKoYJ3d_rbQ@GXBUBi~g za(}Dy`M0;7Mu#pOM8rx(Kn*oA8wa6czz>EJxoi2SjSp6z{4MIGOt3#{vUxm9wpiX( zC+T&luT}TgN&qJ3U@}}dc*UZtqr4TE0fps(;2^KZUa2rFw-|#_`qzJ>BoY8x9UC|L zW~41}P?5KynYs!>@%Y?cLEFnv%v9Zlq}@X7MxgjFFB5b34aY(NOmftrs1_TwSzz;& z!H#Ok4Ta_B!$E+TC8wZCtEs0(LLQx?z4KoW41-Hx=b%Yo!x;((6_cZU!7SBCm#7|D zXA7^|A(SCm5!4~KSYY;D8Emd$E*;}NpAOy7`Ai}vN<)gLy-lk7#8o)F6@`Tg zKyqpPH(;! zN4u`ehQdO4TS}3S^a!#CB`2k^EXk_az}edz6=5@~Tc7wowZtwV{1Mjvh!jMzXH{dW z?a(oV8(ySssva>P((K{gusif&B#;^a3=<>T#BwmE`JaHjs-avO*@w?(|FcLoyFiNow8z&oo{qczT9cq+444YvO?`t8QrRam|z7 z8L{sydvb|@947{N$L?JsmYXx$eTn&Z*-8_`vi5vecTocH0)+L$u!SbgAXHUOSEztPiK|qxPyqX%n1_6*9r)f&p zXtm`eL1YoJ9Gu7n2$Mz}7l~t{(FT^3q{;lAH;PXYxpaL8);fWi_@1>1Qhm|E+SP)Qi(PdeCEzC6R@`8vJrVQ;bpJb{`A)>UEeZhJJJFTD alxg>BX|vDQ%PH~x0+$zL9C)?=|M(xK^?vUF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/2.ogg deleted file mode 100644 index f3be2ac22eb7e4becffe1a1a038b355cbc2414cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2185 zcmY+F2{_bSAIA+YW=z8v`#OxF#x{yDV;Yl6sbni;Yev>##?mNj7};)i#;Bww2`|~M zz0pKuM4@bv<=QSvDAJ9$cij6v_v-gN=Q-#5|9;NzoacX@bAIQ%z3uq;`TifLT71d7 z!#ovOFaUNgkQQ>%lXw{bFa~g3|3c2~;{U`h4&bT&)GQeQZWp&FdWV2{U(OIiy$LC9XZTkb_F0hWVv@ilvMA@N*W1u5&qwMC9DvCw z>uo(aszD(-O1D`n)*bjj446zVK8*wCK3V%nb7B)7k?Hd4z=bJi zQ9GWn#P*r{F@IN{y}yFQh1y>qs=6=SXGo?a5lnlM8$kg;=~MTrSuN95(-91X-y~#quZe3!KN3ty2%tGEDi9Rj%0DPe#n+0DG6@Cy z#g^hZsi7Qh@zC$B&Jq0f>0PAhbi|C#2snvMha;Y3SNqN|bB;M*zc>|rDHAM`H)1EI*_2#?H@#~e~cs?UH&!uEC7t~z#L(JzgO9piE43r_S|~S zRZ!Z_ut<7dr_I6BwqmtSWandPUKuCVl1x|CXmNQ{ESGl+p}u|AG(?vTk2ew?ujm-L z5d)hI%8%`esc7~?VFUa&8_H&NFESu`>XCYZhn;4V+$=u6o((TOT`!aQ?Rbo z#&9Kzij6A>bTLppV+B4{r@=v34P$W8F0Cu$;l$nF*XTXqv+;#QiY;j*B>2f5?6LA_ zh2NSK*TO_ilw6r^CWSKn4%heYXW`peUT0q|R=!yHc!+N%=N-z`CG%5Ou~C9_tEVf* zu3qJ);etGJQ}Tpg`eoasTj2~rOT4_E`X(;^Xw{Ov1hBDhnM_wh*1wCPZ9W^d9LBs4 zC(Spcp`+N|4o>u(_t53Bab;@@N@v|LHk=wUxL`1Q6C3fhB+`12&gqVN@RrJTnYWeJ zVo$+?0x)$7?Mm|HtKa`%irt=CZkqESI6rdxKc>(N{4~%>fqF7sMXgSLgY(_X0Zl7iyi-%H zQDVm7IizfnM3bfxS%U{4KYY>WImvsk0{Yru(+8v-X|pQCT?m)aM_J4zg7&?p40<$f z;EM#YsL{r;U`dJbS(_@t#G8AOhuoEABpHh~3D-6v%)bQ}9admrrHI_j-(2554;Fd9v87};jED%{Dg9DcN8RdxO9@us~W=3Fh^=?gv_RAUWE-=z^X=0rZvrVQ}nc>vW>>f)<4aq zeR_jfeV-L6Wz2i3G?CSv=UpG-W%*bq##CM+uV6~2Z5#_8X`j#Xn3{erKJOA&<=5sJ zkWs}aesuArj)tB<)XSJHo7K+!|J{Cq0Z&rs?SrgR)2#?uclcIiMPiFl=VKg=e|3Ow z$iqt#oyM|qPt1+8r)7S4aWypGQYN}QxtDjv;U?}A$D7e}I_0K?2bbSEYv2b6$=hlQ z#g|0PX8x$z2t|!<9=?;(R&cvqhUJKo?c+Nhx{hP?MN?w=S9%2E^5H9?*Ay3{#Ci&C zpSfOXn^eB!CHn>ffmn3vlIaS{vf+-b+lbm0IS~jW&mb}a6QHg4zLx}Je%q1sNl7@u z_;Yfm@qkhsDlel1a6t%cG-Mt|HMFIwOK8hMC3KD_Y5jI@i3V}&#cCCqZ@V0-B-3SK z5bo>H0c!J!i3TO`wPumaeBsqVD#}oCpZpDR(E(q4S=~`!mEC={^%5&l+$+-2(iU47 za@0a4zp6|*<*y1Pm?p4WuKun-0=)i{WvP#_vH3x5UhrOj2@v(YCbZO^Z=flrdi-TH zC@ihw#zH=`WVj%oOIiV zngR&-6?NFF@*`!@{+C$nVsU~(Y}%3X4jCU|j!i#>`wc-8*L;j zSrCzAkGrYqo~J&mD}v;gtZV#H!rZVft^4_ tf3;^X%hP+@Qk&I1GkNN#ytP4lU3TW)Re0(r_C@txm#6lu(%-+{^FNU^<1+vN diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/3.ogg deleted file mode 100644 index 3ad6f1093d64ba5967e4953e230af293d404083b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2178 zcmY*a2{hDQ8#l;qG{#bv8WAeXj5JhCGl(o9OXDqJjI9}Fl+tI7#xjl z>pXuD)GqLH&E&O{1SMwII5F}U};!3y@Y?MO~ok2-%MpcL#WA1zo7 zbvhZy$gAxS408~@cFiM3ZTU8W|H#c$&8gh!hD9PpV!KEw9pozo_LZQ0f&*v1ce>bm z#a`t}^F>IqNaOQHPlFrCw}+d&z31Dll)extsv1!uFKmi&9Uo~qc9E1T_7>S?~V#p7Fti z*srcy9YhlzwWwrZ8mvEc$YY% z$F}pX7J`%F3{6*9<4Ym$*!A;i2U@%jRLEAqdE;SldwQ3g+fV|LkBOvah2g3;qA9AQ z%M;TRAywvbSd#jGA*FR|f2T+J`VlBxB1L^~mg~7!2D9JsiN1Y?)#`OuX;?!?X&@O4*~{a;g63vf z2Cy%2#YjGLRtMz0bREdO$;`?x0kN}}ZTI~=nsF#?N7z&l&=)L|*Hb^(qZv+#mi*2O zm7?UBrsS6uNiq|)_w3V39!L7XhBIfBJhP9G&sB`ny19Qln0v9U%$!BjZ6*!(nn!=Y ze&eL0*{7`@Xzu^?h_vEXSKe89RTpsE)BQo9Y zfC-9p=sU*osO&4+s{-@5NcCCE;?76YsneP{DG_3r=gf3QQBd4*q0WmFeeyaVF2-cz zpJy#wei~cq+x=+KOD@9>oBNeMY3TQ$VNg=(VY7{-RZ6|cn8oQ0RmWgL6FTAI1kj!u zNBjiT@TBl^vbfvNSP9F%GiJH*25^rtz8J?A==2lR8%RIrUakAkTH#Y#*D7S8is+PV7pjaP7e|u(3ZU*lc5s>=F@aRG4!Y-gYEnCtqzqhP)K!9W9@f zca+aFmngsqrF087^{86oAHOedZrENUn2_JAjQNq2H`wSo7n*TjnPVLtLrsgT8@tLq zn>|?EZYfg5KXY<|%(yETf13ePe44<~FcIqYoRp2)QK7rSU)$NOV0O7?-nv}S#BgYF z4bkbuPoyX+aa2YvpusZ`&Tvz~(7<&YXv`!UjX_aR$gH|=UJ9SlOR6Q=E$ugs6_4b{ zgBlJfewOa@C&bq+8R>iJVYMLcm{0<%!v3L{cf{QMiklDpf)RVI=HTY%t8=C29jcCT zj8l+G-0;y}A=6Jgo9!5^7&5+jIBFzG09oEyr+_6EVAns=#P9i+F}J}R*H`WaFUyK4 zu9hU1C;I+X6OeeK#z(>#G5fGEV>Xp@?TvCqLUj<@8f0UpvnyEyRa!|oY)z!>RjHK~9dkU#;<2Kmy35hIVYI0Nv-;V>=Yb;swfaUWlyS}_av0g+2;zs5erGuWu&Um<_1dQdLll;((k#Q z`89h4uM2Drs()vX0I+upxuAtnaFiAhKnRqPdhM;PE>G##NuouB#)=18Ng_tY1~&={Nnm{kA_XEPhJDpGwUfR6R)5-u(MnIT z6d}%iRML$*A=D==7dHnH?g(k`IQ4=akmNB=r0fCNY-Ito#kW3X fp=+xzfVZ%16 zo7mXWt)~|ta!ygPWZRH{Ua>G1iDIBnqnjSU)te z%-F!(z}U!WgMbTGNJLO%a7Z*x-~|ahV~oHwRu3lyMhX)DUHCw|fD^<<;f+g~jgMkv zEcTI3hDS${VnU*U)2D*{YyePET5|qKZmjB}r1YXm>$x&(zh00e%wR$bIxXhAffj%* zrs{g!r4E`tF0)!Oo?|h~R(op42*7s&psY0Xf_@Q8A-m-v{yx&ZI^tJ80eZ1gG=r>y zMQ)3tHt}FPpy>r;+R1M<$8tEafqbFC7CP?MF91|RLiq@+@qj#D@n#&S$M7GAbjc}e z(q_rLWVE&Cn@I)Qry+yBM*kq!Z>~WHX|)VOo-B#ZN6ex@7`iJ^xD-eVFK;=XDw0ie20;T&h2U7k_>lm8;wvF9SXHVQwS*(zmeVx5jAN*!ze@&M+wKQ^AeK!DVB8p)M*#)zGVP6g+^{ANMqmQ)L zTe^*N=M*S~@e*^XF0!~H>I_aPUQ5`~6-bSeTfQ2svfN-IcY12tYR_G_npG@3AmK`z zei7sJkB5-!4-#KTSY`*g|1+Yajo%fF)CQgFW`7-#_6I<1t-`%arg`qXkJs!?@3A{) z%Q`OgPx_LMAYmREL_@e*{q>$FkLd*e)>^_U+c+)He!|w)D6IDx`t!Ule_2Jg^r%g$ zh%9kCz5aIcqAAQY_1WXMO)P*ZVi$i+me}Eq?o^NOtwk6d5TR&ULjPq<&X0ddZCQKfW$o7Dk8 zH61Rs#N!H5T$XuSEfVTV8Fvt|cZ!z5Wf?p{`*Y!u-0J+^%I7}SAtQejG~`D>RRLRC zb&1X_Yj9+;Al$=Pd1XSesTJ)X?6SwrWBzmNYLUe4lpKGqvJ&;!zLJK1E2Nmo(O>{X zYI2#VF#KI-OP18+Ld1^!kZZXv@GK3s=A|m9Qn!)t&q*KJ;5sM@w;z!K(JHE=P1n7b zBh*sf>kNiKtGu~qNEFN+HNG!w3%9UH+^EQOUAs%^?1L$(WjZr{C#BR!X6fmQolW!Y zzbd|(mJqtr0T8ai4L>3|Yg1b}=ygKF!jR+jz1*#%OMRbId0nu9J_0PxHJY`&% z;c$ZQ${|LZMbejB(YPTa*r9U{@+2;AlJr6-EqTUGv}ae7oSB|NlKiqJZW7c3T^+?& zhL7U}FQ~1}Ju_-MzUGrvyePIKCMvTp#ZSJVQc923rFGDvo_H8?Ki?pS%eZ63T_O8a z&y9|~EW`%d;VYEH*4tX_(69>*nNv5EOeJw#of7=`$IrQHI~`kI*hn7EBbJTKME=;W zFQz)o5fA==>)#3}>IphPlZ$ZKsc)-ipRmG@_Lu(L=6#RB*0go> zu@B^*gyE>>VCz|i9ZJ6(#%>W#GG@XolSC)c=$<`OyaS(RSOBP{-V8>33Go=~@3c<$B^U^C5@|Aq`=*ej zS92k|#N)9<|MsbiCjxEy3KRo<2QSjn;HWn94_8;KE3%-OozwR$X_d|Uy->gaUJYDi zsi-q?EV*B5s->_qPv<;;?&-4Ob)(EhpW&-y1)pCP2Vv;X_n+N0|AC;J_bAFQeZ9w> zVPe(1pjoZxa?TzDD8!#Uw`5bLZ6F=w6i_I%Fy% z=b8S6f|Nu|HNSnDn4dNzUv}TwkG_6sC}GWzE`L{b?5+BEq41*8ZXXUDb?;?dSrpkb zmp$rT-8JfTvi8!q2ekmWT}l33X5p>FpJ;N*dYHF@JBmVcn3qeEX(Km zQ0w6K=0nVNK$Mk4l~R3A-YIXVUv)W?@vfjOIY?vi_aqZNy7qgJ{hnkZf-PS1wVoIb zB?thNSJ-Bq&s!<}Mzd<-Tz76(rsTyFUrG8ErM-wdMUa{w7h`ziVL2j?387oHeeDo7 zH@y%J3g{C?^|646L@$-s>(NmztCjQ&i~c*6v4*wS%nI}-woo2x@xM%gLT_f7CYxQR Z33^jzjT`#^>I(EGw;=|-sjfhw{{=S*&eZ?_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/5.ogg deleted file mode 100644 index 29559fd62bda3da558bd3ba5cec9c6e431abda35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1974 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 tG~dD2hl+Q&fZCDyfGFH=L~=n{t0k}R*?Vz diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/7.ogg deleted file mode 100644 index 28ecaca437145903460cd9353dda68b976aefaa1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2125 zcmY+F3pmq#8^(SUAa(ob~M+%AM%)?aDWAjY!d%dsszOMgu{l5S2=f1D||Ns4d*Nu*d@DY;``%jQI zxX-qhf9Xqvh^wIE&n3Bq1!Kg;t;D%!ej?~C{J*hV{TBA=l5w0Bsix@PqmVXLtccGT|DZw z-WsmXz45saB`2jNUHyT4-*>gwUSp(Yw0?XFN%*|P3`d|=(TdirqzGp2+FF`^u`!u?vRZ9cqV5? z(3ec?ml4;DKZxz~3tTA)SygWz!UT2EBQw+ls>NnORGuRaW6Z09O+UKjar4hVk{{}> zIA7YA48{?lV8Z%@up9cVB26LjF;|XL*bZ?-E7x7ED`9rh#mvVN8^t+u ze0vUW{I0sZy3KdywZ=h6ivvB zr0LpBhQ=pg$psnK8#sct9t{DtDADw6=NWtPN}JJb~1pb80Ra;1W;weq`&(jU_Or|hV!zg0+GN1^)-I>Kn_C&t|9o%8p! zKXghZ)qV*0s^uJGYmX!7>r+=7j{uSkk%f0)SZ=(qvwFs3t-kxMHUzv&5kp7P_96zq zv#1@NL}JCxG^T`mNGYPL;qVgTI6mWdG0+tsP4(b4dw0+x z;2$p-7>#GXH17uBEv{6WBo0nrHgOUCLm<0!P>WP&)B<2n8a>k-t9FESe)|~IB3pkz zT}}*Zz)mfCk~vH=7Hd6{60?9lvJvwvIBA6E=FWA^yZMHVLuJxOYIGR)%9!TahG8x{ zB^*rY-6qurNguDCeow#=Gw!l(QLp|H`ThHv# zPaD2v=HAm&XAUjIciaMQz#Y2N3>$>tX`(k9UB3xuBsd6oPUf#)M^l{sI{2u47Yul% z*L&@erc*%07|gnFYlqls3+1KVWL!_aOC##7c3xn(+rtj`=%w}@ON<`92D7szvIZy#(ZALD;r1U0MIl=)Rrrn2L8q#Ba~IN1 zeqtk!C9qX@P1}-73)UKH^syl71KFv0HIL!hSldc$1M(j1?=VLF7k0qzSbKf1WLV7O ziRD}QQnsOf0{;c00x~?&MG*iO!+2vf=w&zpM3)UYWC$EehbP(%ycz<$Tz@Bq4?sc;XXE*1h6tz+J zY6w+wJceW#%$al76mMfb^XBj)?&P}nF8QoQ|29#Mc5;q>T^Dg6n&Yt-N}lywc4;{ zt0JJ?QoyG+OEPW-Y?HU6;OuOt8SRm8ZUd@z`t>jx8Et$jc}`CYRSS`bVs&Fc;wDkHHT zX|Y*Ct15K#^ikqj4PRHtlpajr6`yT%y9?R-lp##+YRj}%I0$%;Ahk+xGAPdCOtYiP zUlyu10Bt`ZAjp6>p`Tp Ku}y{io__!@*Xn-& diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/8.ogg deleted file mode 100644 index 2d718511d102f9c020bb5ecb069ab00f483ff666..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1519 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 K_SVk%fAKF8(lQ|c diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/activation.ogg deleted file mode 100644 index 58b9b4399d96ceeee2c2949a81fad7d4b147ab8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11373 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 H&nN#6m~*5^ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/err_pin.ogg deleted file mode 100644 index 391d984fe82a12cae0bda19d38da864baf4ea572..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3600 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
  • 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/language.json deleted file mode 100644 index 918598b4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "da-DK" - }, - "strings": { - "WARNING": "Advarsel", - "INFO": "Information", - "ERROR": "Fejl", - "VERSION": "Version ", - "LOADING_PROTOCOL": "Logger ind...", - "INITIALIZING": "Initialiserer...", - "PIN_ERROR": "Indsæt venligst SIM-kort", - "REG_ERROR": "Kan ikke få adgang til netværket, tjek venligst SIM-kortets status", - "DETECTING_MODULE": "Detekterer modul...", - "REGISTERING_NETWORK": "Venter på netværk...", - "CHECKING_NEW_VERSION": "Tjekker for ny version...", - "CHECK_NEW_VERSION_FAILED": "Tjek for ny version mislykkedes, prøver igen om %d sekunder: %s", - "SWITCH_TO_WIFI_NETWORK": "Skifter til Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Skifter til 4G...", - "STANDBY": "Standby", - "CONNECT_TO": "Forbind til ", - "CONNECTING": "Forbinder...", - "CONNECTION_SUCCESSFUL": "Forbindelse lykkedes", - "CONNECTED_TO": "Forbundet til ", - "LISTENING": "Lytter...", - "SPEAKING": "Taler...", - "SERVER_NOT_FOUND": "Søger efter tilgængelig tjeneste", - "SERVER_NOT_CONNECTED": "Kan ikke forbinde til tjeneste, prøv venligst igen senere", - "SERVER_TIMEOUT": "Timeout ved venten på svar", - "SERVER_ERROR": "Afsendelse mislykkedes, tjek venligst netværket", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Konfigurations-URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi-konfigurationstilstand", - "ENTERING_WIFI_CONFIG_MODE": "Går ind i Wi-Fi-konfigurationstilstand...", - "SCANNING_WIFI": "Scanner Wi-Fi...", - "NEW_VERSION": "Ny version ", - "OTA_UPGRADE": "OTA-opgradering", - "UPGRADING": "Systemet opgraderes...", - "UPGRADE_FAILED": "Opgradering mislykkedes", - "ACTIVATION": "Aktivering", - "BATTERY_LOW": "Lavt batteri", - "BATTERY_CHARGING": "Oplader", - "BATTERY_FULL": "Batteriet er fuldt", - "BATTERY_NEED_CHARGE": "Lavt batteri, oplad venligst", - "VOLUME": "Lydstyrke ", - "MUTED": "Lydløs", - "MAX_VOLUME": "Maksimal lydstyrke", - "RTC_MODE_OFF": "AEC slukket", - "RTC_MODE_ON": "AEC tændt", - "PLEASE_WAIT": "Vent venligst...", - "FOUND_NEW_ASSETS": "Fandt nye ressourcer: %s", - "DOWNLOAD_ASSETS_FAILED": "Download af ressourcer mislykkedes", - "LOADING_ASSETS": "Indlæser ressourcer...", - "HELLO_MY_FRIEND": "Hej, min ven!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/upgrade.ogg deleted file mode 100644 index b3e1c290fb6f70915b42019b124c1b85808a29d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3074 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 M)R`(RDO-d81`1lwr2qf` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/da-DK/welcome.ogg deleted file mode 100644 index f211cc429d336aa99d4926a8e1da8fabfb3b7c38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2849 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/2.ogg deleted file mode 100644 index fb09b608adbafc991573c6a46c8583b7d2d5612c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2010 zcmY*adpy(o8y{<}&8%uh;kW`n*5y_vigQ&mZ6CIUW?`1`&t+6R^Z4 zNzpN2LE1(Pbv*K143SI<5EC;Kdwlwb>Ku zjzorrL{Y-e#{&MuLl$NLbtg(<&W_)R{n*ig!Z1V6!#n5V#yn0TXl-VVf0gT*^mJ5| zK*p0z62U9B26GbfFl_&NQ9;}k5}=~wk@5GaPQCUfyR(h)OBC-%->F-W@okBDm1qpi zEJZD8@`=Z{=|AlbNh0H0JR2$$TQ16&r6&xZcqY-6Yenz{)9;kHKCG1HPocfN;K~(iZDv3)o+(kIKmRT0XSG#+3Qxk-piBRJML z_uxJ+%&h!&8P3t^*#2duMZT;jziHH%*7EnKz=g@0(A$MoVTC^VulKdy8d{L|)?SyS z#AS}^NIn&g0aP`0x-07#Zhj^_i3D{W=ATR#oFb`^Ryv2{A#|ehd)zmMjn_d#h%nW& zd|IXEi?7l%KWOjcMY+!C%bXrrL6h=62Jzc`b5dpScnu`%<`ykYR@ik%pE`%FX{zKR ztd7IksNsQ0CO}o)!x-ee&%vRCbP|2)uMZQR5!NbA&7)`a`MQcTw=H`ZWypq`xu?Y} za$0hch#q7{i?+rUZ2H|sE&F$8PEO-jYET#A7}xs9YHZp4dwp*FJf2f_WwaL)^Yy)1 zR1vXkgDE zFjq)WxkPz`5Iz_|?QKgPzF-bewY6K>rzOc0K9UcVc1lFvga`^fgi!+7TgNzF{yH#b z2P1!v?bnYA+{%WuGlzvb=(b<6za!A4YHpdrc;h27Np_L3y6)R7-amqkeb02@{((sh zg-=$V)Y810gxd?P`^GP-GGC@aLZf8^0IIq+x2L!wWX6pbH8@t&5>X*|G(Ip<*U$8t zvb|7X8BCay=8Mvzs5dUtZ|QC0lNr}#+kx~|mS%!Qx^3Pl z&^K^-c6~&}t+o$vX%F5Q;nGf03bfCi+wq|@WwdJd+7>bPJ=F0-sRtL*d@(Um8{Pi* zgIPFjuKM0XbB+}Stefr`!ShDha~Dh1EtR`mU#+c%tXX9FEZe-y2*zNpFtLLm$o8tr~4c(}P{_)@~#nTTFlI!KTR8sMD}_GwQCU zyu$A;Do(YZG5X9%>mV^2$GkEEubp)nv{&^q17^0IYKvbVXkym{a80i-AGi{$ zLEvAfdR3X0`qGBNMzfas*`Jy&J#U;V3jd^M?p7aHQsVrI47-+G3p-pR6qHm22b^}Y zYULtY8*UfdQoQ*@^^yDda4f;NfbV-}D1Mr`jz>Osr6)=kJQC1ttKW{lWQqe+v;uUZ z_%rdq(q$>e!WK`-m?{~R(HU0Z-sRyBQs$t4>C_!p(9<1&@ z-Q8jEg-J)COGfiU8NEeiMtCNb%s{y5oF5sO8u|fe6wdhM)ClvEDGt-d&(-ph*nzKUaNF8lGB?5&Sbpc zdXm+dUMPT zGb{9_IWWKbRM4TY%wcX$lWR3-3d~VQ$Ht4zJ$Jb8Io~sOwP<%2D0`Y|moctugY|8%^n{tR6F^*O*L;N@8G0ACEBlSvT zat^^8iSR)n_wCzM*r^BpY$^$dr}(S6R5gd(uO^YO%=8qJI`OZ2p+C8X@e^ex#cl5!hyFD4#jl{wMoHe9eld)FbQ&Vxs;+@JoG;mODHJ zQ8Q@;CfaFpWz{${xc;q-u+MnR!JzN(qumf!oNS$Wj0jj+8eGl5h;*EOYuu}s@A;OC zr$E>T%$T}{=Q6_fxCc_Frj@gl+mdC~d2UdteaE>88r&zjmO@lyrso8=ufPeMk!%FV zEQ1KRxO_uKd&EsF`Rsn&Ja)8VM-op310|`Bx6G$q3sCEdAM<&GG0h=-`hrCTxBRDv z%j35%|FiLtbChDZDO7T$Z!Tcoh9Zr(zs~3TzpHr+vN!xC5m0GwDk``6^S~&}#w28f+-0?d1$HSAT%@$aO9@l&g}J zgo&AP!43E!7oP9$DoBkom^`uaAu$}Syf4~$>1#4FkrK@ZcDR1O z5ea5q$onuDH6x$H$jC`;w%8z6^(~+;GvDMGuOhzz2W0lCA+2AO#sNyo*5S2zrP0S zy?k(vq7)d0={b)Qx=ejt`?KY*&fmJHx|)$X;l1vk*X8NlrUy{+>=0 z_>m_~zfk3|x{^84{pgRqjnCS<$E&(GjH%XXQXbThT$a*G!y0g6sjFGCm-x?*tmfaZ zn?C(rEXgU=Tu<<75qo!ZS3=+-V`_Ef(0b~n-u@7C-JV}P;-0&^@;?v(m}B>juSzTS zt~@^pPkN8kgWgW?%6`Ve*c9kUD}`@#r9N&X2{Kg+!-4vF|4+0)8IbF1v^J57- z?sy}R=0jA5jUT`(VfL}Yhn_A;FvToY0bLr^E@3p`x4HFq{o{f9Yz~gs_QdSIyz)nW zOV8QEGt(msszScqFn}35;l-wv52}QR#UkG^WY03;r#kwUyN?PDI_EAfoD9jg&S=G4 zKXK1%fHKxBn;-VkTFachmL71A_sElW-I|tXrnFzPH=O-y;RO+}-RkhDF_iY(?9v9D zVorCzv#-zP$AJ-mpO94 z;0#r{uhfGO!6SLrnbUqL^b?E`0aHtTc9qG@d0g9ro29aeqNf7=GJ^O(@ml%(V2xH` z_r||VQ>LW)bYYV1rMAeGtLg7(&$_&i69E%rJtne+70?kN<~=bcJu!uf^F-pffktzO zZ=S0}(1Byez&&HRcNp!Wk_l`DQAd+ki2g>Gm70iarV?pt>yawS-&!@&$ZW%^B%kbk yOWEircmHJXI_l{$gDSMP+RrtbwqZ5f+|O2MlvShuYua0($*Pe?)5o0($$tQKkTjbB diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/4.ogg deleted file mode 100644 index 46db0ce511ee70aeb66e2dfe33c3b232e1e99cbd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1868 zcmY+F3pCVeAIDAOHU?v4jd33{>{eDLB2jLUtn#{~810zMxc%LSP)Ppntz0He?y;y5 zBA3cc7^fIwjY~zex$cY6n@d(2YX5rQ^RE4!^PKa1pYP}QJJ0hw=Q%$|UtbrIJtF@L zq3Ns8oo$bv>;>3f$IwW+9gRYT!H&Q>E__2Ackutm4i1A9uJfm4*s&elmEud6hE5zP zmwb$fdd7N0ef=Fm4O+Bd?+_|2{21hULmtrtGKrdj{ue`_#QzqyXool`b_(xY3jf5@ zA8la^1o{OBhJ-}<1>0E}n;ir|MS0}ntYw`;*D_7nt$dJVYJqra_Q0QxaHFEfQu1}% zltNz4Sw9B?5)q7c-54La(a$fAzEjk{8RzKl)CJ{Z5Hm4xG3K-V``y_UW;$6n$VQ^` zpIVUQ>V}_Ng0IoWwNc2)kB-)*A8s%VnvoIy=gK|by*(Ow=eZJKp*!74HRJg&H zTS8<)>!fNw_m|6C=Df;0xjIR3Yzv58%7fvG%WRvu6+KdkIe3j3qC>B1=TTNCzzPk0zJh`1!*NoHfkU3r!Im#o`Ozb337r6_ zjf1%GAgMJ(yr9tcZmo!9wm3(Vk3y!Ov65$*(!j3v^0AZA*wKut!X`}^LhO|3EjB;c6+ zYVGcHJ?~AtAp9~@{9{sipBLdwYVJ``Wp7q}wRDjWXW+Ivub6C=v2S+UdDP0?i--5J z?mBOakZHC?)nsiAV_Fdh^F!R2Ii<;na$E3k2f zUZu|7E;r45MiZyJ1V0v@$*6io1o zGuL8I*+Gre-f!Qv@QGUj45{)HBNvHf$)O^ z-&PgOCI+|=@}%M|Jyi#|);(~%h-dKvdrg=gxj;t*`k44$9c)R99ke>0W7rtXPS5>$ z^e~Q3SrJpNJTMNxTjOr8TZmY;%t$Q7U70vVzrYIH=PtKc`ZNbyxo;{o`WZuoa*{&FhyC7j|wZ&fvi>+i(~3N8Y0YQ+8coRui__tK)V!D){YsAVD?=V*E&FMW=# zCO(f{@irPhluV7`QMj8a?_?}HDu#lu?lkp@cxR67R%OvxX4ETAR8gc!)xXW1JocUC zoP?E+gXVZFzdggJ%7))HG=*+U96kOg`|HNMnL@f&MPcar9oo%`LuYdv+XGj1@M*PT z@FWqXfNbvD(TG{;l%e3?V#m5{-WWn(O`DKi9jc*6=>19a^F?XflHc(`n685BDS8h_ zPD;*sE?@n$m9+61eWdJljcn~+!5K-LNdpz`59x835|hUDZmiw(h*R%yb+6r0tbW#h zw(Lw}_b;lXdv%0IN9HX(m1urLA1zFe(rImk`eT3>L zNZVxcI$v~+yw&nY81rw8t0XT0Em*6=!qFLku$;{Gkraho#+5bUeCFXa(R5h;4<%T zm9eti_iaLm9-sI&AihlqIJD)JOCaI8y1D@TAM~!=JoIwk-yWoRyV+9W>MoY$w7QFh T)IZq9u-z`Cc4a=zS?>D_0n=CV diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/5.ogg deleted file mode 100644 index 3ceee0fa189854db6acf6dc941ac80906be66787..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1979 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/7.ogg deleted file mode 100644 index 3b6957d6bc2964956f8708d9b47025cba74c336d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2139 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/8.ogg deleted file mode 100644 index 421f0187cad892633fd11ab3c945837ea05cbf10..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1751 zcmZ9Ndpy(oAIA;J+^3k>ObxSSZbK#^hvqsdmzisGS!bEKbwpOjw<(l^nad%HlbA~p zrOY*#aoj58lGLbE38xc|DRZXt`~Cj-y+4o7OIxQrQ>VMkhxPdek*aMMWbk@M9$baTq4vk(I6>rYb)&Zx5c|RZHL|siv z!(``5wrYS`c@UZf-QAw_5~ehJ4od8RQvp>K8CpO*^VX``%Q&!9<@qZKCmeow23CpJ#hcS6Dlr=*Iv~@43j>XdL zV}65W%xDXeOG$V|&34~OT$hY|wvZCdb9r9c{3^x&v&Q>Zi|yfKxhRb+Jd+Zc-U#B< z1CAklEh`L@qG?Wu(F|?HXG(&2_IaJre8#~2lEWU+UpAVw%l2)zUHj5_><$r;)&1)7 zA{E%L!!5c3X}tt{V>ngnXQ1y>xFoX~Z+JVPl!BKX!WwB-dU9hoPuUs$E}UMnD9*Ku#l7sz>OsEFypFyzesUylind5t?(ILWZrGQ^ z2c|gobm|u^(S;~3{bN}JpK3a_H!+pNlfurur7a5L+#mUaV=DOOH1O(|%!-7ltbF>934}Ro-=V1H z+Z@aQZGht#gJvywW}z3%qFwdQmrv*fRkw3aF6>0sL;vm)YfuzyZr8H5c5gO zV21~pjjc&BM0P6~gsLB;)!g*Vz5SkD9qw0RRc5`lB&AYTJsd*?5b(>rtQ0rD$3KV< zOHb5^tG+wJU~v51Km*F@ZLNQ;>RJYEDK7Et3x+Ajs%Jg~8&#UQ3yoep;0cFd2Z%;l zv8YtR-RRlXQCBg$`W2E1=6p+)-LK8#Iq3__@~x^=0EM~~QAYAjqCWDTyy=2NwW_?K zESUHFoz~-;W>opY#$;rB6D?M}{g_$&!mj_570@PAyOmJfg_=hQzSUwpjHD5tJFk)i zhVlV*PU`L<`S3#^T^!=^*+l`_My%EDTq(i0pJ7{y^3Xf!YQB*P=Wd82HlgP1M zTStoyjlmm`rX367P)E;>0$8SP(i58%j$Y%{c{z5C4I;?kKA*StNukfOd+^?CC>m0< zu}NN3n8Vx{D*+>IbIHWc)N@&v;ek(UonKqfxcL(jx1{*S&P3Iix||X!06zezRZq<~ z6-Bgw{M+k8`=s!zDVr4%y1P~l(TE>(0%?e2;kq8*(joD+a&w;*+G zT1@S>9Ju9fMuKaL$aR73?}d(hdk}@)Tq@Jd%N% z!6rDxt7f^MkIVpI#Yh-*vG7lCxyleMrE0W%NGWk?gJz*H8u)G=<$$kl+*L#AKIU@2 mKzv4GTevg6HwMY0FTeMN?~Or16mpa&K1oPROaGVpfBz33X(9ap diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/9.ogg deleted file mode 100644 index 40b787696ef431c283666fb3b7df428a03110f8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1835 zcmY*a3pAVA78XS)K~O=(+e9@ts7{Jjh0sSta7hi~5eZcxLXawLa-|Qo+R9V~^{6U_ zYE|h&Nyz9-DkI)4O0~2Zbkr+4#*~`*b!Oc$d#$t9`Og0K_wBRRS!eqmKOUf20*5~B;mw z(K>57&y~(ZE1W;LU;P55@UBoSC!98cjo0xXygP^VdAayv*Why+*GM0-TR`tu)1lAV zj$a)0;EY$NR?qbzmRF<65F~55KK$?jd>y!E$UWv3g5W`YNPr-dhv{SN+bk4B<2(Vo zgEzRa>m)am#x>jt+5OVtl(8wQKhCU9U3=-VTdG;PoJ~@mhXi>w2cY{+*AC-n3nEJ3 zUdPNE!Jd9OcDnAIfmiwucsJEbDtAfh)pI8tg&0k4v~g?VxcH zU)=`>?_3_yvr?>}5MG>Je#G~E^`r%QZ{hwCM~jA2MGbA9_QAa_pa$|@RnfI*<*CnC zHuS_*q1KZB@d~d#JdH&R2cFy4T|Cu^zr9@9a47eF%-G^G*B?|Wb(#IzZFI(NR5~`O zW@m?pKzLP2p`>;@Hl}zM;5SMfJUQSn+!ul~2+|!=?3{cl8P`UHuEl z62Y}QYh?!KRhCE-<7{HPY|X&wBmvHv9O#t^%j5<6#$&buS{-^Y6t|OCnQdOuj!%vh zHK@2}qW^GVZ5X8$gbrt%Tn)Lrc})Qh8Q-cBEqoMz^XubQ-gkIz_tMKiX;G1Nrq4|# z&%|6mLFI{$$yz@XU<%=pKP1Av_+8Ixdot2e*>tz3<V@AHk(=oBYCZs%G z6_bBiw~+pN+QtK3q*1f>wt&d|h?%!6N2liC6KVldgn;n$7MmLIL zYK?f6MJn$pZMVGmUdrHe;pIw#Z^w68x2Vn9*iFZK+O#?8HwSP&Or_Twm!znEBWktU z2sGT0U%(Q0cZB35_7zlw5ogWI*q1C*!tFA<{qhM+6W$=o>#?iysP773YbC%?Cny2& zyxGqR*7Db{B#u?_IZ|7vgxR;>87);$#)8lYoaWg#t?+J08-Ct@q(^i5fuZUTFSYv` z0(`b9^_N4TdK@k94PMW|C#6_*J*}*HckBRaPg_z=qfwVdXl_}KnkCYfDA0Q^lD#V3bQz5@K$`J_;8& zMn<+|LzQ*o>jg>1B zy^8E1*C?ri6*Pzq1N`91r@{~(mro!3p2^{B24^+5EI3oQN9kT7r)03Xil2(GU3Rgh zC@RT9wra&nhV7$a zS7}^h1Eq+aN!@Z{=Z^($j)knI=7BmGG&69<*rO*e)+o-LOh|3KfOGH-Z+6baVZV22 z$(iU-)lxYW@(p)YtJ=gYI73_pn}C*%Xby3K$8Kn#$y1RGUXJTMJhke_N>~?ti1&e@ zWhudI2$JU^GKJNth7(UsLWeL_N15T@dh6IijF?Lh>k#&sR+f1wZ))|;XNoJ0y91`- z)gG{a`yOTXfEl%B7)|Sd2q;1gFG0e()3eI4-?1HkytB@e+^Tv`y(rVzn>;hqR^0N- zQtG8r@k5xM3Go7_0{9G#)iB*ID?>-+=?0hxc-!E6)q{#-({7LNd@KU@RsLuhY$~=2!KzIkgk~!f@<*%4*p5yHhBemy=gTM;)89@HDQLCRmb;nDqRG zxU?u_KZV7DCFz}#AW?;mC8vK;`VY!kl1pjZ{)IdLLHSVm7A}A~zf23I=RbWJ7GI{t nHefr;I&w@AiQFo5!(nSFfVRli`Y-;=6u?`uO-WlD1W@On#yd!? diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/activation.ogg deleted file mode 100644 index 3dfccbdc49b27837799531a37cce47d419a037e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14512 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/err_reg.ogg deleted file mode 100644 index 430b87611f5650ffe09ffd87fce893aef294a69b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11221 zcmY*<1ymf((l#Dg+})kv8r(^OySu~U?k))$bb;XR?kpah;BG;JI|R3HbKiUZ`~Gvz zo|)dRo|^8is;BCiQL?g9gMxwj@3Ad*!20*Hbogin8e7T9-Sv}&i8(a%2k0Jy|A;94 z75{(7UvX$i>ywoJ8MN?Uadi_bR}{!U@+KaZyd122tQ_p@eqCi(#b(#XJhIJ8TikQ#kwJKkmK)-|2|Y78eSHr7!c^>;NoHK;_2q1?&jp`2n@x+ zL_S-hs%8G7g2h?YfWzKabNC^e`rU~4G(QF}o%GFI#^R0PVE8rdsB zNOGct`O1_V1u&F?K7yL>)9tuHYrjoLAuIXzbGOIR^+^~_kAfASlzdbxW+dQ)+z)~! zzrLntG&Ay%k^6A44VUx_W4mU5@FQceS@hRdp@9vpFdz5Vw#55c_hKRM@UCygItUe4 zB8=NyuPSm2v`;9cz)(8M6jZ3;o7&rI{>a{Ib!{P@M2X4zeu^wH!Bp^zU{TUmqn+Y6 z>SPcN&sG_Yt167ttp=rvv+79PXd&#m^cP zc|9iY&isB(9W!pH4ma!pL#b#%oo&7$#0YIV;7!poWKB(YmIMFbr-8FRU92l`S<^mXmR#Vn82*zAJYLHuK~ z{401)*ekt$zlB2^7;QTcIu&}u`o7@+L#b)oEie4w%w`pGp0lu-xIxY_V!7`X?YQqo zt{agsQe8tP48An=w9|bbf3%p?V2Ok3BqH|d%PPLvQnmsw%ZFDEGzf8rN?op3tG=8> zL{-=j-ya{MSCAG>>1o-I>&v#y-m`CQ`0IC95dcH!DGE&|g)bMx%tFi5p$*0*sip_| z4;#1DUjgRu?XGR@W=gWwUTg-mBr#4*Q@uS9Ao~G|x zg2QIi2Kp%7!vHL9P^vXcA7$H*0PD=Fj%~Mzueyx(RC(1odj@ViKL*g@Xlqk9w_`~c5o>X6Z^f@7*(iEeP0$Fj2U7Q zvU%t@QkW?UnsNq$D&j){7K-2Gs~|}c0a{x|tE{r9OGH~CW2(%iC)V3S+!*sl^du81 z-q1r)9t9w5czB-NV|+9A56oe?OKHQi@gDf(y}&;*1KwK5_LjhsTj+3#1DS(xhOFFq zF&&Ga-vp}n$(Ky(}2+L$@f%Q0UFq!nX5K?7$&_( zTm{3lc_Ma_J%NQ;K^DSWd-B|v=@9Ru2iFabW=JeX=1R+kayruAUhQEly>c%j>3>M{ z_Ys);V)4aN3!MUN)uXo(+Cxa*+h|o)jmrKQ{!M(ip62D2w)ufIQ^O`lLbcdE^QgmO z(x75FEUT(goj30!<0=Hh++0Fm(|zaZ{zNfSx{;Ch@UO>rZ%w0o-M4XB*?0Z@TKRLu zh7X7xLJ*F2rRc54lbzqBDLiU9ln3$!4Q~zG!Y6ysbnz%Q;{&dl!zcMRXDmOvF#~;0 zDrUkPe7m$OsH)poFqv__Mr)gn8cW-M4<$uk79Zu5VdT0$6l4Dufe8%7#zS!IfpQj3 zc%aI?8967WMjTl>h3^qV6Vx>`6HKwqu=ku@1k2#?L_r5Fu$0;I3W(BG*5l&QY<@>S z^ehb8IqKrb^C}+kA!T$|+JGW5fr6L_9oXJ<=J~3ZW(;JgnV853V*JgxC`0r}4BOR9 zc7^q#wQ_8tf7qei;i-fE@SN-Mg}84lY(Ue^sjt_(KUNh7E5?dhm;Se#%e;U;VnP=$%O#7El=> zT`u?biQm0lh?$93Pyg*6#*uDEqA>Ki%)9iVLEJ7Nv)H!d7-`&`E^3=YK7QFJmlIe4 zSyrlwC-^r`dGp`vyX2|r#}?}&mMTQKKs^EP$rW>wgJS#nKg#yy4cw!QL7NFy_33O$ z%DSH$9ix>hH>&A7xp?>1Q$SP8d{NCNqKF1b(iI1u?}Me2-WbKU*@gVC<&^R{&e7z* zMa&E+%AWoMszCvN5%?cag@v3y4pcQ`+B>+|d)V1HI#}5mTj=W=>qAz95?r<#qu_Wz zj@D`52bVgCjo98KN-rR@ckoBq4U5fEVDO2?u@evJSGQ-LQGNNcsW4VmV8n??CFPSx$2eHrVrUJkXA#bt1%pDKQ;bdkzp8;%4S{qiF-jw)Rfly@au>1=)E)1b zLunj2u=VnWf z^4wyLRph)Y%&rkdxx5}?w&#OI7BbMlhBCa&eO^)Afc2J6*fL3wi8-Zf{cMUo1c*+C z7#4M~-s=7iP@TIG3rpZbq`8XLFEy#FVHzvD=F;}?)#H;JCF|c9e%&cY!TyFpwfo+{ z^^I*V(m3aDB!l=CNqr0{@;RTzZkYs8I#N#*>@Ot97yi7%IooS9V*Z49WGd_?Ir}d&$#qwPYNl{K$V~kX`fMwgyp1$^@iWYIaU%wjs zDw5^?S>9r|=o^hN4%WzR_ASNyC?ZupP4{q;fIhDr$CXju%6F5eUsb-s;0E?W_9<7j zF~{HYc;OUb^$q)Fx=OFM^C=;?>yG6TLRyL=yaT%+qayseOpp1q>V}iL$ zwzH!-I>%d@d$m>!k1(3JQx*)yPG6K2Eh)1_vZglDSCsuu&=5ps^sQMijTwtAiH*PD ziie~dN~t`c0Bs`wTC1Qi9&I?7)`H6quEt`%qg1JRO)~ii7)nXcH!O2fuqi;qZ5=_@ zF8opV&Erkp?#;l82^5Q4>L5?2+V;&94k;U)p?C25;_F9sjKVXAy_J6Wzbnnp_MOe35ayAscgu-(qdZ9I4`uPd1WYd;KsQJMFR~2{Ak}UW?r+OUG~TVRDBM z3U{)$L4+Ow@of)M=)HG9JQmL`KgP+NXQJnoKL{eBFB%DIs1FE z$%*;2qv=*jQL31wq9av2iXw_vK!uso0#Kik`mk5dpPWc8v78B9txx8kM_QRAF;pRm zFd0o^!ka~a?$r7B@3Ywn5-hH>ffnoe?x0Z|ga^p2E71ZFU&FJ|xk@)CeK+%#mq^IW z&^@_VQ|~8ekq$^T#-BplKK7X-F|Ah{w9xL7lLA!plL_+9$p68`9^rrL-oM2r90V67 zxLE#R+B!HvpwZ6C!QIi?!N$tY0%Bt1bkJjBxoTG=ONiDAMoO5yAN|?)J;LRMWC%>s z_M_@oXick7#lkhV38vuxbXco?;f@Q#on76YWP&zAiZ5!;5u)&nxX*b|X&5>eV2+E` z(A8T5J`q5 zIAvdjS$G?epH~yJUm}@4A&GgAtHoX?aCgbXWUAtF3U0M{8dY&^3ygumUj`nRoziAm z-7&^j{B40?ym)f4?I&prco!Y*GgWbEesVM zBvof4!I|n7O-LyD<*zB^K~F}F^7aPT5KzgPk6+YsC3rwXStnqNq(u~WkH%OS@4u}4 zie@KYRSa(r)CM2QSAU%LzYYT^tm++6ciRYFxS^6iAO*5?0^ZK4$r0ST`#VFbaP z31c9oKp6r4II{&yck5d?+^;R>hG)HnBS%2<*}boP9xcw}bCm+`o@If~fD7ClYfCaG zR20Nis2gUz0TkOvk+RRuZ+eFIorvz!9(!uPr80=2_-OYUF43=}kQ#=YS2Jy1AH(1& zf0td8UBQ>9r^#sjl#52^hMRismyJZ{?dbPH^2HyWK$*iQCe2a0udL?J0ZbQ9T({Gm zxbIj~r2Plz-}9*qodZ1jeN@r#iN)=O9?d@66(=)#{F>&fu#+Ms{MFWRrh@E#@W%Sq zwo&iopGH1#{If$hP!4dDeSOfmvp<^N@qqd+hhcKdviAkbKaVLDo%0RDR1Q6FdFm}+ zDzfhHmUWz|7IUj_{v1AE6=N4dP2)$C%(`guM)kk&bd}h9Y3)EYEZ@~GLYR|W`M&!| z2s5~+3Gmo4zLY$tKuq}j6P5N&qBVj_S}KL9$x0nC39~vFR{lfvx7vuS@arcL%zpa^ zyoHU|*03UvK$hn${8{ zl@abyB@_6k=K_hLU^2@XVDB14@&kQ1&#Un<4GnmRilns(3i?XB)LO#LFV{DWmS<_v zv)lM9R7O$4xZ*pW^>69rh!|+cg}I^Z^C(aC@7`lksTv z_uQn!F1Q=G8>GjzGjzyEbB_S3mTd_!K;jl9b%$HYhRmtDWM#XVMU8m5;l-|pDN1-5 zgQzJ5;njh*`G<~saU7dBQ<(|=8uD^we7W9nUIJJPcSLnn&bcb05T^{ws}9NjV4g%Q zO4OCn>R#T`;GmEXS>Z<4q9?th+J~hH)qeeb0I!(8=|%S*-$adGLER%8?URvNc!a-U zH?h*x?{Uxz!BVa>P$p&+a_hY9h+v29x~CMH5ZjQ?)BG_}bmJO{_>&@*CddTO zZAone2c=b5+VwR9WSo{D_bP`O5KJhBvuJfaV1NzTEox9Eoe_I;z#i3f-AzbzX$2n> z1IIj!t_9X}+jWNy1xO?~EL2oqn-JsNAC)RLwNR9dj|BxJRNBJL)R7H>H5gt`o zDGaYNS`oaQJn^!z1nqI@ig;CJTg;Aew>QFs)384Ma2r*&Gr)KqrC65cS#MFf>MLTONy#zroW-nXV zi37e21{MSQW0v=vCc-58&Kgu6I*XK-PVLJ)as}{MDv{olk(UP%X#3?OEHks|rMDl2 z8ZeZQ9PYjRqp7t$HCBo#;M{QQx|KE?87KsZcx2j+$EiC~?5biuW!U-is;c}Pe3dll zGbW?Q+D@NEPoMDlgF{O*BE44=j+c&=1J{$5FavAt%1~_pHs!4wXU5YE#KZ9DF-R5Z z3Zr~zkadP2c`Xp86wtQB0dP=#c`059^FFCF>G1s{K9dN72}WQSm6~Gr65m0j^e%s z$oin5dwzht)R_;3*@U#P`dr|T=aD4tUhFPWwLk(twPDeq{U3V71SCB~RgF^5#ptNoS`l}|XaMFsDWD~0oyyP_{pgf7=^ zz$TS(p|JtPwSY)uZ7hvNn%DSFaFMp{X_v`IOsX@4#lAm>##KNW^0T|U{924mM@^)t z8GY!#CM&_$DVvuw1NpL?QIN$6rKzTGA==>GElp86Njg)52~qkk%0E(lU;z~j>fUL@ zX_y{El+u7F2zztsv#%n4$D#FMkBh&`x*~fOt)*04JH6|V)Rx@z(+YPefCsCeqYU#SxDLldnQj*^e7~(sg<6<+un7T z1N}tYW>o$MrqEW*imlaH;L^~GF%AE0q;-a?;f7MS)F>mXrx0QkFt4iP~eF3 znSwK@UNGuYOj;{nm{Y%BaFM|{auM4>5(CIAm6zKnsWsI&IS;5@AF#P;RNC1BxY*Hj zP`0?x8U9G>iJWSTa~6QfzI65M*<>cw1snqDdQa7%9tLu22A?>v@=WOtF`JkCx!u9i zRxub~j!(-iQY=$~;vIZ<1EIwPZ|Fr013U<1@8wFQ3TV*t7(rAY>#8BkOQ1PPI45OeX2s(9iT)d{f^H8<;-MmQ%yicO+42~AOw zj==Zg5-bSEY@?cq1$FPa3cuR{MM%Z_F~W0ukl7`e^Q<@xkzzN#%-o_MYZM$sLK11= zLNOVPp-QNzidP`}_Rj$q+u#exbJGX?G5R9PM^JDtpFs0n1FCGnfIq%e=jmi`+zDmf z<41C*z^?_2uhd{6s2yJnOz6c_8JIFs3Xc4vg2c|L6{aBcK<3ykV^r`Mpu!s;IoG`B zKJ&I;(@5fS{;m|z_L#QVYKWH~eR_2!=~N02!GAJvUQ<+gchc$sEh-J10uwxgSMx$y zE-DWh)1>jPA4)#S2-u6^N3=%o{$pvCMItZZNfk4tzG)r@uPz4rkq`m6;6BG{nV)e{ zIesEXsgfOI;_Nsy*3SAz*=vNj#>8;s_MI)5^S`eo!GAf^f7nw5$XT3b?K`G}hl`Uf z1jd{_9KBraZJg{OC{7O^Kw;9id2=+h!k1f>reh<&S3#n3!SnO1Kcz4t%{jmk1?_;7 z)J|#uaY+1J?n8u9m4uE^v`m;rs>IP>KKJnT_2f*vKQ$JcX>65;is5@`i^Tjmz-%2+b{Z zq1R3-G8tQxXFXD+XinaG^YOS!d-G0Psr`kIU(Ao)?vjzD2ueo@3C6v`*BbRlHmTaH zXcFSq(PP7d8ElnesjOE>;x{Qn_r_Y`HzTpMZrT3hh#Zr;pP&p0TaW1q7SM88ePeCO zmN(2n?^4E|S|{U0z^I|2FQrB89>HJio7JhRB_azHRbgzd*2SQgZ@fvl+(bmr3v5!5 zv5d6Z10Gy{;lk3mmwX6u#HCR>xL+c>OHi-PdN7nIvkI@tO;Lnsqyq;kaO4hj2lqXi zzj^YQ)EQVJ0p;@o{Xbfd9MrxJL^kISCJ|V(ci);uTw0rgMT%cK{Hl}u%6ywOm7Ny|Yd_E6nAVPH1s z(OKD%w^y$(*q^Ub{P6obC^F5yP6$5_2G7d?bkprh=> z`YKYu_lLBedsZKSroO^PBuyW2^uuVo>DP+!VqhYC%R_Y(FIXu~`b;b?=&RW9_b2uZ zXU|Glq8zqMvRiTfDTAS)y-qOg?y0N=G%yS8IWlmvf>TKf1xmb0y-h4XpM{c7{y%F- zQOg;UXk@ZthGryq8(d09fE+f(*YYN5)9^J+)O+2cXcIY7%CF;f1d4&Ba-xQCluhB% zDZ~6$-m1tr>(=x>Fa-n6o$Y1@2Vrjoj5lpjg3??fQD*&gNO7X-IM*E0)RSh|{RRII ztgol;Q!6M3qLjMbrUXI6yBuZrR7$e5im*JI8dfUtvZ1k$$7t`UCH19YQ4{92LOr$f zQiHTdRsMjp@5kEot-%DxEDCPk@g~I)Em=RIGo@2N^nX7Yj%P>*?N&2goqJE3ZjbrENTXYjCj=v|P9HXq(@cHZ zP!048h(ql8i9qGPGitY^imLrGmBS&xE{HViS{AE@DX%)t{E5Cmjs(T*?pju(FG8Q3y0k>sMLErb>m`+w z+5`wL+v&qZEY+eD6mg@t(exc*;>tgk(cChND%7y{g4J-F>B9Lt%_f;o(wAlWxUTwV zuuI3nAGLi=dNU8Am%d9tAA0MuIahV&Ghw<5$fL1V~V&OoNd{Sbf?Gm8IFX^PS_3O(cp}&S!3&K@N+}5K^7i za0_`eOp}-cFPmi2r-&bA@v3GQyTvxAFrK3Dx?Z6DGDJ~sKH*ioF>iIk9q}Pn5(kAb*^f6bv461W+*j2 z!R5h7grz2Jf!#H6Hzv9w+=i}Lf&rh5Wq9`Q4P~EVwL{M+wI`H#p^)9dp23*TgO7eu z<)G(ZQ+=~K0P{^&a7A|aQLKgNZ%|sPvMW?KmxJ2{jD_80C$=c#46r06*wCbNF zs8ZI@Z(CGceF8liewvwu^G;m}bxQsbgs$K5q=QV1KDYT*PK>>30qwphR_ye}?-Q@^ zy^cJ*uuNH!oE#>*nICR?);i`K+uOTJXn&C-xhnrLg0hnL+zup7{?08Y%Jju344ZR{ zFLlUiqBXCBxP3&=EF=vNN%n|&@YWw|5KD}H2y@fO2QUBk{ig3<_Vyoyeg`>EcF_%B zx;b0B+S%H>8dy5&%8E*Sgw)xPS^y`xD>h|Lbh7`_)tf)MC6Y;B|3eTh#h6#A;DSw+ z_<7BPczQ{5q?2uAqQMLCuqr)D6-g`250+23KY}axYohrrul*J}>%YBiBd`~3QU+o| zc>zPiLfE&hwBC1|ogujD3`wsgvTJSZe`+RNXoOfXc{E4OxSD>I3e194ySC~Si)FsC z?yq62i&f<|CQm^dxl&vuF7bVH&Xud1oJIA15y4rto-**X*7qJC#p7=k5lMnAMqi|Z z^~0T|cXq{k4(y!F8Fys}bb!HUlKvl8JF7)_`V(52jYmm&had$H1yy)51?p^iVTT+* zh`%<<6JrnXqdW_L_NC=RzfZUt!ZM5d&nzq7(7*7izysHh8U|M76dLa&_Q zm>RGhF7Z`Q3fo+((g<^t?JZUZ$9i-ZTw6MINgAy;bIoY%1Np3pl0FrdC!PF)w1De; z9d2r%VyA#TA#sIcp}VVR)!6$%)zv@j&C+Kt)*CFKdDjINR?c=g$FP+zxRVuLpL8K4 zamQ7qi^PqAkgQbH zZN*B7-@fi^T18VEBgNpi>^$wba25-(SK8`z-3r7cXJ)r7dIrgvBNHGPxXs5|C*Xml zv*YI<@zseRKYtK)-YE}Wc5GQ}ZJBxZsg$U7y2QboPaM zPlts-yCW+q+l}~!a_`$7iYF6ZcsjpRzi&P{3hW3>{Rq|meLhpnEigr5Pfm(#qskx< zf#|QhfJDTiej8Jnuve(`w#XMHJI#00ax7ga%5@~Z@tt-f@T>`d(CK*P)myekFGRjX zSlwf;BInK&MoEfBSO+X+BJYJ&rYq^7y7_=a;)#RVdolKV)P1Jv#QD$WFYo7HY&h0N zq~kmOphH}ME|mszFSe7;(9Vi%d4!O|SoJhj|NGfiiI(Bql3zWZX0F8QK1@kU24SZk z-(r%#qC7Ko@2|uDBU>i01nq*IFu(t~wZu|C>txD)exu=Qbjv4houvTR>p2853>1Hc zGJ}~bvtq(eU;RD{V3@^-LFR{F2M(&edoKJEv`A$i?z`nnC(WI0skwSGhX!*!((if_ zHC$YalMw-X!ZShi1hbBn{XI>be0uarr@q?jxAa6{0a({G`16kuwtRE>He5{GnOt}= zckO)%5(u3|Q~7h_W58D^XO5eu^l}xgUjKzVS>rg8iOQO7=kl%s$rnC`!D!MV$(mh} zu_HityG~M zB9PGEP+iP;WW&Z?=20O`R>HQDM2Tj>HOu|^c?RlhJ{6G{V+DeQLSb!$bVd~qtHh@T z`UYdw(u8Tt;6iDL78DugjRQoC&9` zaiK9uO`ngm;+|3J29fK<-YYQJMZPt-e~6|_94myarKX9ZU^~CBES(yQmPvxVEX5}z z_4f^^U5n@XzM<@JD`sAtJnMT2qxy_SW_rOhGlc}i40>xNl1q>@3*FXX*b<^ak)E^u zN&`zK6@kVS{^Hv!$LTD^1o?6X4-4674&DLo3yX@vnB~#;WqSi|zB9FLWYVw89`QHY zRmy8i1(FJ$kyQX|*GsNIv|75saHNORyt$RoPY|987b&Tm=bC*Aorb!?McEYx&_7G< zhqTE~US#-Vld-bml%t!0Kzt_?MjznaEhbax6?cj$C~a2H5>Sr)9O(oM#l#2rK(WFY zAM3ghKG34dtZr^2+UIsIunSL=`xoP<47tkC@7}K}WemTYDjcBJ`E7r0--oZ{v%?8p z&`>9g*9V29I}Vu#+Pir|&o1JAngC7qb~nF7SbC2UtbF5#rVHvA?<(l=5Sp6ODm)` U{BPMZm4Ej_TK^i^;Cwawf1jQ;8UO$Q diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/language.json deleted file mode 100644 index 724e2676..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "de-DE" - }, - "strings": { - "WARNING": "Warnung", - "INFO": "Information", - "ERROR": "Fehler", - "VERSION": "Version ", - "LOADING_PROTOCOL": "Verbindung zum Server...", - "INITIALIZING": "Initialisierung...", - "PIN_ERROR": "Bitte SIM-Karte einlegen", - "REG_ERROR": "Netzwerkverbindung fehlgeschlagen, bitte Datenkartenstatus prüfen", - "DETECTING_MODULE": "Modul erkennen...", - "REGISTERING_NETWORK": "Auf Netzwerk warten...", - "CHECKING_NEW_VERSION": "Neue Version prüfen...", - "CHECK_NEW_VERSION_FAILED": "Neue Version prüfen fehlgeschlagen, Wiederholung in %d Sekunden: %s", - "SWITCH_TO_WIFI_NETWORK": "Zu Wi-Fi wechseln...", - "SWITCH_TO_4G_NETWORK": "Zu 4G wechseln...", - "STANDBY": "Bereitschaft", - "CONNECT_TO": "Verbinden zu ", - "CONNECTING": "Verbindung wird hergestellt...", - "CONNECTED_TO": "Verbunden mit ", - "LISTENING": "Zuhören...", - "SPEAKING": "Sprechen...", - "SERVER_NOT_FOUND": "Verfügbaren Service suchen", - "SERVER_NOT_CONNECTED": "Service-Verbindung fehlgeschlagen, bitte später versuchen", - "SERVER_TIMEOUT": "Antwort-Timeout", - "SERVER_ERROR": "Senden fehlgeschlagen, bitte Netzwerk prüfen", - "CONNECT_TO_HOTSPOT": "Handy mit Hotspot verbinden ", - "ACCESS_VIA_BROWSER": ",Browser öffnen ", - "WIFI_CONFIG_MODE": "Netzwerkkonfigurationsmodus", - "ENTERING_WIFI_CONFIG_MODE": "Netzwerkkonfigurationsmodus eingeben...", - "SCANNING_WIFI": "Wi-Fi scannen...", - "NEW_VERSION": "Neue Version ", - "OTA_UPGRADE": "OTA-Upgrade", - "UPGRADING": "System wird aktualisiert...", - "UPGRADE_FAILED": "Upgrade fehlgeschlagen", - "ACTIVATION": "Gerät aktivieren", - "BATTERY_LOW": "Niedriger Batteriestand", - "BATTERY_CHARGING": "Wird geladen", - "BATTERY_FULL": "Batterie voll", - "BATTERY_NEED_CHARGE": "Niedriger Batteriestand, bitte aufladen", - "VOLUME": "Lautstärke ", - "MUTED": "Stummgeschaltet", - "MAX_VOLUME": "Maximale Lautstärke", - "RTC_MODE_OFF": "AEC aus", - "RTC_MODE_ON": "AEC ein", - "DOWNLOAD_ASSETS_FAILED": "Fehler beim Herunterladen der Ressourcen", - "LOADING_ASSETS": "Ressourcen werden geladen...", - "PLEASE_WAIT": "Bitte warten...", - "FOUND_NEW_ASSETS": "Neue Ressourcen gefunden: %s", - "HELLO_MY_FRIEND": "Hallo, mein Freund!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/upgrade.ogg deleted file mode 100644 index 716d7cbb84fba7dc06be7feba1408b57cbbe54ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4370 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/de-DE/welcome.ogg deleted file mode 100644 index 69271ce286782155a663a0d1488ddff00103a4a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2814 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 Jb6yf{_-}x5&rARS diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/1.ogg deleted file mode 100644 index 4a9b7d29d50b04b7889cb66433160aebcad0504f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1744 zcmY*Y3pCqj8<&Vl*DflxVT6N?lf$Xf&#-t4md> z(o0HFmqrm?GHMt(QCin-)w-lIP3WkF+5UFE^L_T5^Pcnm-rw)}J0B4W{&{2^z4w(3lG3-ejr~_lec%v!H zHm7!7Dm^BFlMo#h!(h=**xT6Hu(@b7^wP*kH!g9h+0}McDDiiy?27xsJ=Z`u6O;;r z-?7_cZ~wwYE&kT^KWjQqjbhi=_Qzq9Lg(4{R9_t!U5(wIZ7-jH8guFbJWrl=4gGGN z(ituj;glC0t+~ZEX>2aW81OgnpG{nK&`ur-v(p|}pDK~v|44At^u{$0`ONHkTUtwA z&_V>3xmF_BW9I^St$KVcc}-m&!cCsQ(UA-3KE?1xPub!xuWnXuS0`S|nD#)H6&CrFV;9zHBG6yq9fp?jQV_dWYm8F96z!>6 z&gW8vwwXs}Ce|L*uXIl-Ev^g-k|PV7cHgLo%7RHdn?)?40&6nb^TYHrg~t|hzTucG z2gX@&;aVk$g6bcChh%HE)x4id4w%k}AfEFXNR10n0tO@@{E^)jj1p~{A2S^H2+UvEI+4ysH^>sL_ z*4(}^k)FpN-jb6N_;q5MnZT4!3kW+KvTrt1GW;sUdbuAQE4E>`6XN-8&hX@UFU6s$ zqaMgwGeB^oWA&(;>DOznNj*{bwCKx21|k$=%`)Zo;?pJKhZCAoe*f6omrlvgtHXz( zeEkJ%AKZQ4ASAoCEzB8nr@cXa@8K~=86>6irh5al{+KZzITZW)x#!zhtM0JZJHfJ+ zt;8~M^5wdh+cdMU3>&C|d#}k;@xWwWYl|KPl|E@YK(grCUURJFx*XH9qq9U+Nlh49 zsJf|?UB`s#me!tXuKfY~V`-xx->NX5_2kF+P^F88@mx7FpO zg(L&~0T!)Ry$W!7C*`+xBHYm>^!@Niriq^!qnN}s6lC9bd-4sf&))-0!^y)jOl~ql&OB%45gtX|LJAhsvdg2Ttb2_W*u0!dZfM-v7+uH{uJf$MS&VWjtDvvBJuoF8HfqC zcb|`-#|1AR8BOOz*q>xpJwDr2%jW7Jw0jbtIjF^!o~CXkL~%C= zyL*m{E0E^d3yXdKLfvf5|KkGP%`AvEW!?f7`!;KD0jf>x1Ao;fUl9Gvw=rfj3!+V# J?N?QOe*@@_Dn9@K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/2.ogg deleted file mode 100644 index eeb149d785e2f8eb73d41361546657894d7c870b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2003 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 kgP@4B7!IZk@#QG z)r~rKj*#&x4@m?eJ~`1jEGSe`(n_+^|BHmMBmaNw$R$CP(jGV@iQAE%3W`XS2XEYi zQo=0(W2`ZN!R#osz!er75*Hdq#(`W2$N|YO)Us;Z6pNcY4fbROioK`Ee__}e`{qLaS4hyQZX?Z zF36a5sdL#J)t?^DnsjMfroQDXj4l57$?S~D%7jO7*T@T{e5oZOg>#QuiEpkUe2jeX-6N{T)+Q>nKZj*ynDW@T(1-<_0MqGS8l6Lc2K? zyrgj2Rq^;-lA__<#4=T%3!Ds?E%6{#zpxPM3j!Ml_?dQFK=s0Hqzo>4eqs~s94!s8 z@NIt*ANg~qG*G<$eGnGoX)MwRy@J3KI* zNwHG4L($zr$aLm5vVRsepuIDa8sC2N2?={NM{tY(-B7ysK>v`PD)J ziK35cojb@QTRvkFj1l;3^ar3@zWj+aLDTi)h3iZ3u)r)q9t)RJ-a4vUGP&>Zo2l!r zgI2(p)xOeJp-Au<7B6OazY)eyM?B?ex84?QxP3e_4EGtJXp<*A?aB{rS=Qe-9RvcK zlS(}&g)jQAesMh8aCLE!3!6v^uk?{oHQclv#q=n3Rqm_7vgEHtctj(Sj9VbhsTe9@1EnTGMpm?;K=g30M-ZJGja_E3`)&KG2S!5fl>xJitzElm_6Y416`fzd5?J6}wXR5p z7|EWd8McTaKEJ~>Mn)Tg^)ecVBpn;Q&Br{~UF|KadnM$ew=}H!8?G(3;5LL`gKvn| zuen!&V?IWA=Au1ju0`@~f~^J;U#qN^;QV+keL3OKq2oPiqn&h{g|CMklV#I4bIjc1 zOK!6MLw*~#wj6P!MzEF8u6KD|GLC^s_SR%)_;RmAm?I&xNLs=xeG z*32+cK_T}t_-%Bs8zgv))rivZ*nN3*bGDh4RYs~Tff4s@>Go^he1o~2B{Bc#njalS zsQgRU%e;`dl2gGgTAyY9(8CLeh#OTjy>TJ0{YqO$SnB+C)7jOMt0psorc%jFcC|7} z08Ol-O>Kcb+JI(9!Q49ijE?1R&hhqtyt#g^IjB^lHOuC5z=F3cX-xzman-r766wt? zx#X04o>}~-wVXRgZX!|Qk$J!k184|1OXmWXe2o~0#kx<@=~=G{f3!_6;r-&mU23Ru zpoa#4G<|7$aaMxz&OXN4HQE5!|OG1geG2>U+G2wUeop42DDgRZ}N@se#AS2 zm&eLqj;9S*Ke;W%4uJDB$0@|kx+7(+-M2oUtWV_)VmRMuE}RG7MnwtnacQi1YFRzJ zw*@a2p1GsuyEpN$>`yd#MoBIwO25k3fk1qjChJu;r~K#?`2kn{4t8aZL{V1Q8+V5m zc_YQyWPcP)4R*@h*jlFdM|Q7IXNB^i%mESmAC$kc$|gbo!Pk{m`~HP?Y0Cgn-)=34 zcd>W9M7uIU#Qri|q{JL>qJXh8T%h32k|a|h;56A~`Y>U4Du{NKZ7ceBgFOwq8wAlV J?ZCil-`_T+buIt^ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/6.ogg deleted file mode 100644 index a831a4219a79e540cbb83ad1450f68be74bcd615..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1717 zcmY*W4Ls9n9Jd;lle07qg}kj(Y?GH!%XuBySzdN4LPTEXB{$ZVXl&L|%)50g$-G@S zCGu8Y(jl|dnUh;f>3&r0s^5yUH*St@G|?qkl8^1QPf!?H892cOQO;VS z%&g5&NTkfM7g(V&XJSJ_zsCUD89+nX03u2+Dk3-*DEvDZ+|myC0LX%6ms%hE^)u8z zfgGO@9~nlDJVo?42!O=U-2)Pel-ST>u*3XLG(6S0(^Hf$emGTh{mR`ae;CBk)ZNHu ztlUY8xc;qgao8!y13JEgAtA;YRmXdp$ysw1>bwN(gD74RWWI)-$mHlpGAybX!r>>p11lJn9oa=kZ`@wAoQ>#aYd1Q3^6mB|TFRwA!zE z*M^g{TT+pcj1AMOoHv8Ni^N7a<}ZDe#5ypd=tIhiOO|h@#;#dc@$|Rrl4o2_Qu-QL ztAlC*YFx`l%`SsQED{5*-vJY5c8{2}J?moxMsK1k^&EFt-6+G}6fY_qtWeFhwXqZP zeK!ww3`j2KlaJLoK-)Z=P&8fdduBX)3NGx?p@ zO6!!13>i2Ia{Kn`L0Zbj2^iM_Xs<~*q0w_Xfa$bpG5%aF<5rdSAD80@vDvbwoa2zP zGDFu(-zek`!44=52OM>uoX2jMC41Ry46Gw3m)@w(aDWM4c}Xj@ubrl?NUH9^vww?Y z>$UhtHY3Tj@N~~^kVb0MRi1AFK^%C6QEuwIVcBWgt5vsD2*yz4VM z5aHJ0nt?WYXybK<;Cu{`cB9)sq1%w=7G8%$&BVOJuC4Ql^ypu@Sh#RE!SIiA_LpmI znR6tDfnM8$(IM?2zqOdR-ifJl7Eo_B8IT7c0}II{tI4p9}q_9M1FbYa6Ld z;6d=ak9~d`9!CzPwte!*nfd)ssm;%CJ%jjxon z45PADi3-OP3f=?%W@tU~#ZCC-h;QR*ndU)HMWxm{^F2%DRFk*7!g%nJZ%l~PB(c?z zBnl<2T0t;Eg>uYUW*!^(*wMQ>at3!6!ttyT{Tm z8oqCYauEIFq+oLY`Phz`=BDt(%9tgT*`?>NpR2z~dU* zG5{0ml3Q?wSM4L>dQy$|)OI^N@74_t^If^z%rKCx zg+N|7N9a+yrIh>p&o44CB{tl0IQ~!}%|n-Yu@ihnyqYMF9;u9+MHVDCd|Znch$1Xj zM(U+tzvWTtk4{isfoFPO-oub3G9_B)#aXOWTbW8?XsPeLn9Ki?kx0Z_jXr61c&ecO z-Bh8fAv&8@Sy3ygF5{d*TK1AQ&>C6@`q(er2L~rzL3NXpZqGBt4_5uVeKK0 z-g$XmNZPJAK{~ya({J{So>)+}vfNoU_pj#_TQ49R7UVv}Ot?^vg Vk_)i^&~|nk4s-R2WKiNGA`_g|8bz(4acU85NvEEOS2zAQ7~ih;scR#6 z<4|m#kE_A=UArAQ#7Px=z{=i_;_%(IDOKuIrX^3?OM65X62F&oDqW7dLsMH zryalL9<+Nhq0VjUQf)eBe{G&k-^G&Iz~17YCu}|w?NS&HzWU&2Q^FI!8SSv0C#^K$ zjU{Kb4dFBn40aymSgI8YrsX9d@`%Het1-(@Go&MF z@lUUXE5`YBu;*7N9MQOnOi#B^;&9HJBSEKs>NtC1`7m20DKh0NQ2fKwDT>U(+3iS~ zO@AC8X(!nkw zw_bX6iiv}K3=csxc4zc*YyI6aDq@CPwnKKL$~_U5^71GdSa-eJcdjN?_-@q>!qvlr z+h4Bsb@Z=%bJ^JCbc;&%Ikb$%v4Ne>OJhwNoI7lWO1kVBebnbV)m-hJ`K)}`!QVo{a-JiH_>HoIvQ z#KDaEICIl4vc)DtDabgD`)%&a%-_FH(RUr}##T6uWXnvvXmk3G`7CiSXhmD3H>EOA z)~@(}nM7Q8q1Z1F&^Tr$4w}en-V(;Q!PabN@=bR_YJq4mq2Yk?U-b=M_A_PUfvzEh zHNC(rdS(4@iv_aBa7GaZcx#9omE$<3Ep|%$&T(%IRn7Hf%AIiOVp+BNyD-N9NBQrl zrKVc?TsywJA{q<|BxmAdZ~0!+uIg`ricE|GQ51DRNq6U0(e8Wcjg9 zP7{Tl@aN?}%#w^oD{by;5XyLvxfJX&_Ei;0KDC(^ir;cte0)~WDI$MTbQRCJw5)R8atF*WroV3-q$Fi-f-8J zpXrp7q{7dk>;Wv6rujGLfgQ1bQ>ne9(?94R-fF^TRZW{Z8<|+A&ADpcq_*W^H|44c n`)Ooo(I0-A7@tOlrh418t$YW7*qkG4+T5w8O{skYj@Z8d(Nr;f diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/8.ogg deleted file mode 100644 index d7a969652e737b73320d7595ef27460229e45314..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1788 zcmY+D2{hYT8^*<&TJmYtE~63=OVE%uNo&S7YHe*%s-v|;sZ=yVENu<`u~aElL2J;l z)KaY$(}qOshR#$QwO4DYDiS?oDPpOKIdi_x_nvdlxzBxm&wKAZ=U(TaAa@Z_k$=m6 z8cN=qwzul@K?=@SBdK}bdP`vM<6*Mj2IaHz0eB~dT6}RL?5|w**{De{HL)vlO^PYwbyv>P_YVQ zy9bE@5wyVYC@O{YQ?Rca3WXv8M>IueM{0HboGlA~#L);SqroS@!E%-Gi?FkSrckN#pY!(q8UE<0Z!llKZ>)m;}Jp&_HtKDectk&8_&ZykWbjyMjuA#p$ZFs156eh|qVC@yyE- z5N~huHxWFx>A=PgXF@-H+*6HO>sYA6m4LVxFtN2y1o_wLa1(Y5!t1YSs<`hjvrNqM zlG+KrI*bIskZJN7Q*RdxZobIpI*b1sSDq2|2! zQx@VCX!nvt*4esJrwevPQx`}863LRfgM)`??=A+>Rl7N%o~=H7@?_MKSZC8l2D-~9 zxxHxfn=74F<2eaF+Ng3LuU_o{HxB$AJN-40VeL7=ED9>kOYPOX(CO8$>$Oqz!^q*! zpQ0xpU{}P*HNpBYJ3TMmlD|WwA;?j$+6sA@i&fGH! z*uI&L3_joe{Mlo@fr{XBjlG4a^}tDn5i*TVYK)ljTu@ro4oqU*CVTDr5rQu;Tn>b)ND;o zN-W~w^EEDoGJm>T;-6XWx-OgDBU_v4tlEYKS;As#HnGBMA=t%RUsUA%1QP*0Gt{vG zqEckrWvuGZneR9@<|lY-oBgyniw>(o_WhzXW<6!j&FX_~MV+kX*e5>o0eSQlyeVWP z{e_@r$gQ+8kxiMZQhy_B2pw;I73{br2_$=3*Vn4?v|0|(5&0UCN-qwARYy1^Ku4Rc z+?P3&EN9$S^;+F}81TRW`uy5?l<2De1lvL0QyUu7GKj^?CPqCj zeF$xcPLil^{={(FIKsbVOFW0HV(~goAKR&3zD@0eg&>p{Yj0p$rX45dMPfTG9f8G? z>agyzToQnQH6fVLq;300hRd*)NJR8h!TaGb6FFPu{xtuT<&d|Al-7=IlNS^z`L>5P z+ReQTwQ}2%nFFV9(3#12-qmNnjd=u%$yE*1E37?p^sp+9btcb!6c39^Y>SXzMayNS zkUb`u?(gjw;zybWQ-t47`|*~WHGIoP-$mEnZsq;cUzWH6CQGcqNsx;Cd0GiDO-EOs zluie{hKxJsmhUfJ>)<;~N?WjM_+{=-Pld`#`ug`6srOvRj^IyPwM!T}Pk-RM`;WOG zQ=>jG8(iv^j*S5?@xw7BKvVs=cXz2YWIfV#d?(?-!vTY3vlChxu+@YqseAY0n>HkV z7)g0&>a>!}_2oJJ$51J#a>j0#L7{Q{r%iErG8JmNiYMzBff=512WU+C-7gr-9IXGE z2%Jj-w6#n@<_kkMr6tj#b^4=vWoNjqQwKl8H$h(sfy#0nAGTElt$M;PL2jceC;1l* zoaXK9HrqQ0Wplio=hQLsoZ~GUXMw4xNXD<^8|G!<=jC$}EXm{^gSOX=ZaOk4w_*zj zlO#Y3X0qh^^xn5pk*AYtK6r z>o$R?XNYwBgV>@l9qNKplT;O(u#i}-xb`-#7{YiJO*ihI|EB6Qo1s5P0@T%{-jsDA zKIVWkvS(g;Sd5&h6Bw=$tvPEf5!{}I{BixOBUWb8O@hR2Yp@#SUF}mswMq@D#%lBG zi;l1SNn}YLfVR_&vyv!Us8*7gRBudAuV-t?A$a`23A6uGxc{lNRh-#=R;c&6jKjEn VNuk2+XNxiWU7^~StRkGi{SBzTK*|6B diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/9.ogg deleted file mode 100644 index 8ff0b072882323761a276f1edb22b7e88e29b2c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1561 zcmZ{jdpHwn9LKGx$VRiyx*+5-%4M^P(MU`rxAGto3o*-OMp5RrT8vsa#+;Dc^@KRc zTw2XSE(wvgkP*3rkwVj%p7Wgl&iD7c&+mQT@8|tJzdwGjgTMcIiER@93L9Odv$c&0 z+$aM;9YP~W)_yo&0Kf>q_WX@FY~lZD3kQf#FEMru0A>q!#`%*#;+wO$YgdjV^$hip z2*ehlBwl{OJ|Vt-VHmOJBleJJv58cf$s%_0!)LYM^9)|c94sYf^m^;Fo*tvZ z+#aFi8g-d_qSIKVXJSQ(GC|5DeyoTQwqAC&CYeA{)rjk9tzHUSlf*6Fz4I(uNf0_W z1`tlq560d%*ukcsvWrTpt+y8b@XAngMlXdP(-MYXta>eaJC#6-!yoEg^+8kb0l+Wg z-Iq`pEt_%L`U>3jF!FKOS864q%Vv+wo2EyD8s(Z<@8kdWi%2I>)YY18JVuzssLP0& zVg$g}Lvgt{pHB$`F+TF_Io?Xovn#>j{H8Bzn-F|^kx{lZdS7cDYg=W}-rY_s46L!^ zu^d5fVVkOMQzO)y9=w1b82$Rk`~3hyIY+YCBhqpiY&EV)0qc9&AqNN)xN7~4n;mWG zle%pJ((G45;g@Y3qn~2|(0uLbs%17|tol7zfv6_;Muy0RIHm*Y0@{XQ^1`!;^=6~lJTqpr3TX2Tfuf;SW!`G1 zXJP$Gino$#4!PRn4qeeG?FvA5^*q0!9nX61i|o|Tt)Lgy;yX`ug{G6KG-$7Kp_>R- zW#Ipq+miuNEJavq8>&}i7Yt}-#l1`mQXkYe_EMA2b1OZ~vynx$)s|?LOFulkRD5DO zj{vNQd=FJ|FR2^<^8x`B4!N~V{53g5a5ck0IZm=T{8QlxkzjDGg*Do%Q2JnwTq9Tp zq#jx9im`B>vVW(xvEx>t^DlVjYz#X+HY~KNML`NQUn{qoRo`2KVLe>-6+T>R zG=8GWGbwTDj@g~uD?dE(69d;#f*a`W?CB`^=?{N!b;q>u9it)jw(IBfGP{h(q(GR2^Hm%E8qDrMLTqHbA#QIE0mw>1Zj4|wNz>e?$EB667o?qY_?H!8Q$7kJc6K`IcR=H7pNQtpye{nGS!!I&QF zL*UV9mjxRX%%Va*;~`Dag#XgGQ1(h+X1*Xt4c+W|8uTpCepWm?a8^QIHMMdTQ<>Q! z{b-`fCFxEssWCzux6+>bom$!A*2CHsX*k4VX@DDu@}V(f)Pcf%N?$sMPq6FcK)6&q zTrf>1W9Ae&Q9x31XT6z}&`2Tc)B*Q$`%X)3Yi0!TF!sWbLpS#W+NC$s!&$zo>=;n| zL*TWK4J7j5=V-UJKbS`zRg5R*4=l{@@~vkSGSMZ6lM^TQx}#gZZO`Bj`sSN*xH=&t z>lSugN_IL$!S3KHJ7I3bHsH1(a6lAuzlFsFYQ3hX)2Cp>?+0?s^7=cfXS7~1IYK6N zv+t+{lSerK_hqEb1S6Z zm`u#%sHSjZ(ih9`9Ru}j9dV*xga`$D}{`Mn$ z2fj}5s|p@P2}(}lZHA(hJ&~4g^QjQ$i$M?YN}LBAuU(mzR^HwrDP>O&O>OjH*|2i# zhRPJUm3)`+$#~N9P5<0XPk+ixR?$Ls#n@E$O-+Pp!1@sPenWyp-ixzQJm9a*t@ywE E4-u2=XaE2J diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/activation.ogg deleted file mode 100644 index aa8b401f81b23b2dea9df1b046990cba93af3586..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14003 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 NS93Va`1tzJe*t+vR&f9T diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/el-GR/wificonfig.ogg deleted file mode 100644 index fe3eb6650f70bf02b4f2ba80116d2346756d6891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6031 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/0.ogg deleted file mode 100644 index 51dff412fedd95c8683f75a7340433406a38d301..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 zcmbuA`8U-69>)zPlQ5PvvQsh07-EclsX>;;Rz4$S421~e4nstJ$udLsh-@(;EwYrQ zMq2DLmT^&H(8bXA>zm!g9o>8GKX9Mtyv}*OU(d(;bzZ+cvDdD-@bL2dSN$)SjvTaj zBNiDXfej^v+xX#qK_E0J-t;$uJ;48`102MCjRfDc0+}4(uJ~)=LfnZxKH@4$8=;TT zMj{UgId1vgAcXk(5ly%rf$M1-a7}H+pa7o`?#KTuHm7qrt_~I-9JO$|w?oX<-93ct;AnsX6i;6o{d~%tbcv^RsRG}FauNS39nY9heG>X))*kMoC6y|>F-Rfc z0@o9xFq3@y@}V5LAVkg)@j*+5-~{d3(@Fk0YSW(-F~IIjYgP6Ruksx=lu(M7bz=_L zK!*^{Cmq#YxExux@O_A-F?ugakR|)GS2EC^s0kh$Hyvx!Gz_0FYA`X7lW=yvn^brl zV+9J9Yynt?w=AZpt=cW070+$BS~WO+5tK5$A97d$8iS)?E5}v!oC;DPN(65$xq69U zYgW!UEB4t5vp-h*uZ%>#uM~YXuhA)TG5Y8us7Atce?ZI%wg^apK zUFaPU5SXz#F?oASoGwFzm`)dxR%xdsgv@{?s&Ar%#Tt8$|7*Fm)unnwslcVYp_Zuo z@DTIOF#gNxJ3((00~ra0%M=)la~orm7bUd(*-_A`>G?3H$=R&aqkQ}>Z)$p{tbXL> zP-H&-^~HU$Q#0uB%6z2sp3qQ-qF$0p*_ELJfwcx)$;LW4NvJqU?{QuKRdurL4W*-w zZn~-TA}L@cH$KVMU6f{ICn-lG$# zmM7z&@6fu>`dw1N(&qz56_PKXh?U6)erWcb(MH&JrQC-g!;C+Oi0{ucX3DC%HGlTZPMI}gWF-B{W;%UFbZYR ze{s?Zf>xO{&f#fb#c=Y~@JSWxHHfMAA+NMjtjrn)zu%T~+n^NhaA=vRGSHR2Z6pMr zv>bGF3_3mp_GjXBpT2qPhKwBR+G*gFh3z+PG|+x9IW8uW^ct&I?l3q+R_oBGEIvv+ zz1hd;p&e z-0ZJ4&h#$p#VCrETkEi^=-;u)wjbw{V6uB#?y-$+x|z?^YR(f%$PWE4L<4pUXIbXJ zBHQK|;;8s8DPbi-wMOx#!{x!B>{%^Mv%}2>b}#uOYMuJ}lYBraXAIr39`>ngbYg<~d=_589Rf zi&^D;(?FN~nV*lN*}9aj9Gze;a=vQ`5nL<*bHF#r)N&u9&xQS zkODaS%~$xVUA{dJ5bMnWyZXApj+-Cd&h?~AX!Nud*~}o^#-x9V>^2Wi1A-JrOVG>P z&%ZYpP5cpssegxz^V}o*Z&Ps|cvq*3;xC!)yFG0&)+8R~l}0|wijF{ofexx{hYm?~ zsqg(@+7PwHaM>Wf*VPv`5^XXEct=_@^gP$HhvArJ1DvVbB9aH0e9pH#QU0T+VTD3c zb6@i7Xov3beFbk4h$)-g6)NJRdR;Xc;4L)HcRpK@;DpXo2~OUYA9~qJ`*9tz6zDL& zA=F-*yX#uD2 NDGKiHYW%;$e*^W~Z+ZX# diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/1.ogg deleted file mode 100644 index 814753e437af20755d05f6a0fde75de7941685be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1569 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/6.ogg deleted file mode 100644 index e398409e43c2e82fc239f05c864ce48532a93ac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1764 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/9.ogg deleted file mode 100644 index 434c320d96e67954da616c28825c10b16b25064c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1653 zcmZvcdpy(oAICS5OLNM}Dr<7daf!wXvr6t8BVyv4VX;k$rn%pm%SavhQ4JLmp+d^= zn{$pfPAJz&IHQ`&S!b48%5t)%Gj$%nzkaXB5bjRz@!{uRs4 z#A&1SjA8S^+r7@m#kf*J$Y8JyIQ{51#A^fppEhu?ygN0z2MM;_ziIPo|NVP<&<0GYvE$h#MyJK(fCtL>)j4(%io@-VwUxZ)>^E5keR@FDk9 z7t3aSbxf7)k1f{foxUI>@DfnICy6w4rxCFpEBSyDetPtk59VI%KC38687_9N;$u$A zf1?sW_+0n2)T<&^R#8=vb5jmtXMkO{3wswsg+(fifjZgo18*I;>P@!?rr??vT-WI= z8{&w=<3X9q_Mn8@9c{BLx~p>4i5JTU#KT6{;#{P`Iw^YnGQw`19e4^0{8xU1t%V`cxyd}_Tc*Ay-!9>i^SMGg}_T$ z=h_V)=XQm`1C?)di0^{31*YC@l@WWknzN>D$7sMbPjg*AT2pMY{ICO8LN^;^TDqC< z2v1hUIl`OUfdw&Xo*kiRS1{w}FPxxk7QaC~v+vSPRIc4!Lx_&01 z;C3x0@fQ!i`xb&d75el3V~Q`-4guSmFT}PP9Hx>EoR_u)vF#E^KGnU>8=BVNlC*{c z7H~F`oF7QC(1PNg;IwD4$=xq`BAwQHw5?`VZNyQ|?JEbbr*3<=a{&R;nEv~CvSGIM zmni-GOZ6|O2+4%??j)(6L~YS`*)!?N`4r5*A+01auj~_OByOp<%8eVEmplJepQU2#H9 zIxwAK4r78ykCl=6H2d7~XzOyi_3SYrk`2L@KXnwt(yU2j3fn#cH zHs{<(2z|@yRc(v$?joMKhD4nBD#qYGT;3PP%p3T$7s-i&Jc?@!p6nJbeDIBz#OPs} zL3*ueU0aVVqeJjwU4tXF8H|V;#$+6~RNs0QhmV8j!x!JWHI)mB9-%4Wz(rZcE6CF~ zGP*O@5BqyV=%l9(FKm?`-JK2!jK^s=z{Ue)$tq7&R=-F*P+^5{2qXIyLdPoU#?GA4 zPlyaYiwa#G{Awny@!U6ec`7NVw#%T(pn4z@q6SSBhXYDe?be2YQ(0V%uWN^w(UmaJUTH`^!oQ7!ySxQ`8s_8H@(>BJVHa&6?Uxo zA=gTKn!<@~i$9zK6hdKbC66okcm7ja4k z&_l&0Ywdu-{s$Jqlud!-+k|UOledlQ)QFHT7H?Ec37w4LXx3};*x8corOmZ^!gK(< zVj^eLIOg~mL2Q5;|4(ujS(8!xr2Hl@S!1?&$%hjZUZz-*K se&kz7e@p32^744M>PZDC6aaq+j<&w0qqK(2J7bowt0tA2>i*y1Kh!(`1^@s6 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/activation.ogg deleted file mode 100644 index 0e9b84397fd7af3c47c77304769ea62dc7e6e58a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8855 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 bZ}c2F5{Mw4C1Nb-eh|aHywDQ=zk~k+9X9wO diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/err_pin.ogg deleted file mode 100644 index c52fdf4a52fd5883cf539ebb13aedd31bcb93f02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3805 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 A!2kdN diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/language.json deleted file mode 100644 index 1758d34c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/language.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "language": { - "type": "en-US" - }, - "strings": { - "WARNING": "Warning", - "INFO": "Information", - "ERROR": "Error", - "VERSION": "Ver ", - "LOADING_PROTOCOL": "Logging in...", - "INITIALIZING": "Initializing...", - "PIN_ERROR": "Please insert SIM card", - "REG_ERROR": "Unable to access network, please check SIM card status", - "DETECTING_MODULE": "Detecting module...", - "REGISTERING_NETWORK": "Waiting for network...", - "CHECKING_NEW_VERSION": "Checking for new version...", - "CHECK_NEW_VERSION_FAILED": "Check for new version failed, will retry in %d seconds: %s", - "SWITCH_TO_WIFI_NETWORK": "Switching to Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Switching to 4G...", - "STANDBY": "Standby", - "CONNECT_TO": "Connect to ", - "CONNECTING": "Connecting...", - "CONNECTION_SUCCESSFUL": "Connection Successful", - "CONNECTED_TO": "Connected to ", - "LISTENING": "Listening...", - "SPEAKING": "Speaking...", - "SERVER_NOT_FOUND": "Looking for available service", - "SERVER_NOT_CONNECTED": "Unable to connect to service, please try again later", - "SERVER_TIMEOUT": "Waiting for response timeout", - "SERVER_ERROR": "Sending failed, please check the network", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Config URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi Configuration Mode", - "ENTERING_WIFI_CONFIG_MODE": "Entering Wi-Fi configuration mode...", - "SCANNING_WIFI": "Scanning Wi-Fi...", - "NEW_VERSION": "New version ", - "OTA_UPGRADE": "OTA Upgrade", - "UPGRADING": "System is upgrading...", - "UPGRADE_FAILED": "Upgrade failed", - "ACTIVATION": "Activation", - "BATTERY_LOW": "Low battery", - "BATTERY_CHARGING": "Charging", - "BATTERY_FULL": "Battery full", - "BATTERY_NEED_CHARGE": "Low battery, please charge", - "VOLUME": "Volume ", - "MUTED": "Muted", - "MAX_VOLUME": "Max volume", - "RTC_MODE_OFF": "AEC Off", - "RTC_MODE_ON": "AEC On", - "PLEASE_WAIT": "Please wait...", - "FOUND_NEW_ASSETS": "Found new assets: %s", - "DOWNLOAD_ASSETS_FAILED": "Failed to download assets", - "LOADING_ASSETS": "Loading assets...", - "HELLO_MY_FRIEND": "Hello, my friend!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/en-US/upgrade.ogg deleted file mode 100644 index f27ec7ae917bbcc73cc854089bfa9e7af7d6b598..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3112 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 A(f|Me diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/0.ogg deleted file mode 100644 index 98fbba2a787c690581788c34aa2aa173a25a869c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1841 zcmYk72{hE}8^@W^*oiC=#uDS$vQ8-FS~8Zob|Nan82l_@&=Bd4Es+?bTPk}qq-=>X z*0GJ!iBRgs#Vw}D9W$~Fac8>s{Qo`Yyyv{n^L(D~yPWsDk1Gb_$p_;5&xCe4cDyOb z)K;JWkn5#{cmz5qgrDD>zc=s);>yGSXFQyr>j`AkEb&|MaIYXtycjp)5|kJUH!?VG zU}R{>Bb2!V9UUAKf{wG|=7PC7BMWZQNHsDX6~it3SJ=9T%W;h-%-d8_7{gBLbTAsg z#$W(+w_74> zEIMWcNJv*^8VNU@vZh1>@G9!*-cto9!dN=mdAFa(ZZDKmAF7tJm@}UGV|S=H=1m{R zL09WN`9`NOL8-jvthy$TTIX0}Q9+EKZ39$1f2+8tUvPRtf zuk(Cbv^U3Ck%w%$M*?`wqs5Y1i+_lpV~Iiu1W>(k%aY=brHR#iPNM^^6;|;Ak1RYp z!77H*<}e+&lA=}3iOVLJuWgO6hXZ|_WJTIenJ-6B!Yp+YA7zFsm}558uz$IMl#lvP z>?gi3zC9>hl)WRgLGBJLOG24b1`Y9F06gp{wWJT?7!qBOKU6(Xnm$imCXvB0pX^_h z*PlT})}T(X1B3%|Yhycg4XSDt6b~OsTV$zXCU><|{rO%2+mzoP4QGubWL*?O&x&`t z3o{JoUymfwbGyRLoR?`OH+wb@>fP6?GuOmM>IVXND6|ui4gY#RJg(ybSh9RbZ5BH3 z9CjBX!LTC79t={s(Fp@ik8QZDPz-Th9}6xvA6~7jCZeY%?EHS$YeaH7RleY1YA4G; zDPuT9xHLQMRTC;aw>`kwB1)u@^E?ijvnxad@EU5=uaJiEb!%pz&KPC?eT;S44ea^= zQs(!CfpDmx$D*_Q&_wH&PhD1r<38Sx@}~ z_FeR2HA~lCmeZ30j`I5c?If2sh4;TC?!OmvZiNAORn_*!>tDx8^f%px?6pU3!ugL+ z5%uK3;v$AC1G(^^lvnL{KPn^Rsf(%anKSC{=Ik6(fj0-6-}M2^va74VPN+X!xk`Y` z3AhzVyuXL(? zOIug)QuVc7T_$2?rmz{m7a?)GTe9Om!G5+b-~s}rQtL2UPFvwjyk4CV{Ka+t$dc{b zDQ$JKKyf~e4!8G15ppM<#QDN)ToKoYU)pA-sGE71wm#=raxV}npineon_PN}&jBy0 zEB5>`tZ`LgUbd829YHtDpc#vU_S+Bq@om8WW!1X<2+?O4kRLw1k`@eyA};QH|BL}O zJaJ2epNjLr1PrxGZN6`Ac5YABa=f>BZGdPJk`3S$l@B8xH=R+^ECrv*|3LLBS>KUu zGr}k`&=>=Gn<-FbKbf-LM%(fJ(`i=ek#B1^^F|A&AR>B1^a4?vnD+3jh)>fB9QZaIAVz!x}gF z`58g$`+-nt?RyN8hBtthQ{-i|hgT<$spTL(&F)x+QTLUmM|n}0ecPueqGeSwa}@nG zVVvz=Ofa~aF4$MuWJbYek^-YpVeuXtp_A$H0V%lYQ2;L?DL4{~^;^0~o~q$naH9*3 z;08@Oy;=yU^@9-RDA%Qr`1V#xYow1e=|6ggK+eREmhq!!fVopnOJX@lPY(e9AI@F- fxs>bibpI0~O0noavt>rCpO)czKe4s$tkHh}Ucg*4 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/1.ogg deleted file mode 100644 index 2c2f4fb62c70b20415339fd29dfd24d2ec43a8a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1519 zcmeZIPY-5bVt|651;_e8%!?V76^z3E1*OFvsfj6!j24UsV!=xMLCWC(q?{4RTN-vm zp3xShJR~u_mryDXB%aK)Ga~oS`L9(oi8MGbtaa z5o|EawB0~;KmalrS-@-7F@@IeCAyQuqUl zb38%X&sJHV{~DWD>Gy{7*|*1hn{Tkoczey} zxtaIIhu)xGuTS5;wS0aOC;VrgXV2Dia%M_PEo)V>o7EMY=d4fj`nJqx{*G^R;!m9o znIqFa<<#U}s|zCMPlRuad$uAXFgjfJ+phCZn!X4Yelx5s)4Z5|HA8q>#pExM3nwqw zn{a8bSk2p+JA$9?5BFv-k7MGRmuY1>X~Vr8satXtJ~!T7-gmh1-1g2`GwK3))I~;kXbPOr^j+Vx!IO8cBZI&zx7X6*TLzBnD4h)GxlvsJ$d1M z)f2&snYugrgp|82|GNDD_2$TrGH)kq??>XmcvINfbN|}qy#KGh#hw&9us-gB?i2+M zt=(%C9E|SsJbfX(OTYhaocwEtozpx2ZY~YCPWEcxwzr(>+$#U$0QFH8LQ{78WV#wT7s{OuBIkiTX3&h?uXqp74o&wy=Ap|8Q&9O>1NU-7T>!-}aZo>gt#c)n+jZ5*HFPWKbi zVxfI5lf&Yki_M;Dncb`^)5PJl?9$Pui5GKUuFyMkcgOyz9ZRF$qJ%9J8AR1vu7DY2Ux-wN7+p#wkY5y-F1v3w|vVzwi4Z>sRdSD;;JV zITpTy@nwlH1UGnU9U$j>s3YH+(5#u8bwSI8t{=t^?4 zG?*sKh>JnIs(CA1;)*dP>oxbM`#$fh^E}_@`F_slbI$jiKhF2Kgok_Z9OC(}Js^ z!sFt@qwuj&7k!+qO>MLRl7zV6%D)vC06e6x7@5MkUo$+Z@OD?ADsJRY0WSa4w(Z`F zYpFau*HN%Sx`iX9|3dK4?eeRCWn#ox z6WejxV{-Sr@APys>+F9dUzu*A+)Az#hz(a$ANH??6J3Ct-0fw|dg3D+Xo>9O4$;gn zs^l-nS|aH>w@?0MH}eCd_D*DGfn)j8XS&Tfd31v^*-tKItUYNY#zW`O#O64GM*dWP z3p-{HkW^L3k*ecp9`yjtO(?v`%a07fL&{07QUnXf%EWtwxLc3SVz%g~@19XPNs^st zWKDKbf@RcEJ9f1Z?OVU!d9kpgl3fh%jvW&<9ec3w3%|O1u0|rV(|@tq^3rlk6LAt))qRmqDLd36w_g7lVt?Kf7(eCtvu+hR5I6*NH%1C zrJ|;;18jnf&EcvSc{NeeQlFn)OlG#O8g~m6O8@e1=3%gCYcAq4)y=(7D{9X+pf9?_ zNUl!swa#wZ%@5JjI(F5+rQzHHp2WBc!hQxw3UXAuxFZ$bKHkDrAPw6Z-xCP@Qcfq{ z%g_i;E)eHgk;hYAn;TcVKfY^jj;oVwJ>5erGDnU=22iFNck6$jgHmzXKQ)V~FPVG3 zC2_2xH_0^O8htC`^~nkt)k$|Jd&RsOY)`J;BNtkgEZ?%3aC>7j?*=bJuk8ALUIjIA z0=l8nq_Ix5u=~-8`(pnjx3eFL` zXo%zI?O#mk#1&;~nk?pyHR zj_;(2A_q2AHy(UYwHfz#IxRZ6w$&_Ru#1zIP%FL3X@`usev|^2oU@E0Jx1_!0;W{dHOE-~VY-I-$4i&+bHal+nCo+pRXK!36FSoUSQ`kshj7XGUg4PbJlC zs?^uyNvMh@Q7^{BRm+i0&(KOt4J)scU}+a`r`O9(W>vXpPzx`wz(}4k2xn)tu{7S_ zz~&IC85q^0Gx#MvNBmhgGW3^P%V}%f}G*{ zLwP&R502KsoO;^~d>*CR`^^0bpmBo$NgBaFTHUK=x!ouJVJfQst(!eJAyEP#pYDe< z_+Lp8+6&&u#h-%*jvrr4G8~g$u(9JGNMH_y9|B;~YRwE`DDjh!3!x K`3EZm5#w(Js%YK- diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/3.ogg deleted file mode 100644 index 6b6ba47d922e8aab45166edd320a3b87814e675b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1747 zcmY+E4K$N`9LFseo5?jJu}q98B~z_oF1kuDVw&3MB5c&2Fw7d$wKg$RQ872A7fMtt zyNcMnl{>2ArQDR_ddaSYB+(G}(Y@#1-QPLSIsfnT{rrBYZ-zCIBVB(-H~|I{eJ zk}MsujzT90(uWZrx04n^g+TC-`oM39&l3J`E#VMQ-S88ZLtK_{zmSMH9q^4;2rC?i zwcBckwYOg)Ou>g16&6jU#kzoA80cXgK@+?B=#kK9u<`G~Zgn6B*3#gmr6>m0RD`=n z41*a>kB$Zo_!3+7`Mj&tkgz9Np)JH1}#eD7-qLp_JjFryTB&LGe`6 zd#+Wst3DKJ)n?lr(2lQbr0&hnA~aS7X_dN^4V;Co{6@C~T3uMCS zX8zKQYJ$!kc4$?(jO#g88MWh(R|fWiR8x01S$lR6mh^t_c6-k6=CRn{Iy}4Q4Du)d zA7gQ{2Ny3`w0o(fTszW9lR;5Vxk~I=LA^iZ?o8swlf{t!6H?-i*>>^!*dAqNlu%qs zI@8@I2o&}AXFeN3?xOQkOM;|F68hOP#wTCvsP@Iw1%DG`7Dsr196pouqT*|}*o2JC zjLqz2gFlF=sb|Ny#57uH#J4qiVanl3$naO>QM3LV>c=XS#K$uayD#j9UY71G>XGv} zlatJd@_DHTFKhhsf@OW}!4WaBm{f92+3YN5U_>7^iU{CaT1n|np~lrz(%QZ~We*}+B4evtgUl0zUmm<}?7jQ-TAtLS zH(hE`WnZ%P4*l%3aOXfyn{S`!s6*Ew+|+j|g_ud4gj1xW|D%o6;?Y45c|)umf+CgW z>UKyDPva(MYGwUybw+J*XuI+i0Dl#xW*i5gox}X?S|JL;&T@T&l~_ZX30hbe}v(3esvWha^FCd=%IJhjrN^2rtx|e zE8-iZWDzExKBNEqqoCX19q)8V7QnYQue@oxgJ))#5dthE2fQtiIHfg+L)m5h%+gR3 zxMCvYm~;HL!msp`)9qb#0~cm*c#ceGWKQYru7VSAjJv=gwC*##^vR9bR3hafUneM^!IxWT3 zna#@jipqug4U)@4;Z(HIOw7D<*9zK`?I<_L=|(@cH^4Wu%0{AaiceeTNBW!IY_;!k z-jKhzDcS3D{xF0br&yDI9#JXmxH{3E2+hOP<|4%2+s_qy^~sC?Me>$Ern=1YXY<^w z&c$7s*0R8uHS|5}2peG+--oR0<-#6oT{iTM8Q^z1H2?Ghyt0-2mD8&pz0n*u6)end zp+X~Gw_Z$egu5NxQjj>U@$&gD!a2=NZ{{wd;#>XY%XK|lvWZ#6YsS)o?$2NXeF?he z({*JjX|Ay_rYG}f!*%P2S04iSXk&xGcKyC2Cdy{ECje2~cTIaTFH9|(yv>!n678F( zTL=3=l&mP%_(7AR$0fy~4IB$69@9s8I*K#4`L39u+zIBL(g4={HlifI4+bU-Qb(N| z7sY$UHsU$slPBiZ1yoAl!TFYhQ4J?$>%_GJD{6_h=UI5LNUzg>rQ4C?hiOBB+O|my zfN!V|56;+lTU_(2_8B$a{-NDZhTR9wrh{nOqo=dik+M%AU2@+&e|~{`M^e+B2B7Iv z6q5cFYCK4C1qtvCbfJ-yinYNxHzO@inCc=t$e!2Dky7c0 z0QLWA6*tGgiSVBXD!eLtWiwvI1(ix?i65TuE!Ds4eEcoczooi5cvQH0%9nvLuJTb3 ZR%!i}sXA7c{r?3)t-{JHR2Kvl{x8M+8fyRm diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/4.ogg deleted file mode 100644 index ae5909cab9f64a5361ec3e4fa8d699831c2a5f72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1871 zcmY+Fc{CJiAIE277_yAvx@8MvWagG(tk;Mv*BY`EDIvsI8rz`KG-Kb&*ebH`%Sa?! z%;;J#L&;JihR$SryNJA3bZ2_+dEegOInO!2@9+0{zR&ZV=Z~MApPwTD1o$WZqQM!w zwA%$j2TIsoj|j8y@w^HI>H-;;z9V)#{J+7&fm~&CX_yVf^Kd6mzc685#WT`Z8+%gc zBvxIWN62!QPq25$Ri98ix9836VfDC8tU{o_R|t3Ge~gWKxEwcl#=J|Nvx$5qZfqMF zL?i};kb((*zv=5c=n$xq5<;t~;eV~qI8GY`$HjVYd}xiae+&_zgT$Ei?@nx!_hW8D z7ouh!R0+0^e`6f`C{Xc}Yd*eSUTffpTU8O)KpGYk3y{BiU~I-Fnto%3s+06+YALYj zTpFO*q5~Q_@d}l`8OxG+|JGUXiKbBV@l2~;R!;(Et9SXdCN^&5YapEhcOM_0=q6B= zQDg%*n;@6qYr}GEI66eiiKtNHbT$Tnk$Vdm6|&FBasUTQRf_0ibo!FR@E-%zUfkE}J*%V7<4W=^8NDEZmK~8#a^Z>o!%Tqt#Up~{S%I;_R6xEw6gux zKO5rl=i}qY_4t+oZ%%NZsM7JW^}t7aQ6gtmZMraGE0DNNF{0_h*!D~6TFn{s3i!>Y zD_tglhQjxYCsrPQi@LbE5(esaN@y@nNuJvXv+@Tr(H64?_crvqA`0qVqsuapEp%rs z9pC(p!QYEfF;$%SNHWzk&o@PMUxq+Ej_Qh9H1>E(zfz^?{zsZ#SxU5F;CAsGp1jPs zu`mtwD2?eNO4GK`<;lCLYeU^p6H22^suG7%r_b;X?A$6;-Z)z?6qH1nRl`{@Eo4Gc zOTS^oKJ1o1CmFeKBU%~(z!zaOOgmt(rc$=Q6ZYud9b@}qztY};vR^MvfXz#(AQ#7Z zJ})q}vTp4QTY`OvbCM%|9O4H^tbXaQHg+m(^d(T`k)TEd`xnIRkOcIEC~jk^5j3}q zNLE!mi>Vgui#M}PY+^0!B!N<-j*>J$GmDq}r-H|pup0CMw7h__ijmJuP2LAkyzN~n z_eA;Hm#{Bc{@GiN$hm{g8+w#7{-cw^^O3nUGr=Rb+Uem0Dhk#0)BVIfC&R`E6yh`a zso0|_=iuEr0Xs<6`H5Z-3ppV(e<@DRMkGSr&K8h;ZA%V#uKmefX) z{(PL=!8{N~a#*lo~vvtjvZRkRBl30A<6L@&N%g9V+ue<85LzLo-Q;agL;^0!2+ zSjz;ef=c@Oyml<8cSK2AuBRm&f~GXzYUYex{x=!=^~FTL`CKxQq&0HNp|&Z*ZqC5P z!vY~rZpSR@5Mpv5x{?d!j}5Pujw)=Y+_}|x5?`x= zAy8$dz=D?irWQ$MZ*&L3^K%^So|@t^D40h&@C!e?pA-SW#;l&u$lI7@d%ZEQh`#lZ zL1{l>vwIx3@`EAUk=uqzt0VpdsyJNOEC&r1AVaAqkcl{^_R&|uX1VcV&!$!F?z|C0 zM5u?pcrFaSy|>F>vN2uYeO0YQMa6LO8i9%s74pdTjjhc#-eTS>^~1)A8F`i23VEd7 z96H8{EO;1^on<`^Q@*U3OZLeZ*Wa-lewcm)XVOfd{wxh0FYiOEZvX!24`uw`FU~y= zGDGhMwG2xc@EVQ~YhhCV5RG`+ZSzmk#Rf1-a+z0Gy70B$N3ZkZqyk>9WI7OZ4OS)o zqCSv8ph}5CnWasJU7OE}w1r@rT60^9Zl4Q^4WL8O^CgFajxgzxi}Cdgt{faX&nSf} zkzeZ?e4i+gq>1kX<@-bdbJMHBltB;%LjeCDtouKe@>!SX`;So$Lf_y=maBhYi*Wis Iuw144Hz)^9{Qv*} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/5.ogg deleted file mode 100644 index a8a4ca3bbe6f4e3540db8a6adfd90d920df63a0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2111 zcmY+F3p5k#AIDvr%SM<{sbMoj{w~d3t`Q0~HDs>SVy-ixynixYL@c&>b6dsSikHli zJ0Z=jTuKQMMR|>Ksc7Em|3Ck~_jk^7&hve~pWp9!&Ut?4{G4$(6rTX!f8(X}Q=Q%I zoGUYfU&c8+D)Ll-FP5L*kiQ-C3vu4X{};PBKTjQuX|v`x+r?ddagjjY$!Xs!m-KbC z477B#wRefbycH1YABGJenDIP+o~L8PGj$Y$1O38yiT^2V(Z=I=v0HfeQ3{6{9#Rf& zI0Bv!92!9g4U52;TI%CT^0MMzKyx?aBx_)%Sxjo#{jvw-LSI7B3@WzN>^7w#bdE^i?HvfO5)>GgxU!OT(w19YvZ2;n zdn;zu!EyiOw+oVmHx0M0svifD+7JrZ-Z!1{|%G| zCyy^SPsVVUUSX4^W~L~xDm)1aOE@)u`(lhU^Ib^(&j-p6t`vEXK?fD$=$lr4?*`C= ziTo-da{4nddYnF0#t(J`eHjq563nEtB-6K%uM_*SF{GSxT*zl9tqyW3pV#t+((~N8 zMLRfWG^=GK8`=_;r(lOC!Qqs|H>|MBSPR$QQ?VmiQ9b#Cm6!QMh#vQkeIID^F7ZEtL85W?9q(wu7EKgO0}d z&E7Myc_MpA^G2tX#cRxk+Wn1Z?vJhFNh(T|Z`XStswhb>CFrNnX#Ay|=fxS%S_Q~A z?5=IyS9&s0aw)vBfqGv5rBx+jM<8BhbpefWCHa4#HU1#F7wace85beYD*U#Ic zo4(mlKB~$XHemcPE?;FX{`e?Yn)RY5GpMv1@r5?{$>hg@YMV$rNg3XBA^lDbP;tv- z0QZ2CR`bDGr9t{`ba>|@epM+fM3rI3HWeyfzZzoLw+*NheEdx9saLMxj=uy~w$1nrZ2%8XEPZCP4$S2}N3k*Q}q9i;+(l(yh+c!YQ zm#Y~L5!V3hnaJ|BfYB(6SY%J==_Gc?ux#nLbBJc2+SM6Ga^08+RZ3`|oCvQ`l#6Mw z37lcoIoyeD?2*J`jO+O9=#WJ6AJqdwWnt1a-iJJVx9(YM=b}>j<6cZa5+Msmgr|Dh zWvG5VPVfh&TbG~QTFL3WO-{ET`>&_@_b6NMSRTc1rmLXaU@J|x~a3~Eo>n~ zZ+RZ(w>~mjQt*z~nK0IJ;Y)R9Y=+h33H2Nn;{Z|g(|c8o>JDdfjh5P$iL(GII9h}? z+YOy?w}@ba9>J8mYd@A@j-$jhVwVyUzOP-cuXrDH?m+#=7UFnod$>Qj06CTP=aQPY z-5)F4U$t_dL}WX7%!`KuW@(+B*{%VHm1y@j42lnbqk@+FhH8;S~o z!1Yxwhi=MoKXc~cY>tq;V^N)i5GBlRvxAKx$Hk_bIOJp&ymot5FLMlx!9VWICYn2; z)-RjfK$XmR&Sl2NHHH$qAD6qZhk5^pU^abMP=B0C9EHnX&RgAN;IGP`oGzwU8mZM^c?+F`A_yU8uOsyyVf7!{$Du!A<(t(-&p4;mhaPc znhtugG_$Q5a|B(6z-~^oX<=e{vNzWjoF%@1CrQfy7vsrNkEfC1r>_#@obZ=r2tZiR z@KGYh>gaf#dUq%$yrXMY+?!h9Ik|7)aEqC}9p^+j)2aYZf`G-n(-mc_3LP9L6p|US zy~4#xDj*ZE8Y;JDF{>d|iOS>LKIHV=ZYTQx-L} zV`>_Jr|FB|GPduWTBA#S#gh(50LJdl44%Ee;@Rw>STRUQu9;*d`6-7g8Umih_C7H*xDj#?P?FTFJo8A!xMYxlZ4tE#8xe3L{lo%TA?jkf(|Ll3pI}@ zTKh7C7B$M)OBAsa%8SnXy_)ma`Of*i@1A?_?{_cU-`|OamF0g?|AMS~n#xi5^Z^&( zp|>Nfe7$@C09`;U@;e27O8UV}H zv*sJ(jrH*jH)Qs_nLRZZZfDDWnhDg4XWq~$N~Q{&U2x{=DN0w$=)ph%xv5m-!Q zkiNc&zBvYeQ4mC%j>k_wtfKxNg&6if7@bIHHRU9^@wDU$Fpd?8ote^uW*6Q0k04w* zqI^EEpGq9``CJg#JvNUSre08-Yg$!&q|#{Vw$tDZA76sK7w+FSF5Cmtyo~v8hBrRO z#2MRM(jXUCXE(w}bZSP~qB@eBa0rm(qI56^4{D#614-aX$siH*aL6#DeH>9ssdSuX z7wJ{Fg~7|o-k(t$$*#!y&(Hp4Hy5^Dw%*|(Dw131bbsxNl+1DDj<75`Mr&>+n+p;1 z2X1T5FyZ=B&D~!NNK=)L%_*;IVjL4{e~#mt_3SFI5yxh06q|=`OuQt=FCDeb%fN5* zmcexHnm$hq;yJF<@?&VXN@DOb;*X`K6^56A$Nax(DqngyB4BInk!4fV8{v{1~C)Y#C zQWmSX6$c*%f)nWKRHO#qH6+We-b5qv%%zSzsdj4;4ayHTaVgv=+kL8G5J!#a(g-2$ z!OLT_6ze#a130+ltMG2L$4lvIn-n;H4y}rnq6kQzrx(2bQS*ak{3yibf=a$I4;C#Um{X1oA-}TEz*s1-)U&*tDwgK9;^kc~ zx$#d%X*?|Vy$Yk3LZAN1;gFVnp-|p)F)6Epd0W!I5{eq^3PQFMZ9+)>`)0J3hD_vh z1>2G8#i@308^<+X{Stk>mQnT@AF&n~zuzi-vn^rogJUD>kRVEmQ(#fg z)=7H2<+}5zGgmcigRH9vY+N;2IEcwyya5sc#Khv)s=AVcSD8ynQS_Z&jy_xY2L#%b zA$Hi^(!cU8DRRnkyST>tOWrUqWBozqST^M@wh=Bw^LS=KB%he?%7^|M=)Z=MFDX^- zYo;gR5-%&&@jIlu%369b7*ke?>ms%q$tPw{`ehYUcOf3a>mUGyZrs2;OIac<%lyuC z2oO6|X9xWDAut4yF9`I@trnmy|MX@O6)13&dq-V&K&f3{ra9_v+1Lz^0>Z4vP9&`; zzwB9t;z8e#Wi4lDDk=Ac{xu4@zJJ!frOf>HV@DUnhdwb9d!eQpvFH9$F9t7rC8wG3 zo}`_iJ!eFF8ePguX_jzkn+fg;i+tDdnymVOz$W{O@BZk6AU(eZ|rHP)it?^TzA!^-q0n{5~~QB-tx)j89$15i><{<~$HgznoD}Vu+ee z&bOsFWAIlbv!eGZ$UxWrnFB#(FgG051SmvJ@Ekbj!s|b3#QLLI2Q$nv|E1$9yx<_I zaTQkbVz=1HOjg3+i}Ie|=ho<&wwxz@c^P@Y+QI6hKSahmyG~qjP35du;WsDlRL~smnGFT{LM;lv<4crbu`Ipot_;QC&tE((?-WFnH$v+2GhWVz*o=VCImx1?LKsLoL2q3I;i(>9 z1OTCl1>jdj1k<;79I?BaDG?a_1wjxxl@`0_j{R(H4o(*=mhiyOfY7;>+Od?8prQ&dsUz(^NAJ!q0>6zM9th*-?C2!EZKLZO?oAQ z(CH;C&|}du{|Pbmw^p37Aib8DZe$osLg?4sp*LAU)LGwzRfP1ZJ@L9$$ zenrN>!O{+yVV&8liK~y^Hz~bz1NU-l?hmnA0Y{+YsIM;E5Y$GMN>qGTJjI^X_WN(b z-Z}f@H(_I@Rb!h@>{nqh7zWSB3+xG(n=z-kY|xwIpWL?s_C$C0AX-W1rEx>_{vRl1 uW3wN__BY)90}%x_&v2Qj`z-f`+F2(iI-{&`p#RO6iO+N?VP}<0)cs%jMv)`{ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/7.ogg deleted file mode 100644 index 09e7df4e6969f50b4954c031a8762360ea7e2d11..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2157 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 ZYO&(MvI6vvrd6f~*+x(Nfe{1<_ctb+K}-Mu diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/9.ogg deleted file mode 100644 index 4108458ae8bbad3423d4cfb023b0f14cf226f547..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2020 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 Q)!Lc(-**nz{hRpz0R3_UBme*a diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_pin.ogg deleted file mode 100644 index b3e55f8c9e811b9b8fa43c1bc5a7c7ec31898d7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5458 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 C8Y({k diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/es-ES/err_reg.ogg deleted file mode 100644 index 509451e4806f339cb959c9bb93bee724c4b29ced..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10160 zcmY*<1yo$i(k>1`gS%^RcbDL%EtbD8-?CftGq>!JLlZCUTm755p&jQlN zApq&*pm4A=cZR(9&%ol{5I#tG8~ANfp86qOm@@L-&OXl04lefQ-rhc*p0)rW0WQkX zZ)v;TpZDn%!mPA)O72EW_+tpSCcE!cQd&7HG% z`{s$&n}j{Lz^}R(0K~>c_HAQ*(xsGswi8^An=@Ogb%#aveO2lCd-rnukS@w>WP?4W z)9dJfJV9bTJM%gm)_>xX|2T?4vx(E`+KI&;gTr514uB0|*OcDsAe&!_8QRWW^^s9; zANmyXYuzC-Q)Tiq>k8+0?_L)?KD`XL4(eYMpK%ajjnN&ZzFcf-QK-?h%+?s)eJ6!k zGNvZK-TNREomJZTFeYt6eqBzKxOZi*Hot+rxfaqk|LY_3;%!tZ-rwOcE7Eh5uoL+?;Fm%&Xjp@rZG!Fhz|;Z@i`Fvw6lD?f^52 z5D~JgI!p9L>n!;^@S<#WBj>MOCr4{V!NrSfZ*n9u4 z<~gRI=>P8<>X<`rir1V>)vHU4X zJkjeN=t46<)G*&l>0V#C(~|H<4FE_*)jGNuY+cWtoF0h3ii&~hHZCnAA_gl5^8u9| zplecK3a|lvm;JVN|2SZb$)+!Cr%}&tfBFaY1d%Cj;p#8-QS5bTeXGL`MY?eE0R#C3 z@`&UdXxgJ^ty>2%U0Ns0o;`|lxV4(GAV5?N0HmSq0Hqsde`3<0>7!}22xt|MH9o%n zu;~>g@AxDJIJMocOCKdl+b(5u<2tt?{ub|o!fGryM8+1Qm0OI6Dm$=#<1{bf=k#t( zF~wdmCWyPHUD|%x&6;Kr-zA%cD{KMlBTbY0zLIK2WP?9sb#y84HfPORq!$Xy^Sk@) zG%vafw4cs(p&x64=5ar}a4x1ChWldt0L-!asL|=Fdzpf5$S2KjhzgRLNHEO5%lU~` zr}J#}GQXsOK^jaE*-CPApVN|*$6AH$xT^m^aazl<@Jocn=}-fJ^i&;9;qTTFdIF*h z^ksw2$;cH@4BHj+J0A6H{VvVln??BXv}j;36-&M*0vOK|p9snpfKv*7o755Ig$2I*q7`tk+v|HFc!7L)c`9^6Zb+7K+ok+YZjAH96Zu>KAUOq0 zFXx~J%8;&ppzN%AuMDB|Roch#+EILCC=!cy%R4eno%t-X#5;O6b^ny05p!ysNnM0bXX^BBe-qsV%nDf>4PRq8bEdci0jU9#NQXvAg zpr0%?c$Afw>1A8~i)TIt20vg`hy^*WT!GZm-3@HDZNi9dNw;Y?kWSnu>)ws!m(^t8 z06V7(m6S^_#<_S}mL$tA-=F~1pA-asK|~jY-XlPWpR_3r%c8-SAx!2grcJjg%6_Oe zM#oHt92s4+)81Aow>Iv-TpjNQM=582kK_Z&y1#TU~${NHE<79i+jTwkJ>kn`#84Y zj~GLiqovDXE)*W(POez7n~@N)^kAeU*_gsc)y((vt49}r2PuWVANV?g>QXmZRc@Mk zCiX?4);(Y3!FY}>x(Hq$#Y->lz{JVWv%v--0%Pn=FdRoCy(pwjc!0@+Fd4a)u;cmP zj3FBNE3W729b9(iXSkDyhn0fFRb;mlS9A(I^ZdcRRBswnoY%9iZ=1MVxhxN*(;8kK z*JYwcy)YxW4~mRi+8+=MYSC!ru4_hCMVMD5Ky!Bby}$$GZrbLIh;V^HIxzY$(1+ZC z`nwTj*{a>uigjgPwgenJNH(omss(3ftAvI(oc9qdm1fdRb4BZZ@Xd9d=gqLS7hXBd z4E}jWi-dd0HV@FnmEmCjs+Ra6*f3*vHYBp;8@A;;N8FC*rx_kg<+gk~-9y!cWFH*e zR~M5upi44$MNj;^)vaL|HZD~FEf^_d$k3*~_4(@luD6i{VZ%=h#agkTx(7MIzV6U>u8hvF7GsF(7s2`pF85?%anUN4Z^71nFN|bZ( zY7dn(=^s=L33`Lze^3<`Qttsa;4v*7?c80R9UZ&?4)#v&UN+v4jUZ~Z>`l5r;+_3t#>ntzR_{6HIHU8x0!2WgSjgpCM2} z(XEEfOYg2my}(Xyb$u?&*YnCQ8atA3`V&VX9iJwUWU06 zQ@rp;3SN_DhDfE%SP<9yeQnsCQ7O2+P3vFDk(1DA69h#AnYDw6@Z)!>Piapc7W%z@ zV>-Iar@bVg`Vgl3F+2`m4(q7XxsMMVe{)6++Af@vd8MXQ!# zm3n71%L8{od!1_b6z9S_cIDE0dvQzt>=RP`>TT7q21!X1t^8)J2WSO%Tkgl3zv+H7 z*~(e0$lH+YdAF)Br1>1`f?9>z#@R}!S?X2c)?VjC(sCX2!bl7em&Oxj-y<)QOhc{; zHK=$Sqk}Nntnin)l!u1ZbN(l}AltL(Vi~z%f9!HP{Eb$37qlgFo5grP3rs zJ2mvYT7BePI{di#pxc%fOq0``&pwK_uBMdj4dw87wt+tR5q&G$LOD+hy)4&dYZyr< z4t^vsdKMy(GQT?z)75nTyEQ=@wXPMBU-_;aR_{C@U`0dS@lyBW5?qP~*KNjb~cT5Z^RNcpy@#;4>M)+z2Btw$>;h=M4VQ0WUYGwdOD03bfkxN43NB(Y1J~kZFGc4=|G<q2+5rhpoMaWG8Iz%cwPl zklh_m3?Czp>YWSV7_(8FZ28F{xftG#S$XCUOmq^Hw4iM&sWClmF#9kdKh%B7j)6TO9qqHMD(L36#GQ{~5hognvO z6ZBUSg;%WGMd`7kO=Sf(D&*@lpA+A^Zmhfi%Cc%UD;clO=cxu$TdNxXe6q*!J5u%T zXe=sf8Oh#w6%HCG)Q^JFaq!g`Fh93H&E_hIv>ZU|eE4#SCI6-+O^B+F?<2J+jwohX zY+bA?+J<$-C_3Yl7o9Ho;h-%=v0Ws%Krg(gnWchqK7KHbVmsR1M?Wf@L-*f_zOG(V zq*`@aM_v9JWD#@G+P}`x`F-~7EJ8EH9lbGYJ}5hh%coML45O7Axg|w?RToCe zgi)3Bzh>w-Ho}&aA-ingk^@yEOK~8;2k)v#GZb4y>|;9oO0@|O!-W7LC4Ia05&2Z( z$mb9jmM<)2M)9>CaX|Q3DQO||z4rlipOte#I@3BPVi}(k;5ACM|F9TFMh2bn3yOy+y@v9c|yPeuRKJc8!xY$1sA0z4w`^+m?vg1}=bM?Y6jiVYw zz1c9jHrZ+F2-MEVq0D6rRg~q$uHa`{TYb}atdH+qtYYpbY7how)H=4>4zYJrh}MdJ zYPg*j*1_J-J&Q)H?tB71o5;QZ`RIrHl33q=fN6Cjk!YRGH1V_%GGNaT4doLG0rwX= z4n7_rB|gF(+PBl-T^>O^H>#G5%l40+>!;xu#-cR`k+$E3neDjlWtZ=qsC<;r;~KXu zerOQT#@?aw&4D)Cc7Z0st)>k`;6PY*B!L?^6v?v|rA3+z?uVuOi_eoc2l%o@7Xc&J zt9?0-G%Tdu7j-fyq5lb9I&K24%u2C@%z9#_%nD>*BT$oSE+d*sm~+r zGj{k1{{GNNt@=2yS6+jPv)1Y6%hVAPQ{(x1)59t(VSNaKSJIo60V7HM+On@9VP%H> zmUv~Y;9zJC3`u5b;g0fTM~U)UzTNOzt|k2keS1Xy39sK`S~v*$GR0vaVLG{ZI9dsd zvI`2yc)Q!WIsyPdT52%23N_WlRePLEnsW7cGVkZm^Oa`C>21_1>ZIjDf@vr1l^=Qu(v>?DxGPLGVYlc z{W+Tzp3I?7-quxiky>Bjc!LixeyuTa6!)aNR)_{B$NCd{{<$mIiQy2Zm)qyu^ix^3 zVq3fFh7*o%@U;UI?ZCK%6){@LgL?%~ZZ5R8i9vvmh!*+qOTBzZj1RP_Y6`OSm*8VQ zFlcxCm7miO^{Q}0;zRk`1Rt3QA(k&h9$ogqVk|!!qHX}T*ksmB9zbvqtM;ZO=Y#GM z&(J90(LTV#7cLfb#Zc~qYMEd%@qSl^JFIP_9VlxVE^g8o(&!+oQyvYE7#A8s-JjFp5|X!v{w7z6k6p z4!;RWpLAq#GE+}OjAFq1 z(>{1Z==?E%Oula29O^8IlfJy)3=BoEWH{EJwT`W&*fH+`KwK=;!{88wYM=m{06#O~ zn7E7)(T;Q*s!WR00>fx{5aTaKFMJ!BN_|wB)GSJ-jFn5rpp-oY8CUkVbO$PI@TKX| zE00xYOmKSk2o=p>Ytb%MdI_yqmA!43cfV#P z;9?CfuBnJQv}k;wY25MiF+27*C{a#R*+t)cxe%)PC994GjdIVjpXT^5Xz5}@&Z^2> zmQR$G{EU%#3Ec*2f*ad0+42goX|Mz|M}Bg1 zMK(=j6D#5)H7Lw&NwR%eG*e@F9!>G~okA3TfNp7!Ut8qK97vv|f3r|o3k6$1i(wwy z;cCZUwU#3kY@wF=X8OI6OWW2#iUnmw+!U{Qx&`BRy?@FhKwZNX7=n)H@(H8X4irO* z?;BKOQ9YA{3LK7%_%xv{+Y{s^Mc`zx;fcDft@9HlY8E z9!A&6;ZvUTv)Qpz3E*lcwFW#QgsLC-)rq^7)c*o1%S5N=ZkzkCd|PRERl~4gxd&=XGtW3mEdcTJiaH00YQ?eR0ga>KyEj|-Nca` z?h~Xu2{}Rh)EpdIOe)(JqmQgRDSF=@Z(6!Th#&i2 zBnu-nv-pu+N3#BQ?)&G@fsnLf$nBOV1RXLkGC=r_fI2DyqCsk!Hndt2HohbEh6ctG zOZLK+T%0go`4@;~BTuJG)-%pR9e^FQsZ8J>Se=9wiN6IIOQ@WWw(s(~M zus;1tpE7@L7xf@_`fu*_`G0T%{}$B=fv7PZ+$DAZmbL>3KL z{990p(#dULjK$r|?42T^rXsB4Z3EWnnffiw*DbD(s|a(p-`CrEP$nJiq}QP*3!&j+ zvF<(;mIpt>ZWA_{sZohsm$R4W`j@tgLfNicI@{G*vsYaCfiw*xiK6pgws#AY^h`8V ziz1;43g6OZZKW9B1;#Tb1ypy^=;*$r${)Brm*FpjF&+D5oCr2xY z&p<`@dFtLB_}55#^cJURnSM2B!>1HVS51p45y@+e-DS^Qj2K_oj@P@9gJxFv78eeFElfXd zgCr&?NL43ZZ6KON52i^*Ezgxd;CTE5OYS-@_T_T+*3D0$1rG0Fxu57r-OFLPy@U#d znWkHud;s&q$aKR=2`Cp4u)&Q_vh+B|o6SSUlFGp%ycgWzdH8B1lxJsS)!JTuFEph6 z2{7~Lfrt{u%O+W|oJ_qQVsWU!B*?d#f%mHSL%%h5`Zue%S^Fhlyrps|vlY}W>FTsi z=n;|-1=|^ks0eG&eEx2aYndAchCYmd`ioC8sN%npTW-@NuIDM{&>6 zhqoBz;CBq{oC*uC`qBG9ULgK>jGx>2*>jR zH3?h0$lUz$_?fmzWNKeYVUk`CKuj(glMAkWB60)svRwtl#8IYk#`@*2UgEQ0ZQ?xv z4QLvDh<92p|Js;e?8_T^>1%hoM_41JiZemAX5w2;PYTFgyT+et?BXiN+PL! z67VnAg@2aK6MOoOiY3W!#NIaClR{W+Lxl6#aYP=Q`={)ti*DZvB8=p#-n}n0{J{2F zi@C9V=;?={GoU>#wu@|gC;gVe^QGdH0hI$<*q3t>cBsSJXTNNFRhM#@OLn0f1iSAH zEgh6LnOfhNLfv#X#?4FB>bj(%&-&omSZ7`QPR)<}L=ZI8CjihfhLDR**9HrX9;d*Q z7~G$c>-)K?M2=!{;H#`;*LjHI6eU&r3w4o`zQc(;aY)nSA4tcqaxkeZOr=ZSaSm2yV(13#A;wBk< z@G)aB+Mmv*orcjFS5VPl-9~3W!cL;zrBBzcyq+ok*@owwhDao#!o~|XP3x{c0UTsy zv~3~|>bD;SpI$mZX?fsiC614S+x9-2`li=hUzrk*=`g*{Qf53;%Eaf!gk{r>k;yuL z39h-U$V#z-UQbKe=KPA|8}zq=p2z8oh6<)!$=Pe&@{|z6R_4qkW(*vkI`oS&l7>IE zV(0$Mf|9FZgovbWi|Ks+cMjndHPa>zGaK4`F<;EY0_x7F;)PyF5=v|5f;=o1#nGsX2I zB!^3b2AJNNhAoiOFvoAaoDTY@E@>T^C5^J%p4qEIGV67`t2QK7rs^K( zLM6nH_0sXMwE?&|TDy7z92}h-AlO0PxEM+smZ=DA_=T%_Y)@IP03WPkGMr?kK1MPcAt5UB&qi6Wwtw3-UO2g65=>iZ-?VJe4XxkmKJ;u~(cq zKP;xz#G_7~K;_3szF>4Y`F?YVqeBmhDt)fsxkO{m5?_jK) z!d!{CGJDs&lk$TKhf}Oyzk{h#gRwV^{#t;8At@%~3d_eIO5u7o{{DWS&#q5Ma-A>gd*HWHy1XU| zkm7c_rrV=}otG69ySlU7FaQ4CNIZcm4^0A*2vKaI`(fZe*hT#b=x-fex2wd}AGCj= zQV;1p)EQWTDn1l8P84OJP~luFZ+~rStSJWoNvT@0ER@d+d!H|cgN(XdDRaudby6NE zHA~(dT|`wi4RDS`i+AR@B~Uz2)Jpm+*{)v0vRp{sczKlbna2QKpc|Je4I+KD>V9hb zz)*N9Td;E?^>WlLmsqva^z8}b((;T{h4MnqiLyzd9c1QHE*fG2@1*6)C0r0XHnctI zVG&|GKQ!SWpt2wwIG7r!fk>4?5bdbb3r3EQ>%) zy-+@BZvei?EcDzG58Zev(#b}zP-MG6fPsoCwcRHn7mKjnHM=>gvE)MZsms7hC7*Yd ze-njqDvha&Z6me+t7w3+CYQA3-nHNJ_I zlmCdr#kqr-#LBVl;HInV51?K4#Hf<)hW>mlN9t??T+2Iupl4GdC#iivDB_iB(q?!a zr_7qDp8EQ!=G$;}b)IcFVDTyc_~REqg>NN$=*zDwR}TY-JgT;6{9M^~DZzdnO#EfA z3OL}2p6y<=NaG93-Vq$n$Q&rtp)s5zzmW*rhC_a($aor6==G*K-Gz*1x{a`&4rCI$i8 zjl91|!&X_v7~XY$D}~=vd6Zd}M4XXE!&Zx+{w<)SbT1^D{TLA0PUB4cmqFm3>~#K=mfBC8;4g$GZjJHHXNmh6g1-5( zS$T%sJ1m$C?)_{eT>7@(;aOK4D4xzoQPI8Ut4w7m2k3i?$;u|2dfFYY2l1hkFK_`wv`>!jN2`#DHGg2UvLnJB)~V=cjj({*{GBbVQ38aO z?LwgK0|X8gXoqI1i_l(hz_Bfxb8e za-*cR>PPSi5xYbu%^aKvpbNC06Hq#d`U$WWm8SfToG%6Sz4UpTrQs{g#T+;^*(^|N zDX=a-oP0Jac=It+His`NE#5WMumkJ*T&vj@zUAwH97bcw~kZ)3^bs8BN#F_M3z7oQ3P!v z(6Wra^0;y>{9y><@KMpHaK#TOt@N#Gd^BWt;8N;2O-K`Lzn&@<@9p7bnk_rxf{K8Z z2>0f0O3jn~B9dsih8|0JWO!m_qTi9>i>;5OxYmVStQrn)vspC-ylZ+^hD!Q6L-Z`Oim9f z+OfIT;%sWAI-fp&>8Ie(;PZT$Hoq|@=Nd00KQ)d(6X@DlYjJeVK#sTqAXuRsW7V>c zD%g=UojZo^sum~^aLgaTk~wM)9)8=#Dw)z-S$}GUj0oKEX6K<=XuM*kdyyxg_qUa+ zA4iwXl^62;smA9G)$VS6cYHTn>v0*A>?KyD_E3qoO}0HlU51qWWh~!jQc4A}X>ls1 zf0t?7+A)p64YN+=k@9K&W+Fwd+@?p${12wW=?K52MgPH6L`Yp^Y`Ko=;9(^!Da_8o z3@L9LkiX3>Y(&u^--bLehXXe=55`5`>+eB`jJB7)YF7wX^C-=+Oj_rRi;okutB%(# zd(Sa#XF}!RV4cj`l~Zg{Z>ueFo`Z<+BwU2Vyq}~}`DwsrV^%Y_w=8)GrE#?NEKhLM zBWO3A@alR^+rIydpM8ei384hfkHh%_vqFF0-MiMTA#-(()>GVJ5ES_#_puFXOd3bCGYKg=x zdW3cB8&3IbrrM-+mhd^DsC9H>SI8{aM7+@1Nx-~(2n>Us*nZ$t3i%X!U;uqvcp=bHkH_4~0A^I2)?uUt8fK6|K*S-3ZVJrm6GKA%EFIM{>;XTvCZR#44+%1kk3P zZLQ0UVHg!IAP&bK1`Q4i3i+1(kXu0PE&Tq;sKxa}j?#0+ihtH!8IpX&KpY7-lqQvp zvGrYXIbI$_98u!>Nm#+tvdzU3dW4NQ>bo@~`{RDWAy;4K6aYj+hqR20>h=`OKZ+n) z|CcDlqK>(|82KNSig_^(fc-!8zk2gHuKq<;s9*gbUI_iK-bUA}@&Anjp+^2aZfDZJ cdpnc98}RbDO6qIK;=;p<4Kaz!_HaD~(0cMKc?A1cU7-IS7*k-1`U;irq2 zlee>rp9&sx!eg>vJSfZS;qK^-clv1$)5Ya4&av zUq5dciU~-4;6?+UUjMjxvQ`F+BYluWr=3UXdt|i!ZS_`mJQEiw51gVrjb}eLX;jAE zv(XF!fT3s^DV~xD*SrQWiMa&w>Q7NH-EoE9GZPg7Sc-GiIoOU#qbX)91*9J(H!hM> z-_^Z{QH!9RicApT#KBMkLNV7)qkj4LXOm@bh$;5E>|}AzP-s}WFN5>m#DZVOIVMRc z#tPcN8pFyx_kMqmh2(Tty21BU=xn@e7^etv)%61vPj$`E2@$A*c_TvWZB3motuW0D zYiRccXLJz&sr`~GC6~w^lvT9)NGTYG5)$rEx0f$cXsG?x<@E<;KV=}sTy*iRk&5-2 z!hVdwa%k_Ou;M2J@wQ|AbTK_JXWx5v#mM)om<=wis#R1BM>R|YkJjh?+ zGO5L2?SuIFVKc+P5u5vAb{(P4W2(t$Q5;I%gHE+)Bjik!m~uuzUXJn3*8yhE;HhSf zqDz^CC=D>dLb?wfyTBsHkY-kM7UM0GNnzfJ3Ug0Qb_F7#$FF5O8NcKBx322Rp~zaw zhLAI7m~#`+M}ROv3(B9I6GqBEN{3H6m-Y#;+H8>N6z8v0#kF)$e3n*wfIP0?qcx_K zl*+aL=_;F~Sn{PmJlc3|kIE_KyqzK{xTsse+DX1pKQ^YGCXXsGO!JgevNznLp4X2X z>va&GJ!tp^pO>fYW?IAX(vpKi=sWD#c?z@{J6zQ~^=Wrv3K^f9{cK64Fw#i*dg}*S zO@QQt=`%L2HXb$+t^LsoVm7Nr+m+#%6fb4NcG;ahKPkBB4M8p9AZ1IGOPTZc+y?GX z$wg+tHYvd=#Wa=pTguz6XDc|lHaKl=K}q&_pE}U}w7isgIw4YRXi5_uxN+@S8>DS# z{G<9eeI>r4e3qZh1L?T|;EGAZ0{7z-GTxe=)BYAcj~E+3Dc0HIf+$x7!mcz89bO@l zZPJh==uCNH{z?DYt7;eu1j1yN@*JmBhi>}dbcnfL`&O1cF|xhbt0Tguf~L4I}4?+PTU7r{oiz=OU+vY`Czs)*p`U z8H0T(gN6-M{VFe`+NQ0VC^jJS*#&EzVogq%T^X$(u5b=RAg#vB-`Qca-R&#WZ@YRj zotj#9{)AE03yvdAh~I#Oer;c)yNx6*T(?{zP#?* z*x+6S`tzQHRJ9lL*i#Sj_q4!k*CB_ICs_-OP8uV+2>O9hg16U((-xU3MiU)5dLxWW zOj@^1U(*OwUe=grNi`bmeh`0u4FK~?U81uZPvkSR86_~fwBAfs3WcF~Kv_5S)Io)D zw~wXH-gCU|dAHZB{U~k?r!gl0mm8*nW-|qp*`%PlgkmFsZ!ZIQ*?dXJY}7~TPdZE9gdSa0vi$}oynq-O zwb5$URqyF;$(z6DIUV?O)+arV@RXXIgUBfI59hb%?P%Dq?4vS|EAHW!_V@#Y z@JX_o4z}fHgELcw^UrqI;bR+3@1-E(cTiB)B8e>L~`=#W1eutW{?liX>jDI_34)9EPbAia|cNPA=*A%|%m zHV=Jfdl(kS=#rrtGP7eZs*XGQ$p=nb_J>T^TjiRi2E4pY!#dhL$|OO9mYQ8JwQc+EgHcJ%pZid!6tq&p zk-t|goxniLlvzI3HJd^ca9vY}xn0Yx`f-)Ca#v7Mvnq3mVY|?sK#3yPW$*7XOP6G& z`A){i0T46{CCJ-6EC0ESr*OpPO_35ICp1U0Wx0xxQT_HgA3}|E#88S9P?-&HtB%FF z+@=$Sjr*9VihhAQBtm4U31_($WUu$zSM>L`ZLcJ$*@K7_ipf}(`1nk4@&X02{Hj)d zm90w*R9y{;_E98_iT~;(5^*J}|LP<${u?+_CPwe=;S=O#AN0@-zi`u41#9Au#)rx0 zQCHcEKHs^ih1mZA$*W~aX%$iQqjMlot;e3yj&3pU;Oa2#M1anXEx&Rlta`KXz{yCs z9cFx2QtfAfXodqIF})u1<3V4B?XTVs0+JAQ!MFptDZ3H(^?|m24)Z1TG$oYteCVG> z7>W-R4QzbPUOf&`1N%-nj&9~c_1IcQGve=^iC@1z0+=1i$^Z&Y)d?&Q4RF&38hOhH zSs7&WB}Np3N`h*<&LG6G_1mcCj5D;~hJBOi;H%^&%=P2I-HR#II|RUB!gTqr&Mwi5 zhnDA8-8`Bv1WRmDr}#xVJM#XkdrjDoIS}^j7j#I#EGP2Q0Iw8#^4rdiXfSBuRR$fEXh763jkuL$Wu)=m=Ft3rL6p|?SgPAg^+XDz?&=OsRxBTg(z`VrSNVnE& zY!~yadGRPimLBb`sgLEW|D;u{OHrs@Wq)4avq=MyaTHsso@$-&>>-5p`J3(>xa=8C z*p|-R7G_e>NZaiOOL=K>jQSstu<6T@T$MDN0pS~^$Gp8cxyx#rJRhQkbS~E^OxN*aO2r;Ftyjn%Q;Xj7lwn2=v(dAX2p3aZ6+U7-$!ao0oPcc75n>Mv`leDZ zzJjH>9ls`~F2AUpYOae^(MX6?_0E&3k2rFS#TS(sRZd-3s-7#MscE9(AoWsnIR4{Y zXn3dbhr)Fymb?(54QFd^`Up}-f+9b1nPUD@;~_QLDAU2FoX~9{F^p|h*jLq{>`TuX zJF}mV$t@J69v3GP!V}l%+(wD-I)cdKBdS-E`p=Op)2!l)&u+DRHY{!@69l8iMuVsB|fxSnFhs- znGj`Cl91OkRh@ zhFj`fl==N-86`_PbYHF0V_Fy60_gnG1AC2n6q>Vrn*D%azk#hkIiE1GecVhkKAB!hmRJ6ZlTf+SP&#VBZ%|CDUx zi?apqE)w4WJtIE&prm%WijCUg*xj+nS=aAjjor1bC5G&gWNEOfeEyGTt9 zB@>pUsFwknXT~MQ6rEX|&&iZeiiaZBD7-%)4+k^~&5Y@_hjigUYyQ;pqB`iz1IIZ* z1B|^))VWCKQSV5)NgJkX0U{LYc+x^65GP^~rrU*83nQ+=OA>!GliaDtgDyraO`8-N z?g{m+kEy1htX~8$_SmU+8Dmz40{OYmekYDa!%0tn)Uz5laoRqSBYe2G-jo`&dOeL1 zGktn$^|jce-O^TDR*3QKW3SlXWff|OpK@G}zF5vIdN@$o!UjsOIw>Y?+FVbUL+ut@ z_V^-+(ftE=4!$aFbu4pm*$L@{1t>^k<%w$Jaht8>lTr{RNKCrAUea%t>yslYWT@f+@}k?9Gnz@KDj@4O4?&t9l<{?-elr! z7h9#r8wOKctM>NmO@_H$l8R_t&Iv}h8Sb_N`TbOTfloD$HQIfA&cud{peH$KaBRpr z{7E(YR-JkpgMd^D&NJq2sS|Kw5@_z$#Vbpi=4(9d0(_|tYNuH;sdYOi9Lk%u#a=+8l@)cpGl>*I`sT&C zW+p{9jaEh-AClg2n;8%ObbKNGttPy!aa8HBHWr(D?W1H1JhI6XVL#C=M}e& z^Z7!mFl-u7)Gba8?p)qI({4ekewW-|wWEij7+5I1hR4+|k~Tzd^sUtI2W)NYQ9Rpx zvoU|jYYSvus|6Bjr#za=eUJ~TOcF(jj==Dbph@;Qk$noPWT%3lmxrS-Iq>hqS}kObZ0Cv3KPuRN#Fkb2hEGtif2hBw zQ$UEXkFRqO48g&{u(op3<0JcYp9x>~fC?}Os3{>zk9Ra=x_T!^{S?E>dy{?=OmvJXpCYJ%kBX8>nw_wsX5~9aVWs5Udj}{GU z_t5Y1NTdVd8xxT?2!=b39ICm?Te5yhI4fF#^sVR<5T80Jxd=LVAAE!!r&X3_71xI$ zL?Hx^4b%eesHO{LNSqW~&3=?HKfoJRb!BX&y&8m1hnyE1{D7FB6Rsx<4&6XqChj1#fKT%tHIgU|I>N!ht zYdxa6U+GQPKeP%%2#GaFZ-HbOQqr(j--muTXXr}yLj=oq_=tgc?Q}JDbsjc1bjvqb ze#s8`$)ky*+uRqFe+7U3HSH!3hwIZpj86JY=rQhT48Ct2(&jA^?NZ2~h= z9_fgVe=kmBOH;Z+tu|<2#Nu}yhJc6@l-!lJjunM2GY%?MUZwxF_Kg+8`5ZBy;eSdcdDS zDuZ+OC7gnI&F>ZOtKHm9g+)|r6tTB_|Ace*a}5`ocOANxs6O?gV?BYB`&Fbd)~GZF z-m1Th-}WkMDZh=*`7#Ms>x0k6R_S)I1n*xhVNr**mJXG>O5+Q{p-?iKdvK zGnky>&&<5^?H1PM*aY2y)4F$)~XF~y; z1zV*Cm?a z`7C3164zd2FnpI=uBrudwb+8hnt-`{AGEu&B{?2qa`=z=Dn=ZqtZPE$E;Kx?%FwqEZ~f^mTLT+SY3`@ZI_+a}HSr3%6% z{Z`MtRESR@xl4rb!DTX#+{4sscWbLL*Vr0 z*fTFMX=*Q6ZQ0CNjNe}ue3inc5m(HY$Q)2qDgIW)XZm?Sp5Jhf7v#spFK18QA`biM zFZ(L6-Ti~vczacPK*R#MoNzgWm^Mm47D4jkjy1g|sM=P>*d~Zfg~`Yl@?H1bBA8h? z-H>IRBlDf(0+5ChH6~MLmcp@?!`ZxQh)3hdoO#_6AaFDawQxD&;GOts&h3eho{<2Z z&G5}BN9f&)Y>0hwHL=DdpknGGyu=qyqIv6Op*(j#&HE(-YG!Z6cvMz9 zRHYT+>gCZeo`N2=e86iO<8TP=4nl5d`qR4D-K!xo10(9VL4|j#8wJH0296;TA*LRc zr+dk6s1&fc*?ns1yw*O>e$P71_Vv1L@*fnyapeUu1L$Ko6(j+XVqqbXws zPLYwT0=W2J{)tMT$}0HX6T7~Uhlw!uG1_o-{W#-c{4c9r_1bsT_-C&t`0WDWB`w#d z>oyyydPoUX2GKO*pLv9&L#3p550E)x4!h^67Xd)|V)Pdr57n+$RGe=SaGq|W)4{d;jzk?*~0zyL-+ z??6{`4Nd4(85x=LIoEInv)SZ*7C%*wPMiO*r&k}Op{HU-Z5rz+_9pKH$dXakmM65; ziL?1*TV;85PoB=qp*l7zDTWDGbDtHg;IPo1PKgX~uhwsxWl+P8{Q#Lou2;`=kh;C# z#I^H2AOV3Ox%d-(-L-~5Y!^Dx1xNJE?{3*aX z>4ohufL*Xj!1*xHiNKZ)Fu1!8Q}+^CQ4JCKl9$W$4cwM5SK2cJ`54SJy-pho^~WiPy=fW z6o$tzv5uLc1U^5Y3Y18BI;nm4Yn+MBcZcTKB_1M^4m9FMLDExwhq*4Hb~zOV#XzEY zJHGtlkGqq@8hJFz^_J{9z0E`Os{$3Pvj2Q@aEeyfN&ZwKo-4^Vc?Z{JeI*OvvA&g*Es(KMZ+I#V`gr|z}-RB$B2lg2%|#0R>SZb|*ve#-q-V&IV#f;A3?-~!VnFISH(3G^D#KA(+}8r{Wir))+Q(*ir6 zu0~Iz&Q{vzZtY)x2JB28IBBS`rh7{-`~U?*aDsuKEKtc+=2ynf6Kk^y#IfF z&YYR*s_t*5rno^j9<;afNs!?40df>|KDSt{yHxM^7M#5EuOf z<%&|QAs;T8H?!%>=&B zV58(4v(?No%GEw45U^m3j-XVr!xZw9k_%&1UfdDNLkCcFbTJ4$HO|0JDNRC0;GtB- zOY6FsnhH^5GyVRWK!(y~r?KpZLYc+T|Kb^!z<<7p+HUYTKy69pjM95#lSPI>wh(rj zOm&;v?iL3G(J_Wm$E2_7?6O<4ZkmcwKK~G7nl68N9^Fe-EOI;DfyJ3=2}>wwp!-^4 zn9f(4f<-S-%)UmP-UmRG6=*X6yS672+FgwOnpr1yo%m-+Y%F3CV7mUGYvMMr!Q_-hoFSITam$F=@{AacjYf**3N3X4x8@Z z;Dic3Boh2Q)!gs})mTdcK}^&wUsz_RJ{E~O+BCeWoS`Gt3+}KUgP`eRZxy30-G2Sy zI@KTucxaC5qucC~Lp!SY<`N@oc9om(0ZV(5`V+R4KJ#YBLn}#Uw`kR;L}11@hCjcL zep>YItCVZ2C({R9lj=DX3Ijp3O!Zkiu1Ywrb$F`>gKOVTqL}S&#)`QOu{kTQWuj?R zeb$N{M5NvT21Zi5eUf^YMN{Ta7OTQ!BHmlG*}*J1bQlS*6~+HnDdrr+i2PjFw?I(# zO-z*Kdr<7JE5!hME!R1c)V^$z+(3&IN?RYOCus|7fJw|ZW7fAaJ3KvJ5_Y?cv7`}z zomCUj#EbTg!iyG35j=#CZvqjF^q(=%gE|CchziTw8W!3=p0Zb{70U4B~Q4moOTeEZoVP9(U=CVsC)f?+T2 zvaZaGp!t`o;3TEe(eP1$LLkmdIZpEjXjU++TXSWkiwG=+sj^oG~W#=E-p1&s>-3di$d%CPyLO$;P6S__S;oM#dr zqeDb|m<&q$8>?{uTD?NQ#E2hI}W#U|SK3K)+Dx&9G8-@wi+=vhX-dWxaR|7p`?rLdL&9d%0 zfeDN~@06j7vvQ)pdG=a*ywjP$m3hmnj)l!TS@D(2=X}P?`8gHd5|>;U zGsuRFh{@yE8|V6NX2oZuxn5chQE$H(r1^&xw@X-6y*rFA#n}>^w ztAmAyGtk|`7D|Aw(2PpgcqSF87X`C&KaDO*cxP1LX}J-%l@;D`CuU>4>V`{0N2q!0 z58pHwI%s8tE9yLliYVMGq=&tpkYssXj6Xqp+rkSTqu2>)@ktj7%0BRrO?$T-ilmRH zX!Vu@5;Fl;0RO4CSh@^Gq^%=G_YV5Endw`RJoW==C9t|@Io=-s=0|}TigxQOapud+ ziBgDVzUAWN4$`3K^oF2h+Xc(MJ*=k}YT>e94dMMMuat0QCJYmBezn)eX(ZD50U~mx zVAzp3)0!je;Ag5UImpvp3Q4?<)9%9r-Stj+b#&LRd4xRuvycWLwo`^Iz7mu8v>%#( ze8k@7CrPkroGSM6MNxX=cuc1#jrW$iRn~!6&iVk~ix8!Vp)i2=?uf4m1WY*5N8*j`0=4 zNs@h&-5W>p{#7*)`Mml3X_X-j4SKA7?QRjyAPir!7L3%j}3ibneVXr6Qdu#hpt zge%Q=8^!t9NmsZgeJU&ajvl2*6ZQns@*w<4NGA1^_;H4%=l6OsJ21s=k!H6b6`8)! z%E0?Iy|@C8So;)cYA0z$2V@jlfYhSyUw;H3Hm|9#ar%m%{OxjZ6N0D4%5dX(KE5u$Hqmw{_!A8u7pgB2 zDfdL(5s`Cxl;mJ@s@4xT9jT>Lkf+T>brX7S*x!f5L2~Pc%U-a%>S-Vx47b*s2y?Qw z-M&qnV-^z9v;Gz40O#VY%H-^t63N~mC>~7}R%sww9$2KP!U@Y>-D??fgi#{$_nFSp zMG$XOU}b1U>DQ9tsPYkw+BFpnd&~~QH!&}sVEhE{KEBn_C@W>$agRcJo=yrD!LJrX>!K~1m_uX^JOt$dl7Lo;7Ggt)D$yD8s? z7zlAboO>_aN;YJ?+wMLU^Gn+pFVAXwN}32gXq)m1lv?G+&{$53$~_<wH!p?`Ar1=YO(qOkrcft_|E-ut&p@AC{aYGl5oA zboI287_MQkwkMBhj<6amo>*80pE|&G0)5nd8aF=ceuZc6l}uzw}>gY1ntDPktg3@mKqc|wmbOV`zt){eTN1p zeT8(->cS@pl1XB}X~HrEVKLmkZ_M%%TrA5ZrkrRyrrf{_t@7F2Z~n2G!*BV?>+{xoEK|7z+zdmdee-mT zj@^O)I`PDCV*P~T@S4j6nA%rDsvo#fRa4M2o$|eqe(wY`i&LRR{S{(huNPPpD!(ez zlgoNK<^7>>{14H4OFShc)cCw|$&k>-^o~6&v&bP0Z9$rB--x-t-Yx2#1mi%jyzqQ~ zwLeS3g1^<)_tK+6-SW_ve7u(AR4h)*M9)%^p^%J?sJOHH6K?xC3wu7;yJG`Z^Ms*5 zUg!K_dECJ{L8}7zXc!L3*2eZuuiZyEzHzd(rTYLbWFuR3+W_P8iow6xJ~-pnx!RW7s|8H&2mj7BnPc*#2ecPSJn2z_0sG1SmrX z?-(xO+PFG6TH86hIygDIIJwxkSV4PHt>Iy(P0_`!Sj zuEjTHi?=DWMs|dqlbTCPR1=nVO%x+i*8<=&0&->Dyb{yt!-KnCh9KB4rdk>PQWN{d z3W~0aPyQSvL{GVIPF|oKPI2G%>h~1IsNtAG-MHtyS(?aa`*v2JDm;>@yV@uxa$$WQ z9-}45&5gi{O|WK{%Q5brj8^3^dmo(xKQzo~&ZI^L zM2mBci@SZfJXUvSwACtvTf9HSacf0zZO0xdMJ50B9h%%3nOZ`}nyNIq2uDnPyAv6= z7rT`2H8in1mZ>Yc1=K?x!Z7A%gaVqrUlTKuIaWF+b7gk(RFqWMr+?@zoSME^VR)S7 z;0iFhj7E2Q*Wz;5l$PE#GwQrt{jxPc75!(Qto&ddIk}_-Kv6!xiV3f>n5-a6n@lmIlQmr;a{+le9>+ zW6-mzNyBggful2Ew(88!BLTTfwhI@v1z_g~>uB#!^UKB$2%@2_uOrC%VqN>P00TiA zP0QZ=Y?bU=*HAd*{z3dR>lQ9a-9a{d$gIf1^-}SCYNeTA7RpEc8UeC*@0yXO;daJ{ zn(KO)fbo__ZyM>nyuWZt9Og9fY<@rAoRoF9T)H>lVr#N*6@9Il%gS`^A%b*li0)KN z5tA=h>Z*9d*fayoWl!`tFcJk(Vcp8*fP!B?2_=SGYiql{$Hb@N%2`Rq2}ie>u)kmM zz!s+tTCKM(aQH@le`3}#O;IFF{q3>W*zxH{q)V6{Nu}%iU`Az41;~e805mY@^QlUr zvRV=H1JqnRCOmbH2Rfw6Aa}zu?$SB)K=hnAmQ{b13Y^^TjA<9VYvqRZXV*6N;6J`j zYhJr_DEr4HRF$fpH@SyeWZ(SWndz(}8n|CJHSFdE+kHv!4}%-KTT0eSr`kRuUX^R4 zV_Su~l0FBar&cSPcj3|cSU^79dXXDX!v+8P49DRD4G0gpER7Kno9(;}nXt)^XuG~IOCeQIlX_tlBH#jK zd(}u|MrH;=wij&e0}VYu%vt-p$=ehy57I^j`!$G>g`Onfx$jF=AdU|*5Zc(_MGHP| z;}LCC2qeY^Jo-nf(PK`YnTnI%kdaZmAH6f;5t<@k-Z}0J!h>*hx zXL5DBoQ1-t%<1$nnl@Ru4WyI!e;VlZ(v1v+F~)to`{NSMkTH)`nEq0^pc{Y|{1cPS z#>J87h0jh@0Z}MwV_76?JN(yF<<2J&98!b(6zUBfS^WZq*VT{|j2#?InEsU7C31UV zv%BnTZAGl-(*xqvhhH4Ka+?}1kBoCj&hb!JKeYR%1v`bTBE#wdFItxJ&|RF6dZviB*Q@ z;14WP-qcLRfqJIAfO>ML*008M(}gsb>v+CjKIogALL3ft+;^a2q}%SS0=2G%nijX$ zQnV@N6bP?#SW)F;Z0k&dFe*Q21|l!Yjo!=BOQK{Wa#M()Y#3fdIKh7jeZhO7(i@j! z>=Cq{#8*CbRP{$9&2QA#t)JWa73vZ$cZAWcBif$Jd1subLtwg#MSKQ%*YFR~BK)2B z578n*i5A(f%>c{X&B@u>)<*M#h&+Iu9U4Sb^$c^16twIzEQ3kRGC_RN_ec0I!*4Ts zENBp?$_kBmk<^Xwx?3(W%*srB|g4o@)Jg%o`c6{Rbk>96~XdM^2-Y2y$n5WT`DjljP>&qEHUC8t^tH8jUPjW^C?hqZjq;VQ7 zwNg~*U+oHEy-@+1r>B6xJ0a*%X#~N)l{v(La}!Usv+(*l_FX)W4T*(^&%@c&MLi(m zgBoTBEGMBT_Jfm(XUZkw#XiylN)sejU4G)wBu|VDjHQvV*d1v6Fjg2@^XHAK6U{Z? z@3>1vR#|SD<)o7`kPP-Th6*U&_1h>vwSR)4Zq}pB0eDjkOdGrA#yzxOhUXg|$zLKN zb}6%_@{48^p#-lAJMzV&G51pXq@d&YOMtF3Gwe@u*HC{KHQ4!~Yg>gRg}x?IKI;Gr z(+A7Mi<~S4#tBAwDLJA}+}ez)TtMdQj>{O%_2=GC2)umeg+n@^<a>rqI%+{+>p53^UQSGaIzV=Y`ypO z4nt@&F#>&xdk^OXom#Zc7)MeH>LEe`44LFVH4A-A8UTrgL)a_sx7v{s%@{JN;hz8u zR<}`)JP1n5M=qhWmFU74Z$5@C`Nw`dIHN2-7|$64f^Z2@)qn{Bdj#cb-&G;AIux@w zC=G?ZjFaWG{Z1qZKCz1xP5-|3SVlH*2#T~yY+Fm>z~Q!^&Yb=Wp#vB6$b$=QGa6d zPGD8LMv!MoeF>gI1WgQgXrCi>&1);D&E1)y6T%}8`V0)}cIM;J2Th)j{6A^nKT_1$ V>BxWELgoL`rr@6b*GQ-|@INYmIgtPW diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/0.ogg deleted file mode 100644 index ed0881f476f86a21cd264d6afb7143ef6bf333b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1975 zcmY+F2{aVm9>-@ajqK~+HWTY=ijQLiSLWFbu|ou}0QG8rddhQ1L8Nq>_j* z8B6vhjJ=3N|44%py_7e4@4V;z&bjB@@BMy$cRBZ-`?Eu%od7I=|Ah6Z(#TP_o_;9> zC}bBF6=CV`g8~9|fE}K{5xXP&zj1^EnQC-3ARdT3!kvB45!}oX8=vR^ZB5u2m?j*4 zL`X54{}sPbls^v1^!%8frY_UegoFh7hB6cXJ+U#3$uZ+-;-gJ5st+Csp#37lqp{f7 zaQ`b_KE4;#)G&BOx#V+y?8}0S79YOB)|(DPD9gCwxa1)Ii!bjJth+yF@?yM-wZ)W^7cphhSz7oAlMo>dDXir29^yp{sk!l-4%3 zS`&%WPVu7{yo^k8@!2HP9x`^YbtK3jtQ#v_=`xv{Hv30!52;75efiIp{Dpe!K8LJM zy}0?$`ew;tg-QsvzlfvCUm|#KT)%Gbk)eGPvn@D7l;9{D=s`2gg1TlReAlto-cr9V z8M9;XO3)M$p69r)ly@Q-YnB`0vMKqnK537Vu$RRClyc0I=<`8N@gggFlvlhamb3Xf=NofCUL2_Lvb8El zQF@L0C5TkhXCb*a(32$doD$Xww#&Bg41?(A!V>KCz;y@8;#^ zy`^3BbnLOjz*sZ&5)#%N8OPVQJR>msywY;dM8Gqgt5+l}zKl8r6P20-xC&HL&vl2{ zIHbsVkt(714t%cSgwXC%J? zLABMd9m&{JOMM^CSXoVuC)(^5xD*@zqY+CBwnsiI30AM_7{cJ?Wyq1ahZb6pw^H9{ z%pkJAV$EmAf#tW2@_2I@L9z~(H~Cr8$<3Mv&`o^{SU^*rnE5~puP^&jM%OwueKrM9P{}rQ6ZfgC-T4T zrRktY%gGGMd6H+0YO$zebU-r&htEjExe?yyCHcIc3rl-E z-mCaPD0F~Q47FP20|i{upaR`~nhL;lC`aE5CT*3Z2F7*<7hOHGgTS-H72GFac?PM0N`9CEjS2k$O$&yH}ZX z*(Jp9(Z>BB-_)R$8qsc$`;wp9XH~c9(KWeUjR}*+Yg+x7L1q=>`GmEEU?$)u`0P z25w!f+lV7vv0P2H+OSEXB}mM-pMY9!xxfoLOF`8m>xV1|)faK`sjW{>gPI&W9L|#v zZkS2y!zm>5>J;&n>a*De#vNGi1=H=;KzKpr@a9*}N)|_TLYtjy@w~)>Ne;g*R^Ck% zg$kswxj4K?7{R+g<2rb%O@O7B4+N)HOGeNSz+!sl9Mj#p^d3&PRMc5QG*PEKG7!%L z_O3N?3`WJ_^t&*4h>XsO48O5O4U>(5#3FW;*L(Bj>NUGC>pM{A!$#}X>Gd;CxC9en zu8_RxWuwW2f#GiXuM?|d%PJ8`%YI6S7NH&-s`vV=H@Pn1D z)X9 z?cEX`^fzCrN0hqRMyM{!X67<`nF@OQV^-p|r{RDPQO>bHlNF{gcqxdg^R48oLP?L7 zD&+eT!wLEZUIE%GC2?QqpNjhFkP467wv7o+BT;ksoY;9>sA|=H#ju%gEL}iYsfZSm zXV-!3A!WJgtZREm(*9v(!jC5d7E0Uqo?uu(16TV8TstZRi-u6PKjm! diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/1.ogg deleted file mode 100644 index 401059dd1ebe601a1fa628b3d64a313bcf08b3c8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2234 zcmY*a2{hDg7dMRTW0yTUR}KWnM7qwKp<5AgLM zQD_W<8Xb%c35_*jaltH3_c)8xRfviR!m%6@w@Hm6bd@zrI3BrL*{CDz&beNl8_!Q>RU^RMApR@~8q5~4@koB(1W=yujM zGoH-%KN}Ot3!}^8dcLtmpZ#S+0g{wBPr+mKXLp7FY}QJ$t)4v=Ra{fXm5|kI{*yO1 z(mjpHPw|y#TSU$iD=iz<*}O8Odq=PAbG3X#*3gQ6;!T_PBxbwQC<|Nv&CMGSXNK;RLXce z*xrc7r*lVol>sCrSQo>w^By%GmaOfwdrD(6M?>OI$Efp@(o3oieVTD*A=y4M*Xa7l zMB18z|8!+=h8~DZQ*8)6QeNWixE;}1duL0^J5Q>c-r^~-h5D-cA>vTM4S~p?qMV+e zELt5UzydD9~nbe}vxUrBt$pSfc?6^nyE zAB;p7ZmT4fe&eK)ce|&!mL!=CrVtFk(Z#m{mG(b8BxRrdk~rX-x$qK9JeCU*tQkOpL2Dk_`i-S%2<$-w z+?d?7Cywcj`0y&)m2Es1K6KB?ro~gMX2H~JqEACf0wYWE4X7KsV9(d{raSlw@03}` z1^E~UNX9KxYuBJ5|M|=Fgz5w^koH42jQEv}_}la6d2s5aEABWz`i%zBoK{ z*Whpr2@+%s*FR)wf;_V*?-!dg;IifDu5DZBDx)Idhq+HC&q`V?2bX#evivTZ6Pm$BsM=WFscD+UPC9Vx@Wc&JH)~S$@h1!ZRLv}$W)e>Dx z#uPw;D$&gut@g@qmp&ZYdE^xN!J z-EbLwfJ#VIp9nvBa>nN>BsyA8lQcssEo&^fG;aR>5)$6BFS;-5MSVQ-RKdzTDf$LF(xW(b6MT?aIqU9`-fi=N0+Bu z{6v``2F`UNa}*|+cB93Blx+86t4z;73rA&kc?jdr+@2+VPa#Xsp_WCg*_#TWF*uvx z>;Vq8JZmn)l_u7gINEs*GVna>@fPirkeD4hD1wmqdMSI(>{Gw*Go!*n? z><;#0bQ>PK_HiTG^~|C#PcJgc)YnZgyc;USg?FjW5Ax(DZsfj7e4ur_?dfWSk{?z) zNVX+Rp3sO@D-9^tO4o zTmYf$z6Ekc^&~k-5#P?obfo{ZQl6ezP z8t0Y|!3Qh1;dAv4-a6&b75!E4Y^r3iao1xWrqh(bN;J(D41HbGg zhGg74rWPOwRS_HkN^iPPt@>~#!M#@OZ+UnNX~pmN=_^n3O{X_1`0B_B`Xc#6#Bt8k)@ujEcls z@N}OBKSI?q**Ej^qI*{Y<>a~BBl8y(mQx|Wrytnm+wbA`d-`#(-0Dv1Sx&UJhK2?} zQdHD6NyV*}E~)kf8doaLfbDBT9LUQ;h`#}uD*3tq diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/2.ogg deleted file mode 100644 index 5ee8bfd5e8498ae304ac48e4b535e84443c4f438..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1626 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 W;5MRdcIpCnhc0gjy+ap3=zjxDajXge diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/5.ogg deleted file mode 100644 index 2ac536b76b3776d629c20c9ac6d90c1b4193f697..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3109 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 V%R>K`mvm+G7wyx4UtL(J_dkPB+CBgP diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/6.ogg deleted file mode 100644 index 6b9f40a13833d24ac9b3c1b053353302823b4f71..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1909 zcmY+F2{@E%8^?_`*|&sIjD|3VF^m`!mBUdO8tX7LvW&*Q%n^wU@+mo%IYz}Pj%6xQ zgC>o=I%A1JIgM~?vW+4_mXhz)_g&xT+}HJ9*Ykh>zx%nL=Xu}jxv`<4I3Z!7|3<}p zA8lv&q?4ZnQo=?j#Qhvh3<80UfZ7Q^5bO^Azu3V+fa26WcLHH{aCc&8oHX#piAV`S zA>bBpgo()xp$R;}k!PcVf@3j&cNXvvmVk-S3J(j60uui-v27c`0kJdj&Z1yyK{X1e zTw~(Nk&$8N;>f{ap$;$@nF`(~U7ne0#xA53cLhxMa;EM~^?tKS$wDilr1n0L5E|pBx*e@scb@BL^dYxg; zTG#WUoW;hl{TlKar`2plOaJu&=m%k{Lzb!yD)n5gwthle%rP(3>BDK-i8#Cwq zio6*J{0Z^5?>qB&S&0YWdL>S$V=5N1JM69ByelFj4g7(cTA2&uCJFXzOW~YPuCgAv zYlU~ToF}PGQ~15m+bT@&urL0;;V>}$w8`CWN)q#zQhL5KO`tbr{uVQThTS=(9MasV zh9$LtJFL4ibcT$XkHdPvdFrrRPpM4HgvzP!iPMg% z-#96RIgcfs&iL+pdx&$V48CmPCzxQ@<jZq!4O1HY~T9IDw!dvtbds$*hj2;DzO zQYn2?qgG-*_9?CeDSyw+w0OMj5`nuNd_pMr@n9Pr#hKAPRTsR?h=RMhfqSDYB25tzug>~_o{ZMSU4PvUqmZdkExMIA zQ-;gY+#imgY3Pj4&NYz2;6RwK@gx1_L z7Z~8+>8C%GQ&B=kWk!7vY#p6w|3u_h$6gTEHZPYf8<`gwd)=aNf*<<`_%n2iO<9-m z9=IrZO@t}*>cYVQK4JZf^G2!zzH+qgy%9OWX5lg3AyZ~Xb~?c-yZpEMAx|)4+z`3x zY=g%X_fAe^HL8)EQwL?d^+gK2nXH(^=AQm{qXWb_&yxH-&Dg~L_aV}A@@|g}1l+18 zrNB3XqSd7e)W(F+*hJ|B^~5St;#B+GWLIuOw2xhMat5{j%=uwU^2Jd>M0YjoJE4RC zc7AYiKlxFrOMzMi4%;Tq0X@7 zb=Aq#gW9O902}j3!}KsuQSAUpfu92@%Tx^^CBX`ZsCMmDMTH?ot4gUG{j~-GFW?Q3 zN@bh_Vltf~Jl-_p=%-vfgfv};#JsthdSx?7O3Lp(b^ey;1zN3X#bJgX1+8DB8c(Jk zfb2jeKGqhs4~pw#!y6&VU!p0i`jBUgkQ53l332iWmiR4VPpB$y6Q%nbMrH6hKGO3HdFU|W{5P!*@NA#53WR;0! zU0b?pMmnlxb?E8C<|?EBGoL|1x#w4EP) pM+6wwcC@Jr1C3@^Q2^eR%5YoURTNPFD9Vi4?Y89aUIL&v{|2DUa83XK diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/7.ogg deleted file mode 100644 index 568e6c3781864f650b474e8db965fb554cdebf93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2461 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/9.ogg deleted file mode 100644 index 42023e8f44fdad9b74791673bc990b4e1afcccf8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2393 zcmY+F2|N@28^5&&`aQ4L_x1XIzR&x4zUS-vV1k1^03v|@SZ+SQWvkl_`r`^v z9upNyIvj`(00L3KX1`wuW()tHZQ($nGAJA20WG(1EIybdB^+_V#|4=h>Lc|H5r{29 zRoDU}{38Pb&sqw7{z9Ljnb2vd7DhM|DGdB~Vw)F2PH0<+w-z-u&RmvtaSx0p5uzf( zNZ~PIkpvQfNLGeOfo>n@5;V6A=-fP(;y&})sr!nckDce#&Y$mG`zxw#GdgYCfGK%%u#{ec|b?o*=CfMXK5j^?Or| z#0I=%ZD zbJzE1ddw2ZyEVbv)=Q+t3vvn0=dKw$r3T%lUNrVuqRz8rbe7{seE=^du+{eqw-bGJ zr7PBvvUv%aHbV@7Z|+qX=Pe`+a=)Rt7kupKm@7zeP^$H*M#zgNa)_`%rAUfZ7cwh5 zO*NNDhQZPsG+u?Li8dNbrA%rdx(j>t%RoQtdo(I3`|q0M94``eeIB0c(3jDo)pBqk zF=l>5(*JS8gxc*W)K|CBEXV3ou3yy;TMSpHcU0M^>}M&?G^?3Esn{hr5&uq)za$&L z=DPtm={0O)#H*#F!U@%x3rFkyAd6KF5z&+ZZ9Pmu`uq|B@N5?S zxX!|KjA9cfPG1o{HPSZ812QsOTCCIWa#80^ueZCh zM3Tht!zDzQBaoJ^uS+#PwJN4WvKowa)Xk(hUzD;jQ}G&RSt2_iVfyTI>uacJ|h`ods#$EHRlJBtgiihOdVRz)JHru`38I) z!k54<-8vQtMf0zI%1)qQ5A6xs$6zoVoTR1*^2XI>r{ek)c6Imb5i=b_dz|rq!k4XgkrH~1;xlkfm3)Y~S?slUPpw3Wq zg|=TBjQGg;6R@hclRm%FlNRzr^+@k&kK}#{LkHMFF1T)ndjtltJ)YSxu z9aO)pg`8^F5AbI&$=L|2R#l8C^!i~ z-`LwVj#p}BU~!~B7so{$EBl<#iW-?VP&W@&c7$52(ve=P#Qoz*F>@(^S=NVgrTasl zNAXMTpZ)UcIW*y!s>M(%8kF09W^JCp)lt9!ixbkmWe(Y`#g}X5vfvATAZvJTWj*8I;$w8=m?iV ztx?D5m5-5JH=j5~Sk7mlTU>(L#FSj7XxM2;SLnNhi&;6o(R7aKrPR2H6qNMwOwIfv zT7Rl{|9U?jtZ)>ebCI85w5{Am_%!#vh+n(>d8#n?=pD|kk53)$q&DI@o!^(3tY$25 z4dcBx2lyFA;6A&7lTre9Pe34(J!H_qt#`Oq6rhrF4Hq6}>6P~trywDXnx}V|v0j(U zHcHt>a!mn*($b;nmYULS@@**LSE3C=JMwni;{AxS_+h zyJQpb;3$652jrKeF)GKIKJA_#(fL%+*aue_mxpCz`#{41B@nr5tJp`!Q8hQOkWQ^IRgI~Z%{k`}-i_ za5#~ys%9wp56LpSvTyjLjR~8b5wcylY4;V^vG8YyowaQA8O#i1NRVo@8}g3Xrg*e3 zh1;53ce^0Bm~!kwT~3o8gkrV%KyKJf*Bj#5BWrc0wOjti@)ddUWce>m+B%O%%!EJa z9F^xu5JS;^GxEjPH59^I(x zt;AU{5feb(p(I+UwTBaMfKLJ62F|Vdk*?~!ia(*X7ygn+-UXHzl-aE4G#{yNBjc=l zlc?b4kkuHJM8{d!r2U-d@={Yj8^V+5NNDdk(M*-oNbN_Vh@$`3d21+(zbRqpf7wz6 i^xxQugXrH_q56%bVbK=9=N0PTymc|ZN7lulP=5gm5nJp4 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/activation.ogg deleted file mode 100644 index 6bce7f96bb418e40c59eb793cea45c98b4306387..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12991 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 uz<WXm=FyA@RXuQwar1^&+*8r}K+tF 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 X|Kg(2|8Ohx|LsMie?@_LpMLod%31+$ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/err_reg.ogg deleted file mode 100644 index d2933769fa49ecebd2434893b6283752e312eaca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11655 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 TV2ktBzh--r|Gfn8Xzc$1F}d(` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/language.json deleted file mode 100644 index 784f6bdd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "fa-IR" - }, - "strings": { - "WARNING": "هشدار", - "INFO": "اطلاعات", - "ERROR": "خطا", - "VERSION": "نسخه ", - "LOADING_PROTOCOL": "ورود به سیستم...", - "INITIALIZING": "در حال راه‌اندازی...", - "PIN_ERROR": "لطفاً سیم کارت را وارد کنید", - "REG_ERROR": "عدم دسترسی به شبکه، لطفاً وضعیت سیم کارت را بررسی کنید", - "DETECTING_MODULE": "شناسایی ماژول...", - "REGISTERING_NETWORK": "در انتظار شبکه...", - "CHECKING_NEW_VERSION": "بررسی نسخه جدید...", - "CHECK_NEW_VERSION_FAILED": "بررسی نسخه جدید ناموفق بود، پس از %d ثانیه مجدداً تلاش می‌شود: %s", - "SWITCH_TO_WIFI_NETWORK": "تغییر به Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "تغییر به 4G...", - "STANDBY": "آماده به کار", - "CONNECT_TO": "اتصال به ", - "CONNECTING": "در حال اتصال...", - "CONNECTION_SUCCESSFUL": "اتصال موفق", - "CONNECTED_TO": "متصل به ", - "LISTENING": "در حال گوش دادن...", - "SPEAKING": "در حال صحبت...", - "SERVER_NOT_FOUND": "جستجوی سرویس در دسترس", - "SERVER_NOT_CONNECTED": "اتصال به سرویس برقرار نشد، لطفاً بعداً تلاش کنید", - "SERVER_TIMEOUT": "زمان انتظار برای پاسخ به پایان رسید", - "SERVER_ERROR": "ارسال ناموفق، لطفاً شبکه را بررسی کنید", - "CONNECT_TO_HOTSPOT": "نقطه اتصال: ", - "ACCESS_VIA_BROWSER": " آدرس پیکربندی: ", - "WIFI_CONFIG_MODE": "حالت پیکربندی Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "ورود به حالت پیکربندی Wi-Fi...", - "SCANNING_WIFI": "جستجوی Wi-Fi...", - "NEW_VERSION": "نسخه جدید ", - "OTA_UPGRADE": "به‌روزرسانی OTA", - "UPGRADING": "سیستم در حال به‌روزرسانی است...", - "UPGRADE_FAILED": "به‌روزرسانی ناموفق بود", - "ACTIVATION": "فعال‌سازی", - "BATTERY_LOW": "شارژ باتری کم", - "BATTERY_CHARGING": "در حال شارژ", - "BATTERY_FULL": "باتری پر است", - "BATTERY_NEED_CHARGE": "شارژ باتری کم، لطفاً شارژ کنید", - "VOLUME": "صدا ", - "MUTED": "بی‌صدا", - "MAX_VOLUME": "حداکثر صدا", - "RTC_MODE_OFF": "AEC خاموش", - "RTC_MODE_ON": "AEC روشن", - "PLEASE_WAIT": "لطفاً صبر کنید...", - "FOUND_NEW_ASSETS": "منابع جدید یافت شد: %s", - "DOWNLOAD_ASSETS_FAILED": "دانلود منابع ناموفق بود", - "LOADING_ASSETS": "بارگذاری منابع...", - "HELLO_MY_FRIEND": "سلام، دوست من!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/upgrade.ogg deleted file mode 100644 index 9eff121c10cdf3621f77a49e6b44adc3653d49df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3495 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/welcome.ogg deleted file mode 100644 index 108a62d8d97ab44ff2e4d07603b89495f3afbb64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3309 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fa-IR/wificonfig.ogg deleted file mode 100644 index 179fa5ed5fb6ba7b07b8d1574cd2e00436ffc2eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4700 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 au5Hi-BuDd`0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/0.ogg deleted file mode 100644 index d368787040a11652c49f01e640f30118a14bd2d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2108 zcmY+F2{aUH8^s?~_AJ?pv2>B#(f6J2bDwkGbDsbE|Gm%qp68tRJUDlEYYr}s|At2W=&F%|m@Z_a$XYy}vp^Epov3@jo`?#GbB_ngtueH)?EC%-3NnX{r{o zTnY5mM*??G$a$RYW-Z)$i(ni{VohJ2Q$Qgu0dWtvgp1n~Nfc=XXv3h<2LGwoQ|G=nj8sNgVG>}GWI744VFJl`IDCBn8D2kpa3`U5+*qj#umi4yXHa5j zC%keodf)kICfY(Ja7Vf^P%SL%WKiNft%BGJfM#g=D5ZKHm2?(NCsE+=!Y8Z7PfaJD zyArXlJ-rh~X|T#p;0V&(*hco5k}k{;z@pZ5ztGFKyJqOAV0A*HZcSY-QMea0sZXw> zLJ?^uFz8wKJcTC5# zh!zq>L7^17nLp>NCYV~YDeLGmCbwTuGgItD=4Oh|3Q*IKCFwGJX3J(J{kr?JGIk`m z2i`cZ9*E5@(!Sp=HM={zz{SlePY6918m|$jRVte#Hq;uZHRYF4b!AoPzMYYYd2D2a z1!bWgD6%X-i2by~Q9`0XA*EL*3jsdl?j5~~)T8a@fdPg()QrF{Vk~sc`HA$w=9y`o z^5+=dl8ZVYiCCUKqrE+(R_pR(Q>y=7P6o4}ShxFz=)q-O3EU>8GXomWv&?W@Fr}w! zs>*zkgNs<|U48BLueI{GNZh5OS~ggN!Y{QIc`=i_H--87+@&1QCHVUn(0Me&?jzX` zLF*k)1UK8>f6_SyFld%m-BP+}ofID6F)wFnRqkK@b@YK@=0}>TZ?OY14QmIKgEo#m zhGEtVitDyIysg@#8s|s(@2k?5Kfc8AiLhG=Ep`w?1H*jZ>n#8JceCY6x8MMG%Nbj0 zyxSSfVevjgvt6APSznN3Q ztW_k|fU)`gc>fMh%wAMRUtloV*s=(dA=@O5b~(BBBb?n&Xz84g9CNx(7neFk?}}L= z=RMn6(a!(H0$<+$&0M%AIq-;z#|s73Dv*R^{UBXFV02T(ZE?30Gg2O(-P}bRGTIHk zZAYn#uF8Wo80p^0eH{1bM|Rcdz!2`wVJ(b&sAH0?L2?u*j6{LSSM#7bKb$n`#$-Ex z(P>Eqm|Us}x6V`FszvuTYdH~3z?W}{NW5YuA$)RRag!24HuY08PlqM7xP$4d`sr!T z0ybsLv6tn_)s@N{6iW~-3zY431b`SQnEq~{;>>DeS$iw~^3YFoA z7wS{Uq^Kf6gIw6j8PQ<?}L+*;4t-jf) zIo|srCApAyMdi)pl8cP~tMljA;%6&g=et6V&lQBm?T@bg)@QiQU)|EJD?0vHl)km1 z*~=Bj&u2tgB#JEL&S;54*1%?Kh$bkq0=neoJv$MNYU9Z19E+SC{X@`c3kxR<-%D*U zZn15Oh8(#)rOtZLdX_g+8BP`L)vV*W!{gyx0pITIZ-Duj>(4H&MZShJRCp*ali#OZ znj=vlPz~Zx8`;Lw<2fXB2?g2J1{!xipnak~)R8K# zid^*J;|s?J)if>qxB;C0EchpW5rqJg^zYFASe9(9p>Ek1i>)VWpKe%uedVt!ai9?r zMMh37E6DL^dS4IKe!tmRDeRHmqyyikR9jZdbsy(#Pox{sPR+y`4ZV<>SG6W&mb}Bf z*fZYc4X;8Z+OytHsJ&woKBxERh`gl@J?Re#*rb5lpF67{esAJ7w%r4dceL;pkSLN0 z0Mt!bE?`I@WZ+?i-p5iCSAy^8c*`-;9~83*#>BD%iaq7%OGp_$S5W}?9% z3!;_N`LzijC0;Ee&AIJ%3Pl9^LsV7-;(|HE{Yix$wgMjVV12AxmEs$ WZ(*x{)on^S?6TFNlWmo&9sdBlaoEHF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/1.ogg deleted file mode 100644 index f496dd67da811e2aef79cd29d4b0bfc2aca0e335..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2169 zcmY*a2{hDg7q{=FD8$TIn`(w(%vdISB8p^B$Tl-#Bs7gBG0a%YBpJIfN%pnoMJl_| z=nbExRF))EnB=u2dH?#p^S$1C&U4QFJ-^?*&vVbY&vR{jeeJn;xc+DTXJf*4+z`}< z2i%f2LD#NY;JmQh+`8PY?!P5AJM#bAj+`4n#7Hp|x519w!OQom7_ejIMZ#+%5jqH@ zhQ^Kp3@lur&lM~#!~o!Y01k-(NTfo5pZ66Y@V|+Tp94C;b`tMg%33;8XTKZPJCGC- zh{s(^=fFlf@BcF0^R2ax+zAL`Kl4PZ=$NnTx zlp&D(A~)x(VuokOcd)pDR0l{6Re$DV^@#W4oVi6FdQ0Z+Eyz9X1l$C&Z)wipq6OIb zm5q2B%kNTe60RU{Ks*wXAq?)al^Qn?YL13H7&N>puVi*e@$5vYNge4dGo3(Dkb%^& z(3)w}gBbEyy7k)a3Xuz(7orpG4d)fD{AK<0qSXN-Argmw2T}_5tPxyAnSvkPZ@7M zrI9)%=H~RsYMo8F(tRLC2Q6W06{t@!Be9!$GR?MihN$+~c(ALe6ti~%>A#E()(Le& z>K-b*O)oURckT}C^oAVeU2xN^jOl#r;%(~Km#_;XsS8smfdh2MFE#5qOUESkc!~d& zn;w%-Z6cPT_tP3qaU4mBaw|YDD$q5SF9eDWy(wRk3B~c?i{;z}4toUmL>_8p^V_9n zilviHL8I}?_OR{saDOiU{nTJ5f#Xd=>KS}q+d}ifdg&Ly<79Y?3951AZKR}=l%DYL z!@9jH7voOVf`7=u1W-f*<%m+_FO^ccLZkfgitulGZftm%1LwypKM4k}_pg9A5+Naf zK4(?dMZ939@D}lFOx}pzxXNmcX^e2Ox@4#qDk6)y*g**@R1O0|xs(%l6p!DCY(mRYp=)!p zKb}_Cwsr6|cl4XkZ`4}el!w+`+5G7U-M|~@8w&0(JsisQa%)~6m6qRdVZd|vb46xO zBpVig5{4gb^*LiD8E$I1RXl^wAE0N~_Cm>LYg5b{7 zj4yt&QUUa;ILU<1&yedB6>guu{xzr_^G;hkuO|$;t&0th!nb2vxa{9nE(~>RTSKA7 zIJV|Mfrn|wroOK6U+-2AuP(i-*58$5#ArJPxf;P7+ioS&Jv0C6n z@m}XR*ABFpRS)H5DYDhIiEU3GJdY@1NvL!(9aE)Np_0yv2VE@xsIphr_83B0WzQ#Y*-vgd^t0n3(o7MZg2P<4=U*8YtYqW#ov>!olh1KTFx-5N-LVyHZ z%ED{Ukg^(aFOPGb+u|X>2o$g!++$KaE=o~TKbx)n9*HXQNti7A_ekW6 z`0{%q{vL_EfC~dNZt&@;s;Uwwa(nmGolK_sm)a3V?1md}U889InIc$p>{pFLtc752 zIIGvWl_8-_s^hT!LF55WAA$E@co&=eZFv`>?_d6x7QnmM0_1YvKY0Me+MTz|ma~fm L(5}daU{2rP3^?Rw diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/2.ogg deleted file mode 100644 index 96a2529f3a300156b5b5b57e97e185481ae7a2e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2158 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 XtnrnhfBD|_nOmd1M_ZdBL*0J?f<52= diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/7.ogg deleted file mode 100644 index ed3197a080eba2d8f67f161186a4ecb8871b0871..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2468 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/8.ogg deleted file mode 100644 index 7f81a622fe501287262cfc0732ce62cdec344787..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2240 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

    WxSwmMW4|$X_2Q|TrLglVZstIxIC;$YuxiLda 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 C!)^zAJ|Ls`0lc*!wrQ^#@#la66m~G6w-Tiz# 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/err_reg.ogg deleted file mode 100644 index 32561bfc06f575f1af1afee6019e3e096d99f65b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8709 zcmY*-1ymft(k||9!QEYh2X~hs3BLH^5}W{wE$;3C0xZGZodAn_0wG9n4I1<<|NYN< z_w_k*W@@T>YP!0szN*r)v(tk^fcxL^#&fgi^)W(^#2lVb%gx(U*~Zcu9$o~#&-8yp zv|h#k?|2o5hf!7Bv0d+goJ)_aLy>-Z1gz-zW(gi@y%N12{$gEpw797RKuN$CfnLLV|j> z>2V<^e&iIKbZ5q#y73nj@?bOeHIFH`OB1?tg5pH_euNhwh=Pi4&Q;$GsoL-x$aMV? zJajiT&;KZo&cOnq%A*?;y2*6OFpyGmr?8}7U3Is(GphPPW#|0~Ju#4Opp-yn!=W5^ zx0(dITre8$VO$=OdFQCZ3>l=6O7kqEK z7W3&{V-dFa;fcK9I?e~=Ssyt*$HP|dtg|XD@w-u$6_`$zJo!-{lOdH>2}rbM*#>)m zapiAd!o0ah&xB9v=r$nX#sZs2WTi?Xn)AMs^{bt~kW-%=SCi?GD#*j?)GLlKeKq`mOn@ZhcAc%>fg^{|n zGb_>#R5`QfY7L2$+S`#djxf5<^xUK*B9d6D4_URPZ(ELtpjd{opiSie&AW8E?yz!O zn?#K>)GJU~>~dJKY>RtoSGI5oI7^V~C@w4X?y|xWEb7XFh_xblq!u(LQ3 zEG(^JxZ5#ZiuOGOUul)N-=0RTS25@6ix`d~b&HjU>gCS_*zRH0WX%1dU5*`fT5jGK_gLj@M3ale!ReBDv-wj`fPvSqzd0C+ zagY(pjx@19_@4M%POz*O9Fzw~%_bjPRF z4{!PTM0+iNDzi=4=UIYROo~JXg6LSdd=hiu9SQjC^x5tfJ8szW<{@*7lr7x~I^k}5 zQ$@YzpC4S(G9_4CjErHf+; zGc99fLQLOIqY*|yuPfV-{VDvsb83?D6I{^43G~`u^AT!Q*`j^Hlh(M`*Bax_;mHqY zX%rTbjkkaymuh)IGLoyN_^>q9Q2&o?mzS#LK zpdy*ay6qi8W28Gg*HsSp3u5CJCDa@XlbNWzfzYs0tH-Su<$*oyo5>Qn=7r@ zY}@cKRZR8g0NT4^lxGctl~K`pCD#4yB?aPmP)qP%7ha=k`=Q1m35oc5Tgx=@O9Oz7 z(e@kS@PEw!bPT*{)%Uifs6_oh(cjaK1)i?bxo-1$>AyK8M&_%6fzSk;1 zBa(F!&3OW)uo`zRbN{s4FBi}oY9&~*SjD~ae$}d?x;G1<6Pn6fE@Bu( zS5Lg9Zq?!)N+kwL=tFFS#ZH=DP3P(63DtXuSY#LD2f_HpA|$WxEh~sj@;%#8Cnzl9 z{Xmf;zEp;}aW_CPbgHTS!8uj-zCeWNE~MzUE6oI0IDJzi9IH4ci_kg>w;XP|6D%M2 zxP>+>L;P--g70P8(u&$fU^`R&cwP2&h2dC6w?A-0M9Uf!YQ%L%EHI&Df2^-;aVjZ= zR--B9EKjy^)0gbq>QAJ1O@|r&*#y)Y%T3BphJALbP7GNm-#mjit>(3Ee7HchtN&YZ z^7l@TNUca*C-ziPh_?@4jy5de9YwMMpF~;?6B?Nq?tdURB={Ad{{y**usgv9uO+^_ zr>C2fv$Lm(rMIV-rN*>Li|||GIzC8

    N!hft@o;~g$D|o_?Ioeo` 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 M{rAjDoxjlk18+HD4gdfE diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/language.json deleted file mode 100644 index 2326ee4c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "fi-FI" - }, - "strings": { - "WARNING": "Varoitus", - "INFO": "Tieto", - "ERROR": "Virhe", - "VERSION": "Versio ", - "LOADING_PROTOCOL": "Yhdistetään palvelimeen...", - "INITIALIZING": "Alustetaan...", - "PIN_ERROR": "Ole hyvä ja aseta SIM-kortti", - "REG_ERROR": "Ei voi muodostaa yhteyttä verkkoon, tarkista datakortin tila", - "DETECTING_MODULE": "Tunnistetaan moduuli...", - "REGISTERING_NETWORK": "Odotetaan verkkoa...", - "CHECKING_NEW_VERSION": "Tarkistetaan uutta versiota...", - "CHECK_NEW_VERSION_FAILED": "Uuden version tarkistus epäonnistui, yritetään uudelleen %d sekunnin kuluttua: %s", - "SWITCH_TO_WIFI_NETWORK": "Vaihdetaan Wi-Fi:hin...", - "SWITCH_TO_4G_NETWORK": "Vaihdetaan 4G:hen...", - "STANDBY": "Valmiustila", - "CONNECT_TO": "Yhdistä ", - "CONNECTING": "Yhdistetään...", - "CONNECTED_TO": "Yhdistetty ", - "LISTENING": "Kuunnellaan...", - "SPEAKING": "Puhutaan...", - "SERVER_NOT_FOUND": "Etsitään käytettävissä olevaa palvelua", - "SERVER_NOT_CONNECTED": "Ei voi yhdistää palveluun, yritä myöhemmin", - "SERVER_TIMEOUT": "Vastauksen aikakatkaisu", - "SERVER_ERROR": "Lähetys epäonnistui, tarkista verkko", - "CONNECT_TO_HOTSPOT": "Yhdistä puhelin hotspottiin ", - "ACCESS_VIA_BROWSER": ",pääsy selaimen kautta ", - "WIFI_CONFIG_MODE": "Verkon konfigurointitila", - "ENTERING_WIFI_CONFIG_MODE": "Siirrytään verkon konfigurointitilaan...", - "SCANNING_WIFI": "Skannataan Wi-Fi...", - "NEW_VERSION": "Uusi versio ", - "OTA_UPGRADE": "OTA-päivitys", - "UPGRADING": "Päivitetään järjestelmää...", - "UPGRADE_FAILED": "Päivitys epäonnistui", - "ACTIVATION": "Laitteen aktivointi", - "BATTERY_LOW": "Akku vähissä", - "BATTERY_CHARGING": "Ladataan", - "BATTERY_FULL": "Akku täynnä", - "BATTERY_NEED_CHARGE": "Akku vähissä, ole hyvä ja lataa", - "VOLUME": "Äänenvoimakkuus ", - "MUTED": "Mykistetty", - "MAX_VOLUME": "Maksimi äänenvoimakkuus", - "RTC_MODE_OFF": "AEC pois päältä", - "RTC_MODE_ON": "AEC päällä", - "DOWNLOAD_ASSETS_FAILED": "Resurssien lataaminen epäonnistui", - "LOADING_ASSETS": "Ladataan resursseja...", - "PLEASE_WAIT": "Odota hetki...", - "FOUND_NEW_ASSETS": "Löydetty uusia resursseja: %s", - "HELLO_MY_FRIEND": "Hei, ystäväni!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/upgrade.ogg deleted file mode 100644 index 5ff02a6f2620a98bc742db9148d869fcb011df9c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4239 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/welcome.ogg deleted file mode 100644 index 14303723340b351361a246422d422e992d677d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2828 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 Aga7~l diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fi-FI/wificonfig.ogg deleted file mode 100644 index deb233a486af7d462b778c2643e10de3d971bd4a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5423 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 JX-_>G{V!e#GZz2= diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/0.ogg deleted file mode 100644 index 1f8c2fcc3c74c788b2585f25ff39eb0edf33e713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1571 zcmY+92{hDO9LJ62SxWY;jAaai5M`LgzArCijFiIImmy={MMEh|mSIN5zGNmQSxRs0 zCu05(tb0851 zTvUX$ucr?PgaGxp{X`u0@&B}sg8&ErR$&Y>*vHYH{t<_PlQW*temYtjx*A%Vn)?J8 zSiYCNLw$V14S<<9Fw;5>47KEf1HD3li$8-o+vxxYXg_%WQRnU8>q22+p`ihh0XQFh zLpVYW5Ec)UO-pd!?Mka98xfpMOX0Kbf1J?25g=lGOsu+OaCQXI+s|bTOS#S<$pqg! zlvMC=#$UDU`<9zIV)QwH&R4nRw)?_lxrFp})l`?lJiy2(eYrRGFGm$~#|;_=^w&w>q2hI41THL)aQ zktj!WUiailHc0~wu^=J&FjE_};pDkPi8^J3z{R60j42QEHvq=Y!aDeLnX7maGSaHd zEA7o4UKyia@ME4Kt@Y3g^zGmHfI>x*!6^s;?}vQN zsJcC-B-5Pm*9{yRN9H?oNaTc_@2atQMQBIV2P^`-IxE5hed|~ap;;(>oCwU2 z+*r&}RX=hUnTj2!l3*RlS&tv2QDAX6agN;q|8Fnyao(3`^gV$jMGP5dMfS73&gd8{ zZ$~$r6u{|jx@9@dBNR)dC(+A-sP$f`E(g>k#Civdhd?^Eso_4B^+kwW^wKuf4k9Mm z1dmUsQ<7rNF!Pt4?4-sz3iHsz@{hCf=v>4;DR;Gzn-f87tFiUG@k6;ZNVK$wP)Emj zVt#kV)7z*I{Z}NEP~|zaH#X=?K1U)GrN5sE%LIe{C8G7@wnov=Q1}r1N6yrt&app z6(b|lr4sFBzh;kCn4~Eu51Xo+q@{L$MT@p;@sPl}+)wL8b0y3%j=ZNIH7)V+9-hBD zy#bNCHR)8)*!3dLm2=yub)w}KxrLPDOg*7a7%B52zJ$-qinmT-@e+c9lTrq?7Xs%p zSrd(4VpVjw?o9QG)Pwn47}9niIRiO)Eh|3)TNLlLwKDdSKCf6u%X7^O_aZB>crjt# zf&z!+HU=|iEc8^tkb2jeXRd28@3rNK!i(v)Rz$zxhSkQschvyKS0>-@O|7XUt71ub zNrEXBFCfHgle3W>wJ{)3iP;rixyC(>Nx|95CTy`Cqj9bbhsE*~heu^jOk_D%m0S4n zl~;@dmHgbjRrle#o9jqti972ewd?+h5?AB62cy=i8x#-Qw#U>!xw~5)X7g9NmUOaG zo>Q2aeS%mH?!h?bpi57cutLg91mc&wxsK5P^uZ|w XeXyk^67j!Wz#qu%BpiGL;1K@+4x-0Q diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/1.ogg deleted file mode 100644 index bc383648c5b617a9f7914094d915b5a968e94bc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1537 zcmY+A2{hDs0LP7^am_G9OS#VwhKZR!sa0%_j2=5~WrmbL(YO<7ry0tXopI%8oQ-JH zNXm?y&rp*gcaCfa$&x{0rFQi8ZT9=#|GnS$|NVTw@ArP#;9xf)VWEHJSoL@I_K|bO zZVV!ijfjps9uyD=fuJF+e%}%7HvXTsafrY@mmR+aIkb(t2Lwk-3;s9<#GJ7}8e1A8 zO-;866~PyDo)8`wL_8$O2!afW5rjzf&~x~3LGk;r=p&YZ6KH#Q`%=EcWEVteXcQP6 z79DDL@Mn~*kw73xT{k(aNXI&XN%7;xr#&0j$>4Uv87ex<-4hShHOnM^myfl z&aY>7CDG@42Stg|Dj-QylU;$^oD3VTeJ*VkUE(6QWT>Ojc-J$orpzxg4YoHsC&Y*S zd~HKrZmTr2tncLE4_0ZHS_$?3$KW#8ifpF~9einVui5XrH*I*66)Ck3jtD>W6**6% zkJX;Fq}A_z;k_^f8y+V#M1v%4U3SN-l_~EopL2!P z-`R%cu*2_9=!Hjmu`DP9M7adgTGd6!F=O*5E4ZJS> zp~Vxqi1A2(dUWUGoF*FA8q7l#P|p}LF_%hh8YenvA$b(Oy(yns!_Ah-2h#1ESH+BH z)GN)81?rNYnAx^hl^4bvM3bu!Tl1tknDkTuNK(_vKcOhxt&EbVU?VrwUPNzpK;32V z2P;!Ay<_Smh|H7cUCoRbb0J4V9(57Gl_im9j)^K4J9~eFpWak9`6}@yAR}LGRLXDt z1X}vjvZ_m49VUok{(3k3%KCzE+w7*V6*UwjX=#&RUQmkZ>WaUfzmBzT!dw-)8`v>n z?bNN}QWrEr1SoxohwMs6j@wyntXC^F|99J^UlLU54QYGVB#- zVdH88@HqgTp*^Yq3?>4PRjVQA+YmN#Z_Su5SHb(LqaNTMHR8jGehtsA!2hhw>#{45X2 zczd=9k!7`urjX`+W5$sgKHl<2trbk^lwx~H-3?Wx#C}9Q zVZK+l6W3ALrKKB@&A=D*D|}i~`mB`3;9pHi8=?{E!L3uj#xfY-(L&Jaq*;v31*1%Y zmd?tB^)Av))&~ACMD6n2S&1BRO~8LNRe@n4YY@8zhjz{!A2Q@`jaG6&(mq+SPyQiZ zPL_Xto$g_T@MQ2QHR}tdXxQ7r)p?wlL8}<^OQGlss=Q%vZ#-9eRI2EeepnVYX#Sj| zxLil2ZTQMQkc2=;xqt;>A~=|o5HU=Z)y_mohAv~meXU2T`Sr;6qpkza5|o9>DBsfr z-Yihv?^O?qNKpR%l1IOjPUMEswubehz_}=~(-M@AC7|W)oZAr8OYVUAK>M?MxFzw7 z*_!F@FAaJ4l*%^``7rl&hkgZ+B#nS_(&m!ln{kKG2fm8$)*H(+&?mKJ^`#=?I5nQ) zW#5weMscg|CNH6O_VTf^H~c^n94-#>dG}L&LdZ!{>+&AZp7`z__hL_zcM%!)zCv3% zFX92BXaW4P=u`}DF9q^d~bNPmdR-)52DdOT+VJ_hr5LW utaq{kzay=7M_d1B3LJVTTOYME6}TPEW*Yi`yPOBWjwONH!S)XV*8c!oX}(_o diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/2.ogg deleted file mode 100644 index 01cb65bafade20bcaea3d40e16212defbaf1b894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1628 zcmY+C3pmqj9LEh=t}~n{RK~1?$kf~^mkm)am4z4%`fo0C$vupui^)=|MHoWHnWD{H z!l)d&$h{=FBuTDw31@oFbB=z`^FGh}eLtV~_rCA*y!O7nj(q%l|CZo%h}7oPvDV!T zByArQ7J~Ni^ag=Ypa!>Jiv6bkUv26jULww~kwHeAx|64Gh!}6h)-(Li!`hlhG_|#~ zHVsAI@Con=^!6bd@t7BnY3uQz_FlX{E|9nJS7X7aH9U`3n~gUwr60lYhWZnNh{5>4 zV1kRGuI@2)b#;KW3juoD9q1y^2<@zgstlXuOVIy-4T+NNi?>nla53j*l3BfJc8RJt zN}R3oJn^ZWp80peWJii2UM{oitd58BUSvrFj_^avM z*?0E}5#}0SZviAFM6pqM=k9ox!%2?K93@#~98;h~5a%3RiNL6@Z%gIF$>;4PV~nJi z)|xCv+w#M64(Z3Y`Ff}$#OvI&;^%iHR>;3ZV+9lV^V$fNV@%=r&?+w<3k{aTSURgB zcTI|1PyEn*F6`E^7J!6MW)INvDss_2AFqddWki{FqJ_47^H<%s(b}f;)!d>|-?}cD ztMSaJR^Phk`zb4mO%TT_T*{WpUsiysaP28~$W&7p)wnb!E@;I5(K@5pN@RX+iF0@} zsL?I4Qkd=Rz;~Z|^9FGn%+d6yH$YNBuxoEX=zp~@mf$0L$!qbovCPve3Kr2V9v8;X zI2o&i#9`XB*@4#4@B&hq20z1qt8X)d`fw6CE2if-eIs`a1;&-(<2F+Kaz?S*) zbK^Dhy~51;x$gT{-ST^`JO~|wFe+BH#to8Om!)|xgfTfCuk=biB9?WosDvC7Vvknp zm@m;s9;SOg-9tgGnhcm}KAO`MW?$Bk!C$dE^*xvywA=R1z6@82KRqpm@YV7}d4E=E zb7362LsT!o6L;Qyy`twXT}u8L-^hhG+WoEYPg6yYt4z)g5g#%D5?q-boJhTU4<3e7 zhr}SohVFN!82%nCaJ1Dk2eL1FUfWuawPz+xat+I8%?iNT^4MyNpF)p5~ zyG9Jv#m}bD)LLF%OI=8yGVhQZtE+4R62v+zW&1J=;gPo~f<494=>_j10v=v~bOj{3 zXDyI7-&Z}mXz2H3IfZ#6+B7pIt++9ADw66NWL_F0_Xx~%NsEnPVh$`xaB|YhZUukwIpdF?P_V=oIjnd zjI|#wN#OlWrOf6IV>IqS{lqf%d;*vYW9U+Xq&u>}U9%LjQ>d%V&?RVU5~l$&*-bY7 zwzGPFMRZJxO?Z)7mxV~M>VULUZenunH5B=TmE`;G!9wKOf#^YoB|w5gW%ndayqu^h zUx^dK%l~}s!x6zxrI^~;R!ypGT;{Io%r%PO*KY?nTwAz!DOJ*@*3(8rAnWjvCV(U< zDS}MNPD+U>Y?tPkIr)foZhtW4WH2_VXPX+XA2n^B&dW+jg}S51`F;fQrw&;310;y# zb|B8IV=!HbOHjONCHE1``urLxrF#HtGN_d{LzxA$Mj>Y=M6i>J?Ne~Wnlk=-07-Ti z_%)3Kf4eI}fu`=;`Pj`sPyizlHj4sx?Tk`|P+9CoB&Iei8Zn z#p#ATDdqTgC__Ntx4ea3nMWD^&v*&7)yK diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/3.ogg deleted file mode 100644 index 0f4054539273c0c6c58280c04bbfbac5b8a5dde6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1514 zcmY+83pmqj9LG0_5H>8ATxYIHDbHfrk#r&>UFH&5WGFlClg45AKa-S$tY{C1*6hfo zqex>j6vr)>X=rN4p6KEzXF`ZN=fBQ*PCLKnd7tO~zTeOH`+I$(qE12-ApefLN#0f2 zb=9!G0*tK`?62X^zI_$;K4{8((L5Sf^)v{#-&RL+#!Po4Z3&1QvrUBG zG5viRIJ|LMu^@`CacyF`U`?Dbwq-UuENj}Vpr3u~I&Z^L2&<04);bnFD~gy1%r&*i zsYdgia8-pW)l;h>5OZli2|!u!W*xuN&A@f_jw#@(51<-V4-9kEW4j_bJbLbrn;KR5NZcn&m#nviwzN(SvF4F<9Km-X88wZ=tGtu|89$+*G47OLtmJ zO(#+Jn4a0esRu))p0AEm{NZYW&~%&E$BfC6Knrl0RVGS5kysok&Mr$&-)_N=Av9X~ z)n!kz2^TlLi-$`Y#B&f{hqTK|-BaVu z#2Q)NhIMHzRFtrn`)-7L1)4+y=nfu~HVdMSNThrD`rY=^kc!R$rRqe=B{vdafokT^ z{=5wrJ%(YPa_$dwy2l3)%X%#}R*||KXxc?nvwy~=C*ClMxSp94e-<5kFvC-1%S2K_StQY!PdQn(ac9dDnIff|? zfr%#p<|t-|WIU!aPk&GJp?t`mTPTllbnSYmW>l zlnbu5>@?D(BVBT96dvY{k`~0kO7cJzKl7t?nve7Cb-?9d2ApZvm0W0fSm46&nX0IZ zINy(T-hTzG3{7bv$CeNgc&>%-gv0G@?&&Chz z?f9jG5Ocg3u|S?62pWTj1OLd%|Ds5PXpR4({*F52*6QC0pCxoBkN^Z+4ck=}7<$t+ zRjcr5za8FKhZuxGt5S*{m87Vajq)pnweC)w5GCaitmU9OR`n@A&`Hv@ALy}%9jRe4CE&o))f)Z|2 z4SLIv{>`DMZvG_2SI>J{-BA_+FUeXJEYGq9e;=f^@OnsV9+z;ug0xA7_62k>wahbx zPEOxc8yzF3dYUjU@+_$3T!9ed@+~OYOHOhwsN|Bbb)5d!3u-x6>L|bE6CUI8 EH~F`*o&W#< diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/4.ogg deleted file mode 100644 index a476dc3806947132d413348265ec339311002afa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1395 zcmeZIPY-5bVt|6^dehG!CRgGtc1B_Ug3@A-)Wj4eJ85P%E@IV#WBaGhXwXP<`UVHrI(mhAE#S4B)j$i!5 z;yB|a@sB@h_u8^3ZvJN-Dpf7A`0u9~QmV%}|Ea26pY-yuN%7(}7w)XfZdO;`^Pck+ zLkRnxqsEWqq&>A*CahEC*clQ0<$nL6?Kw~8#khWy6WRIEV$Uwg14~nmuVc<zKUKm}6b* z3Dq^Ll6j13MBe}{Rh*w+@S<2|=1Qx*;T{ov`A+&329JVHf3$y}aL7D+RqE;Qu0{#_ zW;5u`4*0NJ{|dAA#j?kdQzz$jJ?(b7Y4gQt?}UmUl_3hJBy zN~{H9uedWhzp}BEs<^w_;=(gmZcu14pBC|q2~??WVjf3&gnRkS=e+nR=c^UFu5JB$xNuLW@t<$J zM?}*1STx$LdACfAm03pKeG>O3TfPm4{a4D$&3MYD7pIurtfIWoM)~dj zvNtFE`RvH7lAb+^ZyvAcd3ji+-?CY2t!e7zYnN*nqi1ZKE_tS3P~hOwT|OSx+0DwT zyZ>H`UfMaG<@}tJou*qhFy@}JvE=+Fs<6uM#nF|<5^tELg!g1t-n00!$ZsX6Z&7{nOFz2m#nm)VMTx)GiK1FqM3Gp7r(hD*8`6iNP* zx@GXr}DmE<_m2L*-`@xvzouE7YEJU6H)XyE`{q_X2+J#2V0qR>NlpF*_N2d zM(khm_r6W=gplgr3=5itzj-ZPdGI;oCmyaHxn5E|r&+ZQFa*DwZ94rxtW`thQ!(CK z+0EkoJXbT6=gzy5&BAUuuajeXqs+{WtabugTse=obYFS?mBr)gC1txzuAEO!t}E8b z9I{+^OXz}pt+sg8njhKCfuK}kq`bScejfhaVDXC6ujOH+*pi7idyevKe`s|^ z@ixaVO=PcIj|dCBH>GpBfh z4#(E*t7qH{$nV?Jqu1AJwf#lC(n`rwuQfT6m``nENT?Lju$lU)DDZ^Kv!DK+Y|Cxp zdxWmu2Ii&Op7OIiyVq7F=N0dn6zx*5b(`j76V1I9^(^bAif(se@5ptSb!Rzi?a`|9 zdz&kj?dw!He}8|y+RW!evvyjp4v%lmC&6q!R{#2M%Xl}gn)$drjdkCPgSne8TLiGM fMEl!s3Xn>v%2PW2!O=h<Vy^ATAmJ7oK(7 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/5.ogg deleted file mode 100644 index 1c39dabaea7e1093e66e09acf2ad0810bacc90b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1497 zcmeZIPY-5bVt|5}XeJ85P%E@IZA-}UyxvSerZ;AW=XoawXVLs4iIEFORF;(?C{e*a=dPyhS4*p00XZ; z-X+=1D(ZWd$Q^qT_y1_bp_{sXPeYDm|9!mbkFc_F*#2&{#>+(#MhrW6_DHOpeD%vN zsp#E5k^~k@y^|IS-}~Q6H1xOAeL)@BS@RclJ~~$Huw8?kRBT1#|ML{B20P zI`e;RP{5_r4>BLUn#Zs~g5hY)mbux@@+x~Ay!x%Ks%NzCX;(1w^bmHOwa4oESy&=)@7tnjkTf9}ZO$*H|e!sD%iHx&OtM zS+z`irh08nv%dFZMO@u9u@1gHA@LVQv)nksgip-2Vqgl)%5GLt-4mUaBK6Q?A%M2yLq}7f9)*s`J1+v71%|s6WloG%UPaRHUbZNj+pA* zzH#|nK;KUx-h0lM)&~m*xlfgt6cjgiIzM-Fzz3WE>naUb%M3{mN%j`kkkA&lQYnI;NS& zV8J%YW@^Eu>o+X5G9{WM-px5AAAUFgz^2mm5C8kTaKG+ub&oZPfn%E8lRLRrUvhtG zc$=IUHdoU6ki;pj>}CNW-t9jZiyd_lQ#GxYbO8SAwMt&ZZnJV61(%H?Tf}CytLNfIJ|2r`IPoS%%o6k7|rbES?U1D;6%O|nV z%K7m*^hUDkXU_b|e{a3%NI!a7|FyH~b9s*JW?o+Qla(hAOGaV;g3@A-)Wj4Ul++?ypje|8V!sJqHiYe#0L5rSJ75f#>sX)vvkv{MqcTcaL^m+%%6b zQh!eklbUjNv#QFrE|I@>;XgjQnrn*8Sp0g$%pbFxxbpeS3j*7^_BowS>df$~lHA7N zztViyj3>@7lm8r>dFGJivk51sRRna+TW#E2T=(We`{z&G+rq-z1fqo3+|c>`TX@ow z9xjf^=}ZpkoZtamp9g;M&jwB zLxrjgOP<#5DN$6H@LS)fS}|3Krzg3*_jRnPWx-WRyKBuazkf7k3z6F+zI{fLQ$XgQ zYa7>nzBA+O3YLlXRSm~)`e&AV-g?d!IW4}8584Nai zV%`)zQDu9S9A+`M(p|rwd#&WQUCbS)@2Ug@ygu+(N5wzDMo;IqEY!+Cy-TC3EEAq*E>XsFs6XWfOzWOIoOJ}9J!{elR;j`D7-?aH9xhcC@O=%^= zTJO90SGxPepSY?ozxt(WvC-AtpRd^7OU&iXY)Z>MzhqKP;IS1kJzwlPKa{l_OX^QP zbm&!a)VC&ckHS?O3^MdS9oVk>GkbCW^q8R5N87#suW~uCBe&{NU^JuRiyW~#Wr2xH z*2X;Bm_6fq`qzWm&GHIMJoy#gElmyE6uGx5VtT(*YojeA|1_=R5*58aCM+*p@My!I zcN_H$dm8vfm9$+qPrtw6NNP_`-FgX0s~_RkfvhVw2rM~Vw}|gwut}bt-_ndjTYCa8 z>!t*yYh*VI@`)>`9-94lvEIFJU0)MCKJECym0D8qwPpU-Qz8@HHkEL;eO^}MbpQT6 z?cSflN)LT5+$m1ZZWiI^Z2M$?eRpY4KF4(x72T(1fl=(yoRcT*-~T)N>ceBjEoBRQ zINRQrtU0K)Dt>D9x!aQ~fQgZpk7L360_Vr~Jj&)wF4)a}y!&O{#WPZ~&d>XHbRqkN zB}Y{+X`R{qF;MI0Yt8BNvp=e&=FWAn09q%)epT`+%lBHdzeQiyK6-8}GlPj)kNt>8 z4X+1x8h7D~gzL4A;ljW4&u}cdogSPQ^UX9g_u%uejt!TavzvwaITlTc)!;bdSR3%1 zIV6aj+uvg=em|7B%YIwK`^cKZU-VDKUsOy AyZ`_I diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/7.ogg deleted file mode 100644 index f02aa1ec8f892b17b15c3c9bdcf14a20ad6b9693..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1527 zcmY+B2~d+q7>1K@q)H%$OD0}H0#Ohelp}&%1}O*%2!jl*NH~n}LxfN$5f9)Oxv5%$ zh^R<88#G+Xkq}ZP94e4-BVah>5`mx;DOKqoD-Qi;c4nV_-+lMnU1uuQ4TgYyEsY@e zBhqOr=$Q;xaSn|Lw-2EB!{H=2|I`LWAdd)%+Nm1hSNOX>hnN1Gdg%U(r1vt2WH(Y?-)ql=He5N?U_o1q7`X@sQ8Zml2X zKj5lyRxBOZf*67AK9QATbd&^EshF^qdQl6_%WJ?r^yj1?QUcKMWty@!W7rdJf<<=&vP2mEVSU$tJr)Pgqu7^}Ft9neC>B4g)KWxMk-dO`||qBSo) z77LypOWP!ID>!XaTspXek!3El%a_Z96R$mal%1?3OW$AdVYpl5Bomre4d8RkMTc?$ zPz8faM;{qH`9oUYn785w?RtwqEJDFdDBjNb{>%#nvb!LpxiD_Cmf6E}GVx~vy~p+@ z7rcsbuK-XTh2+)MQM~mQf~FV`(wt|rBL9B#>*aHS z1-HaJ-HxM#GGs&JdEX3UraBs+@A?k27<_wXc4#VLuy9V+#*@QwoP6s~8(BYB+Eio} z6!xvf`V6!679kBH(nfD{)kYPf4Le29N}IV_d5b!(~S5qG;K zhBB>)%qyh`>3CKor&D=cRCKq_J@@K&&i|bM_xJsLf9HSx=l{o(NCbc);NQ|xcG8k> znd1C>1zmh1BV}()M6`keMxpuePXsT=|0_AJAXDb6IJAPZ91n;frGRCf{Sn7v?QN|c ztZi*<wmogp*FJWX zK}(J!Q<7*HJ0~|Z8cks#k<6&bo>wd@l|gpfcBFeQwQD;JZC5AgGBQkc&hzxoqNYP= z21UU_?4G8qbjsyo?wOp4reiwh-P!TA0jsQ_g>F30XZMfDzQz&FI7Pwq{x^>oCf8z~ z92y!!o4u-&{s<^<3Y%RucjWfmKt_~b1)(S`6O)Q?=rE1BKPfScT5)O2tKAD9E?nLr z&YLqhTlv^S_*amiDj(>L{X%ktM?sUrbcUfS(QB>9#D1w7MHxCgV8V(KS7!U|8jFVf++7it>4D*K8)@&p*fjo5^tNP-zHzLf-ggM2T%-dgY z3p{N)u1uZQH5n6OHeZwQVBsGViX9q38bY#u+=PfVguA4RJynZ!d1}g8gDO2)qbehKP%S(kHH3wI9Z795T`HRR;hcV6wn#z}4~@nn(g zoxmCohA9G4aVMm+!=J&ZQk=%cRH;Q(|0qn+hEOMzPa%KD9KlRG_M`=F zz4)B1Y-RDn&Wdv+V9`*@w@R+vM&n$20fZATWB_=rH`|b|x$}$gJL=MddRmOD@6ung zf@MDrAqX#S|o(n^JxV9ILmhq}QFqGW~5d-MhFU^ympc#nY}#AbP7(0RvTi z$IjSUt<>AdA!lU-jP?_G4wxUdlq~g=pGp)VKubXT>dMR_t#hf^3L4wi`+#1H*z%5| zdV%n;d+)cDY}p-}0!=Il*XGFDV^JSlGCnTp#c4Lz(MsNh6I`5iKGuk@+%EyDf{RDT zC3VLc+Ssa&TyUv+Cwe337EZu6M!2r}i_|rENB<`EdrLeTsRqpGVPJKs@g=pA{ZcN-PB&zT~r37-TPF6bX5s6gJ zv{|1C<)1EmGvD=R=2;V83QH3LYMc!CM97J&Fvu@?d#(`FTi!;#c;(fz?%r>D$}z-n z&h6Y$DyVVUZ7L?{`DeSR6*)Cn$-e zHAlj%9b?A{=TD@++>8Nrrgd}@n@e@z%zmfc6s2GEI+wlRwEKULy@0{2XSsTqb*@aU XOWxRt`DLz5uX6yx!~r``Vm6o%ad diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/9.ogg deleted file mode 100644 index fc0adc8055af8fcd706870e1f3d4bcc0db5aba90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1604 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 TuxX6S|AobC|AozyRaW^Q=Uje< diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/err_reg.ogg deleted file mode 100644 index 94632fcbb1a95fa3c2b90174cc13135ef1c656e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7125 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fil-PH/welcome.ogg deleted file mode 100644 index ed59bce9adf1e09235ba98a031a298f92e091b6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3754 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 Sw_NkzUWE0pne}dGqyGbfPj!$0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/0.ogg deleted file mode 100644 index 79b8faf8251f2bb2a0f639fcc0376d139b17c3cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2291 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 vYfPNaT_yoVg~& z!Vp7cF4a(S2`S;>fyW6^#900Pi;`7ep%zWo2TF9&cD*@Bz|FyEJ7MB}1_xjPQ%Km3gh^o;ck zV6c6KJa=G2F=2k#NOLZS;c^BhT+#p<9OxUyJ@~g{%TBJ2Yx|D(gNjp#`XcV+altz@ z0v8w&6XYL^$3}$U33AfHl_K!n@4UP`OS(f&L3_m~=f)z#jRQ0$LDLvWau-Uy*+_?l z3xAP5hxM#`rFfl3Lr%E##)HnCRfSM5nFq5fH7G)|?|`+4;X+OVS>lvo1YlSOQdo$L zx;Iy5Ep+*@pvju{&qf8wYSFh!F%<@#HzLNl!OBVJC4DljDQG`_zZ&}Fna#wma>cbQ z#(Kw3hsUwf0yR2_2jH|*{2&ze4JK6LNoF6@Iyd8Uu!U=9;*{u1sw+Tb33CHGQNzQ69{%8zm0t(wu%u0lll zE$BQJ*v;&&^D;#DO;l5vyhwORilvzJpEF*8Q>Ga@d77_Q?%SCeX3Y(;8?#r5tB*nPRyvyb~?O%Auvs~ zRA!Dv?Cqay;)C{FgEq>`A4x2??R`b<_JmwUZy~!qsNk(ab2?LM`<|(_2oWW+0f|>& z#W&P=Cg2ImO6g>4?P14Duj%tEzdN#yPSk5J5vKe#b0598qsnL~P-tTSThRWC{f$qQ=>K;*Ed5}EK z@k@5c6I7J*3KBnOEQ_8m{~>6!!zwroq1*&VrKe1!sWMW&1&?O0|QFS2>$r?UWwJPM~UZy+i@78PeE@qLz|tt*5|+UarPinixR z^IRM81a;**tHKNq7sjMlentAMwxj-G5b#~ zlEg1d9>RR>;`%{4-1<;!nN<5|fh^6DoR&jQ32-`h#7MX9u#ftTi0Y>#yDns_A#nY? zY)Lx9d?pZ3s~7et>n7?ehIVdFrStfN#Z*VeE!Cv7u5!%mi1)A7rfMcn{eP$r>m@D- zrT1#;hJnhOu2yHvJ|auBm=097jf)%B5NGiOs9GC;yelNDSqyl?UC`(Vzx9*oCYjYQ zC@Az4Imr}EnQz@Y|I`vgpep^5_lgwV^Sz47A+l?nyYeKCoYaYcO!s(5>DF}& zr_VVRi3NcL$3LpkH4vGs-^Yo)$|1QZN=e9vH|56pJ`)M;>qls7{-Hmsv5Q6^#l);CQn(rbNdWH;u|og#{_&0Ng*Gj_7B+1JtJI#OqB@6uad!$K`h7m(m77(mA9c#??;lwt_Ld0S79M_nqV~mYTt*N&MYIZQe2)I6@B9&F<8-d;)t5_WgAqIM`)?_> z;s_T@d_TQ1WSW(C7@T{;3uOiK4D=VNTO<#{eDDNCU!e!dL)zY{w@PV_`I?)Kv#me}$D?Fp4KmvVQ=Rs{PvKn!SNCe+nyVAf5Q!UomcY()t5M?@WTDQrDCrEza$3kv99#*)Q$GoE&|tAd6Qt+Jnm_9L)OWuG!9;Nqp-KeLmaS z9*z3b@T2tSh&!!*4$D`k`EtCEu<23Wx3b5;E?ThOwC%7{GJkbKKG^1dAN;!$@^a@6 z&nt6>y!3T-b-5{qYUG)M=%a$~IehOc&b=VuR6ff`ek&1~YuYq}Y(jN4@=Vf{GM;zQ za%RqsJoR4q1>BLPeP=qF7E1(ahh=N>&R7bkEJt|)*)1{wJ~JyDtFzt74ai@d2=0e0 zdX%3LH)0}Yq+)J1pThpW1lO*&4f;My686JKpzy{;!^M?)lx%{eJIrpL5SWzsCZDv0-Cp`(H$rLnrs9Vm%o+ zfRKg%^&lfp6dC|f2XwgnW3kw?|3CKZ02WOw9e4@Q+OylDFhRVm6;o8m)zc~`&YVzD zR^D@nv4*FwhacKAP>ZE`ur!skEKx-g=XJ%8wejD?y6r3`NXuY){1!4ZS``7akLXi61>2`^YT9&!UM;!#3Ryx1CqgqcM8}p zEzDqS1cZzzl{e%Q$_C2Y351bj#%P={buluuu_J;Zs!(OF=_$j^XmZ!^E-{+7WGe`2g@r;zgP#CphS)v^&;;d9mrEzWCtN95nVluQ=2X8gnw<)z{ZJK;4Y;lJoL zhl;4q^RAB^S2wXomBN03Oat7z)zrebBJr)pxp5PjF{CvC%lWL>X7wLnx=3N;mo;NM zjts13u(bMXi%MJp(8Z^J3^<6|RnXM#r_;_Fyccd%1>J&!UKC~* zDJa*L@y23_lCmx5r%nBuGayKUi|9zN)j(-r4y?-T)@_&|Q#*>YU;8O8r(`(HM|>0=y%L-X+&HoXhO(+?hLtEZtnw`WQ5!xgMo4pfS{Q z&qXl~#O(>i5@qDe(>v;?9{h0%uN3gg1`DXe1A`P~ZaDGS9qWa5HNmTRB_r!gcW~EH z?HJF++h$yAoT#$zQ%sKBvBX7=2BR>u?M@jWb2f?EXj3-kTc{D0Gd5Y|}y=;RPhYmIm$lbkc7e0QUitgmJa z2$!*?DBa9X@~*cb%!q}QLsH%Hmc(DA6$ryRB;3PXDtAF)@%Jzrur!EWO}6DSw+p91 z`;pGUg^^s^5c%5Mk0(76}z~R^siW=v|M&Brmk_g9Jso`^Eq9#te=l8 zH-sME61Xa(ti>p_#Lwk_i7Vz5KCgp&+iB_vh}fn_#?Flflxij+g-k{%)RGdJ3SWH7 zWu9y*O?YWJ`Tdd7H4l5`q|3WvA~O*4=D!m3Q%OYz*I9QeosBVsT?%}6kxc8hFDnS_ zd@oKM7Y<^oCM1mFfGIjI>DdFl+1|=7!(AmqWw1opHpjS;>+qGEZQnQ%5{^vG^xn8} zK3>zTf`~*s9!Yfq<(hc4bur693HS$I}FaY!}lq8M`U z>z(-%3dc{nKb{COk4B^^_)i9I_MWc31Enlv-Pf&tGO%-JKCwq%uVnF#;Us$(M=Ww8 zi`)0tbh-Pn-7HytpGuGO2hrWX9JWV3q=c&Crd4qD%zWwA4to!H_sPk z({MteWt>bZHV+^P$zzRNwqTDuH&h&*g}(JcfK1VZ9R> zQm{|yR=xj21m(iB6-%Flk9v0nBMHepfm`lF55j`ogZ|9eNH&N-_C&VZaKH%$f`{w6 zMs)?Y?#0?Vs&kbN-o@rY<|a82;U^=Pqg0j;#G8=gDx=V*xv?;TF`w`GQ55b<9t$yQAx;^cj_=5WL5wuF#?aVuno@RKBGeRg->5mYvrE4ez z-7?pR*%;u%Co*3&TXZ=C;i*V&H@p2@ck~-()gl#e=z2~BcU}nU^U}rw#1*?Tzoo-D+4=H zGo8obuB!P=U+!49jE>&5TqoOQ#!E1KUCM`6#rpHYV4hK{9II9WEpbhhw2}ZSLSB^Z zobqQwDUm0rt zOIFXZy`&XvRlzvf=jvvPKN{09^QfSpmfatv`GyS+mWs_w4)dUr7G?iZOoBXH6CJ#LJ%J615S3Rs1p>DGl%Hr zM(BccxcbBT`t3W41f@gjX?_0@;Vr!n3;d6hzR(7LqkY~?0ovexFN^o7`6~2%^w5g_ fo0rA=)W!h%zEfEATMe!0`)gp)zMU`YX@h?Qxu!NS diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/5.ogg deleted file mode 100644 index ddcce17e972de767bc9bfc6c34ff42d06d082e7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2558 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 YSmx`{)nDo|^f9;b{_#~hs@Hq|1NKKwNB{r; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/7.ogg deleted file mode 100644 index 293d1c02e0d5fd1774ae7c4d3079f07a072cf9d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2321 zcmY*a2{hE}8*Uo1XJ_m(1`*d}Yb-@H)-VY%whS45b|MmGLL_njF=7-WWM8w3jA86u zB*~tL$k?)k?&#k0zk1L4&i6gv^SsM>&wI{m=H_N`?D(;NtuMfQ;P9!7m}UcUoB7@h zFmS!@0s@@_wb=iXm>tUhZ-;Ua4KWMjeL-4>@~hX~0$6E3Cf9>*sKOQ06yS=AhYAte zarMUdxVZXj(Krl^gCl4pT-?*$*@x!%Phjn4nvQ0Nfe(vXkssOPJg=eT>f;p<;0O44 zxqEp#VE`O27t2>es{-FabXCc&@OpN0tivG8O`pjJZhP4=TAqPq-+DX|#1Qj8M&d{L zlo019LJmr!lO~_*jAoDkj+2LxSgW%8=~Z@T21CBIGGG@63cM3_e^yA0y6T!J=3<{-a2~cM&j!e^pCevovZ#> zBFh-utZV!&X}wH%&9&UKG)Z(+M&HaN^Q<0;8@y-*N)1tsG_bDs#Ebvz?iWipJGu zwx`Zlrf1UB6jr;UMuKm9cCeiXeAbw&%s==G>NJ3pmX4}WQR!X26`%WOMDvcDS}7hGNaX2h z9RYU*H&IL(U255kDjo-LMm>)BA(49EtX$Ro%z|=-pe@sq&;S{YnJn%iegzlgINuRq zU0PjeH2#Z<)NV$vQRl>%tG2g#8z6R~1G#c@-pY1;*ZMW(0US)aQD1%h2^!Bl?H9`4 z9dz1!c~N+uyWd*gG5!Gfu1oIQA(hA9JP-CNlMqRy&k_3dnNLf-5$1tLK?A2d>VbPdSJC&DRI7yvf#9@Bl2>`40(>V;)RQb5ZBN6vrO>u z&|scG$tEcQt_W`N@q82tH)sF((Hnv@Lf|bT!3e=-LeI8QO{7Q*>w&11!qx(B_L6GidDfBF^ax!@z8>Acr zToQ>-IBaJ@J64Y)jiLDidk5)aYoDN6M?E|DgK%!M;+9ASLXy3XZDZL;6r(cLlyEG_ z9^Xm&qp`gDH3(@n@OD{DYt%C^J!AFk>G6R}s={jcq2;NQnF93fMNwh1$qgQ%{VVEO zoWp$2C9hd1TPf0}Q!>@0VL@J0onuv?N#BA!Q%-p7oGB`)nuEDKj-S_wDLYl?yBd%M ziye%vIM0UKL^9OxmDzwUP&b5uy!i=KZm?N z8{&sZS70B6;IVA>=U`xvcectFbxIo{`vc?7V|x$pX7Z#58wpPz90_MB4o`-bLiw@@ zk{ceodg$U&R8JMHiKkNTi#xq1YdBASdWBs&Y2POj(r(&3I}axD7bviW>rOjYPcrKz z7g0r2B+P0Qq-%PW^WOO$NJ`ZLOHr>6yx!RNwnDJ2_tnoYXBi{iAL`${ta4Cq8LXwy z{WOz#-=#xLg2=U|t zsou)yaWzQXxC!wkfD;v`N6du`H-T?5sMdk*8#tw>l*Vh)_1`|`MGu0g^>nz}#mu4|>{b{aQ!Q`qS@vlkkw0wa43Qq3j>PD5^Pf1W50-7b z;J`gp9dX8Ybo(z~%Xk<$GOIOx9%kH`fLDyLHZ zLvgEXJplMOe1uKrT(C`tq Lqx@(MG(`CuX(m0L diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/8.ogg deleted file mode 100644 index acec1122931321f32fcc7bc141fc04b51990dfe9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2362 zcmY*a2{;s58#eYW43cfE*)`d+Wo!xA#=b?_#xOHwijnn_u?>Ujss0=0vcfT^Lv@tsB7h5u z#`qh<+`Rw*bpX-z9|`nS{=Ybt11RX@p@T30aw@lVhx@ZqX3X3Jy;T*#YG6eLg;NEH z(qMNz{k&lJAr#J&!YOJ{NJSBpuZJIH;lIYZ%@iFaPK{3wmCkO?1Ju#bcg5Vj;~#)R z_#sdTFJC0~0+40ZxO)>>(2TNu8}`}ZLPuO)9y|Okj0p!1d!D@I=jRZQtycrFg)zlX z@bM8u4tH1$a;PP!1XegFkXSAtQ@pEOo7#2jPbqYjGY1b?wng)qa95+Y?K|5+Po1?< zq!D@!rh6L+Mux*ttMbwN&ojU2^CPhw7Z{1zUky3_DwZTb*MvY$FPJ}t%)KmOL}ZjE zF04CT=?Cf=LyEZ_SW5kXvo-5om@;^31MbR%%b@W&U}`xM%O?^mY{rLxA!_wmGF{M~ zpKA`eWE|yU>93{6ito5XL9(0;0b>JK(>HWitA3{E?hVc#TpGdzs&}ZzF{>>WFU{-^ zcti*h<*TBF~(ytCGgSLTsdUo?u=XMDO6 zZZeG4%-POm+Icb`<%~T@Ag?Ztp>GCJJKQ2#AlJR>!P|G@^LmhN%?7#Xr8inhwl@8O zb?KeM_{B{g$#DXDtgA&{GP3gzmLMo?&6@rp*C$t+)Vw()_M&(#NP{ublrTs2t+A{^ zvL$0Q5X5F8UTgvmV&`ksGlM_wRps)hd zU4nx0WPj-+UDB(b9O@Q=9VzK6J^bKO3>f}&h-I}*eLucjn?y5mTZm|}rt60EgKX=G45af9sC- z-2wAdHxqm@zcswW>RXHrm+9b^c0p)5{VTTPfjgg|5ec~!%>JGe7fl9LU{CM%9PqD;gzuO+mTxv zM}nRglWCD1RwW#)lW&1`>x{t4z*f&OK+h-6$sIvE_v=cJOfalbXgt7Z?T@FpS7nC4 zYmxI6FqvH$TcC|Wl4TohZw3^J6_!YfYSVP)J#y|LcMo`iZxp_oQ&ij){Gr){Brau; zkx_DxRQ_QjLZ#KJWkk5|ebo&vmId>bSw~XT7*_usfT8NOyQ-yYL4S- zB*Bcl5AGem;HGMv(-|#LmzrOV4MsyhMSA!Yj7|@%8?vELv>E7^d2T(` z{JSGKKUTqa)R_<}zO4B#=kJyZk;lgPdAI-E z*~qUYI|+WJVw>cUw73n6t|HjR9w>J9SlG)tMx>LFSTV5_Swy#5-~%m}1Bt_tIY`3A zKgp^2eh#T^Q_6+l%8-qUI<3-|IxZf@Bp#BjHkk)O_TQxqH?TI(TC`4j%sR}q=N*2P z4Pi1IO5;Hn^J8>uEKPS$thy!9F*KQ=wv%=kIJ+;u@|919~T`OdK<Gs8_H9H zk}g6@qwQD7j?z_`G8>*Aqul!2%=UP&Y{q!MryTRAY>)2C4ALSl`EQ1!8z%Qg66@QU zzsO1j*jBVUF4}FnGss<2oZV@lB!y&?iR55QK-K>Hr)eoQ^paq z2XgZloS#9W#QsVw&kd6Df~0*Oa_1L~x>D@6AM#6{yE#M3VJfsL?H0Sif$vF8Z8s7t zz(-R|B}$id;l_EMdmw{1Pb)^BCrF=6&$7Mz?!!PXXqSF>LVg@Ns3}kH7r@cAIV#<@ zm+8aM5lrfEAm($5NA_=bBWZrar2nIYt?lmL5b3P;3GgiY1h{!-WuD^ZZ@v_KhApw$ XJmX72zxh_*+diZHfIqtn1(E&+k%LWl diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/9.ogg deleted file mode 100644 index fe27acdf3b18dc683f77561daa26be83e5fdf8ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2100 zcmY+F3pf+%AIH(K;kagMkujT&EKIAz1-KO zQ=>zXm&5S{LO3DN2aCnvN%C^ybJnR8?L!QP$8?QlC)^2_;CBNBBEPYaci1XlS#

    +1N&Kw|R(daH=nZrgT6e1uDAOxdY)PI&A3dxNl+f4E^K=xRdRJe>;|><* z5}yri!e6SebGFByl$3NU#mJ-T!+e-z9xY7E{sM6?e}ah zMoI=(%{dNXu8Yv#mbkh$)Y3HZBsCRUeB_*T!5iSkS%RmDdnkvMnk;_0Daok-vM%z` z>t=_!NFan^Bb$6Y0)mo~)su)#4cabGhChAo=AWda{ z(dH<<`F}3XId@CkIIwLo zmSwpB`#ek)txTz7>K0fF$=%<8e(|J|$1#Ir7tAcd`goE$jHTq!qdm@A!@Ly|ai~u- zJRJ4lgkgJfN=w>v8H$q;nzCHuD|yPeeE~i~e+#12t9Lg}lq)k`l4(Vn77KGcp;saq z+Q(rVO+wx?$jH1LFXc?f7rIREx?xV3To`ir?72CSv1as^B z3_KhyG~zR!J9gb57-dImNUUbWsIFk{wkN<1FHi|ykoyOKA-Xwdk#Uz=3dK9^<}NN~ z@dDuwb_(JK?;MvFDIcWLDcG(pSFFCOw~(Jid{uP!)$^8)tzNB5BPEWKp9F8>Nia1k z&aT4z*Iowu`YY$L;5B4n^M29DT0tTMeE-~StrxeR-XEsQ<0cY@4mBGufwQVb-y}?f zEwLs0a>F8$aia5SfIIU-v6WQdni>4t<4y4Fg!!LlH)vWZ$P5Nh+O2>Dtr0Weq7_Yh zR_n35FEgLGe%(W~?nlhFdZ|*LbkYr^{d+FQqG(4d^!vyWSkBzN!QuQ8I1({c*Zgh( zrriYts*q`|$J&iLW-No(yT2q;&z9%ewRhqhB`SPnh;!zX5n{zNV}L;sWa_X5@zt#c z$=Z`!G}J+*89WK9mKV)qB05k~ABpI`s5^+@!iN*==pp#w5@%LHw(MWGQpr}M)l6)z zHdn1hku=`>0Jc$g`)g;$m|>#?nk*eT(9qsQy4t$AMXdKHqiAQQ$nQ-nj>=v}3NXCF zw9lxYWWMgllN1jdlOD~UE(kAhcR&qfoY;RX=~CxCIp%1#w2J0cqjiouhXjbNv^X5~5QAq|HX$V*Izowc!6@-5I z94`2C^1Xs|lAboqorCK8b25<owwj;4W*>ig zX6iIS*xyi7lm9)!R8#?g>qoq~=h>bJvES#ST|__GDC9M_5NEnwA0A5S0OBIPLEB!e zH)7u-hjdJ5db^$$Uv7HxTgl?u*thS9mjN>xz6`l5a;9j-d vhu`;qow>5S$K|U%nRznHgL_%N-s6_(?#--mTKyNx*L&Ee@V#f?tG<5#5roaa diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/activation.ogg deleted file mode 100644 index b48f215204072308fcff060eb6dabe79614a5b9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17207 zcmYIu1ymft(lzc7+}+)SyL)hl;O;H~g1fuByW8R(+}(n^2Zw)o@16gfb2zi?^lVLc z)!bWktACiAtAK!k{O`!Of{Fh6NL*tT4vO}}!PQyH)X)SJlnb<1?>|F+d=3Bq$JcOB z;D6(nk#eB?U&B=m&7Bc|-^dxdnQ^c%ax$_oGk=XB0REZU8QYtfI`IRq83V7ea04&0 z5ZhQ9*#mF8&s|1c!crQelW2IWAk)Ib$L_m;&daTgCog<4Ot>xQL0t zP$JfW-%w#{oVvG}=v4SUQ*T^^^I@JWM#||%5+G|)@vJX@RXAnBhL?tV z#ebDv22HW;S_h(_!iHHRd8Kd4E)=-`G{RyfmVvc5&U^f+6=tUyUN>(f?sSp}J?1$& zrqP=}eVT^n0=x(B>x(}qXp3?JiX$#;uQ8-RY}O9D;QzI-fh|=#zEY5XCWXhAM?2h($=1#i{I@wle)5q3*qjh2kA$ zsI3D@Ndcs!e95cBo`c3ZAK_swe*yMsI}i3^_yV*G zFHVku`4?>NMuuAmFw!RT9GMk4e#u*$tx&D#POlC&-MEqc|UCjBVk+wGMCMIT(nx|ohQEvdJ)u3@R+wbj2#yO&ld zH_ITkN1JyUT9CFbaN|YNh0NhvcI^6BiKxV(Arhv|b~qff7``WLx()Rj8qvvMZK{d) z7**Ft@w!9*Ul*@3_W{GnFxG)&WSu=LLlC!1;>J7m5Q%!9el-?Ff%DDzg16Z@EVvumf#hSB2LsFgfs=3;!&#Bl5JRzm_7yZnyX3$7gQu>~y0zVhDn5cQ zp-~$Z#58%*X#81Aw}eU5iAZCyyW78_zqmTn( zpyXVEn!1E${!R=J5L)lq%JTA0Dm^i7bd!klY1|D&rc63Ct?buw`YSKka+2Z?0JaUg zj16HE3!0M9x#G_{u^D;yb;j?X5tW#7W6|?Kk5P4M%kXIfP`$6EXCj*j$|n5<&p;^3 zV?e0N#R!w?3qyusq8vIg*Vp^RV%l5TqD)cvxe1xUr{^c-L;GC%VdzS9sP^3yC2Cqy zQk(0&qw*v@Q!aQzb(6=&QFJ^L5y(w5Y2eNVeo-p<3R1RY1A~Nws!_}$c+{KfL^iN* zLTI0VcyE@~vb#r;R>TSBVv21``Lr{}qrM!i#4wi{3~SIS>X+Vy-jQ@{apC(3+BULq zWQ!|bL4>(r0sypK(uTg18jumR+(+K#lOY7DPbAp&{O{Ly^^LR9HeN_Kv`m;TA z`V3?&JDticNoWPE&QuY8W{u{v^2`;!l3lyKxs*Dkd1K*DG|F^gM3BJ3b}RNuKO4Rl zxT0h|q=6)7L?IV}0&auzb%$-VC;n6+9p-#8z<@|X@b%#4-dcH4CPvHh z8tMsdSO*dj$4_V#O*23{Nmn}Z5p^VSljMJU*W{d0xHvpn5CGreuiJXwsV^Xi-1j@M z<0GMgo1=4n*Mxw3;^W4^AIYNap7Q?3?uLmMVP4`Td`JSDJB4efCuGrx)Jt4F@`g!i zeY|UY;raAm0{iXz#diNCFmT}cc#Ja*#nINy%EZ9Nz{JJX!Ohv(+2IQYg6-;RbACfs zO?bstXqie4|K!af*Lo4;g_m}9?jl=n!;2H`Pt|oyiFwV3<7*_WGc@mq&_lVqb)vyT z2?!TvUgDb`fxH61kXBHSTEz+bFFdX{{C3c1OL%Bc9wkkI`WrWG$C`mL9dX%Mlmdh~ z@{VX6x!UP!z?D82u~s-nLQ~eqt7_D!wgMw=li)K7{Lp24=p(ces?PoZv*MHdk-Y;{ zp80V(9GPu<#=1?4txCooEGn&| z?FE{z-}x#;^|NzP{6~mw33T8|w~D87)V3L&jIe}G2_jjjP9RrtFb}53R{o5#y$LMd zpq!Y8WykM_E#{dBp#5D~O|T9mCgI?SK0YBoWedaI|9g5MALuaqk@^|^E6TqrD2zNN z%Zde|ToRhawt*E9;-{AY4Js8CLuZOzo+d+dg5k*bK`Rl6XwqNq4GwMp2-OGKr5lF* z;q&f!|8|ssR7#{{{}i_l#KUL6G_r>@gUgM-M~lu1mN&0S8b}shp50L$%0P$S^su64^7J!@#4%Ns z9YKaie^LRJMkToADi2fMSPgQPBRzVue^a{a;uNZ0B)Hr5@icXi5#`Fea+K_KAK}-$ z=?~U{1Y{I6y@;9x-;nzduymWrQ~q5<3FsvMBjiDo0>^iv))30>>CG)S1DWlTN&#)a z>L7`4J<92!#?3D(j?alp7VHdHrgNKZP#8r)|LhO^U{N^)koBNBa}spxAJ#BtoBn`yRs&32L(I0 zKzA(oYUoG;^U#;grkm$I7A3XI!rg{dMvGleb^UAWh=?u7O_t@7Hbl2gWAy3g42iaS zd(^_!o+Ag}HI`-)&0~6wk>O7Gkg&kS=nB0d6EWe_5wU?Ru*5zm%d*XM{ zRauuTJxL#Mo!CKwAqySML;b|j-$3#qFIL9j(bct$eIPvyyl>@m;@7!qND)w_mT*xlwV$0}a(_q<+$151>QiQSfeS8TY zb9wqyqNDQm*J3h3QTU6p6RHNg85n`0j|rYW*w-Wh!k)F2iHj}a_lJ&G@QS)lLs zL<_%0_{C2g5n#EG`&=vhyB7iE)_ADk!_63_yn2s*hEaLPG9*o1IPrngK3eGPI+1WV z@!wAB(Eym`Nz-Ek^109ouss%9L+C*SWF=8hl;pJdoVD3qVA^f`1VF|kYi{^~+aeEB zfH?+PtospLa)P6aOQ#_=DZUmh{`7lmgFCEhPP-Y+wAapzQarM3@kyq4S+v$}4o;G3 z9`DC2-k1w=txoa&e2Y#DmEYjx+%L07@yb?h|HR+$$d)0>Nl|?uiKx4~Q0jz4=r_gM zKzt%=4Pv$u>53IqXFU&ER@BMAV8STHqHOS3c`|6?-!r`}3JDEdlxf*rQKI!>hqyX3 zDF4Qg+&-Ce8xp!rUB|en54iUhn(aK~Xc=Rnk<1)`GD70W*X5@BtEVq(j8o{bgCXw{ zPILHy{|UY;CiV=RC1v%~<3o2F+*$ULrn?4FTJg~4-vb8@2nZF^d$LN?2n?j}_!Jgp z&e@kk0c^=W5+TJo7eqk|Y{iL+BM@8dR^j;LELK@Tr^E+G)xr4~;l)2Dm!?({Qs?Bzsg1kAnOVv6whR{;e zRfzxyww6;O2>Uwv8P_h0t8(?)j4-~3qtss=9m<4-vAKp6O)?mWVJ{uk2-ysIvm=ik zqf!cQEq8GQ(Uy^3G3rAvTk$NxsIM?hEJm)%$4Vz-jz_UBmlDyn#Xvmp0OeD$*u$D<}lqPBlSr>c%Hg zj$z&;k=7Odhj^l4jx>g96p`Y(H`l>7vP^EN!{!N=A>aL+ zAge1z?byu&E-hKb-P5)InZ?Q6ku9Nu_P>Poa)QGS*uU-7R;NPdb?fsiDoMx)t zM-W$8qY9kMq(S#T3E;~y7^hhjnu8pF5IX&Xe?M72{H(gfAkEnxsuxHKe=uIL3O@L` zxzpq2J6zhdOH-b;6;(d!$YTv&wQ)P})5vC4%1vr`?6dGZXGc&mTDfh~gVjG%dQeQ8 zJC7^aC5WzOWOSM0~Bh=VB|IFRfUW5gk2JHGJpteFmR)6Gue$%C|yqgo+bbgsW zD!35cMP1kor95x&a)P)dCQeAFVO{&D1Id5IfF3qctN#4I3pC~;1Np+KY6{5B@2x{6BUsq5x59X(==n@dd%|%AGq%6Cz+f zN=V95z={;`c;Z*2(~SFT0FPF~8(h%rO zhPr>rkf=DL%>Dg*q!3c|pLEZAS6dENs7G@{2uDe{bl zYy9o$OC6B0B9VZcAUdw5-=n;wKe7SEdW<-&tY>U3Aiqu;Imw_q?_qylJ z!P+IzqveRPt;sSYp-ha{1D=?NUyN(w`<6dO$;cTEWSkwo7hzAmulys#!_%3DyH7=! zpjVQU2yIPcj^eN9K>j;Qnp88I@6>Kw03nK=q*dO0!oEg8w3eqLemSlAYydmq-laYe zNr;2}eG{uy6yj0Zf2!U=GDDuT2354INa zYqZOm4tpVjnL$`nXC6vu4MyTf`E?n9E$d$AhK0+1@_5195vV^zFP4jN2X@!yf=2cp z)T7Y*h0d+?CxM)dakTBUdTw0UZD}xaVVJk?jWhCAY*8|86v8-J%%y1?6>XnLj1KI- z|GqBg9h7fvk2{^__T1LKFmSqZ@f?i%X9tv?cX26 zFrp$r!$at9X5~oRdpNIm=(KC)GxR6lZLkTv3 zSqRYGz@j*`xEW;W^RX!2wdbg~TU#Ztv80@gNr0euXe0x<*A;UBJg|+z5j#YJJz7{hvhq{(qDV38Z8%QKk_TS8H2G7e{*s3j-rd zejR-WQ{WR)0jwa=sjw>P!Fel3WV8Qu?)?lehqfY@vq~{Ysr-eH=4E=2ThD0;z#KgE z#>+6>%+`G`QbztXD+gCjHmyZIu-$67Dim$wjoO5yO@-@hdsta|E9Of9^za*x<&bot_4Il}TnM-&(A}YIV7xYt znk^Djl!BK`r%1>GLJQXl)6mUHhK|X%(w5+#SgtU`_tTiDf+yH-#t4?Xjr4f+s{B%p zJF943Y`j-1+xuI?oyf0FPw(-*0ZowrEU(-+2MsXqjy&D9r~XC!MTGMluGAcRkO{?a zo_WM#ue-qRq+k?kALMHC{P}A;Ld-&H@S8dcr5b@Uz2S!)F?DDfRC_& zuF~Fz9440r`HO<=U}r(carh#pRD%TC{(O+?!X}3(stC1u?)pd71#QBHn@zM>jPC;$ z3*ie6vmLC;m9cPqmPJ3XkhNO!s4t1T-ZpqS;b7@d)%6A4(SC3~_NXUap3-TIj;<+M zJkAcJFAq5P-!%s&UgL8|$PM?q>pHVbR+WSJa5dqOqOwr-%%lAbP?=SA63Pkm)G~`Z zyqcYL4IF|8MvYI335D}mjYIN9ogdS4orBKThhPSd51Kdk{J zUs)qi7=c2c^T|>LN3b<}0;vVl^KpQXD&sncTMY!U#Z5E4{8rc&`?26FTe#o*eQM*U zg+5W#ao-m9NxEm2bM~;bslL?)dSmO2$GD0~N7M+K%0^#Z7|;E6g2ws~(M?HSGFU?Q zXSRPu2?UTdC|dK7CsNPcMD#2JY1ZJ@Jvfyq13A0EZ-ug+27bMWAVM}8dONHc;fI%8 zdN>Dx1(KaiADb6A`K_e48Ni&GbCN(Ha{~p1CH}c zHO3g8yKDj-e4cHTL+ia8+|8qlSjQeVH?e=+8wC9iPy-HA``{*|e1Sa@q$dd*AJi3h z=4FJCAfO09LIZl+iAX!_Gt+Hzk)t5PZH{Nd8bA%3LptHu)oJY0W1$RP^*fEXhq#Vcc>aC5#+ho~zBeqeiiJ?cGSMjzB+)jMhxJXlci#nN zfZ7iV7TZrU=f|Fvl+yWBcEaqj|SjKnD_2g7X_hy0!uyyG5m= zu=)!(o7Mvd!=dw6gi^p44O-J6e&3Y__bn=tc>E)N8L|@7dDd`2-&MJCNQ#J1FRIHx zaUnEZpEL0n{(RN>r;bmW_{h}vOd=!XQs#Lh@**SZ*G-#Udpi9TbydIY1GGmRVSFg~ zkS4($5hxa5YU{YEK@D(Z|84!aiT-lEl@~7<>5~wtdUtHYyDos@tJAn=n(heII5k`G1qlFYU+6k?~_6CqP@(yU51avEl z^;%TedJ`nkPWRZA?66Lri<^sVfscr+9|cQ7dF=v(?LoeODANwlPGK@(JvPk*2=tRnl6)a0MLb-<}iJK${R)% z1mvehjuWr*e{2LXdB<2zH5C(BYystOV6OLA7+hf1z;q0iClE@@kgEA-tb|e}ZF9#b zLG+@ztpu%puT}Ze-$9awAm6#0IA7IhMG?*rzJj1VGs4gq>UTs79vI-#OOe^x_Mh=MWsiF44 z`>YxoZeU0k7?EW|H`h{pX7Xi>97})i1^iGoL3VZ=?V6r0FemD{lotFJi({@56XCw~ zB)We>{1%3G+m8*f7&;xK{P`nuyFD_Td4CB9;XeE&(X@oQH|o8J@ZtBYzcqNL=-jVh zF=ZLnXSHBLP4x-SzKrg)^dn|R5WzRKE$(pf2}t{$;nPkpOo?@cD11&zuuG)7q;K|_ zpl_Ty^JVGAHWbz1r(jx=47+)M_BvSeb-Bz}%yGCc2kjy&oWVN@!zR){lpzZ@8wt@y=N25tGxeP{iN% zW?0N1Em_D4qw@#SK7wQu_ibG4pqmsz((?DCu;u$+bt6=Jc&0EB(r}Fxuz%+!=H*|e z+!3LB^hZp}3vzEzA(S1r28d5&ZB|HS=QhpuVH&}0beb*(7DNX4h#Cj@zcve{x`HN^ zTYI)Wipi4_*G4Wz6Ke8NF@~g6NicpseV<ZM6$Qo_`Wv<}<=|7~YdF zi(on1tx7cjK$>=kCMg568;Yh6O7Ri?K@K<^EeH$ldRMQ$MZ_c{P^cAo>3xWqCs_PR zQvN2v5z+M?4essr;rN-c-HoQ=<1iMeTuCInF4<~`rq>@i-IKYE_8@CJp5s)oJoEE= zL!1Ie#?o!%1g!!$<+P9+JOJT<9a-QqQUppTH=^awHV1h&WQ4^ck|uX}oFytY zV7E{E3TyX7b*q<_M_=#8_l91KIoS69L>rqLT651wtZPPO)cesJ+htY8g!P?sXdxOb zK?5I9$Ax5X@0QVgiSSRs9U*F6M0+KExa7hRD1-va!9ha5wAZMWbhzYA-^m>75q_ST zr_2H|$3*u(uF~g7Qu$52hbaVJ=m81}fE!qnGW41x|TO4-w$M5^Bizb~NHBJFx!aqrBd7Zn` zpWx6Z-LYpRyelGfWCeLkf7}3*93p(YP8+hMQ*|N=@8MpvvjTC(Tgg~^Q~c~nNrD+6 z+z7nRnFAUM`0`=OSMZm)m!h1E&q#ejy^7xq^MQD#)~n#v{HvO04%w*k`lpymyeXF$ z^79@S?GKrBz}$oYyZ`NbEKBb7zlgT@@miBE=J1oCi@a*h>_t+W^+0#x=L1!Q4Wawl3?bo2+h`ptqJ#hdNE7VvG zfK=V{7*!}Y08WjJ3V$azt%iPqar&1m5jU=+7*S-?_~3jcdq7PW=0H02OGs$m<8-yt?G?CJk>otyx>en=9i5Y&YuG7t6$;-6~_i~@lmmqKnWEaG>yUTBsl_ZRz#d&}@aS#{}LTY-NAg<+8sV!uJ?RYX3p6UFg za>)8mKdt|gf?VL@1rIk3KQ*$Qjb@Sn<(cpv>4d7I%njZt-Sd@;uQR-|49yoj!o@L_=gKQ>GrW9e&FG(@kvp=o_ z3v7m(A&nD>je>`3`e4%V#YEJvX~(H*^%RB9@FDO~Gm~FW%k*5_Krvfx%W$UiT8`Z1 zpnl!77d$hvo}kQjhRKSqKY)QFlU~gOt1c?4mZVD8bb|JB)Lyejo8#^#UgW>T-NbS) z8(rh)EGh_Vt!W}UFhPb*UGUG(KN2C|4s|($!?#c;^ww?=zBSQ6jr}es{gAG@{xuTlJbTa#m1RR3A9PxG#3`=87B+wd(x#< z^12r5I5-rAj9U0OAeAS=njN3R_j(EXn>V9ziagDnHO0&>Lj`mjSt6XLRZxBm7OLn` zX)ebz(8qCPOi`wep9w*rowgIZH-W2XK=8H)LmGcem%deXCm;=<*%`n718i7J>MM>K zVwpfcHPEp4J)2@U$~;q{{vy6Db!_WOBuv6Ov5Tc0TVKB=Lld_dTwof~1nQYM%!^m| zUi_F>^>UiXY&gpEi~2iy6K@QGzZ<9A)IyXT;$j37K@PEyZ`XRk5K%#OuqhHvyZFnj z8s1D?1N;QDFCHj>P*K!flB07QV zT{RTI9|gLE_6m+6_UO*k!J}i{)q5YTsHCrlWx6`IrI0~96<*abb?r-~E|UHR+()*f zd-=F#D&o|GqK=L&Tq3F!q%?zIfQKI}!+3d&`#dp>~e+0+krMf|)cuKhx z|2}O0RW_gZZw`$D*kI}R`{5D^!2xJi)f)2$VjX#EB5~$D_$B!IR(HEIU!2fJkMps& zBx+p9^0fy9n2>i-aB#te>;<$^K3Whe{VUrbx?=?7c-&2tcsIQSdk61LEYU~hdunOd zQ?xcXV_GLKIc%$k>Nxr7pHa&HerC^=Q}C9NH}XwuD8s`uf(o7i4f*s{JWk zeYRT9jFrXKmi(eQ@3h=hEKowAODmGk-7pfS6B2mPVH(-_hz$FAHK$xu}>cb>;FsK9)C8`WJF? zrOS4B@S6EqG+Ytq-Wq#8OE40a;|#@7y3FneXNs04QZgw&4TcO*uC8&`{JQ|}8z(Y$ z4>I-L?FKoKYCOJO?8Yld1igj~7*He~t_8LY$c`q_N}QWlc>5t|Fb9K&WMBsr7c?(= zWMvHAc_pvNQ`emzTuOQ=Qmp1^{p+o^sY_M!Y<=9XH-cpjTBpOlH+QB0-;h0a%0Kvp zHzkgP<7AEfJlTDlh`8duRdObVxi_KI9mij?6krP5BbXTF7blOJrPM@>o5bPL-riE-mHOZ}k`t#9Bg?hvSsd3k+N{~?oM2k4 zpoT8t+*PDSAj@c&DqANbpo9kR{B1OD@A1RKI{Fxss_y^Zt7lLr5$DNHVy_yR)bSC# z{y^h`SMV!)VBC`q!4$fzp45nMjVNZBui zzD{=#ipWN`{ZMsGDJxUJpzdQ@`r*TDaY+R;Vpxo$Bzg52Ue9mI18^Ks zeJM5Vh`N-iAlgP6fVy$^cTnpUbXaFi4kxJrN5$elOldW2y8gr^q(Uh13QC*Xi#$IS zFLPAKly0-z{7*{hjT*p0)D{!6y5C2X+`we`p4Wh21VMqZ0t#6GKyqfDUv(@70kGyu znRbm%W`48J_O0uZVUI)YMsP-ISnc1&Je(X2e*kVj0P^H}^`XzR?x;kv&{QfP$hZLyg3=g z#KAxVOtVh@i@#vnv-6_>Fxwg_F!(Gg8>~jyK|L}NYbC8P>2(|c+tbp1Fv#c|y!p__@s8-?%spfW2MMfN z$tc?_6}6}#AggYW&N%5J1pM3j67a9=YxRo(DHZpLqRJ@Z-tAy8K6bI-H=?7WJKh?9 z2vKmv=G90X2u2&`S(^|vD!r~Pw)IikvPQE=r^5_tH^waQ(cr?UhhTac(Cuv7^tg}k zPLfF<@}&-2J^Fz*Njn^>1tOhr(^~;T86WRCW=1Gj6G%VFIwSGcz8|yZ%)^o*w$)+U zdC)0nf7l70=5n7!87d31FZi`U{~m`sWV_X#A@*$zpc@r3=q%2hiw`3XhmM%aUk6oU z+4y7gnx%oY8`A>3FmFwxV=}U_Dqx0{ zJlm?R3j&}ND_B%Pd>3Gxx*$##4AGQ}GShD5A)PQ_y_-KGpds5RT6T}ds5sT$qQe1I z`kQaH}QqU{?}5~FycL+kFgW7EeA zq`2NOVI)%yxj-`-q_Vi&>N9yUo+?|_FIe{w*i9WgCZ~txKtdKS@&8fQ#Xhg8BOFzHST3UMa&G_#mxcM)j^j3T#_*h0 zCK|fypvk^%g`(EDN)?a4oyD7fLv&+Ldw*}5g6Ao>NRSUTqL9_90*W}Kh6tq)BqNGRE_!I&XeVg`;D^ z${rW|HD3mefTSQwYVW(HFF6$)Yoj%3$-F<(bQwR3IQpk)G2fXt7IziIOgs&%Ea{`` zMvEe#HFBaaS(5j^2JFlKu`n!vP78&wM#+4oZ?D zZ6VXRAVW(WL95>N8Zc2DW%0Ay1`d~lws-cA1e`+wou-CJ>DmO{N>?8370#vc{%}Bq zj=(z`u)?D%VXG0io7zM7zH##WM2!uU%i*l)t)y+FYZnzuQm`u@>KMXljOR_FMn z_?3*0!_;1op02WvYDp96y=FYc;kq?1Zf7zmDBOTz-Qq{YETP2mUJf2T=Fq#hN z-Dso7$eS)b2h<`~;sEOo7(}w4t<~A&$L^$Rj5u#pdU&oLuou|7^pjkCDi>H(NBGr;-LrNM3qb z|LN8xF9Z-&mLp2tTIQf-kamcHhYx{zH#UuphA?O+37RK>KF1`>M*RcOsb2lWuR27n z75r2M!T8qv2gWxojUG${spG0M{2=S{TuzoBAW<6ip5+N2|9NA z2-okgsEss4n64Ij(FLNx5=mlbn@Q*FD1g8duiSWmSF|*S&z-h=?tH7((hZ)YRAVFZ zL>xc_GFOZoZm^Z=I>SQTb|xwa!Ndg7bB@p3ut?oqy@>d8_qpneZ~zpw^eMxm1XF96 zfxg=85*lNP+_q3Cp_xf+=R)oNTkn=iQ2Pl03~5_5rZ=UCIELo|^7D8l6xP~$-Vbl& zNOJnAPNB0Qs164(%CMu1xv}}nY<`Y#%3oUqrRU*lwM*B^#!Y)=5y{LME?FR3K!=j2 zyxc(Wna~ehS+DOrREB5^R40*^J8q>_ArMM;*5()d#p6=-Nga*y;5&Xp%Z43LfCBwT zkZ-iNE@?j=S$Q6`bsrT+E9qK&m->0B_(v*mGv&6TKGFeUE12I%B4!g+R&!g8>G@du zVDKw^QrkY3X~=y-?c$F#elEI)mBHf8!Bw9>u+DxGvDBQYLP5gC(WQzR#OSG~dCh4u zG52r*nnfzm6gV6)_bwu1?8Ni^rV!bW=ZefyxeBeXUo7>M-h7K~N6Tq<7U-0_JBPS3d-cTta3Iu8lO)kuML`sLdth6wF9r*ow96lM)LOamPG@}=mghz zEi?#CF!k1&XEe%^SrPobvknz4M^1Ey1}(Uwz28YY@C<)Lpo97?99gS>R=H1LJjAr$ zRR^kSDR3ppQx%<3av6T`U-_fztYd!dTA&K9^{eeO`_{{r=85~%l;V1}U zF|k2c7x>Rqc47b^QVe^Rs1oNk@Sx}fNjMVai~74U*B;uVZ1!i-4~&ZK@FQr#!LH7y zu%_1&O|=Jju%ECjUSx}HwF+KuU4BuLh=oqk$t+HFO=({{7dr3x$T9fQ;Fbx;5s5sGQs54WEqElxem{4PCG}!Tb&W31@MYRT6`J3Z(2f!)S zkpMj%TI!>oGUd=AO>f^JCN%}w#mp_}7?~lP@!Q1~j>A5#T2g>e*m+B#6Mb;||9Zyl zU!CIr7SV9P^8j$$FN&j+wUw>4lY_0ByRELNl_dSw>zcAY>BW zf3CIVPGTivecG;8Z-Y+DGKr}aYPkaB-`G`{omEo_&6*6G0WYxaKtvncu9xOjF-Z-G#bT?S|`}i+T&s4!h6`poB!?Jr4bU+m2Kq^>d=v@4#(pOkD z5M+k^7)<;-`IyY=d>|-i+x}U|%=w|W- zXE3RW6_0BM2C=A?6Qo2HJvX4sDb9eSot9ShQnCz8GIl|}{dfsnzHnU=8V(SO%{c{{ zqHIvqkP}j@Moj4k#Lp(21?|W{(#o<5K}5T|K|?`nm)X@+Mn~C|4ad5&v2j_!!9g#_ zLG=@!3U_gYXaNE}SVYR+_BNqo8%wv3sV}(SB_VMgv~+@kiNPg8E5O~NG8K#!hUnvf zmdI;LIUAI^<3p$9MdDGyq?k9XbLXhRxvytc1H_7cOP^6!op$Kf>r1I|+|-uy6WHnR zLYW)MI_GdjG?Gt)=Ktj`;~A30}|iD~?Ozz0oP~@5lbaCa0ld z8xd7J&}YO|f7dMXu;<<2nbHrRMg0mtDlM~g0UpKp{uZbCF{#%iXILau zub=7lK_eU}S$c-q?^J6Y2XG)a%{^T+cA?h45~_cXigu;sl=sc`X1E&AB1b6G;zsu- z$)dX){*?YIjT$gK%bkeFj0H|=(wdkso2oVctV!Q-lUeaZy1QT)Si{%WSuHs-ZaDFd zUkyN>Po7WAnzRTMB>1fIHe=_IyMVrDNfo!+*3NFt2ax~p_9(BFsE^~q@`+oGx$wY7CMAUpJ#Z(4tsMS${KlyLc z${Ib>{2ZjuJC-Njrg$cgf_z09DbRbgSBzGkVFOreJe`Hnn&z|)H=c$bNG+?wxctab zTC>Ws8j#rP2j2m(u}m}>UUW5w3VRr!=cuYKEGCpD>Msy>AEu<;@85QhC}u5p?+$cm zbC+HLNCJRruwgd4N}l|P9twG=Hq(I~Fs?lFo0cv^oAI59pCO&j`z0rNy#gLw z;$q--42e#k0-u=cvNcq>7hWAGax3}=IC_(jpjq32J!lH00_GX+{Z+c@G^+ClX-^hm-G6zqY3 zKR)hK2k7Lp*NVYBqHbRK9E*%*L54TRl6vPsg3-;e0MR$6b6y|_s zH5GZ5bqQJEGuX+eph3^n&q&H&m6+Y*b+HVUe;Yxc<9p~&Q;2J>wHX)_MQl(}FB|oT zPw+^DSCVTz+E{6Js+VWkmhFRoeX1vH?~Z`)w=i^q&=8Ac-?3bu)+)2$`UjS=m!T9JTVcR{q>olI6%(0 zW#nK`HXYQZoi6%&kLj#&U{H-lFp9~lMH7jI<1od38i6Q0JtNwa5BbSW6M$~MPrD0q z&8P~uCX*CmU@A3}MvO+~0zdr8EDRtw;)tt7KpuDspk zd^Oui@0We%YI#yNLouH7e%yrRQT)ul48nWtoile_`Td(iXF@8DzDa3qK**1LPs8-8=CUidrBaN%r_gWSz%1emDUDTUMng diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/err_pin.ogg deleted file mode 100644 index 1a3d84b2953291019ab0de7023436531c739747d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6043 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/fr-FR/welcome.ogg deleted file mode 100644 index 4492de76fd04811710f736d6d988aad7780327e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2927 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 TV)XTj2alMC2C1g1wwP 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 Ses6E@dbjtx-x>NaBmNgA!4($( diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/1.ogg deleted file mode 100644 index b0984b635405b20f8f4e76860b9d91e72b25be0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1921 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 E2bL7iivR!s diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/5.ogg deleted file mode 100644 index f8bd9380460b2280f0005ba2f178d386afd69f45..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2220 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/6.ogg deleted file mode 100644 index d30c9e5c51d84ff3194f3f1716136528c7d98156..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3459 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 T`#&xr_g9qS{gOG*x;64IJ33N> diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/7.ogg deleted file mode 100644 index 610c4690cfb5ca64112bda9d1d20a6d9f9208704..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2222 zcmY*a2{_bSAGXdIjAk>6>|1U$$Ted(MVqdq(4-O#gTL)&$<_^%LH3X(OO`vLv5uvf zVJM;OOKyCUUC8buOYZ1?&zJjqp7WgZp7;H|=bY#Kp67RoM7qMk#qqxoa}74%U!KdL z3UVSZd3bxCv$rL3a^g5yH-AVj?aTik`*Kb;>NZy>;ndrgU$rH93bJ=D+WI(Xs-3`| zP*YXiSBSHRz1tmkqWxVxHg|{3scErEH7OS-J9l>CKgNdjY#lrHjrT95cDmC5j@KbL zdAi;6ad-Fj@p8Rp_$xpbK?%%$CU@grJ*N{)A2lvaWx|3Qe*aJ^0|~D#$rhAj%pG4A z5~;H0uVaY6hCD)W#^+AO_WHYA9>28S&LRP16ao^Sn5gqmuECI4TB0X9X@=p2;~^0> zE}{Wib1KvP&dxnjiNkb=>GlcuN$>TWcaL2&q1nJ60Az$XUk*1=xIuvgj;?I`_DJt^ zwFU90QdfLO^D?q%IN2l{o4t|o_UqijA=Xj0GtMCqNkPSZ{c`C6w+6K*`Ay*|50aUr z6yBG+TsG&>>M*rsP4ra@fGjPO{GqrV9(M^c>8jKe`^=P>#%G?kwTBI>=5CsyezI`rYgyrFdFq~Y=#$ycQ4 z3*6G%DfhC3&h*!y%33WcD68=+8SbAs>YpF|*6Z;GgjZGOjEaaSj$lI9E`PCnu*3Y; zcj`#NyTLN6L5+8|i^;wz1tMwcV)cKV5r`|0+-(KO@={EAq%mw4PP(&%BOM-**9Brc zvmJ>R8LTp8fg{xFg#LsC2Pvi@3Ki@~LM*%lg~9TgRV0hvTT-$mMvn*$iOL#T;Tbh+ z`8yVigqbfC364aq9pagQ-+Rl3!Ig~xePa3<3QhI*(JKIV1wEs&<%pM*>XRvEfJ9%_ zX*g6j1dRoP0O*8Lt>L;J)>njMN9*}b=brnCuPe;36qU#bPqDN0{hc#huqc4Mx^d|1 zhby#W*Bza}Be`xFd-l1y7tKI$B+X;S(Sy(n1%Hpis7|;knmtod^8fsRaurz)kQEiP z1(vpL3onXgjx$Dc-@#1u>-3k$u$T92=pOh$KX<44_mN_vR-#$DKp(v@O=zr{UZ{=` zu(6me;mvyy@7%j5w>D8#6ef;lJw98cCI=_{x#OkpqI8s zfn;&PE^vZ!X<4(mz+3Qxu#MGSze{%iTzKvF6vb(qeFd|tJNahnnZ&Z zEKvg*l-B#)bK5iu3qtgBUV1?Td)bAf$k?!)5H=a`vyr6DwQH1)x4R-&`C=cAm5Q`$ z&gM(VLOBC5Xy#FFD^TOF!Yw&ZqH{1NAh$cPkE#67=(?S1IvBxweIZruFPKLSW4+XM zS4!ta&W#yF)B4*8cgcKpuh1R-{uHG3r&IEK&!%eD=GbpkWU6q;TuZO2Bxnks&#w1r zS)1PuAkqdy6g`X^glxC%YmmBdFqVn;!cecFEHt3EkmaN=gs{0Fo~>(<>v~#S!}%J_ zLLLXLH?_1P1`DX>A{MP0VY0jl$?bUpyMJ{I zoHa(_%w9-h|y@VDsoK90baV&Kqaq zp5_!ZHQSJJvrv7M*EV7-A-<>mg&HL$Qmm@!9B$Q?6=NmAJ)9tQSW4#PQpR}XZ#u!p zIX)>#30E-zvV;Cec*U?{*s%lb+(G z^Q`8Nko?}4t|wpFou%?U6@h=(Lrs{&HF_$uuJn~j1p9#wC$&{SM$1kDWHb_vTN(`8E~8=nFaC4aYJIkYR`T zX2pKAE1nqc{oeLZyW(cgOq}I2u$GE}GCKe=5(c4snOD$Z_0Rw;cN%{yRNkWzLRrCw zzjpS=n{sO<7Nu7}LY(^yy~COIgXB@ykI8lsf3oibUQ7 zrmpz(jURF=Rt`eerviujiIPw_9Kih(XK833U<;B}}=wDj8*Flzz4rDSDwRI2r dG7}G;+FXG<;LAq;^6lD diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/8.ogg deleted file mode 100644 index ce834f6952af1ec6cd330580f69a6fe500b3e397..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3889 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 Pz<)&t2L4_HfV%$&1%Euv diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/9.ogg deleted file mode 100644 index d452e955115882b193a408489e7e0e49d8c49a52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3396 zcmYjS2{@E(7iO}|SOytOsVsw$EF;p`vb4xDmT2rE#y0jXOd@0KTNoz!?4)c{6OtK( zv1Ct{6bgyrlOyGNgW^3-LTZuqZbt!6rpE=P`!HubKfZ=Xla$}zyx z|K2^nKs|NM%Ss3p3{HTH{l~1+Tugp>>A8oBOCx$;n=Y}6s_!y`;yu(C43gvqQ?rDw ztVn~RJcZ^*wWGWlPX%S-?~G9}I4)se;i;~XHxE8)4XMTuS4AV4NoBVFPP?3QI%ZQL z$WkwMGDq9KXSUK#1yjJ_?a1LIzQwVS7}vvJf@9NW_+h~aod{yIt|4demHThA8kUpc z=VE?qVQ|7CM2+e#$T&jV*3tvfnzd&%sK)5hy8iC$CeP+G&Kt8t?>kN<`QiE1RCsS< zxGI2);P1Wp%NXtO-f7){Veo)x1(fyOb~AvtUxs)k225UPM}@5HzECyzXg5ez#^9h5 z#E{nB3K=`>EwPOB81{^yM8WU3Szb^U7c@R-HyorhOQBF===rAZg#}Ox@IB;a2RcXW(!bhr}k3=U7kiTwp>iC2teJ;-$M! zq852qSnv0Gtv}4Wd-@5IvrK^x+i1Zty+Y~B8g+ap5>WP``$6Lf!1w$Wf0H`Pm4G;E^MK?q`&7MX2a+@aZp zOc6r1tpbHl@Nqss%m3SD+T z^VBmc|FvsdTCRJbg|+b4QHf+_D2e6E*q4^M19FFMzbI~<3h0_x1vKC6ZtgUspH`eY zwL}6`o%4|}UfK_>&u-!6-Voni_$H)c?Isxi;)aO*gadNk*&=%sEgPpSGT6jwGM=)7 zKf6q0=m1!k%Qq~jQpRQ3E&X;B^@*x3a2Z#z$a z;h=Ak2Nd_o_4D+c@h9J1bl-v0`xaCBicA6Y)31S~hcDAqR{q=tmX7Ir zH?X1pUZnutN%g_s$VG!0Y%e85JWvfbBHgU(*K4kw@`ruG0Bxj(PM&EsjYQ+=xh@)M zVMrE4Ke^`L9=~CMfh$-Hs z5);F(8();9E|ZYLJxhrz$q_YEUl1a>382w90Pl2V$^D2#BG&a4Xje^Od(ZuT()Udv zLRj7(r@oy!^z31!PDz#~bd88T6Baydekrj)cdpqR(pIcom2Eu!9CU$Y#N3_i5Mxy> zypVyxNs7~5g%y4e2Qmc9JQpxJU))U2t3@okY-@#X$mJyFtmH(H4!1*ySPw?+*`D+t zVofnqx6=jm>VP@;{mO;7I*s3#pBWSYdmo|kyS%XP9R^~{_Mmn|1j<$Nm0>Z%jICPT zjA1z3OQv;xqjU7aYkDDzQSBTg1ZnA47YNiV6DU8v++`P1>gdG_HQYDzZM{zpGl8q9 zdO6=B$!_F7q#1`azx1Xj+h6mZ%5r_ytz+HhM)lwd01mHS*JihTo$A4|pFiZ>eAn;?v(9fhq6kA!v_ zS2*ymC=N=2lUsS7`)%tdicws&>dOZcO1IA5K|T^{LDA}PqC~CahiLa-S&${FesGM;JrZ= z#n2KyTQ0*l3`qLJZ8JHyfWb*f;-lvrdiP95I!6XJ7hejzNAJDY54L2!e^lwok$J;AaY4?&?_zM3pI3cCBV;dMjQd(&)4bWo-O1%V zgVoVU_$$c`8++&Ht#35;KdSr4For0m>=2mWlCp$d1Ymz#8sAQz%EEDX(2b>%ffc9Sj#D) z0zWL#CjbN#v;Nn9iZfJO7jGP@q)%c5#cY3jS(c??>{Nk$kzDO_@c8OmP^>6ZN>eBP zQF!IIq5GbsuGusC^bXAj(o22ptX9RAeJEwVD8xE)DvZy}uoVX=F=^xPx}K{pUfIst z{BkCpsb*_hajnp0I{H~Wng44e<^*eZXjivIOVLSaIfId==1$}0IJPaKjb3_hQRX@(9<6~NC=5b3p GLi`8X#60W( diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/activation.ogg deleted file mode 100644 index 31eb4aca4892088438b98b20cf6f5f49c0692a9a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8528 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/err_pin.ogg deleted file mode 100644 index 5943f960014e0870e5ccad711fe6ef955ee110f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5032 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/language.json deleted file mode 100644 index e3570c07..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "he-IL" - }, - "strings": { - "WARNING": "אזהרה", - "INFO": "מידע", - "ERROR": "שגיאה", - "VERSION": "גרסה ", - "LOADING_PROTOCOL": "מתחבר...", - "INITIALIZING": "מאתחל...", - "PIN_ERROR": "אנא הכנס כרטיס SIM", - "REG_ERROR": "לא ניתן לגשת לרשת, אנא בדוק את מצב כרטיס ה-SIM", - "DETECTING_MODULE": "מזהה מודול...", - "REGISTERING_NETWORK": "ממתין לרשת...", - "CHECKING_NEW_VERSION": "בודק גרסה חדשה...", - "CHECK_NEW_VERSION_FAILED": "בדיקת גרסה חדשה נכשלה, ינסה שוב בעוד %d שניות: %s", - "SWITCH_TO_WIFI_NETWORK": "עובר ל-Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "עובר ל-4G...", - "STANDBY": "המתנה", - "CONNECT_TO": "התחבר ל-", - "CONNECTING": "מתחבר...", - "CONNECTION_SUCCESSFUL": "התחברות הצליחה", - "CONNECTED_TO": "מחובר ל-", - "LISTENING": "מקשיב...", - "SPEAKING": "מדבר...", - "SERVER_NOT_FOUND": "מחפש שירות זמין", - "SERVER_NOT_CONNECTED": "לא ניתן להתחבר לשירות, אנא נסה שוב מאוחר יותר", - "SERVER_TIMEOUT": "פג זמן ההמתנה לתגובה", - "SERVER_ERROR": "השליחה נכשלה, אנא בדוק את הרשת", - "CONNECT_TO_HOTSPOT": "נקודה חמה: ", - "ACCESS_VIA_BROWSER": " כתובת תצורה: ", - "WIFI_CONFIG_MODE": "מצב תצורת Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "נכנס למצב תצורת Wi-Fi...", - "SCANNING_WIFI": "סורק Wi-Fi...", - "NEW_VERSION": "גרסה חדשה ", - "OTA_UPGRADE": "שדרוג OTA", - "UPGRADING": "המערכת משתדרגת...", - "UPGRADE_FAILED": "השדרוג נכשל", - "ACTIVATION": "הפעלה", - "BATTERY_LOW": "סוללה חלשה", - "BATTERY_CHARGING": "נטען", - "BATTERY_FULL": "הסוללה מלאה", - "BATTERY_NEED_CHARGE": "סוללה חלשה, אנא טען", - "VOLUME": "עוצמת קול ", - "MUTED": "מושתק", - "MAX_VOLUME": "עוצמת קול מקסימלית", - "RTC_MODE_OFF": "AEC כבוי", - "RTC_MODE_ON": "AEC דלוק", - "PLEASE_WAIT": "אנא המתן...", - "FOUND_NEW_ASSETS": "נמצאו משאבים חדשים: %s", - "DOWNLOAD_ASSETS_FAILED": "הורדת משאבים נכשלה", - "LOADING_ASSETS": "טוען משאבים...", - "HELLO_MY_FRIEND": "שלום, ידידי!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/upgrade.ogg deleted file mode 100644 index ff36a860732b27d50ae223b201e7c1431cad19dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3648 zcmY*a2{@Er`?d}vOEdQDnvA{1UbcyZ$i61omy8Ny2`OWYERkIiX)F;2*_jE04?`hq z*(*YpAxmTZ#`pVQ-`D@Su5-Qb{XX~ooO7=8ocA{M^0K6%qxrumj|<11zINk(9Mf`| z`UN2kJY3vqY1L@k9REWxJ*EFQPU*B%q;z=_O{;lIw{r19vQoboy99fxz~oisVV5qQ zGK8qZd`f8wneK}RWx50oJcaNlrET9h(Ttyn#Du}h# zGvgc~a8n>4bm6DQjxGWX=48f&^tRU8*zK4a=xyl6DRv4mx6P|p?O5TlB2}!a(tq}u zSJi>>U|Q@uzGp7d$|kgjrPXha?dV)FF!P{#NQHv;Y9wjM+C)-$^*%&X(o*xgyVmaA z2wh)61ey=ZGzrS_iT}Bjb&i2mMmVX{rLxnBqR{ay7cWS1XiFk8)@DcpQy;zKk*o zak>zY%7s8fpm=3I|AZ1PF=)rHU=umFZD&7k2|7dmhg#=hKHx<2S@i_@Vtf@sEANSa zU*an=4Jd}8f99h=Wlu^L>5whuOA9BLK7)yILoPFfV2}7pV`gnpgezXpje$g~WxB)IBS-|Jm z$s*(WnaJ;$qn|#g_NSXVLywAxY;J(4!oo|&4Q!MNN#lp&S}($&%Tk7@o{zf@>)=iq zm0o-lM|k#?k2>RFN~L8^%n}I*G*lF`PDAJ5TX&N2bour1dDx-P3IA@o_O^&UFJ}-> z{P4S&p$hPiU(M0)%I%b!U&n+1w6}8#2V%2Y*SgfQ)WB2u3<15&FC)wKVCLG1K0A|G+*vVZ@}Sn^ps8>>Vy}HoPXL2f7qs^4z#3X*IYc_Ugn6=XA=4N$DYnYQMYdnWxmW8X49DF(`oy{yz zux6T|lO7IX4dd&Jrwio`$#v44EIzlvAH2RD{ih1fV?01TKQV$X?v8qD>Mbolnd)Ic z34kE87ZU4c8a!83oYtCYZo3-FN+PJF=EYGC*NS1k4-N$5etp0N+ax_xxGnyBVrtlN zEFgnG+gnc2ugsaNrju8Es^}5{);q zKM03vwaBQc#=E}3?h)sPj8RRpe&x?8G_tcJ?=`352(n5(Q5UTYucSMdOiOFO0`wH? zJgR$v0JfDe&;}Z?id0;>OArVc>D>V(z{C?Nh?uaZ+MA02)b6Y>p3B%0o`|(&5tv0G z(BfhQP3^XFmh}Yv8|7szAAsLR2VDcZ#cGrQ(+GFUoD-dnDnU1u|8uT-@BziL3BeN5 zD#!Q7Z~koTS+|*p(OisRR|P?ZhEcfRS6}~N6oVOe?vAv)M@SHf8&G~kTKUbkDv>LsO3V!XcYG^^mq{ltdS7PSSZ&hFymn@rCO)yw8 zt=k<&D(`7psd(V-=tIynSZn5wcmnxWR7wpETaltd6;+}o^YLrRzyk`^~zJ2by zk;md&;X3hZo9Fz^Uo4gOzQd?fLTUj1w=K~Uc6l;KEoEg#PcCL9;51hF9=*N(0+czZ z5OU2mhLL|fmkedJf7txJrnIf#ZB=6VAMmY${mdIO1rB~w0ot1P3!*w>FigKX<8gLa2U4LW__-AI@2PvRrnlRLAK%^v!YHbg1zzcYfE(20Uxh>rDw zr#_4PXr@8;>;r=D`T9L@x4avur=qN`eEP2?T-QT_ynRJ>W<3 z^RY)isi^uT?f%A_kwA|%_?i-Y!Us&cL%vggskz(=h2~#j``r{Xc8k59J48U6o0Fg_ zCQNd{^-Y`OZ7yP}e#$k)diI@LH1BAfBnuU#zNwGwCxVp58uA9ethgTYhQNJ@Y|@-q9^w!XVnJ(oAZg z%p3E$uDuiMmsc8v=Y95|RRe}L=761%?hm|oY~bLWUex=xJ0x~(MCgNVB_PTU8PI;( z_ATa*K0A47Ww#ZEyitCjUljb1@7tc5tOy`WWF6cTxB)zh&lsIblM=gW0u zv|n~B9DzPB!nomvUI9LHbeqJqbu1h*NK2CauRgh!laT2s!X2Ro6B4$S&AW&k#acYb zd45~p&1#p6UtoGcAUixo?uqM^ceww#wC-8S@@V3{sv$r6ht}`nTM`?OgaIwcoK^5u zSp=Gw7ewhfYLtH0fSE!~7lN%QO5#cEq!J+xK=<+@Gtt;FSsVr3Sk5KfA3Mtv`Z!aalC$}FmX5Wa@ zRFOaV6Pl&wP6C`|8I+rc{ltZ5a9-`T^Knm@BkJ&`%9-C`)L$tdF}Tf!9FH9o6bC1p zX8t*YT!ag0ZG~_y6mm5yk#Eq9;l9?^sOx?oIRQ^nkK+PH-M-FDV>9D7V{aZ=Aw8!1 zu8UIKmK0|8wqG{g;8is~EOI)%WuxE zfr+Jzka@HzjX-mp1;&u40ZX;+I*{WT#PdtQ*h$`Z){+ik*I)CsZrpqijOS_#>XO5( zb!BHZl2Ubu^awN;7?@UGFXcc(;fSFBa0cES!~gK5Juux7`n*1)aPv_`#XfmfG{zbj zc}XiGI<$ihBNmaDh)o8au97+X)n(Iy>-mApqP)nt-`)~Ty`f!7`)v{iBJezSat~9F zWL-gCU7H6o`sG#?i0JVj7h#Ys`=5(2P+erA_db?EmKq3pYJr|!+cqrteB=;S|6h~= z`WwB5k^BGVmYQ$%|Bp*We<^GHxBefOivP+IQvOy_QP1CXyQ|56)up1pltV-0{(l1j C`ojtU diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/he-IL/welcome.ogg deleted file mode 100644 index 6594d37279aee8d28988b61054917a820db4b7f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3037 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/0.ogg deleted file mode 100644 index e531348906255b481fe51cc7f867ef57d59b3989..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2313 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/2.ogg deleted file mode 100644 index 2244d45ec4e0c17710648b427d367e996600bbee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1609 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 JJ%vG(e*wZJ*UkU{ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/4.ogg deleted file mode 100644 index 76caee9002f3e78b0c51622906e27c6f610fd4a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1530 zcmY+A4K&kx7{}Yp>x3a(FQ>6h-OS5w9qESS4o%%OHq;qk8->_Nn48gVDmq@ewk%P|%l+%zb6d|jzjJ<{-}n1`&-487B$D?g@TULD%7qiU zaZQYd-2&<1qvI(a#Gqgh$N}{D_*V;l!~TD5*g*i5Lpe;4(}vwAh(yr@UJeE&gxF(j zcH3a=>^2-`z#&GSiV7yiIsw`#K*Q_-L<~IqG$9IT{2C0o)(rT7+6dklYDFURg5ijf zVd2r_X!2plpX|^;k?BT8(1qi0S9#7wY zI7Y01xYKKs7OIN1(my|ND;*M02_LCwilyB0Es;z&gKs`-qe8Z>&YYVtTCpyiUGZic z>^!>0MCUG!q`pou5T_o5zR2gLu*!O?e3cR#tmK;VYVH@rUjm=df+0p~gIjiZeP4Zu z&Z{`wm~1~wf02Y6cBL&1;$@U>h(pQ^12Wwlk<+LD+Ubh+fNzIVfd(k}ok@}E)A7{j z4_8Ycl`j`ByclBiTJ@LOH7&Jg&C`{ovZ-4+PhcA6Jf3|S)UVi^?W2D3XGQ|Ol2ZD6 zjBu4XwUsj@*v1Imm0zi=mRG=gpRVHGnIn6$Fhe2JQI>oQ+-V|(l+V0NGg&i>xllP9 zFkG8n;Bg{$ty<>AD9Io!e}eLXtO4^C@i9H7FWx>a4Eb7j!w(2c-wx(u3B&}x2 z3qB0oRl7RGlbXQ$29=wa@b_U;tvOipsKu0UlYfrXxxTffiq9VU!{Qz+-_$m3oe%b6 z{CPTdE56d7yDknC*I;XEuZhOoJ9eq7#3UrI;J=`ISIBfEif`%fJX2vH#j9<E-z-7Kp`ZKq>WWGgUt#SRb&4t^+GYiFUyhKXQHs|}Viyk!=_vFMm zqx|K9Of=u{!o^s}5K=ZNqs74l#j0`Hxp=duaJoU&bBl-S{;oDuAejy~Zw}Gy8mEPb zL1kLZqX|XEX}hUXZiPeE?H}uJr=XTHnvK%K{PWgr5tHCam#1j$K$3KM6Ei@)I&T^q zkDVEn*5~SSGrGfggGZ3ggi~-fx>8nDbE&-W-9CzY#L!E7(!``B{sgd^Ma?Jey^ifY z2gJ`kPwdYkLK0{h8m{%76Vrx_u%=@==PY=H+}43;uKWC@+|@RhUxxLtHXZBAaU_ay z0(G1V^MwuZ%LWI6)D zF{|)n`#8ih-#vX2W^1t#`In?}{)T)j6q*we~t}d3YEHYhBSDneV_OvP`eqw}lFoF(^#1QD}%&-+# z3~j!H^LO#(UVPH~CiSa#Pa33$cF0KjYkDOj5Tdb;Oy3MsBhOCmQ_*@_>6<=msVd1! zCD`(YZhA+y$Z%&J!D@HHXFCzN5PMX@%mOd)3z@E?rN)}8+l>nAA7-;&^+>=l)$Vh` z?xT-ObP*{cx$qlhevk{vO5ZpeHm9H#Vdi?jX#joat^7@{paP`Oc|S(ptC$P0g4%LL Uu@j*0as~GkXAp@LX8=g}FRQ!E)c^nh diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/5.ogg deleted file mode 100644 index c96a386811aa8cc7c5d7734bc632211e7f683e8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1837 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 Bw3+|_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/7.ogg deleted file mode 100644 index 3a997d406474ddb17c97bc24f02287df3e0dae7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1803 zcmZ{ldo-gU2k?q2JxwZCV7_C9;9v(DMU1VZ>8 zr9J<#4f24&jw=D9&w(_9DH&A%L~H^GgairDpON4l{J*w?gA{6>;XnnQ*uf*P1ge^1 zClLER-o+8&ig0vr*dYuRE0K&#O-TIigd&Dh#2noeK}TcK`S?^t;=c=fK2&fD+bO)$ zl$pV6oQ97pDLpMYk(x@3jEafzwzDGw2ennDpdSn13#+h7=$j#b*i+@h5}Uw(ge ze_$3J*S-YhYkMx(SD<(~{==i4$din=EK+4T7ik6mN$9R;S%7(8M+B@afVIs5%ACEA z@k4eXtf4UctXq&29Z55qC>EKHG;q(d#CDDz<;5IY05Y@nY5VD#*_y14iL;2h(0yj zz|xpAu!&KVh_sjcKbBs&@6msX*6ANUN-w-Lh=XBylNW3gxt}g-GWI9OuRNQI4t`#C zr>r6rPX+y>u&e@@4k|hsR@&R5~W6giP`Xuk|Acv#Wb2apdw_Kc{KW9Y_~4y3Jo8XH+0D4HQZ{Sh6MrX z?X-L}lS%}P4SC5R<_QjtGsFPe{GSC@bYJx;`F7%hk=gJEBR* zTHQAW!;D6=B-h)r@0I5=dAu(qTz-2+uW`?jX%y2*7+E)JYF3*xnqy>p!U&9|F;wk`Im+H^b%9OwlAAfPT zSIygc>-+7K5SHG&MSIBp{5zTaAbsretLB#x0ks}4)$ml=%8~Jr-rP0y;l|%wGTh_L zwAdb%Ni$YGr5Tl2#g!SkINGSZ36wJb4oV5XET;Tsldd)-_G9AXO~p5s{urD?!DQdI zuPY-97F2Z%*RoRaD?!1xq2s*~gQ;yyugT*sYT&Aixvu&nQ_UATh7dXyWO-gId*joa zPqQ~?Y*p*V8TU`;buK@Jgv}EHQ#j|y{lF%!5Pq*cKX2@PkK3ZY%*GB`Y-j!qi*vMIYzWY*81V^Hg?xlC)1_4lY$XGZ+}jwBtlGAq{6V3i)*c z70wJMF4pU>k{|f!IM0(Hqmr6Fu}}4DPS)DoYX!?uWPfxyVAxY z4vMp5MgA=;K;@`hgP_H4X<9@;53Wtu4oiM;Yf*6XNAencnGXGD4Qzz0D$_ZmMQuCg z+#su6Rl0KcxToNo&8&uWXNh2BEkGtqus)gYyj@6k_*wleE$0zQrC@oI?lW8A zkymsL*7-6#Dh=x7ixzg962Xw(te)N|!Oa6^^nrz*|ECHU7eu>Rh2F(-G~~O~bw|1A z^E6Oq4SpU5pQiy>;cjCxJe3sR|E@z7@UGOBP`T)TEhtpaZuV~4!mg-7?aJh{7exO8 Ds2oV? diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/8.ogg deleted file mode 100644 index 56f125e25b3cafc5a0a597cfb06d1d1bbcdc1b16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1590 zcmY+92{7AP9LL4671!2TN8FUweY0_|y4yI?Mp4~}2>uA_TzBIL71ubbjaD5&*($P% zw58O#Ql)IIVjU&!C8(%o%|>TuSHClF=6&Dy^ZUN{U>J-$8#~*-dO_Iz?qqvd=OYXf zhJ{7lvPUERKpUz>;(T$Cpd`Z_c@!cXGcJg@jKu~-gvN&Y zz)khlSpskn8NR!RQ|oy5&x%YJzm+#-FMlZIt(LfKb&%>c7$l^&4O>`K&~SK3F1z+; zzG9U3f>GBOY#;i{Z7KOy!TNo=g_72Sm9Ig$y-ez!eFf=fNE1)$1b~we7nqv8Tk+Q{ zTqv>m5)8krgq2zeo!lPOK?=;tJ-T*NO}C(Ybj2YU?sI_518m+p&3RH!#s9ZDgm6dN{S>c^Qbu9zq$DK6YiYkEdtyBc;Otk4amEyXp0)6un7E!L9j(wt zvUz#pMf3GB8&A=Wzc<3L?T`9Rb}l z(LDFdayS!{g~oOk6Pn@{8GX>MRJ!o!SkWu1n>YZcqC_TVzMwVj*)Gs|&*)DfiY_{j z%YC6SdV8QxFjQ}T4o_&FBex`pBto>7!lDb!)v-*YbK63*CZmH9)})F4JW-c%vxHNPs~Qq>1+wfb=z zTi>~WW{y0pLsVE=&E~?ZhL#v6xwK%8wOzmPEN+dgF2;r7=!TeAdO> zSVr-rW|+uKI`eF>9@(55*rq{Rr|GRAZF7+EX saGEU^Je{)KsmX^ryVTPx%b!Z?U3X6PvfMYlt>LFrmOC~1qF{&m520)15dZ)H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/9.ogg deleted file mode 100644 index 25e64c0a322ab56d491eb63eaaaca9d533ee07f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1550 zcmY*V3pCSv9QQWQyeb`9vit~3wbPJPH4o&!cEsJ zZ+9vgmJGMK_bQ8S)I|&3NGEse+;i{xobx;9_xXMvzu);{BO|?J`_@x;8zP)V*d{kyR4Wcr?h;QMM>-zLL!Ok;t3`sDFTT&Xm=0+ zhf5q#@d=L!i^YYZX-}I8D5> zv@?5(paIDxaQj;Ody=F|P6so5(89uTMsVXKIq#-}O3ro?HPpba6qeO+mi2v;%S4Jw zS3gxa1kx~G=c_}MI=c7tEp1(sgjLC1hY-9t9fqEEjaVfd=X*5uH=({NuBsWV=O z_qHY)b!YAJ+>H}LRUKTrO6CSP*L2rRTjcfReDC+(@}Q2nm%mCaQDI5R)(*XAq`0?<%wC6kQXoZw7BK(SM+!N8F`R6fK$ zE|YyE67)w)$cHFsZ~^N@iYKD+2b)uk>~~=<6`?r)rMKt>DsKih$k77;3e2Lnnd3gF zhRHN8JW8iRd)6>&&AJ>9+~z*?G{>89F<6LFH=+`H$GoRCJ=SSs`kxkHebKJRPFyRC z*`bng``j(VMA86A2VoZ?dcWNJKF0ab_W0&p<7AM7aGSU>RSSMRz4-Kk5BIL-m6c#W z1Pq{Fbi__ICBJ4-dz(?=nS zKrBJfQn0U_a8Fovx$5)Eab5>;_)py7zXv)qESZIcygJtI1C?xBTv-nYs1*!iSB9p` ze_r}7s4Xgp#Bkl^22e~)TIT~!b?2Vs*7&s3IPCE-`XXAc7mw@qnpF-S!H7m|h3&T> z2DhK~CEM_Bl=#QLqxQQfjp^&ljCX>awV#DFi=wL<4N2$^OLNg$*Sl+AWv~+vca;0^ zULzNp=#8dQV9iB92bmz=sY$)t>Dic8l46*V znc*nA?J{vJoK^?=UU~_RUmIF&jMwNa8Nw;jH6g{15dq2|rYFbCJ z12}&=#VD=gm9H1B(z^RJv>YdD>9unJaKpXi6t4Qv3jwycWe&y&Z zX2D93^^9f*fI#iz0F=AL*xB;^wbshZDld393ta%cQy-&H#(O|!muR$Z9^ zPz)hva*tnYRy9SLeBzQHK1*jb{{jtkkM0=;`J4=e)J@uf;Z3_T1N-zhhW(q}Y;)HjW4X%UXA!p&990m?32&FJN#u-#88BL1q?Rv+2vq5Gu> zcA`@y9c1gw1NX*F+Veqa{Y}a9ZOX%BzP%RG6m?86RhWqeU#2gor2Y6>}-I-cuyiD`wyHwqBA}`--Gr5i{;TTj0PX diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/activation.ogg deleted file mode 100644 index aa262df901432d3ff7e20bcff450189c0c597172..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10626 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 EAI-8G4gdfE diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/err_pin.ogg deleted file mode 100644 index 00669fab025b69b7399d6bc6026d818c692f73d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2949 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/language.json deleted file mode 100644 index 732176e4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "hi-IN" - }, - "strings": { - "WARNING": "चेतावनी", - "INFO": "जानकारी", - "ERROR": "त्रुटि", - "VERSION": "संस्करण ", - "LOADING_PROTOCOL": "सर्वर से कनेक्ट हो रहे हैं...", - "INITIALIZING": "आरंभीकरण...", - "PIN_ERROR": "कृपया सिम कार्ड डालें", - "REG_ERROR": "नेटवर्क तक पहुंच नहीं हो सकती, कृपया डेटा कार्ड स्थिति जांचें", - "DETECTING_MODULE": "मॉड्यूल का पता लगाया जा रहा है...", - "REGISTERING_NETWORK": "नेटवर्क की प्रतीक्षा...", - "CHECKING_NEW_VERSION": "नया संस्करण जाँच रहे हैं...", - "CHECK_NEW_VERSION_FAILED": "नया संस्करण जाँचना असफल, %d सेकंड में पुनः प्रयास: %s", - "SWITCH_TO_WIFI_NETWORK": "Wi-Fi पर स्विच कर रहे हैं...", - "SWITCH_TO_4G_NETWORK": "4G पर स्विच कर रहे हैं...", - "STANDBY": "स्टैंडबाय", - "CONNECT_TO": "कनेक्ट करें ", - "CONNECTING": "कनेक्ट हो रहे हैं...", - "CONNECTED_TO": "कनेक्ट हो गए ", - "LISTENING": "सुन रहे हैं...", - "SPEAKING": "बोल रहे हैं...", - "SERVER_NOT_FOUND": "उपलब्ध सेवा खोज रहे हैं", - "SERVER_NOT_CONNECTED": "सेवा से कनेक्ट नहीं हो सकते, कृपया बाद में कोशिश करें", - "SERVER_TIMEOUT": "प्रतिक्रिया का समय समाप्त", - "SERVER_ERROR": "भेजना असफल, कृपया नेटवर्क जांचें", - "CONNECT_TO_HOTSPOT": "फोन को हॉटस्पॉट से कनेक्ट करें ", - "ACCESS_VIA_BROWSER": ",ब्राउज़र के माध्यम से पहुंचें ", - "WIFI_CONFIG_MODE": "नेटवर्क कॉन्फ़िगरेशन मोड", - "ENTERING_WIFI_CONFIG_MODE": "नेटवर्क कॉन्फ़िगरेशन मोड में प्रवेश...", - "SCANNING_WIFI": "Wi-Fi स्कैन कर रहे हैं...", - "NEW_VERSION": "नया संस्करण ", - "OTA_UPGRADE": "OTA अपग्रेड", - "UPGRADING": "सिस्टम अपग्रेड हो रहा है...", - "UPGRADE_FAILED": "अपग्रेड असफल", - "ACTIVATION": "डिवाइस सक्रियण", - "BATTERY_LOW": "बैटरी कम", - "BATTERY_CHARGING": "चार्ज हो रही है", - "BATTERY_FULL": "बैटरी फुल", - "BATTERY_NEED_CHARGE": "बैटरी कम है, कृपया चार्ज करें", - "VOLUME": "आवाज़ ", - "MUTED": "म्यूट", - "MAX_VOLUME": "अधिकतम आवाज़", - "RTC_MODE_OFF": "AEC बंद", - "RTC_MODE_ON": "AEC चालू", - "DOWNLOAD_ASSETS_FAILED": "संसाधन डाउनलोड करने में विफल", - "LOADING_ASSETS": "संसाधन लोड हो रहे हैं...", - "PLEASE_WAIT": "कृपया प्रतीक्षा करें...", - "FOUND_NEW_ASSETS": "नए संसाधन मिले: %s", - "HELLO_MY_FRIEND": "नमस्ते, मेरे दोस्त!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hi-IN/upgrade.ogg deleted file mode 100644 index 8de0693578be8bbd733720cf629c366c292f82de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3315 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 L*T}aowuk-&S?R>8 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/0.ogg deleted file mode 100644 index 5ee48d54c509304a4820a12c272ce25b5eb09096..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2514 zcmY+F2{>C>8^=YERu#1jDuRe5Y75oGR$YQrY0HepPAax0L`rPcjwYqH+O>@}HK=6< zrAkW(t+mun7g|N=j)dCvi<$5F#`iwYeeV6A|L=Y8J?FXSyyty=f92!n`)?#Aj^cM8 zpDXyQ0VK}{QGzkvI6MG=0VuK6yIfl?d z>LB#=b_oUEPEUey7t8qx(nSO85#s7J;ZJw zH47~+D=v->vUZL!p~qKx9=3PA0112Zgf)M*Fx3Na=AE(ry(NqNpg4V11)biB5d-31`gceQ=g@ zkX48y=F>`f`=%P{>_iU`j*LxuxNZR6aS~*Mf?=W6& zf)i+}(2868Axnu?hACVTs>ebJTVOhGDo5~j(ey_8~l>b$JAGT z+i5iHYr!)oh2X!(B>6TCe3*Y5iWysyv(X4`Jk{Ygn+wn2F27fUoWx|1w6E(p^!1#= zTMVUDKa0AklyQ}}mg)_GR_^lK{BzfWZ-=+noke4>1%OpB?=ou17=j z|KNji5CgMg;?~E~s;sS%X2O~^12ky%{_({hBop z$8ynt!YK43VE;I`N%p~z-q2_WT={#xaRShnxxPxEDM258E;Ge4F6H+^-HT?)_!qLd z7x5a+uMKnc^S;`MZFSX&1!{Yhttrv^zx^e0Yg$n>B|Jsb78rieK1$ffmvDTtySCeU z3Ha0Y{SkE9WYa9uEK@ErZ4+Jn!iH^RB%^?KxTExg_ae2&pS3Mgqnhspl=gqKDGJ}B z|6#@XBUOAY!r@W){qOqN`pHITx$p7RWnwVrz;xIs@UWglyJ&Au8aGp%HC~dP)U5L+ zQTs_#eD#GdriB_shl@zaNeRBH;p@md1o{Acq3i0Oe7_Qf=R^oJWwj?w$ti0?k|4O1 z`gFj?C$JIXb+)5x{fzs*D<&(V%4?EO%HQXmZd(DYhp*wB*p@)96pABN@tynZfwWjo zgQn?G{ZjYnlt%TMZ^x`$m$OU37Lq~F@x$-V`ChEjK=FUniTG4)<_D50*}j^}+Xd=P zkcrM$4_``T0a$NxCd2@C1!5|3^M;68U`P&WY+V@Mxz&tlio>fphbxX8aTH;<%)6Ph z@AYK3#PTCaNngELMDq5^y;bou00rhbH3R*Qsn+_pb5Q5mXU1$~UbVZcGJxZ9$_qd| zWTx5;i_IYbnGVVk9%sPR5@7`oo9LroehLX19104ElFx~eo$Ajiq`;{;3~Dgb?@R~# zt$k@OL|p3GCZ=_CFp@h)&-|!c&D^RizUFqb!OKtJ)CSYf`hI>c7wkBAIq%wBQ(VX< z%$qC_bGB||x)42cv9C~$0E;x}52KljgaS zk42UC>PHAMF$==t)DH(=9v+hyWr+w=(`n7HU3O@=i~6Sfhwm_0kE67Xqtz&4e9e*_!^TN$YH1C2D97TxlJRcB>OthjLslFsPvc6<~1j+xx9NVX_9=}w`z`y7?pZas!XH zly^A~DQJQ}d(Uu==>n2!=E--B1e8s_BhsB!CWM1|e<%b2#oA;AE;d}=m#8J*FUx(=0#dx+g3Hf(}6-Wl|cH@5Rid{#Bi1_z7X?z#IEUUf4pCmAF3R6ZBb7-HOAu-JvW z&E8&Gil!EKPUI_(%>Wm$w;J$uS#I7E?#SaF5^snc5593jWVmr-4}qqrsQ#QR4!6{M zziMGvU#lwXvrVX4#XYJs?T~#T^Gk4nx{vSLjh;ULM|PM@rz5XJq&KfeX3N^LE|=@; z*?i7|Nx$rG%ti^nWt!hyOc01_=x;Tv=f zR-VK$JuTGw;T340s9nYJ^;|kKdNP4xch4uz?vhGch?o8Y$u`WcsXBzZVVZilw2dzF z>)InwxOdw?7l9@z3L2IBnvs6UJ{ofRJQEoNj$G~qbw_k{V_Ag~DxnV-yZ%+tgPbk` t@L!#<#M#60)E+kL5T|!9%hP+@0>t8;OrH9`x@C5IU7p&LSxa8*{SU+un#ceE diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/1.ogg deleted file mode 100644 index 13b1dbe56df94266e040ce6b706afcfd1fc503d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2662 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/3.ogg deleted file mode 100644 index 18080ebdafe09eefc2b6ff0a5b9fc2bd963d6538..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3902 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/4.ogg deleted file mode 100644 index 0f33e69c993c1138557e73a73bd9fed80047e00f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1876 zcmY+F2{haJ7RQ6AV2av_U4$V>JWG(OQcKaK)HWnMVu^-YLh(vpCDtmnO)XV4R4vom z%Sa$MUjPpenx}{G4Z$7b|FdJ92T=Hf^Qk;%k8xMOV9IyE7bm~# zLB=RO6Fn3Xc}yq*EASdIJRmUYEZ`#oK9nioM5%;^_=f|5|4D4w4RC-RCq6E!*g%JK z#xp!LCMt#!8%FXWVU5iZ2r><-%y(a7SH0Lb;o&r|6;nVxwsp0!qH6q>yB>CmZ-gb5 zkrC|bzy9>MqD=}cP_ueUcZN?D;{5lA0pM}%;T<(@pT{CQsnI$J4;uKjw@d)>)2s$U zh)h$|1dCkhlL|6Ry9}LLUG;eErN{(j3dU(gWtE66S{29nCiE!ex|i>{i_N|G+a7Gj zIan4NXUe&$#?V8Yk8!v#;*hqTmBJvB7GjzDQitYa4}Qh(SD}&;((0;^lbE-1m37)R z4PB;IO25;|G!=~^x6@vao@5cVwBM_zCDDy?ct7u0)2Vn`M}h<&aVdb>cLe-9j+tHol=IQMZy7is!1YM zmALF6KqBEwzO~?Jw|nXr5is?Zsc-qm%m@87PdGFN zx09q`1y)x$$FE9?jZY!juXtrIWl5=8$-LmP#5WUW-!0j8${J%BJbfuLR64c!hN9AG zQfB}Ie(!n%++XP*l53AA(!YN|61hyK!PK9+mzSeOtizw(m8K*NhjyPIm@FmK>%+Kt z5t_=~)%;E@Q^#tJ&_5!I0xx1!Vg{m~N|An1#o=Va^J=G*#?o_NFV6j9mqVAWB6P4s z#ot}4WD(fV(p*xdC9YvetQg4smbl@ACdSKY?J3+BcyxIwkbPYV>wwzV(T!G~E z<38JCjdh1|ToaO*Ji^mnkI@6K`(=2O#*)& zMG@EyLK7*ob1=P68f2Q9S~6icP_A*N#iz%Y)l#?c&kGmKZG6Rf^T8?DC(2gdT!&bi zZRK3Vr|qa5bqk{d*}Ky-d{>sqrA$x{jz zr4^COrEFt^&9e7xxOFBG4gY(!D1m3iL{ljZ%CB@Au6(?%W@0G(*k%+ zY+=;Tj+RDf<+i-#!2+}7h3kCfCe&uEhJ3pbs11eP>(&v|(lf!?e*Keu;1xOjQXjTu z2dZG0EJ3)sNcRZGVrZKLa1Eix6uI1np0#~ZvD^JiXnKRplj9O>@BlG#PTzNUTF)QWDGnW=Vu1R$1?>0vw z!vFFC-b4jmHv(dx_tg$E6UHyz#fkF%>A6orvrzKx6(5-SkCV diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/5.ogg deleted file mode 100644 index e9bbedca2867d38356ccd35e25f267d4d31cd67f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1996 zcmY+Fc{Cf^7Ke#>C}JvVj0~pM6cS2nEVmTF%O&RN1~Epes8%afc{S6xrmCriTGdu- z4BAy=Q86@TbqytQ4N*1Mi@vws>)UIcwf67qZ|{B1ALndaEY^Vq!15nseccs*=86k1 zov@17hTV*?^z-s%Wks@fy8T3K&+z}+8P3X7xygJvtcGW}qZc-UpSff075Rs*<|V`> zO%07RLWa5gLVQAf{qTm&m=80ismBaz$_E8_hcXlYUD&9D$uaG$@Y$iD+eOYmKcDb$ zEIuMIgb?U~@o+@x$awx)0aT}|5 zcf9gG*;xts%7O6K>!kE_w``~JWr(?UT9&y#NMzPvTWcsr3xAKbFChOmo1%?@g=LER zjqeWauSVUnR&Ydx3!pvZI2{jx8Q)zO6{=TIpWx$iok4Xx)A`tTplDY2=Mk7nsdt6C ztAh%?@7VX;E_?O3u+NTYTYlj%hE0}JLbP1Drh60Kv}Ipo(Zg>`RX3HbssMU%;=$~!$-sEbsgkT{WyZwbmuj#Vg*isKCy1?%$UU`w~!4ZigLpim5! zM@T5f@WqQdL@Vz_91#poe9pEPKf8ilftu;=7w0E;dTn#&o?dw8E@BnUKz&e0oI3%v zF}@u+;s-^!t_*+k2;O`z_jL07?`1Uc2k67%kGyK=9D{Lq8)Fw>p;3fX_pqapw7b8w zl|L)b+MYqmOA;_-x0EUg(=e3?98pn$45nxE@XS*ZPti)$o{~yB7?U(8v}G*FurdQ7 zcjz3e5@fxCr5*K6s4Ryweu$DACU?A+Kdg3K6PsUr)#uBbsA{raysH2CyqESF##<|1 zy+zO{O8Xxi1bt|vKvRR1GqVkZtpAdMJV-JBO-{4AvGk+(8hzyRjKqrJ7cL;4Fjo99 zfir__;-4;E%93g{F%9L4s;A#MviqJKl$hyy+crh(q_s)!e77$r86o=Ri8D7QS)X@r z0}*I?A1)&kM-P7frZ-y2Ke-~w^dyoqN)Shcf!fxwW&)SS#4v1V*Q({7p#LLg5)}YH|PnXG2;`bSn`4e zQm1Kz?nrc~E8_8}1o;(bJe_bJv$`*s)VuukNNy19kG5K|A zO+p?C(CEqG-3`t@#1^+ewg7jSr^AgiT&l5pp{ZQ+gpPUqaK;rEFz)-1ZUI*x%{4I*PW%p@vHm%Gz zS}@jf=payK(aY#lMQ*Ock2ilsrNS3lD#rC18a!29Rc3axo0ww1rv)oW5d`>lo;O+P2cOgSnfrA(qKu3(KH<7? z)J*3>{%Ok0x8^JwceH@Y%hTiF97`E5SaNTGFUy8Ww@rD0$W&REUHu^6MX}Im?ykNk zwh-hT?`WZ5VZ(j&!Ek~ud5y0 z_88gLOgIfKIrtueT!5G7uc~>%3{M}10Tf-w#Cm62JlT|GGQ}atnf!)bL;j3Y{2 z;0`V!QIn8W7n45RaNS)Q{|tkWl8}`@OSNSn(cZYvBJ>@6U0@UNic0n*AJSY)qFosCXNoriNqtADpuNYbsOyQZ^U3 VHSjC@M3eDL8>ae&twu2h{srl&p{)P_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/6.ogg deleted file mode 100644 index 10dff31d3ad41a116bb27d8e03936f6f416c1081..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2249 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/8.ogg deleted file mode 100644 index cfac805cf956502f20ccbcab7a3a6f68ecaad556..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2509 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 yo*Y$#AI42ame-O-Q=N$MfH+X)n>= z8|Fz$l>CN>!D6@P1I2zFIPYA!v6#tHgP#_?FH{0YQRcIP2ACw zObiM1CzA=@z9bL(iNu zGJwK;$4qHY&@Cm#%=({lv7JLB#f}%L$ks~7&%F|tujzsd4xLpkhDIwOAVo2Y)!UE< zr->9<1hTc79$@k+&N0q&x*_CU(jTXV;8sARgLcy$ma_z1#Am@7j)L*B5_qF1c!`U-QW^! zB1KMtyHA(H!dHtAJ*syZx`IkCmjh(~nd=fe4tqlXMQX_1jfX7vvG4*+F0Z%#Vm zsE~=_(7zxD?*a%9Zab7Bof}2f`$BU%o2>i;RQvRDbb*WL2)FGsZ8n@8*!p52t$auI zMwt%+0wijn{hTW2ek^!M?U8Eq?){psg~!UX^phujV4jhQ7_W~2kK94_!jE6?R87< zSJ`%&2r?uQC8eN}55i>P&3v%I&DcOZ_ku{8RfNX@WrdJ@3R}CaUj9NiNo*$8D`$c< zdFsnOL5ZOR1DbJ>uYknFc%Ld1x}JH0)C2cH8eS+jNKrbA*lILQP36QC3V ze0?qpHCPbb`*YLJ(9)$js`SUdY3M8IrFC-?D&_)YIpi1D78gkEoMPTf76LX>_Ea2W z%>u^MY16=~i3<|7Uq?$IV4M{Ro?u$iG^-UB$ou6j) zH3*^26(ZWyMRR2?oz5AQ10^V~LRdQD-|_HzHlu1dy;3}K(WcW%+5qe>b|yGdd8{kV zd%X0RAt_-pqbVtI{aRPGQjhPyb2NQ`K)JJaAcd|I>*NTyW6*+UydIr+eR}6F8&SzW=rwia zQllHS0sxw!*@%$`qUVElAQDvef?)HZuqgz8wkz%V;}^=8_D47!U_nqshXB?K9GIc5XapK-vuFrd#{>Umrl1bR z$1M^maCn(O%mx!Cc!}d%%hqbL=GBfqcFV>$zle3Nb;2&aDrot->_lTErQ|jHF%zXP z+%DQv)$n$Ax*t!8bzp5@_7oT2A9*?%ET}6vy0N?SBm8ZKSOpFS(eDy+byCFY(F@4# z)0$gqFdC79fT7nyIA$*?#~J4qHIu3w3U%aqE!s3@2Hu2KLpwM>&l@XChbf}-NA5cW zeqSd>^>il;eS8PKIY%k$95CLEj%m}dE!V;L%xPhb#crSPULM+|3y+sPteFhaN=_UG zA9%Htv1+;_E7N$5`^!O5=E>EJ1@WSG+&u33MH+)xe$qUCQ0eh(Ie3lJPTyCAQ+rSi zZ7MvQSo|qkmuZs-eoq)E%U^jys1Dqc96G0DThc0v2lm3Tn@;coa=E+b0!#m0w)>Ej4s7VLqGf};q!ER;fC_o@sbNuS6-k@ zWZ|B1_aewPV@e^UXPR|98-u(p@2HP$1@HTkPs#atF6E^5zlcDc=8xybN<)yXY2dMu zpaNQU9!tj-$w(Cre^%UY@1rcn0+t9@WOhJ5jg9sIQ=X}L9sFjS`f*BV4bkmjq`>=Q zH(225sZxIWSn~tbTjQ$IVe?{xx$0gcM9N_>?_5RJU5}h%Cc%i$HGgb+OsjA|MxW;o zV0CSgAsa*Aoo3I2xLzF zYKgykA}@Csn)qE5Xm#Sm2_i*GlE0^*4KdXX10;-T`0WcG@2WITC^~!9qMN?wAmu@f zO^_MZCt`CqTV(XI>P?lyp8NxnpY@>L@lhIOPZS^L28N|-9HA3=`8%(6blNxP9fXCH tFL(T-qI#F<|EN1G_W!Y5{Tus8oc$ZiRUNA>* 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 Hw1)l%v5RZJ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/err_reg.ogg deleted file mode 100644 index a732ee9d3962e122fe1c6a707f5d7072d0922b5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13477 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/language.json deleted file mode 100644 index 12ce157d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "hr-HR" - }, - "strings": { - "WARNING": "Upozorenje", - "INFO": "Informacije", - "ERROR": "Greška", - "VERSION": "Verzija ", - "LOADING_PROTOCOL": "Prijava...", - "INITIALIZING": "Inicijalizacija...", - "PIN_ERROR": "Molimo umetnite SIM karticu", - "REG_ERROR": "Nije moguć pristup mreži, molimo provjerite status SIM kartice", - "DETECTING_MODULE": "Otkrivanje modula...", - "REGISTERING_NETWORK": "Čekanje mreže...", - "CHECKING_NEW_VERSION": "Provjera nove verzije...", - "CHECK_NEW_VERSION_FAILED": "Provjera nove verzije nije uspjela, ponovit će se za %d sekundi: %s", - "SWITCH_TO_WIFI_NETWORK": "Prebacivanje na Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Prebacivanje na 4G...", - "STANDBY": "Pripravnost", - "CONNECT_TO": "Poveži se s ", - "CONNECTING": "Povezivanje...", - "CONNECTION_SUCCESSFUL": "Uspješno povezivanje", - "CONNECTED_TO": "Povezano s ", - "LISTENING": "Slušanje...", - "SPEAKING": "Govorenje...", - "SERVER_NOT_FOUND": "Traženje dostupne usluge", - "SERVER_NOT_CONNECTED": "Nije moguće povezati se s uslugom, molimo pokušajte kasnije", - "SERVER_TIMEOUT": "Istek vremena čekanja odgovora", - "SERVER_ERROR": "Slanje nije uspjelo, molimo provjerite mrežu", - "CONNECT_TO_HOTSPOT": "Pristupna točka: ", - "ACCESS_VIA_BROWSER": " URL konfiguracije: ", - "WIFI_CONFIG_MODE": "Način konfiguracije Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "Ulazak u način konfiguracije Wi-Fi...", - "SCANNING_WIFI": "Skeniranje Wi-Fi...", - "NEW_VERSION": "Nova verzija ", - "OTA_UPGRADE": "OTA nadogradnja", - "UPGRADING": "Sustav se nadograđuje...", - "UPGRADE_FAILED": "Nadogradnja nije uspjela", - "ACTIVATION": "Aktivacija", - "BATTERY_LOW": "Niska baterija", - "BATTERY_CHARGING": "Punjenje", - "BATTERY_FULL": "Baterija puna", - "BATTERY_NEED_CHARGE": "Niska baterija, molimo napunite", - "VOLUME": "Glasnoća ", - "MUTED": "Utišano", - "MAX_VOLUME": "Maksimalna glasnoća", - "RTC_MODE_OFF": "AEC isključen", - "RTC_MODE_ON": "AEC uključen", - "PLEASE_WAIT": "Molimo pričekajte...", - "FOUND_NEW_ASSETS": "Pronađeni novi resursi: %s", - "DOWNLOAD_ASSETS_FAILED": "Preuzimanje resursa nije uspjelo", - "LOADING_ASSETS": "Učitavanje resursa...", - "HELLO_MY_FRIEND": "Bok, moj prijatelju!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/upgrade.ogg deleted file mode 100644 index 0aa6134e34a4dd540bddda53ed6e11026d79cf5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4241 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hr-HR/wificonfig.ogg deleted file mode 100644 index 89496225b71f64d343b9f0a83ab6ed21cc511ca6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6223 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/1.ogg deleted file mode 100644 index 8187037a13f22b2ef75ac1b77c396636fd4ffb59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1963 zcmY*ac{Cg77Edg-Q(PhXvfzK=`rT&I27R$bPxw@yJI{=c4{a z9VqlzA;&)60iF-Myo2Cu&XdjQz}TdYg1_Ir2kgZE7B=o>>)3Hz__!&o|ERL4112Ci zGz1$QRkC~LB3hK6*1v7o)x-au1B=1QD}iG1 zpDo8`EXeYmB`D@Ay$)HHM!y_H15Gkfg73w`48I02=@gBzaKu3>nnGJv>`4|v3LBLD zq7}WDy(JM851g5euo2t1E1d2l#?xS&t6#DBa#12XDO^p9W3@od$s!VQ->@5lJFncj zpEdZ=;`wq@*)|xQh>%^P0lJ-vD@Dn~K-5wJo?=p3nnmqg-4Gz*emnQW=Vwm0JBHQW zdi?YOcbvXNRZ?tMh>~`>s|)Q80~Z8P2i1ucNAz_U#Mvn3q3EF~?<|QH-{mJ4EnnS) z!KtXU^^~{GO&Qhgh0l~fA@+t9F~e=`&CZNOt}R4d%c=Xbm3%F@o%iEVZ1~P7pphZ; z1^%=O>}q8Cbfn1a60i5SGF_;2BZ^LJU#9k*BjDnVmSV*Dt!Q}ffH!6uOZ~R`%6G1;nmR+;n`Ud1#X_|!Ex%Z|BAs~I8W--A#QyjaS2+ux;m-kmxAM>kp@I-jBc}l zgzfVk^Mtg#{m^9X#6a&3NEoARV1W|BOlyY8<(<2-a2ukVwI`FUUEB&O&vLFy&xgqv zg=T7)+HTfAq4{c>d-6GWc?~d!0@Ym~D8Gg3BaJyTF*pU4yv?Eh=*KgTw8b}t$(Fp@ zdh`PG4Bs25tq?U8=g)~}6X&iV?;I5mh*QR%87OqcU>P+d4^7H+kuF=)^`OU$%(Y%x z7pBv(YLa_pAK9Bjo?q|)VaxhPMMA)8NmKSK(#k>SD*H2$?6Fbp@(ugEme=;cxQ!T(FLkF`mlkwmH)fs(m6}HMs$aHsq z$|vVXPv%SsC8Nfv1f!jJ>8kE0tl-Q^*S9H872B9P$eItYyVMf-Li#{`pI~H>OYe9m zz!;pO61fT$jzKpkFwPxvdgXNw~a8*OzHRp&qi^;yuglqMz1GAYbBAn3_ zhQWaq46x#}ch)|U?3qW*8Z_kq=`$?Vgh(_1HAGT@Yqw!9N-XgM=F2@rOA|Gtj|jc= zF-4{&;m~J((%9Wj(N`bBAJSkOO1Pf4zX$%|2rBXAi223MTAT7sfaGc#d;D`cK+iVAg3vovAE@bK>q>{k( zPQfBIE79boQpYLOa)2T)d|X97hDD9EMXb{_+#m}Rs`;~w3CPV?e?;e!OvjUfaQPUb zKns!EkEiW0U_|T}`pq9Xk?In%6JtvS#u%Kmlq3->L4QLQWi)T)PaQb*hTfe7@A_4* z*r3FHGlIA~5&U0;bf~{Ct<)A}|Em!M$r}ACv~$bdlTRwP=ZfbC7qx`HDEwweIYk(p zlrRsyf}+k^qrSjOh?KhPkC^KYE8ahgrp zSReeG%N1Q8KG{}W)gvd%>SSASvajC+sxEUtAg2ql#ivqBbkV!Z diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/2.ogg deleted file mode 100644 index bf417f379bc88272c41d0e4e7a6b290984fb6e90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2418 zcmY*a2Uru?8YO^4A~g^|0fAr=As9-~P&Xh5LFr9ok+Oi4fKoz{qM->QRk48uLst|~ znn8**LkmS+rB_837eZ)(P~NcnzW4C|zWHX(oO93If9Bpf7G7R99Go2gtw5$bbni0z zvN{PQVi6D$Oz?E`0D&|>O&9->SnSFFS9@|0fVMR#P>}AP+}6!2m=CyP>K1zGlqv>? zQB_gdQ%D1c=VkXR9-cwE0Ot;Hs+s_)D(mO-#}#1Uzs7ovfDWiVT8P%q;v#?bi@DFs3{&~ivd zhzIJqhX1YG!$anbE}ZzHC^5_vg`XPYY=bGL?$q^lERQVmt*<3UnvgWiDifdtyYs|2 zNlBQ(+e*`m%Wh|!Z@O-m2cL}5Pp>k$?rpD3vMp$`c7R<75Fy1MVj2YQH z*Tzox0ui{QOxN+#ct?zrLO@%^EHg_)U%DRS=?a9+tB+O5eT>}5(<~4F7DBcgicic6 zA3tMnJrRx(NU@W|GlK8p+uA>PDBX$u81Hki)6p;CS_HF4EO}w|uluN-%l`iGxzAa6 zDO^W9n?%)ThKWVjK$bF3Ok>Yqt|aG;onFi8Y`7L;F;+3*Ian>8KvE$$qGc zypw{>CuP;^f>(Nqt~S$?)+eIB9xFS|zE;9QAbf6n6b(C$pK=j-V{yBz-eOC)Y{~iO zC6N3B4h=X(ykYEvwHBF&Gi!s#A*ZFxd#e%n$g-&Vvop&o)#E>AO@`H4Mz}RkM76^o z+99G$Dj6(SXgK;^db&X65=j5rA!6HG5`!INejvBRW`gzzy!-6CKWh4WZL-8-D67^q zcB&0=re;zK{9c4rw^dp*GMLfgJM`#xg#>%03txV=(OIz({6LqeviC_LPtb+F`a6!r z^6^}3zQsOy_EiMvCw*(MI?)`N&ugn$;DRjPzW(B2+9EdRoBPUzpVWyGsuNu_?Mxu_ zug)^T8Epi5(l zII)o<)yH!^LoXJGO~%i^+=$?w75FnoGViGjVHNs-vUVZ?>k_1x1=s%>Z^MRA78?*7 zX2bQ@^`i{&_lR+F^5mBG;~6tKkhJP-=xz};ztDcoW`&(}g1s|6nxf;{X?lD~F+vg! zV^MM*DTlO!Jv9YYw2_S5oMEEnfq^RF)DHRxJhcP5b2G? z-#Fbn__sVWtw7oXXc0;73ofv>q+9WgOzbG~y=9^YxbI_1TLXt=@s&E+X5DSr5L1QxnG|4Opx||j#V4x@2`AGq-@vX(Dek837Vln%M53=Fw-5qP zo{?$y^_I(`0I5^@>-6FruEAWo+ zn%&S+SMqDT-df)!-hikKHU9q2v3je&Eh?LCvSND2-iPaW$tRq43#Em4yE{!7SxwDs zsL%6a@z(kVM_j7~HFF9n+L>r5#|d=xVpRR*dzsh^*bknL@i0Ycyc$Ui;VC&s4R$-cl3k~O0@9esjS##C7ExY*}naAg%!##&w0wbkg=euTwFf|U>f9T|*QEo}UA4dlYfttl- zYFLW_|2Jt_?nX7!6fXmvo(4VaJY1-hTgAwc_ilEsBrSI*6XlU1B4w=T(L)j!3Co|; za#{{x+`Uy0HlVCJR}uAzEmvkMS5cXWd5bkgiZ2+t>>gdMpg3?gjmAHm<^pz`r1V(t zH4nkMaHbX#t41v3DPr}`)f7-4jnSWOFLPSozQd6 zu#<(l5>P-+$Ve1Y&BlIv{|<#63x}1P7g>rbs+jw;L_a~wNfP-BYbV5No+BU3TAd_w zXrN`Dw3gJ}?$f4pBUv?B;&GtbYBmMT@cp3{4aF6o3^vy}=uFpqP{uuT2ne<#u%mrw z62;z%2R`wb94dVpLN~eAa%&P@E4;&OA^EUh3M2}`#3302*JmPY=alQQ2FAh$$>X7y z?9_=@1e#(G!(Y?n#&xmX<}JiH7(ZWU-n?q9`m5%WXJPntzcSQwD-buhBM32^W`7G~ zdX`KBcU+})oNuB)<;newZX(w&cpsa*#N3DO3NwGv0(c+$RF&ENe;)wR_WPDt?Pp7@ X82d)P3H)^q0N%&eXEOHr0*Lk>ejRh} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/3.ogg deleted file mode 100644 index 78192ebad20976b03eff3498c9d012ad490a7b2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1966 zcmY+Fc{JPU8pjjLOv{+6swInrphzu)+EuP-)P$g_YTvi0wX~Q)1t}tutEJqrwIZ~% zb;(sGu?~VzY71J`s*9?fR>w9!z4zR!&pGco&-Z;k&+^A}&O-`X~aH41Q z&8Uc&n6O}X$510Qnn+SsOil-#Eqj6eDCYPr-3yR@2tB@p1-)iY_CT3K z&N-}s=cIm27f$CR%9nT|MY>8^L=s$yj^!EOOZiek4P3y~PTA+fcV-0wW=C#<5XI8e z`&2NW{EG_5@m!R90ts(g=!DtCmkxEXR(-pL_p6ovWRzIt7*HE4eEL-FsO+-NT4d&Ik%9r4#V zE8R}$v)iR@fvUSNbFG`^?vCyc^(`A*ZzGbFl-cg+;mcxV;)ZRmfvLXKN;W=k@l<7O zs7UhXVyt4J2gZjuuYQW%a%TY~;UTn21BKfbNdA*yDx^*CxPpIY@v6~ecqBL)whVD? z`kwtk1V`DMwh#Ard*?hj;Lxn~{z>uRV3#X=cc{7&q(6{DB%x3oJ*M%4@Hkb? ztUv_6q)^s=XUxvztQ_qf&ktc4!4Qu`+q!Vfpw}E9-pcp3jv#T#CM=ixufl0X`{N#2 z7<9Ge(DWZM_IS3jT^h?i3dZ(K%%f1H^91+o2bs{@oMN%pd~cN?myimZU;~j&U^5jO z-z*VUl+-CAf@v5AtGxd21x8J5q3ocS3Z@~CC{lLZkWhRHDh z&1c5Vr3uvSSQ_RZ)r1K~*QWCjTM~{oDwy2ioFF4>v3(;5lhT%SL^B_BTK5qt|K;s5 zA0?onGW!(25nB#b<=BhU=n2wq>7VvvTg|=HmfIX=isp=T4mhOLUmaxXN%Z*q@*)(P zG^ZeB-s6!--v2?MeX1^by#W*~b0MWF5mNT89Q$_rW!?QbikW@_}BX%BTg zD_mUr8>qWuG-;2K#RR%4v6@nxGZXmgm;_+^4fD}H@f3)Z_KI6AjLqv&PXW47pN8bd^&oQ515 zuHLqZS#-bZGt!2v4)d4Mhk=F8euCt=0=tVU%hUZ?Mqvw9lYl*wEJ!d3Ja6l&>ydUn z9|wnTxR3M;_Vcw7I(|6~vnrJtay=#Fh7z}x4+pr<*^PrSRt3%uI`REOs0S^qbC}h; zmCd^M5H1G-C$~MHMCQty2APMNaiY6WNNvN3Tney03Mv;f+N&chB1H=c9@%mg>M7q@ zX)T=?w4s2VczO!j_C&0wEo#^*G5J<|&KQ%aLdn3XnUB^>Rbio+wSQTMB0n`i<^}E` zqi>6_6pX5DGVfR%ApXrYc7g__7d+JY)1_ZEk+er7K@qT-<4@I-o3Lwd9IKq8;wqbe zvz=g8R6~06U3Ve9zqfa6xqX=uep`q)ij9%C$XTis5?S2u?Ivzmu5UtmaNG&s0>$6r z54Mm_;iqxCS@ZsV6DOn4v{tiWB1sM+%c<$>+I{iH{Su9PncGoSwGWvgfo2%{+mt-q zK2w@;^*l`CX~mUPIM~~6GM9OJw(a8q76%_>OP4+Gm-}V0=)$PWiEc{^2ZuV}q@-U< zu)qo+(i(+#_K>#OjhZyEq?OGnzHIuquRcX%#ZZ}&(#lL^>z0yd9;YPDXV5jrFZK`Q zy)bk!3^9gvwCAmN1c=|*AQO6-@*(IJGxLO5r#-PS<@w}w6 zPOX|%GfyPR{wP=h5;2^l{8VzBq`4T@GvMqTN;NUxnz4xgt~++n;N*D)6QeQJl4MIj za=Wj#JUFG0v9``53Vx%x|5x|K*LmM4?oqZ_YxPJJP)9N=?N)hT57x2Gp0D@n>%kHP mTo=ov*8;$WI?@z?kEGT{94!l|Z<=!G>qpqGnxg{(iu)I(7nM)| diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/4.ogg deleted file mode 100644 index e93ccbf0395271cf63fd5699c6e4771ed0d047f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2161 zcmY+F3pf+{8^od zZ1wBg?nr`MBgrI(K)(Pnm90X?&@*XTbAs@ZE7vfrAKP?|1;k={3nnnkTZ zH2$@P4nwKm3&=6E5;ey)TI?kvn75X+T4KKY5pm?m578H&ODoVznbNzo_MgZ$qg{4z&w63s z{>t&t!&F__a@(VKccAqcxE5vmRcB8OX^9l&`}Ba2K-JTy=9;u5Ys1Li6O$(oKT864 zhtM3xPBqYNKaV+8+`oSpYbgw~4Z*KEumoGA-XSYcb`PLWAFWeIdk32A26~CKWt@UeBcgjqT4KAQAxjL1$h zFS+;&UF1<;?otpS!Mbv_AX|pMJ@?j(j}iUllV58HR2aMrVjIh8Hj#T(M`lIzcN776 z6%T1#tMD$h@ynD&}e9MoFk-c;?7vQe=5a*~!;y+BNc5fx8I zIMGXu@+Ky_{xjvs4|q-Dnp~yH+M`LdeLh#vr{~{feIc_(oJ9E}@%Zgps=o)6Iy?H* zjW3E@2jvp{zrP8Q+~$Qnwz~Fa$7Q=d&C3vwosFp%A^fw}?zTU<;k$JQO$FZGPc-hx zHuha`lsc=w4Y_myVkK&<6@?{DJo_G zbH(6Kk{H6IPlJ}<4PgoP!Ei2TYBBA%k^InSmxPGQu02gt(&0xzD+4i!`1hpylZ`MR z3gxVEX5@KdeOMpJ35DJIHgj0qO*rgsLM(oc9VRRI_D}@2qzi)(ZW)e67U=6;zW`L< z`tR#<@|_8V=JZsoE>9{KH+ns?z#WQi#x?Fd+toN9@;U7L@ok0mjdm||BKWCA-WDK{ zl7$5U=kdzsn9KO0U73ONJbdnYH+O}cxlEwyL-TUXRovoBTJIym0a5cT4Ylb&VM;J^ zap5ZWuOF-@`3;v+&zb&i^miV-P1-zFU};etwC~wfxLUx zkdL<857$5*ugaIyC^7Idsvak6mop_sGnTB-TjsJr2MRxDMywBCi&txnUQl>3k(RTC zfGZX*8&;B4Cnp0#{2V3)LuxX|1_(guX@lAz80EhBdFp58cz5n8_+g@+?#VwWA8}nh zjpqlSXxz_(5#1;4egGYOj-n+f=*zdpBfY8B#=uafgyELaY2QNi3#pc-X6@=XM?n+z zkR~tl2bR?tRlwIZXEm)P(!^{VUP@k zPS9T&$2&N5AuUap2}4ep<@q2r{&{)&>p%WIE1K0VWi*2Q+(zysRW zvrADN$PT9L3zKP#3IVnF6kE*Wh7@1z;~ZBAe=Yj4{*JyUV=yx@`q0`9Of2d`wFQB? z3ud;W;DS)RX1;Mq;$6_Dqa{a)fMlRYmh2mT}W>`R4%r z7lS7u0gCeMLw>Z5&Rc%7w|v; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/5.ogg deleted file mode 100644 index d43909d38036214fc3e7565d51655988c436151e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2173 zcmY+F2{hF09>)zahK8|bEMdqH%^166dC8Wkh_aPrXU0~RNErV&y9g1AEH6ePiZFJ< zTouOB*se8dvP{;f#vR>z?%Vr2=Q-#3KHtyp_blf*=XcT5)0%~q<$n<~|E1t?+Obk3 z0TQ?v5PZwb{e~L|qy=if_6xaqi2pwhaS&7S)X-=k-9y~whUcxL%oXg75DyIuN)v@q zRz4&on8V%A)!)tirY_TSWqKHGriqcld%O5E6aQP-ppD5fD7DyN3Gt z1p4{=1^D>7*j&cq009AR+U(sEtX&92Ti!1|T~C zBc?cOSj+t^XR)uY^EHkD({g-raCpqYL^}-!h{?tZ%Vbm=wJGW#_^AnJ`us9X=36W~ z3kN2>)nbiItB5Na`$^UQHerM>l+bcbOF$us9hp@Db?bM`7|}?25}Orhk%3!D@9d0vpxXGd0~OdH_58jWMy3`0On0D|vx>Q`Op``Ep0o41Bf2W@lF5Qw z5cvQamx~{S)UQNxq)Ma*zi-z#*O~0wWK<_Pe%?4*7LR`5-RsV->=`$t6i(k%`gz1p za1TzmY<5l72 zyDxO@DPz|v!@!aa4RMIrmJ##^nB(&2P!K3MIp_R9B}N<(ou^=))3(%fFdndq1Egdd z=})|QB=WNdJ=`sh0sahreyz@dzSeN6j*K)gzGvUeEtEB^PP7>q5}V5p2zIPFbzAMW ziloR4=bHQ#@>jM$&Urj8AL62NpY6vGrk> zLcaEh!%$=-EcC~Fl>v6zeHUI^)YQh2e>sU77kgC8=|(GcRdYci7_Y_Ph56PRYaNY2 zFFc(r^eLOXC-ATx=AV>)n#BK_nq*{mmvJtbXmw|zNN2;Sb&*!YMj#>2!$Kb4PO8j* z-%^781! z(|*6mB9Zp$8pQC~?>Ez0UE*c#Gapm-k-oK(Aisbxtm6 za&>?1CHH`@pX~Hn-Rq&g4J1eJ;YWf~P8JS0E~SAS)qF=9BBT*MT|LaE7z(=Sv4Qi%9XQl=h79SCsTW_6r__x z3!6peyg)r|W5Dy2v%^()(!?5ft39|3jBJHYitVz8SyM+|QjYH5jkrVFzVs~=tl{{B zd1_%Hna#-p08-+BDxGsqm7kOxJ(0VxwixscBILl5Eu_F5qeGeck(iAmOy5NtpN?Qb zb@=o9>ZkZW8JKfag>|@fr)c7N57^XJ2LnW-#sg+>z%fxFc{|3QS=`2p6eubX>{0A{ znkZMBK@yA$C$FuJ&5PRAN;XMDOj7N!X|)xdW7quo6^Ei_OVJ1cm!E!%yQnW`%n_~1 zpV)pitRt3Nzxvg$hQ-F5nlbpS*|C<&N=i6DRE%dfwZWFZw-g8#P2uFo)vL<7E(fey zde6HEpkuecSCi4I)2ggHK30{A&r-zFViq3~o=Ct((HyPRw~wu<=N*Cs+3M0mM{xig z4jwFdqwq1iyO(~C9oM~elUop#8lhPr@%GR_A_Qjk1x&2*clQqppwrIiKT+9U;Etji z{j^gTB5X^M&SoMX>8*pG(#zhrAH(AS7!Q~nsI3RsiWG-6bmbf|Gy{{v`pCBJMf@_+ pL-e=*P<=SIzjfl*-(9Ba``dfSxA70Q0JHI1C8qj~C0cE~{SVUC{+9p% diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/6.ogg deleted file mode 100644 index 17344e37769b12985e55b9f10e0c488fa84ec7ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2251 zcmY+F2{aV!8pn;HAzPEBQDYmKF%sFDF^!tEAZik#Y#|0C>)3Z=r_85WD%lhH(6vos zCSpPoH`#`)ku{2Pr%!T6_nv!w&pGco@BjV(p67kvbDnb^Jb_>(ASm$PxB)jq?`*?F z!w3Lrynk?zsk_Tf000eWar}+ockutk4i4a}w^9vx0HYn;+Jz7#&Ofnm3Gq0tqlMDa zId*J^P~b0jUpK#-?tw;p&yDZt81hXWWgjnBKYrqW3gepj96xpn?>s8x(#CTzA;3SB zL<|cJCHjy8108(LiDYF}K)3@Xm@9K?pY}D7m|dOA(bNni7kxYniT_QeijoPqP?gUJ7?>6uB;V_@1xZe#qP( zdJr4gB3PrBbl_dB0(Xo;H7~A=NJgkMjJa6r#xIM2@n9*-jFgxL<+)H~e++xk#PMOI z@c8-qU+V^s^Osqa?)NE>Zi$nS`?SEYXQ#B(V@-6fwvPhKMR1l$-zhnb1M2ZPb3>61 zYICp!uH42Q`$1`=ZSL?*kK}4^6eSei3}*B1Lo{h(z+?!{WsI5kJUY$oCKvVQfBT! z^X!_|QAuS1gA-uuOtjs|$x_Stf62)eXbaGv*8sYv;E|vRqC-CaS{Um&rbWnU!e{on zf;asy^IO-=T(J8RlWfcyhvuDa^M#kP{i!b{k2kSF5NFXM<9zQUT3rURtG@sS5oAAs zafb(6-=`SxhsZLPsJ1(Mgq{3jXn1=Li#%VTXdfPoECu^97uRcbjSf_ynn|}L07UX( z6-K1fZ65K9CG&+n*^6QeFH2T=1i89sf9*2Rw6GawVUoa|WprNoG7}!0J!t=~5X2{igno)vtl_)Mh=>QEOE*S?uXlA(2m&EF`iE} zkqk#L0-|I-=sywBP&_o;7GGk~q2StHvnsyt!gbKCUfxC05#d`Vus{YQW37SAt3L;m zGc^17SXy9~8P#d`STJ{u-LM=HF+8!|L>fc9NNQbC-Ro$fa901z`sT*j9AI0*M-I-< z=a|?Cj){;-uWku}hKV;5fvlgcdnH>kPfC+oTqsqDLe4ie8oF){%H0tL$2TmfAVX*9#{@{eq ztUQWbSEPixd)~#c?o`h5N^AHHjjE{ag8)V#1=?pC1lI6U@^Cs6nbq?6L`Vo z^edH_h}(4CzRZ=(G@aOtX4~kI?O_&TUgEutg|6Dd*i>>mbx-C@ z9?fg~cf-onF`MKc{FpqdJ(e1OktwGTP-lWnmA1QV!Tl1q0Yu1_gCU~yPn9V$l(6Ev zZQb(yc*A}PUM!(xsoa9}iT3=tS0fYT(9oj?&=X>7- zzpi{Q<#u1VsQBZ`nz8ElwAgX}9~BSkn;U!QVxP@gJlyEC4v7)w)#02tc0re^9`x=u z81So+h{l%SPg(LJtuKFKKTatYxkP$d83Ud5j}Lq zLsR)te>I0lR#DXgyMC4Td{g$xDD#IUmpy7HWG6KhcPM0@-n$xL7b;y(!$pqy1B8y)GK9rVWQ7TlV#;Q zf(ElHc{KrlDCAbpx5D@uWeh3_N&JAW3azxuF$9H-y`?;%mwndTS`1Z zAx(Y|fq%nyC8vMGVE^x>e?y~pvosm>E|;%%W#;RnvAbEm-sL{A#_UqHB+TDfzTV}s Lsk`66SLlBOZanx@ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/7.ogg deleted file mode 100644 index 5167c432cda411e9af1b3cb286f8882233966644..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1531 zcmY+D2T;>j9LEVz0*FWmA|r@wL`X?g2xx4PDoZ4+Fv1Fi5yD0YDpfR62gsJ8Oo1?D z7(ixHNfZeq30wskiX~DgWf%yhSOxpX>(%so_wL^JeLuh7d-uD0PNAW$V&Y=|N-&eu zzq_S&_$Y#)PB97bw!wG;2!sOl`hG#2cJcqTi-Q0si4cx7-EKi zo5K;Nrn`g&u!5t4q6xuqXdnv$GK2*XA`V3m1EYb$FO4NTdjJm5ZsXlYJqt4^gt%kk zu_v{&%xr0^{+CTrKARpkkW_~viO_ETLTt1z9 zH4SwkRt43!W%V&BFJpg;b)!iFO+8^Bw7G85N4`*2nUsIC8ye43jO=RLD@Yf&pKgOK z+?wshx5bxTAyEwUQnF$=o3_8e6Xx4Kw~uJeAO@^a&h9;xQce}l z$i%!fBWkcjMCd`fu__DcrQ4bhh2y*??~j~M9@j59^S*B(=$($sG0aVHHVcNKn^n79 zky7d(^H2``WAa54-=xG=8Fj*OVYvj!cCXIDSzQ}L5 z=pg2{Gi0YUTF)$|MQXBEm9?@voy$hMd|6z(@eNrQKf)eqY_B-H5(Uy$*!I-Zm%ycDS|htpE&2kq;LtgXnc5_EoK^eOHY%-!x$Z@)`Y|{k&NND!J5LMVAz)ZDoFpa2d zJ$1NGSwto;04~d^9qRQfU8~8h{!m2}hbnhg*OAnI<`(ozc(DBF@yiN>@x#(&LF$WZ zu@P?)etf8OWbwM7YMgztpgrj*{P3b)KLrMMQj9%JY!>?8h$?&}|5ExV!OruhPe~)d zK=t!8{29y?Q`Pd7EyHe`UlkY`Yu>Is-YFx(d`9joSJtuhOrc92bE-_B@{~UWAsFI& z`S!u64oQRztF&;qzwmo>zCofKgsIpryDcy7R7>v6 zXt2U&ceay%S1Ov@UzWzPX*8m%R8DVm%r!nYISB0?sGv%?#WJ^)b|C1yg9TmTLt9YA z(Nve;Qt`Tzr!s0Rr_sEMRa3Yji2_lSy~r}9Vr*OkRlVa(R|ei4kab6-I~ZrN=EFAg zkWIm%s`q4WO{cCt96E^kGo0kF^f;zymJC!vq={#T?WhmJ4M@Hv)CQ?1j^LHa8NrAf zI2UGt$W}e^?4WcNVJ5Pq1pfQ-%}+4_ssq zcm?3FnVa`Znzz9NelOS3*zKZFVc*k9c}h^Q+=2!=&j rz>BbT&g&wsHFo`fEZ{{_M)vyf*INL`7VX6%79aaNEyb diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/8.ogg deleted file mode 100644 index ba82c28fe837a738ca1ca1c70c781e70d8a9fa83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2119 zcmY+FdpOf?AIAx$hYnM78nX#oNjZd3mQ)i$+i3qAG2OxcS35W_S7{3MfO&Oxa0|2>QJDMXD*E0n4V6=x zr&N@ccL-_ja=nA`baD08;d&UZr=rC*RUr7=&Ys-H{{-tca5--61n(TmgRyy$+sxS>bP z5Y6J0;45NyvbUWRYNBraB%0N2gChfB`={6ZwuGRs)zuv^EMtB3>1~_*&PbFaiAJ&4 zpUE}Xh*0QKkbOaGrB|FLgJj?v5G8)T^e_`qNek&v_ZdqgeKRX7+PlxRBhm-N{0b5p z<0XG7ZmyAqg?*zhwFoU!q4=$~ z*P)_$!+BfX8+CInh#tYl`IX$^g-H46h$|C|Z?voxmDMu-0+Kqmi45 zIU(%+xXZ(*Zz7%_FtluVkeYqqnjGlhKva?1!KdZ1AJ8+2sRpF2bYb?&=@H3g5TFcD zlyTXh{*=y{o``v7qJw?CoLcQ{SX6bg%EeyHmD^w09qzg2YB;{in9#c%s@;Ur1EGi&DNH+}YcSeV*`v6hw)lvyf?qPR%s!aa)7>eg{Yf>F*i19x=+~sy5 zDAhc^kJ1?>>}%UwTcLFEh73N)N=&kFmKp69RB`WU4fL$ssam)q4cy~ z99d4jhPt%4F-UfSMlAYhal`Twyk7))S1*d@b+o#zGvYaaVp_o_g|_X zPf*jAe3H2BO<{d29$1fTT|8m(T9O`8SlwR6<5&CRq~r96O>_RVZ`rfhzbXTiePKh1)n*4M#%&kvlaHRhAZMl!2Y z4(=Z->zE^?rZ!Y##}X8ig#6%wlM{+|MIZNTOY$BedOLZFx#Bb@E# zjr&xuZ)9@bBty8s%00gpnPh$3Kni2lV0=uO2>B(_B+8DOLh4hOnhD>tjKrXAWo5iF zn3~nw>=>T+!*5r8qEciY)T&x+mS?v&a_B*oz44DUOCoS&D6B>&-X4Q>-ZsXGh3#o# zUwDJ8l6$>eg~Y9OuQ-;@%1%^;<~~|Txg5Zm?_#WrP*%Vm+6(&3vJ4a+IId$h#5gjf5Y+j4qhhAD7~B9&hkmz>yW?iZ~Vd z5n<8(KQBH3cn>~=7>e9=*t5YC>p>aoexu9Ir=exzT&Djm!_>-t+YNo{3*k=_>OgHxGQZX?g%sQTlwKN5A5o-_C!KTfXwpD0G(Gp z>&c?+9W4-JjeDgEN!VaJ$-eR@NBicDY`-{0mIPmGD(fGdbM&_o6g?|IO-;N{XI_rg zF(d@WKREV6<>N+H6LVwuP*TmdUP@iqFPou&@{3kx58spX5T$x)vcc17hVBX)tD%T7 zK2rJ&@)ZB+pU92@S}OPX0mZ*=rKTds?V>S;PVXndmX4G?>&Jq#LFQ`vfhAj?wK&|H^sC2h8-!lUCDmVVhk10ek`!eG`* z$h%kX3%Qpkqj;m?0c`MmctYZV0H7{|)SkJmjy3*J%`zRBk;|Nfz@j>>gQiMilZ!o> zx*K2fKyecJvARA|2M4_#Zi7jp|LDdJJ68 zFbH(V%esn`<)5U{d{em}kdxSP#`A-)Akn1XOZ-^}H(Cbdqv$a7B9MNcRyVq^cQ9;- zxGn9EN}KQY{F^xmV(zg*cdH?uMY<=alE7Xw2GQ(aO%Z+?izkN67+zw_9uAlE`ul?ZxihgX7>*DcZCo)9#wUJuetQ)gM zj^U}C);}t=o74Jx-tkXQ{2q6|=N%t+dqwGt1pi5H;rRaGG2fSVH75g>I{tWE)w-L_ qP}%Kr)vivO*;2=DmS(p5P;@WOu3WDAzuY?NZkMZe<+hY8wf-ArdGWUZ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/9.ogg deleted file mode 100644 index 4c1e62acaf28946fa8d6ada05665a4cbae37cb48..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2049 zcmY+F2T&8(7KRfEMaT-FCDH^!6Lygz0VRklxCx+C>AjawgON}KBq)(0JqUu*QHr50 z9YhgH5Ru-ilwAo30g9VsMN&E_{5bz66R2#M0d7jt|a1 zD8MJs)5c0i%Mj#rp z_eje8t-|32A3FAeu`5_aya*P0_^>^VV~n(QakRP0W^`tE)xuTp4=1Vwh9E5(xt+*XSEfWVG2NoftT$aoyB@^X z(?&Y-fAPb;9;DdJ9z~r8h=xQ5BeRGivsJB<$}zkdVK1iOpHgulleN7=na!^jPJu7W7RhIIzla)}f|Q z--cVX*IMjC6>ahW@ieVIU0b(9o%NgytjK{* z=|LcmQ8^8V^l`A#b$U0M=$X5HD^W==+J(zqB#}LFMn_(+s zFpRA{^O_BZAz$*@EOo~ZvRs3&lP!Lkz7ph?-qUFP>`C;n77G%8wM9s)lP0zJ8czu> zEdcvPCXFzIJpA9?{pQh3du8WAi>l|53!H3l@X-V!Qos>MlGNEjRL2h_-a7#cX1u3# zBm2iC;?4Wki;Fd#055PVdx)t))b=G|rp;&l!z0Vx3n`Ya&^ADer%a!d0bkhQ(sN)f z7nVF=j4Cn83Ml*p5dP*UX4#czc{47W?^Db2gBncs+=OwZ*?pYhE?cA24lc%FiMLe# z2;3Rou2$LLh9OA7o4=`zy=bBFdWWTxyyhvvbwT*K5l8GBA^r|~X)DuSEYZByIJbHA z-D-hQ=4vh7`7n$Ws?w|WW-Ha%v;D}jwkTHf+Jy&H!FoR(u)N+}_R?Cx(SCIUYq6e| zUxrJR3OS3+Y(V@mfX#L~zGRKCTWI1^O?i|s)c1i0fgiBAe9QaKrKuaqbocvYV_Bg`D11NB39d4jb?H;Nb9C1E(7Xy* zxjdl#T8Ps=h{N6!K%1coP`djnd46N&;f2UCwiPeAdidjADd45QKZmdz@swHd@HM!m zHfuX)Yi2&{g2L)b9I`fb4xHQevPPi#Wz(jly*l+st)JWNfv+r^6Q>l4aMO-2rUD+?PaaU+viV}HA9GfQStqv8T6)HzzjGuFLx77j?FqR|3>FAxme^R4 zt%h<{i;Wr!rW11U9{CRJFTSUY`74~~(zxP2@Md{IbGL~5^>9hgqxu8CIEQOI8TcR% zUvKb77zf+DjkSw*$O3u zWb}USGjjhZ(IOSB*|VG~nNjp*+*aRDXphD87U?vxuiLKvb_*J?_-BtZ>)+04hL1lA zVhG~msi&G01iA}?^nTZRcoxcepMO%+zeDyn6&daXdv8zkRZ@JQ|Te{cfY0 zS&G5l`?~l<=*jn-O_!#_rv@(^${V!jaE; zJsOvv%1`S0g7$o<96$as&?U3G8l7sT#epHfpxn%-lbm-f!wTV!>eA^r3Y3Y=gqz6Q zfs_>_hNC|4t}Tdu_9Y?7PsUw(p`z~K`D9z!GyVyA>F=M5u;zenAprtB*D(YL7l%I1 zat*a7G3DASNCW!j*t3T)8^@%8XMWHs!m{FL?D-F`fyQD0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/activation.ogg deleted file mode 100644 index 7e8519285102cda7a4623a6a603b26512ac6f42c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15641 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_pin.ogg deleted file mode 100644 index fa7d6372e8bbb7d5bcbf04b7ee3176c419195cc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6545 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/err_reg.ogg deleted file mode 100644 index d8db153ab58033048c1e4d7a8872566922f0a44e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10408 zcmY+q1yo$YvNnplyF*}b2~G$Q+}+*X-JOBp?hrh9aDvVt!3pjX+$FdZ;0^cO_3rt5 zt(o36UAuelvah;&l&!7Rp-DNCIEuf)4LH8K`4~z0U z`~TnG*`Xm+Dw@(Dw9q@dhN-nX8srxRQ!guC4mLhE4tDl;4syuH(#hP}!qQC$GG-1L zIzqmIgxILZ zo5AJsuYXkQ_K6~Ev481U8|Q2i`5>oOvm%_>9AaSYWjCq&wL~C)eU(ag!HjM=Qu$Nc zkv(FTqET!Q#K%XDzP!ERaCzuE!9s&Uh~b46CwR{LugqY%x`P6H?WH0)aCZ}E80ig zq?>$Ui6jLR=NH{G>y+2+2BwFMH7SLlPLnBVc|N69s{POk<@9!w3cHi!x-7pvK-+$X zeM=pIxoOfpm;!%c6v`i!#{*VKc7YNn`;fU-q?Ag?iTaAw|q z+eXIY1-&9;h}w)Yxc@dLD`TPEmm_~GW3HT#2+S3nXz4Y3(TueRHP#BiEk-Dr*~1D{d)(i$`^f^AJ&uV-{f-sn_g*A85c*rZ7P;2mRP=^T+@K2?I$znU7yWsIty& z0NG;fsw>7|gYSBXcIz*4`s~8L<#``x4lNLZh^x;9;l%va^P$80u>`<|NPWI(K$0j> z;)HQy1?<#}jRj2V@IHFF)~*dTLQOg3?EoO33Oy3;3nla)vggQu;F9 zG_5iN)XtN6eF7t-5-26!>AeCTHZFgBuH)eImQ2%H2rc+1nmF&ExK_Jk6GD>RZx5uV z2g}_ir~A3+$(|ZUj~ITeuoGmx`KpNJrUzo9j|dK`hwcPZQaE@rcd;;9+M@lIIBM3N zLog$L8?7krd9w~3`7_@5YYYpv<2x8VnL6d?>Bwg-SqAoEa^`CE;uZX*v73sTAXqJz z3|jJ89)T)Ra(f_v28@}j677k7j#DE&SYtK^=|kKzeE_I>7}<-yo> zi0~gGSepKtmXxq=#x>YhB{ieg|C!?uli-UxqYV=GQ#KzS zi&hi(`JFC+a(;kOji0r}IA%WXa?qRHJ4Nb3i+}~+9!NtEa%8%Lv56`8+bk_=j`DHB zIG&1$faMkVl##-u)3qLGdq)5goze=*Oq0~-xhJe!rq-R)S3+tQE_|#|#O4KPLZiPO z6vHEFGl42I&9{Mpn0xtQb67i zka3){T3OMzW8uHy)d-*6N#78d&!+eo#`S0_Jj*_~Fa|Rm5p-~)`D$DNwI%*ZBwg(6 zA5YDgnzV?I_V+174YnlVuL^?+5qU6j!`l{V>)E9pL(mw3yd*D4mmJZ@!#0{ps*5mD z0~rGPxGVNRDnP^p<<|hWTlF4y7XCw4o3B-426w1Asa11wXhyd#hudKIgr(nkQQA+8 zkND(TVlH0=&OdK_SRtBLHG?(t9<^�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 Dr>x4c diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/language.json deleted file mode 100644 index 399de04d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "hu-HU" - }, - "strings": { - "WARNING": "Figyelmeztetés", - "INFO": "Információ", - "ERROR": "Hiba", - "VERSION": "Verzió ", - "LOADING_PROTOCOL": "Bejelentkezés...", - "INITIALIZING": "Inicializálás...", - "PIN_ERROR": "Kérjük, helyezze be a SIM kártyát", - "REG_ERROR": "A hálózat nem érhető el, kérjük, ellenőrizze a SIM kártya állapotát", - "DETECTING_MODULE": "Modul észlelése...", - "REGISTERING_NETWORK": "Várakozás a hálózatra...", - "CHECKING_NEW_VERSION": "Új verzió keresése...", - "CHECK_NEW_VERSION_FAILED": "Az új verzió keresése sikertelen, újrapróbálás %d másodperc múlva: %s", - "SWITCH_TO_WIFI_NETWORK": "Váltás Wi-Fi-re...", - "SWITCH_TO_4G_NETWORK": "Váltás 4G-re...", - "STANDBY": "Készenlét", - "CONNECT_TO": "Csatlakozás: ", - "CONNECTING": "Csatlakozás...", - "CONNECTION_SUCCESSFUL": "Sikeres csatlakozás", - "CONNECTED_TO": "Csatlakozva: ", - "LISTENING": "Figyelés...", - "SPEAKING": "Beszéd...", - "SERVER_NOT_FOUND": "Elérhető szolgáltatás keresése", - "SERVER_NOT_CONNECTED": "A szolgáltatáshoz nem sikerült csatlakozni, kérjük, próbálja újra később", - "SERVER_TIMEOUT": "A várakozási idő lejárt", - "SERVER_ERROR": "A küldés sikertelen, kérjük, ellenőrizze a hálózatot", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Konfigurációs URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi konfigurációs mód", - "ENTERING_WIFI_CONFIG_MODE": "Belépés Wi-Fi konfigurációs módba...", - "SCANNING_WIFI": "Wi-Fi keresése...", - "NEW_VERSION": "Új verzió ", - "OTA_UPGRADE": "OTA frissítés", - "UPGRADING": "A rendszer frissítése folyamatban...", - "UPGRADE_FAILED": "A frissítés sikertelen", - "ACTIVATION": "Aktiválás", - "BATTERY_LOW": "Alacsony akkumulátor", - "BATTERY_CHARGING": "Töltés", - "BATTERY_FULL": "Akkumulátor tele", - "BATTERY_NEED_CHARGE": "Alacsony akkumulátor, kérjük, töltse fel", - "VOLUME": "Hangerő ", - "MUTED": "Némítva", - "MAX_VOLUME": "Maximális hangerő", - "RTC_MODE_OFF": "AEC kikapcsolva", - "RTC_MODE_ON": "AEC bekapcsolva", - "PLEASE_WAIT": "Kérjük, várjon...", - "FOUND_NEW_ASSETS": "Új erőforrások találva: %s", - "DOWNLOAD_ASSETS_FAILED": "Az erőforrások letöltése sikertelen", - "LOADING_ASSETS": "Erőforrások betöltése...", - "HELLO_MY_FRIEND": "Helló, barátom!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/hu-HU/upgrade.ogg deleted file mode 100644 index d894582637d5e4a49d7b2850231739a3ce44ab28..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3811 zcmY*b2{=^k`!@DLvPQRg7A%raP$-WH65+m8iU`X~|6NT*iK4TyI5+M`W z2_ajS2*2_B{@4HO_g>ez&Uwy#pXYv`_nhawkFJA*0SPI||BawRP{ifs2;!SFfLYhw z+e_2V$`$~S1GHKEm!f+~|Nn7G2N0t|C)GZ{-AlTmm4g=@@s75YkNqtv38;h=1aisX zA|7^bHgH=z&$~p-hKNbsCW2DDE>6~P;)DMrR%#{kh~qNx<)nHD!DEc>4yMnZdw6@o z;m!yTZ-l)&3@OYLiYAFnr#R=>CvTbGG6{6qS?4=nYn(!+6ccgDbq4`1G;Em2r~=lSY7NTQP@^ zS_7+-f8U#iuA$78Aq)tH6cC83hD*i9?Ia|-d5oJ(nZA#9Sr3~&e#T1q;ekZ}Lq_M7 z*RiqC`88=Fw{bb1emydZoP=;MymQ}n z5QNHnUwv3u{Pf6-0HTB;IXNlb84WsI*L}zw^16jDzanH^rV4R^GU?us1h>%|P3z(IhIcpcT}b>B>?<$`5co)I`tDSym9sYjz(BG$hWwtaO# znLkRuG9srb$zlE`?c7hbP1R>ZzN65Kkwww2W_1I#T4{EjwbS45z`nt@qQIrjc}lY+ zna5FqIOdVGkL1LU4%{r~Gy#4%ivu3(Db?Cg?at=DQs&Gu`7rifn7zDI0e*dJt@f$# zH16>5PU35GKW@=>@-LD1rIpsuj)^7#{i<;Jet6F6oo&GxlP8zI@bHbN6sLK&^dwu9O|}5z@?s0mTMq>Z*rZ z%Xoxh3quLCaAp|Wv`fm{uwo0`{Ed~EF_0CAo=qhyCYCAKxPm$|^3Z*S`*mEX5_{C5 zcA{6u+l28KX?znTH?{2HBT-Y&Nr+GR#pd5XagzmmD$_5k^a1~X!`i{S+)=*%xB0#r z7jlFmXM8W!TW%ETWyM=@zXoo4kRh0(|yOp))G$LY~?s#4fc{e zIwTdPCb~FX7^I;vlz1)@M{iehr1bjlUHxyv6AE!$xeS|2;k8Q4IfX@2ia1 zx1ISOhLuYV?Xj5Z2AsR!D4A9AsUCeqac#-h(q};=tbX|75mb|Gs8=$>8{*C($cvjq zR5RPPLh2~|1Z1d*aikXAMMj8B1)H3Q^ljaOx=5(L4>uuRK9 zOYq`g#O&*RBe9OdU!OU`c12~oL@@#RhKn6R?QK8S=+Zvb!@WdOART+o7QK}$QA-wa z$PBQGQ)?ABOS_wqd#^M$+_$S;u(;OxdiB*=n)G~J@=2<`^J7j%fiBqNps4E^1tz!f z)SSs=k2M<%urMSaxV81>XC85Sg5}TJcB+HaCS{`{ z#mjVFZ9d_jOiW7V2oj6lrp22l%Q?$3_E#(v0o9T|DUvRBYIM;(MSj+k6H=`0Nat48 zHkqcKG53}gLrH&>xec|b*ArqN3Zozn5+(k}L$ByQMN(1L!jUzjg*u;Nv}q9DrOCO< zEIt?@KCBqU1raG+kI_}zw%*N4p^jO?L0%d~@OHAmcO>YK@@*Quq0(XTY1rhXR%@5P zuK7`^X!NB&mz{`Es0etrF-0?Nd)=c*tOb8ovT@mqIM5zBz#r39^9(4b^tWeCf7ajM z4cU4`1e^oEgsV`~KM0~6GGJ1|ojEq~`FhhPZRE>GzgXP=5PflfGgniH^WNP|t=h<( zY?n}kD?AONK7Il=yT>Th(jEJmu^Cclj8#$}Sj(0Vbq%VC1kXrWGzL@>yOBHXiH$>O zMT_&B&6gS0r4h5akhj_0-)zhVp1LLGbNaI|-%8VxN0a6h?Vzpj$Ib*oUP`9IhT)BZ z*PVTonO3f8DrxoK@!97~n=OeY`WgnvvLb{()5)rF2;zJ=9Odpz4MXyP)0E_}C|SO) z(~XrP^u3rD9Rl)P{qQX*%e5!$0Nox`c^QL=*`6eAfUy_Dw>Y43dILoS7gy@opiox5 z3~5;)g;icZKQ4j2#^I^Z1EmXf#y)iG%^hfhr|>PNX7NDx(y(R;>UzRqSM?V4Kh7H* zcxluBI4>FToP%gRWAyZKN4R=Ff9~RHVP&^8dZv=C2*r?h3fSzs)?7{NPRf{Z@Cur!K37x@X2;Bn7IsM`nsGDsPk@5g?W65%&^@_46(P$Q7*Yrvnqaw=uuQxA zhC60wNf4;WPaS97i!lI^G`b_MU~Jn z-5z4%WT$>Op`tID#D;kHOx(f2jvzPws&lX3&?(6_iKAjIO^5I2SjGdyd7-CBI!D$u zEHF9H{K~gDkA`}Z>Yxs$hyka0qP_6(r#;^&6%WGViX8lRZw8mhHwKI{e75^Zpw;8f5nBb7+vHP7TAY+2u)SbllC_ zAO}1y=P)W{*wW07&Z4K~yBK7WYGG@1V4d5RMr{vycyVXRb^?RG6vcVeu0WTpf+&L; zDBLV04yRxu{MTmiRMRoAM+~k*l0m@$YYrTLOpfPDpi$u*H#bNww#Rz5M>)%RTla-e zSNR$fKN+C6lK6rb^SUm=+7pyN!%pWfbWV))}&3*3n`N&z1gTm7`p?y>igLa+1ZpU*>f zhu$x466|c6DekF!y=b$Y9jJ!lWF{yJ_IppX{7R)1f;mD6#>M!d>VoC)=@RT0u!Tnq z+wjYuiVezF$%u9GzT@DZku0(z>>lMS&JdpEO<*%l`NzE4eZ?WY6z-#612h=bkeCG0 zU!yJ>#$rc385F7v_8?D;RC%-ksZKAAmATO-9eI0Q7g~Jd@HUOzUCXGU4VakfYJ`E$ z#>UIw_j$bUDZDKViS-GHxUSM@ysY$vdiT#Od2X#O%nF36e}8gU=~QE`A8~lNy%zLU z*tQ1dBvRAXY0dG*aij{cD$DpwVs^Z`mgnl3^3L2$>uwf5)pQwuwA{RJ7eA(ew0NL~ z-f9nx|H7|-!BQ99_R>)gNBlwH|>QCU-ZuzKu+o@nkE>8B`f`j|8 z%3q6#kFK14H2bOcSSC2;y>-A}`f5CMY}w+%%~di1Jd#Zm_|J#Fxl9DYR&)nxq;2vKBSvlz09&^P#A_}Wx7JqWip{O31V?{8_llE&|kag zoPYX-o<#$?5MN35ufjCl# z(u;41cc_nVxB;E>rgLgKbW%+sD8MU}KJcH3joautx*bh?v?*#yMFW?;%LQy`1U4on z7#$KFjg7_vcu^tt;=szt*QU+!Uv6ysGdJH_Y7eYX>IIyo;d(=q$u1>{KeQ?)j0OziZB!?+3rx3eCWXa4iDf(M7RzXxGp~ zpmL|O;Wd$wfi9EnD;Hpy>-uTw5;C-B);|A!xX^-E;Da$u;@(U(A=A^A@nj#5ysL5{m2> zaz5}^m0v|=<4*lzOfmTj(FNdPGNb@les1yxPZh755^Qq!zNRj~%ommyo@TT{d0@FT z@(qY4?KLg;>h%kEcq{}gC5gd(A7q4!=B0hQlSA$>SzV+2igFR>YSH5N+rMu1i%V}j zpE425=^I*-{W%RbX-8vS9uW0!r;Vflcqv)ZXY8GJ>+AuCOx2|y?Sk*U_zL6^@TVmh zg?qitO9O(X>LgPwp3i5P8#AA_nO=(P6T&SgI@xXgdC~5viw!Ah-|o8_f-^^@*Uo+-Y+Sq%HtY|-_L5ZEG9OJGSk>Bn>gqm!kaRS!O?$3Co7HLOLHdq z*?$daj14rAI_=;G$c7gpT%NfxG}aBTRORiAJh?11ty~-T6=P2ZJO{0uy~0hG_+vNl zGJ7YUnK&~wl-=orSk7_AN61-jE){Jcw{3luBuY0wO}Z>^TwL3BJDHPuuTzRUEnaYkI0+<@w8N?Oe{I1e)`N)}7LL$BC0{x`yO}&#lce^IsJ$PfsZyLV1~AL2Q?VcNNn;v`%yUIW`(zilrnIQ8PmVav_3 zvrFqplc9MLIsdtB3s#G3dXTN+!=X#m5wHHLAim(P6cNp`$MPj3?E4TJrHtc63Hz1L zL6R#|%F~)F6jH!$oEMC2kZ{a)cytr2NB39qA#u-w*X>4>{F{LTkFw*Ew*5I>5`##{ z&L1UHuoju|Ih2_iIZU*LOr)M&3_oup+{n|CiP`S4?lUUHeLro96f0{s$tuL(#Pi#J zS@x(}bj1a3Kj!}ue~cAN>|sfGSFke<@J%aqI6QZ^F|}Ve(*0LNPtD${!PqQihht;;tTztM=;D8u z)^qo9&*oYU#QEC{Ia3)B8^P}H!`#a?62@{s1%gKyH)F;r z-94=O1XL-f^CxJm;^417dGS_=XFGv!x2mYUp9FcxE$#$4sYv8s4EO$u&~bUIanJ0{);MyjhvV?XXF6B3)F!&CF3<)#P~7d$u9M(b}JMGUE0 z!{w997^0SUJ`6&B&OcI(5&XOZX#e&B^NRNqJ_or%MP8;a9IfV=WV&f`e%9Zq@ z;xQ;wq557L z{gg9@tDnx^pIXGl&FEUan}o>T02oQ90*TpL%l+~v&uP@ZE6re5=~=F3ODIOb)W+{_ zY&}NVwEob#v`#WWp@XHhV=$jomZ)wqBzLwCpya2e#Yf35^ezh#)9D^sVSuTz#+l-f~g^!eP1-iaXBJT9Z5*6&&ViP&RkWi{f*ox#X?HjWK~Q$wN~x%j}q~7}C<;xtB>+ z|0q%alY1HIbv@xhHhXAfgg@HN-du@p0A2!qD?8~HAzbpW8?tE+>U8R|zV9$y=~a`e zGEd|zy$v~`is#Dn24N2DJ|<!<4aEdE`r+U2B)Vg9^ccS~Lt9t;h~PtBFl6o!Yr+lG zC!QEI*<@q2DNk_Cy_ul>fw#H+Cpb{|`Fi5H09PaG+fgcv*jegMq@Fl=vtz3@`h5(v zm91Hz{MD(6d03)3Lv#AKq)@phT5=b7a-fq5S@t0RFS0A)<1<5(4Q<4u<0oKVnlGqZ z5-rBT{I&~TTuA_w8D(o(=ET|&uQ!m_m3^Z|pLvS6qS>CNosw>Kr!&T>X=Z)z>ri15 zy2~u`;GT8UJr%!`F?FOxenF*7&iK|!JZNbi8ED3;7+ZHMH-$0C?laUk<-I`)14jM{ z-A!?=F&%-}fh#lSKdB{*N%4+9*sUwyxHBFUfSRJl|80T4z zYPq6SlkW%Bb!-S6az8$dDqs@P(!)2{M&_TMxIUp!YUz*{Rog$9`+VlrF!>S+rN05- zB_-$&AtBFqgz{?&GapTLygn+~eXIE#U&R#(mJeUMdL(bl$d6u1@dn7N{<3{2SkekR zMX^ug${}hNH6T+aV9q36$no-pE(Yz$Kf`^?vh&PUWdOFu_ z63eL~c4m+nXNA;Hz!7JK<5aUv)L5K}0hMBgd19F+2i^C}qvw`Sn1R{wQJls<{A2mO z5Bd|%v$|;tcU%2bu9+o3z)d{IR|&@a1&0@Dx6cycOB~C#1N2XturRuQ=L3h&EK>vQ zK19(yC=HP>kzjGTMW@m{h5v2?E?n%f`#H760OeD1i@CR>UJ9!J5hh|74Q12rfI*+@ z?Zpofc7uln=jM{l6Z~`906ZTb=fW4+Qy7#RSchk`&P~ zAVN=tBT`i;Jg}{c^*!g__gDP`0z|aP{yt#;NTPPX3t(iW#&%IJzAom5CDT@V|Ao5# zkJ46GdVkl_@o#KC*U#V3L$#m(($ev7>@(Y+zpX+?|Jp-s*zas@*zc>f<~Hu34~IB-qqRG1JUu{f#rG;I7E9K_;FI#^`yFlatTAy&Sujh|X-Qx#{b<9p1Z7!&)zJotzFcV+1|*B;gRB$nHi6@ zoH~5bV8_^DtF*-HYvKfWU0br5_awd>??m)M_Zllgn^j zqH`;ohM%^@ACSO%o-Ok#U+1^ta!-W1hn4)AY-HMar{e(+VCV9C-eBcl^$OI;hO-Xz z0$e!~1q!4vsX&S0^Vl(^w^#KW>X9z9&NkFHm-Tv;4f|>&p8E!$#V$Z#CN`KHkArpH z`^c_4E;+eHy9xD{FD#SNYQ~0hv(JYb(*b`1dtqX<-hu9=zK$mHhH*O~)aHFF(!Lyl zI_-iBpt7OzQGRo{d_#c(j2j$%UbLcNj6dMEQjMb%<8V>j>!_vC(Yps^tf(^sbQfIU zGK+%1^b9aXlZJx}XC=xY;qjjz630@>0`ZHlk}^gtDMJ@^!aJJHvoLjwvVQa_*Oda51b9^RZf|cCu6n`E#ORxYohw)rR&1LUd?Wc95^5_Gh2>sIg|)T7-M%> z`KwqyfxPsk?`M+F$xTdLw=yxo-(;@Tr+T8sMX2qBU&Tn?=_ta7l7+f1pZDv!QY<%g zy|bkFI2^TUdOSGjmw@hiF~0Iue_pZKEZt36HhARl}(k667IZ-zkij z;%&s_uSOrhhmyX!5r8h{T+o&nYx$hkfjGn$btLvz6HJMRk^V^cY zk<+z7q{3lwS`;j7JA^Gpn8erA%ip2T(QBmpTtI}!397A=YKr#ioS)kPfmxZm@xB{`XGTj((VJ4; z8XYjsT!^vx$slP@)Zlxq~jeZ)eetUN!VD5aNzRemy`xxkg~$No73I|kQPuPZZ-@S}yf z-)SK!(_Gq=V)X3tp-z#$-cvR`v0-`sEc!yEbFeVI)c6vI*B9@1nW&NmVMQDfOQxW7 zq&^g*Vlwv6D=-mV7grZKGI`-ExV?Dl?4Bt^h?nNaF6T^B=Uz2QEz0tEM!2#yvo{mM zO|~v}!&W2}&1utz!dh$T7d+I@wPbGu$q0~KI1Yg20|ma|ZQA*zPK;bii`L>8i+H-v zz?rqTrPvSMUEP*(B0y)JBz1iQ4*~2drK`bC0-+8}W^3lJk#mB6TByX;&^zbvd1mCV z!FP^*q?2RVUb@rFh`46Tn&p9Q)W>Oj3zbC z_(Wyj?dca75P9K`MHVsj*mT0xI!7QG5rtpBAt%=x!$b;tE?4++uQ+ z1w&H48SCWa6-0>hb+`u_uut!>d7=PpjB$w$f@Lz?y3gg|K`-q-I{>kqgz+wDuO*sR=g<67*E97sfuT?duDx5O3sP7aPjy5%sJ!m*oaelaCblvi{(7*Y!P-O5O z8IYLab?R)pfn(5~lD@3Vow!dVIWmg}E#>aSoUKxul0C+oz(!jBPmN8<%(RZ_hhgUev+R`+P8{C^N2b)kVD*3>h1div2Gq46e{vFqNLi1 zp&L=*pSx+9Bi%xwbq}8RWV*yAdQXDQ_o<+@J9V>?7>Cvm`iOv}_ zKtoVaHHlt`rxP$s2fL%cM7T)TsopHBKzS-kybtQt$d6#ydFTOoj>@tr3yQ3HgnHnX zPU>W8n(=lRf&#^M#;d*2^S;%>YlsDGNRVElTxCMw`%-i9785^p++w8?S$ zaQe7|%6G~08<+i$#!0o{a1KHYEILF;vaxl4U3rg>`G232UjXy{u z=E-iL^IN2#QcSIy<>`(jG=h8g?PAOHAaf3~2`Bd<7uRWJNblx^vKv91O5FlQ%uIZz zU5C@GwWppwt%`8_L^eR>{fB%75rv^`1HJM3+deB%Md^DLrjI<2k=fSz{>cUwCmKev zdjLu3oUHluM|@_n1cuI*rvr!e1Ft$gr-M0qg# zl#IRq{8Q54t+;1!`eglKgQ)`%7OJ%+HYqqIrWHwM$uVztZ#39$a^U=r1f~_EIP+uyC3;C1o zpF;yEKi2irwU_lsOe#B2Zm|BOu5;jeqLY^-=15A2u@Dth78CrCM(q5<>49N?gMi3^02eF zmgnZ?27&3=qWEL^2yjqi7eJiIOk9VG=EbHg`IlYI2OjwV>;{g=cK@L=0!R)sLE*(I zP=NqyBj=s$q1;NF1D!0tOii+KW4qAtOKBh4VRpQBBK32AFYzfHW$U`2q<5}KHCcyH zk(u*2TvAY}1U+IFQ3$dzwpX3+4FH(GZ^_;+nlWTie-herE9PE!Z@&>Cao&+HVu|Oj z+tQle0k|s`Y3CsC@$uiD4!?S_7TMCa6G8mUMGVsrhGhpNnQtqwkZ#ahkT3SC>yZMbkfJZG;}2;YWV5{?d1L#?SiXC-pR| z&s7{bZpF(M4M|5Y;n{uuv!l%5{MdGjp@ZxmKox2_~fTRqg2LHA4FQ9#ltZ zjUSexGdW&Xm#S$7p&e}bPG%0HpYbG2&)PaZ1EIDDSs&W2sLz^x5Ms(fE}l>H99F5d z>DES5nsIZ@BEV0cSJ#?aIjPg^mg{HK+5~6N23mO$y$^*vTc?|)hNSo;u4eF36j8`< zx*G}Y)u_rl7#VJx-3}$0gC$3rsTC*~7t{*zbzg9ycjqChPZox*gk$sBz*PiMY#6dtMUp*ha}Bop~pR} zw{fV6A<{u^BUKb)CG9UI>&UeHa9^$BL!g6tg+iS4Dtz65LGv?|yRUmvTDmgUo}dB) z36&|7-GaTRLB}Oi-$1eNg5QZU3aa({#vfH7sG_w9DZKJ~gE8ZQ*uaCc@hw#^Pb6cs zCQC}R1c(mdAU#y`^kptEjjrzgm4Op>)@b(BlxKO2ctfU|@dC=voOA~1?4J;5-FIc8 zY(BAg{k(dr_6Qz}RSVqX#6MWlbp2s%d24Ra&!;|NE=0|{P8!U~9Q$D-R&6P^G{IAu zGjR_Mt+7s5rHG3U8}#zH#jy#3x~^)l?6ymlnd#?rONfNxiq2<{DSLZZX%9_v@eZDo zhM|^HVJ&9*-ES?P17T9pwrVWNtRvY{%c87T*Fv%R-4Z>pi$&k#t<%sn61V6Z4eM~W z{e#dFZp=T{Vu{O1ijT%Rbpd_47OgoKf+qJOvY;s!{-`3I=LZj9-0?aKax5#3-nXqa ze!`STrQ%EXzeovy!n1z5Epmi)ZTx}-TtBoo+*7X&X%@{QWsEl*#2nBEuci)xJR5(o z*Gb@j9}2T#1QuY^r`a}iB{_*u1U0i}Ft7CQBp$Qae_2yJOszK%)&$aQ=nOR&b*1J* zUs)G6D5NPhEnXRN(;?_o1@nm{*7GPjS4Aqc=1+7%%Sq%}VP5YdGMjc%vX_5Nl>4&0 zHx6Yz?-$cZD>kq@H-&bj8RGyTQ$D0Gse?3yEo6NN~Su3Y6`F2`(g;!Oc}ZiPy8u!`>y{SO?v#c>3rfl+l-Y9ganLarwq~#jJFS zfCbYdV5uFZLb{j-h!lwMdt`p*xg%%4lQ1_Y%Il&Dcv@LtX}ym}h@)wRA^i7iVP77G z>ETa8Ny8K#%(;h9nV$sptbNfNWdZFm{bZ8z=V>t7nt8M=-J?@WGH@svNO0w-`ZMtJ zAFZwdp7A|I7~s?T4{Q`1s&t$!lpGXjfN8h$l{;udr{9eT1;TACTo=u8KN<87u2PW; z+wcC^`-nLj^l{V(UP{Ci_WArH2=%{m{P*+m|B?Q}W)Yr`|BWpYxcCc;kp99}>0JB| x79szoZT9-RCqnx85AUE^%m0^m&=I_&82Pjenfq^>u(ZGDhmignb)@lp{6DNmpUMCL diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/0.ogg deleted file mode 100644 index 1d8dea39e7f85e0e03efff9fb918034f410fdb89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2025 zcmY+F2UOF^7RCu85^1s10)bFO5}Jf65O<}Bpman5NgyHyOy~rqMgb`aEFnTd5oA@G z5s{vijzK^PAfYV?hE;)Gh)Z!n+5O{t=PmD^Gv~}V-*4{BoVn-R3jqNxLc&7-4X=TT z;hib2#@7*a=mIe!%od072Z4-1ZQkFJ3p@D#Vh0BS>N%{-5M;iCyJ7;uB!CrrOypHV zJ#8axJzd=$0tyV=4L^cEF4P?G`~XkS1TghrL4jBTu<<{M(X9Xn#7^R!OHIuUGY@!O z^bHLq1QQ~{u6uZT`}^qN$xvm`D0PB<)nxoB^u_w4@U8S^O--NO+&Iz~M@}&thoA2(m zYXfr2Au)a6l5L%_H$9lp*F)D6kQ+-@t<0s&Kjk@~U?i4$C{VV&y|fEKD}N~Y^CN^7 z|5|n8yoL=Dr-n)%^Qt}3aZ{70Y~ygyr)hOluiC&GoWPL4lNA(@ek9YlTII+pRYH4J z)cVb`VB3bm3v+bq!;Y(f2U9v%O2_V>MrmOEHdu$+)7s=t+QHZ`NWu~%<8H`EMlMBl z!b+-~{ahh0&ZaiiF!vjVV47XDnQ+!Q1y9ycW4Uq$CEn*Li*^jC9=Y^DUrWoxEnR^2 zjFcJRjeg4yHc@ATS<`*b2lm^|<*elzZ%i)4h7Do-8n+BQeFoiN-{ehBJ}pq=J%~Px zssHe}C$;VfvgtkvXZVo;x#p}6@{gwT2Ox5*Dww^9R5?6ZO{E?TS%eC72iagsTIs>I zKlfYemOOpVY*;NTpq%5`)-lvoh>!X z4)QKhjlkFE&dblp!@XNVDNd*%W0i`&9El-fOnkjr#eyOMlyvd%In=tG?lY6E72tue z7Ff3WHZ)E=Xf#ARO~E=jTxTtFy)+b9=>GRzii}LROqp`AbU}ck$ z=y7c|OFS~y&yXT4cDJi2JbV1+=?jjWpPSSDDhdhj31##&R~ADdiLS&gnsjGlWJHBV z(Z6Z-=(!sM<)YC@%@dh}ZQW1ZPQ7|%yIuEns6NqIDtF6x%=5OWHCEM`W zy$^aivuPb^@7>g8TUCF0Yrv8=rC}%=*s` z@s0&OaZ(+-TzIPnUSyLXiKZm))M%X~DJ7sEDMlz(4M^L>HFX)$X6P`2RfOrqN35lE8F}p5QOOB$En1eTnJCkLW&6Q+t~Z`63*8&YS}!{Ah^d2di1lR0%Rh4} zm^k1pV<4d?Q-NIKsGt{@EBNYcG*>0=Nz0vMJE@ZF}vTH#mSf& z_EL@xMt8Sb%2}bPzyoBpUx?11KM^LLs>Y+L!sZIO1=5>Hlw zA+hN*jGP1RRc#|FtcH%#4JoJe6sf*~7!T0w5sP1u*ogU#7I8zwrJ1+4t*MuVq?6z_ zo#HR~w5%Aq(l!l=S%8V%WtqvFX6fgvpO9L$8hy?{3-0(E0M)FdMN)EDh04F*ldW{G z0d;xE2UQw|R`|6mq%lst4Xzn(ujL;oweVyt@5fQ2aBDFlV)K(%C9U^w7vkd^Z(y}v zTBP>Sixq6qta3w6r;4!sLUnRu(I?kvgG0fRuUxTE;0#4A5{zSdanUNqS$U&XkUxr; ziX!|J_r$t4^(CxMRxEa(h{jj_@X3+bP*}B>2Ah+8g_3>VmFsfp1RuVsBy(uflFP2J z5F{r$w+hD2yoksuw7~kw)~8Q%@MLMJeZ3^E3B(X?ZpMr6Ja!F`oL-N%(u42>?n?i^ zDoyaY|9krqv6%Yay}q}vJ-`$!&tBexKp^mY{*UJTt8x!~-jxYZoZW1(-fkCAyLOg4 Tt@Q6^0lmwu4cUD|Kym&79;K(_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/1.ogg deleted file mode 100644 index cd8d7cccb7b7e88a8b226ce96a460682ed016620..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2633 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/2.ogg deleted file mode 100644 index 69cdce8e5609b152b8b2db2bc799bb9543eead19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2273 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 OlVjSMljGC&|M5RPT^&^b diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/4.ogg deleted file mode 100644 index f26010febcaff0508ce34c1a65927f0a47242699..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1806 zcmY*a3pCVe8#jhEY22E08p0UsQsXjHB*sumY>Z1nENTXg*>M>rrXd?<5OSGeU7}T@ zl3Fn~ms|(!*rrgdTZm;t6Vo8{x$IxN=lkY+&Uw#yfA8=2{NCrh&pGeoLL#|KNlX13 zy?#fNcDAp>wA?^27itvEA&3wN0v!Xj`F)kR?8yHcJ8}?!;+3Y~gK#_Ya|99%3Y<6* zqAwlA7@Heo(C8h72C#y{0>T4>B5?p00B{%!fW#m|$i#3U@gL*kt$+@Q9pjy%0)y`R zsQCMZQlsc$5n)~z{fVay4Gk$wO>JrPt2ee;mD31fVHKelqhk|D%ySIq_Bi&#!?|D- zqqWLT^?Yg_mpGSvd0;tjD*vICc)c)nZ26n6l>GfGsF;>FNS|Sa_FZ@U)0VDql`E2Z zuRoa7)IHNiVQQ(P7`xpakri!E+MLM2=Qf4QftRn#Ki|+irIMHCqkUpXKfB$~Gov!u*(_YW(`tfLA%6Y1sC*>N5~HvEy|UxU3msbSKH>22%d@dc*&qA#l?T3* z(|=>8L$*UHOnsdO7ng?FlwiU1K^w)Y-K>`ne4JW3zDv1Az9HZdYQ<+gpA5>jA3jl^ zu?dc=qeA^OWY+kQ#Z#_Ag`9^5Q@4}oe%I{G7TikX7q}qbJ?HJKx`o)38B|lIBD(g1 zR>1Y1wxN?l2k1%F8fOwGjpa$#DB#QucaQAv(YU|3HDttL2YVI#9lF8tw0#`f%kaHr zZ&{;M*6bIZ&4kC3=EEbtHqq9koObdf&yzn3uu4B(h^#(b9ACm_MM&DfOI8M%r8ZR%ar9L9qWVCbY13tvKVv5HpOl|#U9NbmqmKukri@~K+ zp{522!Am1%G4zmt+LFCUUEi{13yrd$Hai<@X!v=Z6Ek7Wxh1mR$4!i7f4E(wTjDdT zjZfm-!<09lTzKAPIBC%hn@)dSE6fgj;XJKtALyZn_+*+Hc6F+@9Oxvn`KXYpzUdyP zKD=K=f3%$bM-+x9?&n0%?lG+eYes^s!uW)#*k*NS+ln!`>#zH`11{xT?{)hcx0LuS zr|h{kQ>*lI4;J`Mjqo>&2kaQA*NX!t(W0 z8uH&6a0k7=v0m+fPS|+9&2m(|az@SRbJox=H(~!7lu``MD5!S9%10uldD0iR8jj57 zvPZV>KThI%+8a1Pd!>+8*3PrO7UnW>FcDVT#f<}5+50>bU8A^RA6^g<97}(qL^YQ? zjH58sG-c%q77La*H+VE|saN%r&(Ho`&a*2z)%5{`*=2O&4h-hplbn${7ds(RYrFv~ zs9}p8;oco+@^ znYMgt>Xra08D)J~|CT2-BDB<48Zi_W5%Xc}v8V>P%!asKEDT>i~lbW!Nx}X1Y^+lcM z*!4O2Zf2yL@`>%OePhEY3pY5?udKoi~H)wdAMetzHT+!@w8Jv@DW|L z5cmB)jN(=%;%7p*>r%#xYhJGo-FuhFojAx|9SVuS@%I%v+>aeOsiMABcl++ITfutS zGt#wsSKNVTSCf&CgW9mR$47q|@XYJV)5*JBL?>k{e~GCBPnP`IHDT-aDm|*aiiIbd zVg>KamaNA3M!Sxiy0+&V_(OV&!ODCJSgxDF@Ahgd-J=uVC+7bTrF{|$B$4R+twGJ;1;g5-tn^8A|#9S_z+Kwq$(( G;{OeC6i7k< diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/5.ogg deleted file mode 100644 index 67b41f7b4db6bb8e36d0715fcfbcd9ce1cbe9e88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2342 zcmY+F2{@Ep8^=x7SOSTcRj2UGu46;RJZ!DRyXOvw{c4Nzur9sHP77fOd@=ONB zj3n8bN)5^WS|gO|9ev;Ry}tXpp6fdQ=l-4lIrsCNbKRES-Zo5!nEo3-brI?S0%9?H$a;cw>$Z^HPID)uC`0 zY@ay6cs#GW`+Il>X)|)}j2v8(k%UY5U3K$kO#F{AqLaZfV&8awQw?UsbzXa~z+k_t z*Ze{-F2Mo5Zcfe^=0mV|AL6I|YnDXD5|4cnbbfqoM$6#@>o^jv4N>xx-k5I*AN4tp z=oP+xYLd$B?PnraN4erKnXaUb9B){obL!Hzr^t;HMoVeVMQ>Pf>{%}^kTE!jxB~Ww zpyOD2p6(tS9=c6W@z?YFrR*X5hbO-Cr)+CG_nXI=~Dsj$}ki!;N}??Wf+MnOD3(t_lJsj$T0BxDq@3N5O2 zK@dop&KH-dbY?Z?9-9a|laj3Cd6Vey=s=hvpTEKEfN7nm+ z{tsEcdz092A0T-Jan7q^Fyu$6i1G50TgHwOH^^O8@EKxvRSkI8rONKf#+xc%J%?#V zS+c;HCKON4%h!v+m?l{M7kliT!}gglVDYZyhMcsX3Yv~x1)5rVHhpVP^}_Io@FP`E zo`qP7Tzse77}GF93qkd+jwWsQ4{QldWC4vca?OIxdUxC(bl z1+k$OtY~zPv7`h^s`0$%-u7H&HtuEh%3xsu#7{UCdtni#Yx-eC`uZlI{+)DDV4_c_ zI{4644l|RR140=Da(OAuuV5V&W%f*v$V)=hFWbU``a%=yMflIU4g1Rz+Tzg9#@P@Aq-8r?%pxF3WIl=r=!Zr6$HNM;gMsk9nN4fXAg+UW&>c^)VS`nq|Nty(g7IQVz zY+v++pbR*iekUPx`<@Zlus2`jrIsNzKl86)+MmCsY1=e4g?B|2E_5~L-mJdhEGc0spCp#F#X^kA`JyRUnr#|3nLTFbrIWGOcVD8kRt5k)5+WT(-X5Pn z-7Uwrs3%TEBgIrze~Mp`FDHY*6b`9?7)=`ntdDw$@-ZzH8-|xE9p)tR-(U@f`N)+BqB%u#KuSi?NFkdsaUb=JM6ev7Tf;ACWgg3uti@MUbK{lX~7)X0NCufKcO zqk<>J#z~J*TafC_oLD%V1cVO75G@8vmp=VUaelkzR$cU6Yo=~Fb`FT^TD*G6EIM+{ zzncW;q&~@IR^}zL-k!C$AF@#+5jsGTh%z?c6v4fC4I<-sNIZ24$2E|LPe&~x@ZGy& z-kWVLUOTz()+u6ng^NmvFg~s49i44a$3LEyD~S>hy(+)-tB}J5B38BVqfn~1U-i!2 z28^y-@cA>)(!po?@{` zrQlGFp5f*Kf@EB`0f_*)EW~+oB>TMt83wqrlT5U(eDgFPAfU zb%fPNm$Jmj*`wRL206Lb63c0g>-U3sV4B1tQ4CJ>genK5h?C=_Nc_U{tl~-3vGfL{ zA1*qUJ%uVa2EUY-W4hz2S+CAC6J@EcAz1X|qU`wn=&e_NSLo1ZQrEJ<+D>$Z!xcO7 zu`*jVL-7fn`sWNHicluf7@WA6l3UFB5w7J4x2J}nW-@1*{sWVA8EzLZ;d778>(?_F zjp<~Gm=JjR%GDo0ktF*F3*4c6DeI@r;;(HUp+kSXE^_0XcVH#_GV9qcs zV13f#Pj6&t|Nf^n{^^a(jG<2n*`LkER!vb+5raD+s${;LduaYzjL|!Jf%*5rImAq5 z+uae!dK-wF|8FJq=T#8>ndI;DpVwW^(C>9U+OVbPQFuNH2;F2sAAS3j_7{PxSp#q{ zRdy~<{9 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/6.ogg deleted file mode 100644 index 48f034382a9c02e3aa441d481581673d3fcbb54e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2178 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/8.ogg deleted file mode 100644 index cb9e15b580c9b38516c1d27f068aef10e0bb8bd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2409 zcmYjS2{;s58#Wl(FXkEv4NCT9BEyiT$TDOs;bJg`A&pQnmXc*M2whZUELSOew?SEF zkVwRYv1JU|m!wG>WBbRw|MNfpcb@Z{^PTrS-}#>Joael#z(8jnUY`HjL(rhs!E_$_ z;|u_V3X2H0#`*dK07igzuYV}01N#5$fDYh#A}#560jCe>7kvZ6MY$_>zJvfns18gA zs;76rP~di4h+n8b?%HWC=EudL##|7p7#xHRKsY$fUDOC zp%Ia2{B=SY&c@RcPlPA{M(D3K_L*)Wzs%Yng)#;gJLR7XKev+aBL_zljN$5;7|Eh_ z>9lj+*CA|l_GDFc?Wys#NxXpPmhDUROssL_p%&d)lx=-_w%Eu#ZI?I4{$h=sZIIo9 z51yz9(KtC30iswbaQ2kdvxGK~`m(CK^re!8nE1JNK-7+?W_0_?3U>DFlIr4-nONwk z=U--Zg9gh!)vBv77gY<*o48{`3pxT7$<5$_)lVy|Bb5lTl3KanZwR2JY=!vzozn5d zW2!0iGZ(1e+Rikgt5*SVG(t7Z6=m&NSCe@$MkLXNv`_y4EU-|UEz#49E>MbpZJ! zYr5xYuS?;H$5kIOA}e5??f|m**~}qKPxs9{_2#JaU{4RwdgFd$(QmxrcGJ|iOs5oVx1ol+Rvq4iwqyD#Al&S0(Kgdm_n3{A2aIZLY3)_(@RQzNEjl2L9d z-8r|&AFiIU<#5N?FO9LaV(uz@z0I0_zAJ6wM{ca3S`mA%o$sa4 zLBbRBb8d|53^%pw-_tdW;+~p}=LR8-2U6Y#p2HKBm8k@Ge%`9j7G*i2$sd)*{j{<}m? zJB+D}`Q2AzSHeBLkF+{$PWkgYT+Iv=yGN68pfzKbkGv3{5aIoxox9{$$Kz?sU{d~a2%sb#aew7)RtKMySS zMNjqSjm>6EihT(2(GP6q5qy=(65)O_DvbfZhN^sjT+*EQ?i6$3s=hc{%jLYwVM0td zL3D^vjG-jq>-*}gkNp-FIjLuyl~PwR+ZjT^cj_fq%P5za0*C6qX7`BnrM+CuZ#Feg zktQ>~px-rBIolvS{KiHMS&01oQi;vst=k~O%S<9f?(Ny+c+u@RVvs*9-pt-!BBmW9 zuwqQwxj~gR(QbXzRbNW?<{7{OLu-!i{>H{NJ$QD(XPMR8<3#S&psh~gXSRNy0vGX9 zf6rbPB0h9yUm;ZU-msXCeX?KS_b{a~L7quemWY=5_~P=nxMhv**21#N91|tY#~w$! zw2qqIsJs<09Baw`>C6VkFz?;Rb@4+@qavPwo$saHmlE#TwRsMj+0HT;Ltj45B+98e zqz(``?@|}7FIn34Kbk4sG=E(1W|95QtAjUAC4ri&p8aCrR^FVEtbit?YObl>%PWU4 z#xV`9gnRwrR&ZS&9On^I$%j=aytoo2Qwq(YpAZawYV|jhCw zpbAuh8=YMClO3)w#LErIp4j2Fx{I!cpw0z7$b6Jz0_8zHrs(V`r^laAe@ZXiMHE>o z{G*Bd!F&e-`mZMPamS9!MmG;xTRFL!3hHssk#W{_l~MyX4!*bbrimq|mP7jEp-~)J zk5x(SThM!sv(uzRxWOa3%e@w;%)U7y@zvi!c~(kM&BLXQTLFqmQKd~Qh6ni~;9-;3 z2uGXh3G1Ad8fn2=NkNrHzT0LmZB6T{g?eq0-$rzPcu<b zn~tkWCr9m&_NNgG(4^XKQV zh`yJa0q~#zc43)r8@*ZLP2E?rNu&eg+1D4M1=DI*D1i}`eg*xg&}wp#Whi#<_O=n= zdABgyl?ZFT;|N0wy(g75jI!X|sB&C5$>w={E+k*ElfM}jhhFqLbfTa&uJGjH&@6=- z^U~DsjH>L6*lP=4NuF3)Iu|Nn>Fn<@`S$k?8lEU2E;9ehaIGsN-IY;hY|aK^{`J!) Q8jK=HGQt1nxh7iw2VZ-3kN^Mx diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/9.ogg deleted file mode 100644 index e088c868f23e9ceaae603ccd8bd172e201b86347..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2484 zcmY*a3pf+%8#i0ct>a!O8)lRk;vkoh5;7wbwnES~uTY-jKY`6!c{-l$2i`xFs%)2xINB`` zhmQ!343E6-J%A`0+ zb-Ck|PdD8rip&Wq&ixxn3)JM#r`vTcytPjL#t{!u1^ZZcJ=sX6a^DG?;Rwf|8rYS4 z^`}^*1WQxsn?J?VYerlEaA%iW1S3F$hFAJvT?g!Qt&Wwqkjjy&OKKbXXUukXE2Vc% zq5&H`+Bu7Z-eL-?n^^lAPN!|}AIVp@r+0B)~F}l6%n-WQp$B8|{vsOE60jV6eu=I!UNf#)mH`QRV;ng{L zYz%zQds@)BEc&f7TZJ8!J;-k&b_eNvg|8rW>i~|R2+c?XM+zM-(}ZQ;voA;yI>|g@ z(UcT7xa6g81T5^LBrIpUB#St%)l1pO%e5C6m?1XY4=bWzB)bfm-DmF1h#WTfn4G86 z*Pcn{sA*e>X9^ec8#<3+e6{$ph|Mrdx2rF(VBz#B903l?lMzC;A%FR1d7NvAy=f9Z zNA*2Ad%7IY&Z;7zJIf!p6s$vFc_7S{4(Wj1%jTagC5;_ob{5*bCj-j|hey)>++5Ps zV=5cnDJ*JGW^Wk@M$-E9B)1cH@#_ zDcH}t&2pu{0biwLRIEnI1(f5_UVNy;&l8u%9WEB4UVjZ|?Y%tLxeB2$KbW{+-X*O% zOR2=N5n)^3d7rAnU6tE*D|(p&g+Q2fn8fjh=&Xu^^u|CA zj-UWR}qFqHhc2e$OHkGROs?mHgP&WJp!>p-&;!adUtt*+X8OukGPR(vA&#VYZ zf{3Ty;Jv6SP4&F=w};JM4#zVoHs-!avgmduwgRYh^A}x5HCEY7D##U4PxE+-Qv9r(KIGnInrv(2h+Agu z-L~+|Khz{>+f5GepCrZOQ?Ph8Z47#~ApClhQG;WuxTp3A}41x1%ibAsi z%r^F-_Qt8_4kTSSVWgi3FpL;6WzqV_7Lm3@dEi$hYHO}nSQ-}=H!7rGiy6L36kn1% z*nTUPDo$(t6B=^eeMn6hZu)pyPAtc`eO2YDeEDJ6g}U8UgU6b6yvhQnu^#`F;v%*a zSN75vT2f|U??)%$4Xzpn?-_owq0Me|iw=0R>*~TwQ)UuXIuCYme?4^$H%i7%++>D8tDs$Am{-m0#jS zG9kHt2)WAp4DoFiFYtl7o)S-YY|fwgT%qxLR9CInS(X2Z>_W_gU;&-;l~d}Li%-KV zFRi;8%`3WFOGn@9B(t6nQ^a;BTG;)&@4Iqk&J8z+^>?n1`{>%aSFp#VGL15S6T0;)A+)XzoQKUS4hfp$PkH zTT_;^gVd<)^WDeuu457dClDdynQXO!bZrYcOis^jl=cq}|bLQd(z8?a5#P z9VU(dRcQ&ybK(k~`1~7sPLDbiM5lz_PaHcV zxPBfSrvQWcO$$GI<33`X>K$sP8IoO1P3`TN ze?4h5c8}u>tMCoW;SOPYDJ&XW4X=BjngQsAPuj( zf$<-}N4wjCJU+BY$Gtj|?t~S`A9Y)h*75{_yb|`{j9-m=VUE|nz1yZ+>{ROFfEw8M zFHTG!hw)c=JYZ@MRQFhd5l1B$_n4eH4eZvT`%O-+uy!L%dBR#otFx8YUxw`&9;_BRRI(UI?A~W!m)ArSCtENEYxxKlvg@ZS+$7)Iw%}pesE=vy z*%n_J;2oEaEDhVKO@U`t>~0(o+!NE?XrDW*{g8!+y8iC diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/activation.ogg deleted file mode 100644 index a46876763ff4d79cf067afdaca94f0079713140e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17124 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/language.json deleted file mode 100644 index 11224a66..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "id-ID" - }, - "strings": { - "WARNING": "Peringatan", - "INFO": "Informasi", - "ERROR": "Kesalahan", - "VERSION": "Versi ", - "LOADING_PROTOCOL": "Menghubungkan ke server...", - "INITIALIZING": "Menginisialisasi...", - "PIN_ERROR": "Silakan masukkan kartu SIM", - "REG_ERROR": "Tidak dapat mengakses jaringan, periksa status kartu data", - "DETECTING_MODULE": "Mendeteksi modul...", - "REGISTERING_NETWORK": "Menunggu jaringan...", - "CHECKING_NEW_VERSION": "Memeriksa versi baru...", - "CHECK_NEW_VERSION_FAILED": "Pemeriksaan versi baru gagal, mencoba lagi dalam %d detik: %s", - "SWITCH_TO_WIFI_NETWORK": "Beralih ke Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Beralih ke 4G...", - "STANDBY": "Siaga", - "CONNECT_TO": "Hubungkan ke ", - "CONNECTING": "Menghubungkan...", - "CONNECTED_TO": "Terhubung ke ", - "LISTENING": "Mendengarkan...", - "SPEAKING": "Berbicara...", - "SERVER_NOT_FOUND": "Mencari layanan yang tersedia", - "SERVER_NOT_CONNECTED": "Tidak dapat terhubung ke layanan, coba lagi nanti", - "SERVER_TIMEOUT": "Waktu respons habis", - "SERVER_ERROR": "Pengiriman gagal, periksa jaringan", - "CONNECT_TO_HOTSPOT": "Hubungkan ponsel ke hotspot ", - "ACCESS_VIA_BROWSER": ",akses melalui browser ", - "WIFI_CONFIG_MODE": "Mode konfigurasi jaringan", - "ENTERING_WIFI_CONFIG_MODE": "Memasuki mode konfigurasi jaringan...", - "SCANNING_WIFI": "Memindai Wi-Fi...", - "NEW_VERSION": "Versi baru ", - "OTA_UPGRADE": "Pembaruan OTA", - "UPGRADING": "Memperbarui sistem...", - "UPGRADE_FAILED": "Pembaruan gagal", - "ACTIVATION": "Aktivasi perangkat", - "BATTERY_LOW": "Baterai lemah", - "BATTERY_CHARGING": "Mengisi", - "BATTERY_FULL": "Baterai penuh", - "BATTERY_NEED_CHARGE": "Baterai lemah, silakan isi", - "VOLUME": "Volume ", - "MUTED": "Bisu", - "MAX_VOLUME": "Volume maksimum", - "RTC_MODE_OFF": "AEC mati", - "RTC_MODE_ON": "AEC nyala", - "DOWNLOAD_ASSETS_FAILED": "Gagal mengunduh aset", - "LOADING_ASSETS": "Memuat aset...", - "PLEASE_WAIT": "Mohon tunggu...", - "FOUND_NEW_ASSETS": "Ditemukan aset baru: %s", - "HELLO_MY_FRIEND": "Halo, teman saya!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/upgrade.ogg deleted file mode 100644 index cc2557aeaf23b10117a7e05b3f75be53cc137943..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3823 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 aQpf+W>CAio!;<`evH5a)|6)mA&;J4CRwX$A diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/welcome.ogg deleted file mode 100644 index 57beac6defc567db0096fa114655f8ed5a6cb415..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2537 zcmY*a2{;to8pe>lNaCl-GGs_7VaSq@E4A>Zwjh)tIgQsQveLaKNf&U~vU(e>TZ9nn;rGjrZTZjhw_y%6R z;_n{e9}*C725s|X=?_7Ni^{%3PIy)78-1=n2)4M#Bc*N#gY+vb@0KJ+8c`M z6MglVrN~fx`G|2BI<(M;Cr!f(g99C-T*#^hyZxLj^HbG+u^L6-30W;|(N+p8NT$WB z?4)qcrt?rBq00H-rG+rp!MQT50RQgNwQ-6vhb=)*Seha;!5N=u4ZYl6X8itJ)0Pv# z>wEL$1eN%*=L-fWE5+8NnoXi3XR`_JM zI1trx7bQRT6*Z7q*sCUEMM7kj>U{<>OW69I=W?@p2TX2NFIeG_wU3W?4Sn|{26r4p zW}PylacZ5Zv)@{Jwed=?!%1h;vJjtc+R+Edr;}F&CEWBpk}tK3Sbccj38ykeIG}z- zDUVS6biJQGx{uVd$TK0*NB0(HF07UISZ`JphBReNjg?Cy7_ytN!&ufz!h`2bAtf*d zCns&>K|AOz>R5QHJa;h(MYvd(ifVu!%d*fY=ocAr$u*JZ`Jr7tKrN)iqF7;(*tH!7Ic=SU4LT$cw5tj_%ABR zW9am=gdskJ7dp2bWpQ9Rc5XN-4xs{6XTH)TX%*t(jUR7D_vf3enZ}Az#yM{0&wPAz z9K2hgtOhHzN|AV7{mv?@$em=6*7>EwMmI=k!i`X^>|T--LRm@J5w0%S~dMQ5En z<6uaF8*?ypEC`=nMU2N-WfH$s#c>n>-p-uaG(b}tl8E?WA8TM39mN&HSuy(!xv6|K z$BCg>E%+A(r=Uau4lKicWDi@gO3j%w^F65UQqRl%5`)0kgTtmc7kYQQ=Rt}-ea;KR zphJ5k&Un$ zE&hK8WNmJr{R0{dfND%Qb^&}* zitR~Nz6>$L*RO+&lyZU)U}P-2KFE^qT;&V@n0MI%$n^{~>zHR-)$&n0edo?X&#xQa z2gtMK=`~KCgin9d2e(vo|E3{nIOa>xc*5Vsl538! z{JDrd#on4W0~S94p-rk4L!!#Y-@uZE{TOJSr)TK+RU~5rEN_;=s7S75SHTn2xr_>= zk@6>LjZ%uc^%={eh8HfWLG9^V{#McI(&CWq1%b+?3=`Cf@de2{iFyN6&Te4!gJ4^m zgnAlCjPUz_ zFSOry|LLUw_B`isg~A)^pbNdIqq;A1S(&2u%)x{l^USzqDs^g`OTySvYBFFb^kd{; znv2m|L+a;S7_Pozqn9$nVue!Q7HU3NcRfVJo=kQeT{jEP^}pWEsp`_E2-k|jLY*Ov z&3T5E-cwmii2;N6Te?@_nd8cS*$lq*HAJ0g6BRl0#?jvBEd z{;Kb~wlXd;o?|=^wAqhvt7KWIaLtew#e2t=Z1pAptwGWJ_hiA R{{Nu&HX!W4|8UtJ6N&5!^9 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/id-ID/wificonfig.ogg deleted file mode 100644 index 477acddd0e3f95b6a5d5cc04d92ac137bd2824f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8706 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 RCp!NB_y6B*W)O*+1^}Upoe%&3 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/2.ogg deleted file mode 100644 index 3d7995aca4a9a94cb99ce10cbb36ca05b95b24c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1436 zcmZ{idpHw%7{?9GExDHtP8f@pvBQ{K!XcuDxikuM85xb-B1#*j5Mw5{5>i5U8dl?x zNea0wjgz~XGE-!(XFBIO|DEq2zsvjmyx-^dd!82=5`q#E7W!8rbuSEdjvj259zX#Z z85`{oj0pk&5P+65zYydO{-1VmfZ%51cf!?7h>99goLNs=nZfcTD?VwxtK%=kbg5j5q`h*v?SSj8I@)%l1tx!6ml7Q|hx&l9 z^amOV=`40tC^FM-SwP)RuAn3VR8R9iS^l{85=?G`i0kPGmlw{i>8keS*JE)+ZS5L! zt$oIeAF*_nq#dc7!96+0)5pS19QLa`!h?zjCDJ3utSqbTxo?+UO4N$2dH8B+RaY^qhH%2n~8zkEOtHsfC)%Q#u8-vGd3&Rl(0o=oW`SL9Q zNqrpg;K7PCme^gg_`8Rx*M&J&@#~P{`!{?$9ddd*dNwn7kY!`#ImII0k2_8;)}9PZ zHloq(w;`;DV94c+n{_@LQNSRlgzI_FYt7>A0~4XWuhdtvDXM{?E6GkJgJDqFslMMw zoz@1;e|yv-Gn|bQConz9?{P%%L0Zx4?l&i797j1(M`5S-@kQz8C{B4Yt-qBYa3^>k zvF0rLE_n~l+Lx?1h}ZRR<%2-<3wHj8_#C#6UqJ)=8nI8swt()vdz$jffClDGJ^M6c zNK=dAX2&I#fF-mV8Yv;>txJXV)fMmQJRDI&o3>9vom{W9QC2UfRsP*%z|;&0vy)v7 zR#@+UoSW);zJr?HT7`GjZA>G+ASk=vwz0F|xP=Mj)XI|LuKt|J(jP99lfJi52~VHpmYai)kI4{qv3 z!=~g%q1{p$%kK00@sk>xD!F-a_57|N0WF1_*fig&aJY-r0Er5DR#pndi5NUQ4gi3#tJ zR=ZLq8bsZ*w|EejlY(7S@Jeoo|2^LZ-Q#oHnES2Jh(zdcmlRBlR`Z6n0`0(jUU*X* z^Q;YS(}rQ2IYvofGrs_B5Y#24s*a0R4x)f2tQ1KjL<51>VrQLSRmeSepl5w#Tv*CR zMedbeqH-3quHflx@$pLQid4vB^qBB5ZePR&;XmYzQcaD%yM)%$y`rStfbcVh-e$V%jg$P54q!fKBar@LQ>7~x}P;DrS zscTCGwxp+4rTN?lSFHWqaMR-@NqSGZwrokE9zt(nm4h?gpEYx$t;loKOfVywd3=ur zPtvv<-Qf+^(cbS6Ts)LK94b9pId&(Oxmwgtwsez60q-eaLRiF%*~ajLQe++P_Vi~K zHqX+ZtsAL}g)&1$=D+WS2F6{Aeh^ Zi|~Y!na{Cw`&_xbwY|j>*;)U8{~L2zt$hFh diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/3.ogg deleted file mode 100644 index b22ad1e46226013cef707b2c74129e2410262a47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1302 zcmeZIPY-5bVt@ii{z)@H%xxP4`x%A(3rdSUQWH}c87&wO#DbOhgOtMoNI4^rSD!m? zJ)P*- zBiLY;s5L-!KmalrvtZVC9Tw0Xj68__Pm%BU-|WU8fpU$VLQwLmy?OLnt@`d-O* zyX3BmUwTlo>QJs#Z@ZhAi&C<}h1ITwk2FubQlGo0dIfK+<<@r}qw*_)rdE5zy77N% zyRTR7wM@>Y;BxWN8{dizUTiPgqvU+?uwKvw{-low7BkdWPjA`B7e4#%#5-4%9ry0s z%ev!CaCq^Br`gRaN_$LheQ$oUV$0*3_hkcDC|j1#^`D%+;7h^5IKbPF-!m7 zQ*yepRMeO6_vcPi*(c6F0v8qU2-4?MOn#iOLQl}>rBvA-?>p?dbvvFgZtRR@PLluX z=5}yhjc1l|(UP!Zj1yNEw3r;fo!zXYwrA1$nO|?lmpW*?4_({wF8*qam3RSPlDjmU zLz&&SgVQ!^?#VFxyjAb~+=t%j=Y%rVvgK7ncb|cwteH{W!JMkUA<~HoBL)n zac!Dw{lb50&|enbgTF+TC!cta&{#1-L@aw_KIpVOh7VRb=g( z8;X&fZNJXWm$)ePizn~x{Xa~RoE^6dAKkDQJC%NP$-5J-XZqT*n}q~8J0{;)u{E3} zbPMaOhLep}>-TYXOo`!ldC$#jb86icMUO1bDJ4O+KTFq1-ktD>dxh2$gPAk4n+13| z8`SUeMtuxbbf}DJRpt%l$o_bK-D}<>38y>$d}lvddE#XFfrVFoRTu2dZsz4h2w2QL z2H|X95xh@ib{mj$(fXm4pPuibl}F}$i39otqB`pTj)+J0dmB2JIpxB%pMSX^qXx?P zw-~I8kaPlhDCXY&h%5`_A?bW3i0Xz9hRALJ@{rX23jA~i04LvH A(EtDd diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/4.ogg deleted file mode 100644 index ef01a46eaad3c47d81320e9cd27327c9f0afe3f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1404 zcmeZIPY-5bVt@kG7LNHKCa3Y51&qS}1*OFvsfj6!j24UsV!=xMLCWC(q?{4RyRl`- zbVgf{@{q*zVjiG~Phwe`nW3J!o}qyONQEpAr{*Q+r=%9y0_Bo{a)y>bNkfI4%%psv zMzFyw({=;Z0RhNhkfR<%#yk-$EGY@gD#^=rv$iqN*Wuvc$Zl3sZ_bNvt=YTv!{3UT zb2l$cS`jqq#8;GBvD1)8fq61O_dt2jGmLwx_G^|x7W zWH+m*?U}-q;Ac6_WnpK@qRTgglP;F6^g6aXZk^HnDIc^#JxgRN=bP<$JLB1BbLWnq zn>-nNKU|SL7j?pzIdcyGImNGYue3L+uQ|fpQ+adGJl%N)Gk0ISwW;OKi|qnIAHHUM zJ|^Pp+u?RTfN447_T#K)BksP>ZdO*?Q#xm_*5?HMy6=ZRNN;gm8Rft5oaaulX1>c? zXT4!xeVl#U{ypX88(%;Cq*u-HMRJ&9w6tT{r*v>7{WlbNS8ijZ-GP+VHn}(m%V@accl7nXjIC*WtGl*)b9xz6&z%izb%&zCAXJttNh z>h78s!FX!*`V4Wl>}DmU&6;;UWnM}x^Rp}0*u2VmrmteMO@Lp+-uB~D>KwY$n`kb0#;#*@Q~n!BA>#CK_h zGbAkGndo_LSNOinZ44Uc9u&q_{>W~Y6JNjWb7J-pZ7$U3v>nKJ8f0 zuNt)7R8Vf$cZqbf%EFk^yS}qeZ#*zP-*GKh$$0(0A zq$01`Gx)b|b~CRa$NI{nix?HoY0r{>aE4=D?(tcxrk;?P!F)hjxxP4?Bl`nul+ES| zPdvV^`*be5nUA0SWaWvI;RhC8Wm35BrHA0jyb(Mt2IVdiQl2XK;Y2nwg1<8G!wCd$ TbK!?GD7+K5ng9O-L3A1b&u)yP diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/5.ogg deleted file mode 100644 index d240b88dce0908b675dea03cde8b85fd4a84c32e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1607 zcmY+92{7Af7{(pd3U$|gi&EmKaYY(jw2FxYX=cjyN-mkb=A=&J;YHJ zLlTru#aZiW#Wm^(rPQ#irL}*Zoo)Kgd^6wkJ-_#P-wzQQ>dwW(^joZ#r2F+sr?OTfDccm`&GX`m7r9vA~O{s=xn>Hs*Pj)RYv+D$@Ch{a=KB4ZP= zm`E#gGZP)4P&jps4BuI4`gjoNvI^AhfV3woTUvZ{v13Nfz^mE$5&F~JBjdPzJR0xF zLU;)6C3^MlZ&|M`oH6`Xc+qH+hSnv^sgn6> zq~Jhdh|>B4Tg5Vr`wjXSy2sJ+LU+H!RvI{8SE9VnTzkVz$*nCsEsJjERxWNSmcS(< z(Fxh7rsmx0nrNVprF|$8BD>wuf6JwK|J5vF28B}v(^b7EW7mtdU**j$@6KiUHk@YG9T^11*jbYUw!5L#S8uZ8>WMSZwO4hk2}*3ZC}UO(_P0jiG{CeH$Z+}K=fcr9l-a*p zzQ86wW*eqsv3Q$hX4zw5LkoE;XU~}sn%!DXm8#s_T(b~?qU`c5!dr$m8QF7W7d+Jf zB{IVl%thNx2FN1`Ct5?(WS9P+FV~ZNqjKQ_DV3gb?Yo563&1QjYPvvQGxgGUH|ZN? zY9udN$tsMCP4m6(rgyA)Q|sz(G)2` znPJN}>416p{_dIQ#DV7og}|>6r?R0~vFVblEvbVAzbiNNeyy`ROsf$YM)5Y)WOR=) z$Vb`VWSPDSitr4RYu4GL2bdUKW_eH-4sz?X$b9L(54jv;*N*Mm7v;4&R3gA#Z|_F0 z;uDc08V+sL_U8!~aGozu3}V4l!6!p*{a8`=Nf1On?ICj+vIf6D6BzVN%w7;8_*8Z0 z1^*X9g*^(VsYwGhZePt`x$SN9OmOoR^3M+EItA$7n2$a?VH2Cj)dk+6!K+U#wik%w zs6psYVR6{d?7@vuFY6_ z^8}?k$jVg2DrdCr<~b8p6z;4hO@mM}>{Vm7m50$FBb7ob=FdlGN6t4?i7>P*7&mxz zxoo=fI}UYq7d7)bd$iT;O82K$GU9s4!~&k}4Jm2Fgo2!mKJsL<`GQa<+qK!J>+XZA z6c6`vZWoP|Bn4N(>&po7ct4-|B;b=^yrg-~jE4-hvE-l4+&D9%Qe@|v^pzzk z#Rdq4g{5eN-*a!t_vjNBM~zh0it}($0o!(ileVzI^HY$l*f|h-Tl~to+IvR_mD&gV6qknS;hoS2-@79-qmD>_PoQv8!u+{p z_3F%HZ%1UGr5oH)m1GH&fSGVf2v1DFbfnfr{;8@AfXmNJwQP@ o*%xt~E}%Ga=|#|Aa^JMTIFbOx!H$mqx&xp&T-GjUC!nDJ0&P>@f&c&j diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/6.ogg deleted file mode 100644 index c52a2d7d94d0523613e0b699b7920def520fbc6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1457 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 B)NKF& diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/8.ogg deleted file mode 100644 index acd19e896e1d827bdcbc6b33474991d7d9c77316..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/activation.ogg deleted file mode 100644 index 6381325919b761ebc2e9e887cf27da4616c64279..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12274 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 CyL^NI diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_pin.ogg deleted file mode 100644 index 3fb7107a54718f310d960c7d77296279739f06f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3023 zcmY+G2RNJU8prJzwf8ECU8*HYN>KBlW{p&BqC#Sin5AN?)mT+Ujn;@!)QA|hsc5Ou zR8=WOmDZ^7DNcOfxz6diuj{?u_y7KX_cPw>eV+R<^YE~wprZIsghfk=JTUSwUV!Ug7H1 zb3&MWx%;^J!rcSZ$(|e8Q@Bnx6+}^>~<(0Zs{BZexQz{fk*1Z&`u~+g(vWbaZ1>L61Zm8 zs_&PuMQ+q=$Hx_+8Dtw&H4&m64z`r2-kNT77Uz?n)>O0n>mR3<)Wi=Q_q37EkQgyh zLV%*I5Caj}G#j3o8uY_sK*VI=0zo7GU8%P=h1X!xhdKnoJbxfLuHv(7oh9r*?be=? zkQhlZf|-Ls_Ob}1pb#k?^|+31)+kdr!wt6-OsSr)MifL>kH#?RW_MD%Oi>hDP6Hed zRO`6)=MqBhxac`Voc8|$r$;4gCww$s$XE7@qfaevo;g_X^gH>@_Oez&H{i_~k~Bp? zXFOezqeEiEL3xV%9HLA6s1YIDaZ@>DCk;ve%M0tJRIK#!T5ScZfR|w}JXi5&QSqn; z|JO|i8n=g1uNn*vpk{g=en58iDL)l(T!C+HxieDAWRZX{{|4s*n$~)?I~qxClOo^iCxC1oFRGY`wRk~4sG@@aIhA6vJ)bP?NISW__)C? z`rnej9)KuW#YbT-?rte_3Yo#qPDqS|C?Py&)fyn*u@G9qyi}&34ZI;2Ok(;X9cryx zcD+fjxDs)aDA_5$a+XsSw!YImn;ZO7nW!acYV~2emNq@jt+<4T@khRmGbyY76U^#Y z`-_-Svu`B$Ph!$~lfAS?tSznS6nuK86Nv#z=HIHh?)gQ`rQ~=vt2H|i1>voD{q$|O zmYB8F0lWWu9a7#P`i&A?;LD;{I3mJQ3&3Z8EhME)T(sc(P}xYeb?cpV;m|7;`Kl!# zOJ*603E=AW{sy5}6E$L%(6RmDpUtezsYjyMg2|mpisfwpXQ17I(Q0EU58ARnH-^I7 zvm=RA(#5jknHyTBsXZpj!jf0>d4>`hjUa*{zc&_{L{l%NjaR4HW9f=}3WHtYCqUQR zC1Aot00>?Tjx`wT+n49CYTJtp5SO*`9b*EBLsh{jzNR(90M>&$#vWT2`shl*h7E}kl^{%1 z^$b)sWhaaz`z?*pUWypkEoZ#4&UnSxEku@j^RSb9uEoRaN;0y8W=i)g+B-Y)U|$=y zC}bc(tD%+R^l>$FW|BLv@g}ex@Mx_Hy3Ir|!699PlFCGOE8c4HhYR@xY)e@HP;%8H zwn&VKRPJV&hYTNIWc`V?7c#tcT(&7a@bJv@3VC;?cd^*-rXSNXL=H0@~sm&oI zrEeY>4?T-EI-3MS@O-JOy}cQY7mw*&d#F6|wzcLel{3@7n$dRsG_Eze7(0EIJ8jkE zB_MTwx^I){oc!t*dQ-+`aAxVR*n&<5TrpD?X9dq=R`drx^AMaU_m}t_nv)Bv`%Pm{ro$q-HczqlU6wekir@B{2cu#jk zNLxl?=BYL3*_%PH9ad9NmZ;*1gg3q*(}FHqY1QJ+wJq?=@& zT#;VBq+ID1g+$xF5>egl2usZ+Jsl$7aURVh;@{Plh7NjOn*XV`)a1Kk z&7i>rZ$H1gzA&(Xs+^qM`Rs}mqcYxk^+*nvW?<&LR_`(j2F2P=k)C$3njHSjF zpS}5OUD2q6bopB|jwv78I`GuAxqr5^DJ9uX2`mutV8t zd&3}S)Ywa&B5{4Jy|-9SUCQv{ruj)3je!n_rM-ga;q^uxyjyutO>1xL!9vs@p2#9Zl||mXh~Q1__UNoi)agz-AGJ85lnat z7fBp5QjO2#9^QC1ieF>GKV-ZIgtQ?s>}-r+^e(D}E2dIJf+OBL0P&R`5tp7n?5J#o zdmgWqXAuP$N*m6q4B9unKc_Ass6!|)gNq?mFoYoWc`QR6!d2%Swa2{;;@4V diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/err_reg.ogg deleted file mode 100644 index 3bbe56ed218adc690742b1243aae7bb30fcd6ff6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8416 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/language.json deleted file mode 100644 index 54cc9bcc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "it-IT" - }, - "strings": { - "WARNING": "Avviso", - "INFO": "Informazione", - "ERROR": "Errore", - "VERSION": "Versione ", - "LOADING_PROTOCOL": "Connessione al server...", - "INITIALIZING": "Inizializzazione...", - "PIN_ERROR": "Inserire la scheda SIM", - "REG_ERROR": "Impossibile accedere alla rete, controllare lo stato della scheda dati", - "DETECTING_MODULE": "Rilevamento modulo...", - "REGISTERING_NETWORK": "In attesa della rete...", - "CHECKING_NEW_VERSION": "Controllo nuova versione...", - "CHECK_NEW_VERSION_FAILED": "Controllo nuova versione fallito, riprovo tra %d secondi: %s", - "SWITCH_TO_WIFI_NETWORK": "Passaggio a Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Passaggio a 4G...", - "STANDBY": "In attesa", - "CONNECT_TO": "Connetti a ", - "CONNECTING": "Connessione...", - "CONNECTED_TO": "Connesso a ", - "LISTENING": "In ascolto...", - "SPEAKING": "Parlando...", - "SERVER_NOT_FOUND": "Ricerca servizio disponibile", - "SERVER_NOT_CONNECTED": "Impossibile connettersi al servizio, riprovare più tardi", - "SERVER_TIMEOUT": "Timeout risposta", - "SERVER_ERROR": "Invio fallito, controllare la rete", - "CONNECT_TO_HOTSPOT": "Connetti telefono al hotspot ", - "ACCESS_VIA_BROWSER": ",accedi tramite browser ", - "WIFI_CONFIG_MODE": "Modalità configurazione rete", - "ENTERING_WIFI_CONFIG_MODE": "Entrata in modalità configurazione rete...", - "SCANNING_WIFI": "Scansione Wi-Fi...", - "NEW_VERSION": "Nuova versione ", - "OTA_UPGRADE": "Aggiornamento OTA", - "UPGRADING": "Aggiornamento sistema...", - "UPGRADE_FAILED": "Aggiornamento fallito", - "ACTIVATION": "Attivazione dispositivo", - "BATTERY_LOW": "Batteria scarica", - "BATTERY_CHARGING": "In carica", - "BATTERY_FULL": "Batteria piena", - "BATTERY_NEED_CHARGE": "Batteria scarica, ricaricare", - "VOLUME": "Volume ", - "MUTED": "Silenziato", - "MAX_VOLUME": "Volume massimo", - "RTC_MODE_OFF": "AEC disattivato", - "RTC_MODE_ON": "AEC attivato", - "DOWNLOAD_ASSETS_FAILED": "Impossibile scaricare le risorse", - "LOADING_ASSETS": "Caricamento risorse...", - "PLEASE_WAIT": "Attendere prego...", - "FOUND_NEW_ASSETS": "Trovate nuove risorse: %s", - "HELLO_MY_FRIEND": "Ciao, amico mio!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/upgrade.ogg deleted file mode 100644 index 79c0048eeaa82ede5b3f8a38311eecc8c1e09aa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4059 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 Yiif9A){wRmsZ~4_?qBqM`TyGg0H9o^7XSbN diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/welcome.ogg deleted file mode 100644 index 702def379c0ca73c585ac9014dc91445f0de59bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3063 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/it-IT/wificonfig.ogg deleted file mode 100644 index 7aae624eb9a77ae90793e4d4ebe113c80078238f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5995 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 wj^1z|Blglp3IulIFymv8Ia&6S{dR|C zg9FLCMnp%Uu>nCKkST~@{vC1M$N$ql4iZlKJA4wzY#+x2;G(338>fJnU}L17i5}9x zV4pZCEbNWI@E~lYna~RqdPtPeL_)9QuZ9Z`zXywF(S)2(`@#E9g~}uykh3z23G)g6 znRvcOkrJw+aDXOOjZo*jMC?wL=Ua;tRzOapc%_7I)m1UO^|0eaLXt6AKeyEv2i-W zxGC1IV4w}cOx)4(08#Hg>(ldyaab1rthq<4n4{ai^t`+dR#R-SQ7GoNUYQO8h;zmh z8H`}nbo|obFFFpe1i=9VC6k)u@dR-)3KF*Wo?PyImUU=e#$nNPed7c2)>KnMv7zB* z5?fR2MS=75T--|tXZuzPf$BT_6}-8ISRt~HyzWQcCIGV<=Vsv6>$&iY%5DRe4^Q^# zCg}J+Q?jGf`41>ZUi>l!fsdl0Sv(L+KxksawyWElyRF@1cq^|@G#(DO{e-+nk&t_& z%vB|#6Wwt?WUOfqWri$eTDe$&FdIW_`i+emSJ&g*Q>vRy`BW`yUT2V zrPy+Zi&YgQc$?`XKYHQjD`iq)f@#QCZd#W8mJ673y~M1BkvI4@!6twLGYJoJbx!sh zG{KJW#+-<3*;%fV=}q;~SMUjee=5Q7i6PEwBz!8quvgw>SURoDE-^uBXKSc04OnAK z(z!9>yXK0%WOS;oE{u5|d&f*(L>hmnBgZqa1)6uKoKo9baH;1eOMAF4JNOT@`oW({ zsprx|`lfaDG(HDL`jyMlJy^xfSQ z0*22doU(3x>&+mifv^|N);8-I0HKDUCj(_ZQt7nqz}tHy5qA3kM>U&DV{c#mHJ%vD z&rNxbMsc?*k)neYkCi5ejAfD1XLm6j8xd9}WHbllU08kU&EfT9H}aBvyaZbCOmnaW zAaNYRC`xPu#dWM%=SqfdXDD?6^|vQi=Pl{g{);oJY5JnidTZYxzeQ;%8WERbKU)|5 z^)5qh)QovXF{qn!Ce8v7PbqI0#prbVU0$`UPn{!sgsDF$AFrD^F8HW82 zY=zZ|kV_ES^tgr9daY!FKd?NsJ+#=IYQ7kB zXE~umM=I_~_Ev)}+mcMLjf`+nYc-EuQA^)GSbV1!rtqJjkDpE#CRa(`_hD*RjvVWM znH#dj2T$NAg8HJ}>OG|elCfPh6UoUpB F{{UxJvIPJD diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/2.ogg deleted file mode 100644 index f75a934a99c5db1f19823a415d4038bfac706a18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1203 zcmeZIPY-5bVt|77sgisk=G3lj_ZWr!3rdSUQWH}c87&wa?7&L=LCWC(q?{4Rn=w~2 zkryDXB%aK)Ga~oS`L9(oi8MGbtaa z5o|Ea@5MlMKmalrA>!eLzu6U%QAK~(ZE-v1cp?l5k!{U%PLb0!J zFzeqt)Gl2A)4;n;|2N~RBk6huwo|mOKACM{QB`2J|C(BSUgC#af9yAW*}ckESyEJQ zO^&5Z@y|PJQUdOqX3D%u%}M7NGU@^)eiUCjXt{d!htDMqX2~)^lBWHy zc{kYC^-C81<<5`&7r$o0%!k`U)=Zr1#AP;}_uKgz*_g12pZj+tJU`jh-y-lO(7yin ztS3J6Y%d5*hJ?O8=x!sbmPZB9}3LS0&4j`5wBSjCZbOZ~q8Qh_+7yoAJ~ z%QkIzXd~km`fT~u)=O_@WIk0+ZHRa`_0n>UEf!tMGh_;ab2WFaWLYMgl%rA@SfkP$ zF5P%??g-4Z$*7DhMBb(6nMf8D1Wzdv`i@9!^KYZl+BYi`SMkocdT_M~2PW?p6f8;j((9dW1X z72Je!XBs}zj9}gr`{4005#dnAka@j~KC1i+*SEx$hd#b~MfPybZFcJq4AWF5OpEyA zeg0I5=<$`VpL6rlcFF(D+*WY0Pr>O~Nkas)`?0XP8;(5MvQzxiCNy!UZtoPoAI>{v znKD}tL*aIh3f0N7THK%CTNhWvvg8XN5MFkq#Y09;$}09+#Q7T$%&vExzAj4O*s#B^ z;8IP2rT3=06V$a^+&{k${Jqz7W?b3-H0OYR(KQjuihr+_FN$E&JM#9Ip1h&{pEU)S zqy_A?R9;&*b~d$la1{L)eZHh|QFP~t*e?wE%XA_bzi1kKV2@CLb~a4Bqi=D@gW&K) zkMHZBcIFn(y3EjUezT;X%l~f1)rY+09%at>(02NFx&v6#6-=6wbp|c@^@l#xp*(7<^U+%q`I{gYEK3rdSUQWH}c87&wa?7&L=LCWC(q?{4R6KDIr zi_sROJR~u_mryDXB%aK)Ga~oS`L9(oi8MGbtaa z5o|C^&PJd*AOIN*a+GPr)2{;d?p2k^aVZ%d4tm-~TB4#6%p%8PZ+7zLJ085%xS`K= z-Od@s!50r4Zk7F)*d=Ma%k^~X{``&S?2fKYzU(1+e$t)}!NakEr^Vb(d^0hhu{1*2 zsqhrb+=W(KH*xAlN9nhBs5XQjWwnD1Gic{dh4+V=Q_!pfwzY4a|%*>3Dzv4Z2x{1Znt zJ$V~vh%CQf#a(*;vZ!Ty>7EM_Z!gN39Vnex*}cgpW}@ev1NV=2oRF3|^6l1|W`oC~ zk`*;`POh{xmM~m%YPP zenE9ug#Cvt%&h(qKh~|}k+gge@h+kCiC@l*+16sOJFNG9Vn5rdviZQ%hT5#M%}$JJ z7ysY>DQlhhUafPJ@8v&g0o6AbeGHjDN#8R+!)9yL1*KQpn625bp82P`USR)|P%q8t zzqsmKLT_*7-M%>8VxCIGTdPmfZ(H8Yde8E!W7>`F43d8)ELh{syL!i_`}!AUo`h3=|(f*~&+mWY|lPYsvW_k2_- zw}CHWONUOcWXftOwLMcVEx&ef&yE=ap{MKqT81k;eK(!=&I@zio8rH>-&_4}|7=df zx3;U~HlJlWQG9Fe=UoqqV$aX{u9EMuDT2LZhB${(p?~3Q)%iO&B(8kaU-feC1EaO? z&veD>@`QgePj|5TJ;833zzzL{YFc><&&}3l?uxC;bvDf6=#C1!R>-H!*tJR_f>|)t zKl-~Y|Es^*&0_ai_D_swKkC#VYwxh_MH2h@vSlwM7cjTE%w2P8jpqIQ3cYfJgLZ^lP}9L=ftfNxp$_!Cmv_}rmM3w?B(Z=8Ns<}CTe%rd_O3B zGlKDpromU8cZrrkwW(@mcGFnw4v6?Oe(7*GJjqrg;x8il^sM(seU7X9e`w84bdvE? z1?zaCZ)72E9kq&oYjuEKWmVU_f~8mb{=Z*Q^59F|$Ar20VWH=iEs0?K6jx+6NuKqW RdvB&rzXI3q-`WaT1p)aMTHOEu diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/4.ogg deleted file mode 100644 index a977c97767f83128ea319c25b8607065f3279bf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1372 zcmeZIPY-5bVt|6vFTI37%n;wG9!6pRg3@A-)Wj4Ul++?ypjN=R3Hx+zIYd01IIZN=J>_+-61Nk=#b>mIslIrZXtZy--krIn51aB=e{fRMul=;B zfY0GcT;(>Q{md*SH9o~NANg(1jd)k`_3f|nkNdus3r&1|sbZ49t!>%#Z_)YU6aR>A z`^~D4n({w;P|1_5ofWD z`EHqO!LbP+4U=!QJ&uuy*r~0vf4xVk&i(_+GC!-9XR}Ck6&(xn@3w4h;`MG8OzE2Z zanF<^eOC`!-U(-!&ggCEdN?WW;oVBc6Nz1)`jt$RUUNrZ-yhwOcU@rVuHF{MS=Ve8 zW<rb4Vf2$^WjL?E9b2uP&?%T-9s1`uX$?i8W@+ei|@6b`uinv#ozM zd&V%{+zY<=b-}GvcE?-9$z@nFK(~8K4HUr zyJ(A2kv!Szzx#fM*qdE*__`=J9q9DjIFMQ4)E#%?urhLXUx zwaRx}&+cc;2tIk9cN536ouTe^pC6_E{v1@NT*Gm!Q(q|g)B@>u`+bj1%n@3!{L=JS ze-5pv6I-_3cj1Gp-zGm^`Ty9f*`>|edjxG~t|&-mXPG0fD9%#jczBIf_y?8<_TJiO zznOeiMJwF;BzSSw{tuiY`|Imfr7zslxuKR=w`kJJ^Y5k`Z+;(n=%QrxHN!Xk6RIyv zXAJ-R@lb|z+A{mE*IV_3BADHer?DCA{m-^2`{xZ6yV6;S3NWjvzUkW1UgmH@ zc>N5U>rF+{uKTM`7~MGK^*ihQPlLi~XO;dj!~=7g;}&hH@GcLog;j^*Hx?etlCQDJ zG(YH7e$n-*p#Vp@h0wmh0;V3u3Cnlq{+hkda~gjylk}er5llaK%(WHqJ|G$L?b%EJ z9lLL@x^^VGD(8OU$$RUn?(l>Nn7%4X$UpkRNg;yqi>ASo%CglV3O6_Lw|#ZJzb?%& zUF4;Yrx=s)#lTEm?koS3=WnkSJNWuk3q1S7bIxp7ob|Z>CPa0@v@~+CXcG6$AjE C!gHSh diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/5.ogg deleted file mode 100644 index 52ccf1b05ffd2a6c05988cc4761584dfa1519042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1085 zcmeZIPY-5bVt|5mzjoXPF_)h6PGuDKFDNbcNKH&(WVB#xumdac2PuaGka9*K&+1>p zPDWdh@{q*zVjiG~Phwe`nW3J!o}qyONQEpAr{*Q+r=%9y0_Bo{a)y>bNkfI4%%psv zMzFywesh58fB*!mFibgPKWeCq-;PO6bZe{WLqaUPF zH!2&*Klr&wgG1OqfAtLpg>`EBf#aX~5U%M-0tl4ot_ zO*?khktw38QR}(;?Z)rDe|HMn9@y|%r)xLsbNlO76I$mjj(+B+w$tWT#<}-~p7QlK zwoiQ?-?P@W=1)kZY{2Qbj=&>K4liVN)<3n0cLMy%Sw| zAYLeHclqI}|9980Cq2rjIll0N&b&L%wpuy=K5^7%(woOCCa?%Bb-NMJztBO7Z->bK zg*VJknv1O8Td=Hp(~7X(3-ip^L?2Nzi0|@c?u=Rft!_dDi^r3D-uH!FNSdbQz- zq~*nD&gLBlcc}N@K0L|S^=k6xe4CBQ7v$ZtENo61DGTdQ*#BmU)T|8xyrxNi8X}kl zQx{)$=bT#L(_yKw*r9>t=$&8Uf=Zfvz1MfCKK@)P_+dB4e7~tr797j;+h17vuj)_v z*9?gWW{xjsneN|BP56I~J>q<*_=`uc`zJo_@5$|H3HCYs_Oq|5iWSeEXF6_go_1R- z-0eI)y3fOPN(7VcN`og=yTsQTc~sl%nwKe;XyAA5O~{8E!Ou&!#7+;j`K;QsF@43{ z4`&-97{6#5JgH1zyP{_ObfrL4yLE_5ot)YW348b3=ZmI!TIuMRg#Oqj8eD3_Eb`p} zqWn6Oq}jE+xht++F8{ieC+O*uRfk_+UsD;TxJ>(a8Ap18w|C28v$vX$+q3u1&I!sY hNr+#xAcFBzT#?x%dDdUhwxkj{#(P-t8GzPO{h(Y8!42Jwl49ggi!C=;{NoEVV561mcjUri8 zE`=~Gq6<+%lF20w(<1lV4!dXn+UK0_Ip6nvKJRbCuEL?f#dOj;#Wn|7Y^X&-xu%S{jIH@J{1@`M%LIM zlrltA`BmlU;%x8w6~EmIX(tPmX7-RHOj$avzcHrA*~d+1xJ2s>tuR-S^P7ngYrHZp zdo;8$cT1ZE`2!JO(Jv*OMsPB1UCl-u`tB$Ina1n!;O5XGgu;V9;R2!-AV;7=+s$1k z!s+mKeOon|0N#PO91^wc7TS>6k`sfjK%A+9^Sjd!gt1~<6f|rYqKQ6+9UdKJsXm&* zpKB7>RaBgs!du8f%+*ir6nBN57kFR)I;*#S(c^P=6#3yjG7OWDD*vJ&Gf*cQoG-c2 z5m!_>O(D7(ZZMMG6r9b~l|rJ&6Ua~rSb@n+eFvvFVQXgh>$r?1VX@KiYB9C#FZdok zhMyXpjyBe1$-5z$))<`~Ko6+@&F@&JJ5F)nR_dy7ePttjdcuzj(6G!2_!X8Im|S z;Owuu884J3aALjwZMnX^TZ1ufRo#Xo624{Bf=-lS$N9^sEJxZEgYyIYR^2a@Vt$e7SbIYVFQD z<4>&FR_8@J9&t_R`j1WQ!X!1fPZ{|@{Oky4fc diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/7.ogg deleted file mode 100644 index e98be57366d5c7f4ad24e13f982d4689afd1fc58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1503 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/9.ogg deleted file mode 100644 index c150a18b1f9b258e87ceeb62175435416a15fcf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1565 zcmZvcc{J2}7{<*o*V51>%Y?~X8nVrq$qhrszD9E`XXZyyWQ?(gY+15Twy{LnCdwdW z4JWFxUy6z(kx=%s6r-5o-r?SJ|GLjP-*evY`+lDHynj7-GTEL7%=53DD5gmVrIIT( z0(1-?a4pD!NrXhLMy9`jz5_~U*(rqsj2IY_w2y;6-dmb{g>V`*NtP9^m1M`j7 zQajsA{DY50xvodpsuYG)%gzA2R`V%xtH+gU6Vc3lpXB-j8nQwk^v4$A1(owZ!C8n7)yg6mFiRbcSBE*FL^3vNPE^WUwa$r!T&s$e$I}h4Q9gE4l9K!i3^!R-FZaZrM$1QLp5A_rV3{`)eM4W1 znZ*2?#md+z{_I75NHQE|{Pd#C$jg;Ly-n`%QyS89epw_{f=J5xPEMN>QkAo1O}bE^ z=(L2~T-=&n)K%oSO!;`h!lU!0(lNL@Gy_~C0VB4f0;B`xkH_gi=iO*XW{26T_3$k8 zrGB>)^hxKLSDE2Gn33M$n(A?LrG-WL;w4~h(lP4X+3o3j3CQt4@)%6&^J;xl3N(R8@;78aYVTiC)FIr^ZvFv-mM$t*{+5SOyE^8SQzbW9}MvJ0G~ zvn|?N(q!R0{7s8bMhcpci_sogzArC zKi}G3hL%Y6&cD6%=9y3R-Qt{ST%&Jb4fFYVl)+ep-LTYvj!|#L_^qYt)=jqLco3Y9 zOmrQU^14hrBQQoDDct9c+{FbuRAt`FtDzh!wXtGQK|? zCDa;wRVwaXzf$%jquKAsPt0PD(Boq2-9_Yh6`NR7DRy63lB)C$Yzy}(9j8{;HDN;HLkXzR~`N;kH{wdfpegUpS5g-80<|f`X0o2;K#+Fb$b5a1j!5lj2fE6M;+> z3@WBLdvqsf=hT6iw)S^C8)C8I*h!TT15DS*Pgkd|>WK`RI8#({| zUEeWZ2p=ff(WK?7*+rS3;Lw9;khC(T$j-1>Pgfe^I0T_IaXY2kf;2NY1X5q~u;yW7 zC=so(ypLb9(%A5h#FkcXO%!?n;8WTYA1*yUwfu1BQ61>sW)C!Dcomo}l9jXqpx5t{ zqC9QFO$0V_j0^zKmNI(1&#Rvk-I3Y!o9`v@CGYgBS?_Ra;&h!~ahCzmXJWMky#u1; zz1fP4LsB%SC!ce>T-V%KJV^x2vfaZ=Gq68;kF-5_v0A`GQArgmN4E*{+x;GOU yI1H3@0HE(KftuNJkX`e1iW&_e#Ad4^4l|Yy)O#4QhZ)PuEvFab6hRXIYxornYqi?PoL?h zkB#rs$wp>pZQ}U3@qZJG^nS*D+JA}vdnnc!iFNd^;?98{_Wo9O##Zi*mTvBj02l-1 z=;9B`FRd*5Bd=(Cl;NAkoP;{QI^BC2f9%VZV9e3t&t8$I;#7ux>lXeZ-Hv+<^XFvl zA-5D*CaFjJB3r4T%P)s85u zOSIASXsiIHL)i6Z#SNq{H44unzz%eCGAH`B>Yf>1?WU)pim4-lJ{!vd8vnM$d%uXY z7#ZIkqcA7e+-xLoC9+Lsrm8`G9D=2&JH>BvoOAnExcB{#!p0}H`3@PBbx#aw)as{~ z6e07)uZmEFu>?6kKf(%->|MW#kq&_)&FYZ)5CI@MoHVFS>`~!onRwBZq;+et_>9uF zrZ|wBA$7G%fUA#Ir~UU=9)_?{-bOWl+z+&L#YtnIP>_p3&4H5> zoUxVhQe+`c;cQ8ddy-SS%(pNw9dPoRN|Fx*{d5{yb99_i?k3XrdF6#wPnnX82)7Jb zBj8-(T3kGsUbi~4s@@-Ko8QnQx|y=>2~qx+hQIx5_IcFt_q0VfdQp+sT{n~y6hzMb z6_!d6^MyF%D55~B7x9n%A)kDWpw*YZ@tRpxXuq+SFlR$3*6;VbOqnYf`gf;#z*|e} zNzh+sSSPfaDTN|KOul*nr`_Ox#4=)JZ{w>bRMvf#9}!~ur$R>!V-8pX=FFG%9Y9SA zakR^z_o%hnxZ)|6H%icBMIR?pzAegQJk%u9ZwM@vJr337SFnZ^w|QjDRgm&Q_1$0Q z9*FT#iuTo5-br;;GdnE-nOd31e4yz*o7i-I+2+@eodXXHCV3lmV2Fsp6ro!kSdy^?j?jC(5N6HqNq<4 zXfwq^Rn8ntoyTL42!?M&qH!1E--d_$+eY8e#*?3kz%`5qD?^~_c?US9h*V-?d^}aT z(?3`(gN@0l=Rpu0NUn?O_M}5mk@6T0?Wnnz@9tC%qk|?3_F$*e!aQRYr{bu^)jur7 zkVc2iFQ(mS;QZOkx(cf=upPL#mrfS!X3!;A8?MsOb-egvF!inL+(FeoVGTGJFE&cH zN!xbtj&1CitVxhP$LEvi$ed@zI&q1iUgR1oHsUt?}4W}KRuGDjczr!Z0 zxC>4|+sNoTk0kj!{$X61(m8>^ zxi@ibV-ee=_DcrIDO5YA4adjdNH<04rt5qBcXzu2%Bl_>yD7dh(zFn~TJqbdlXRL*?VTZ?b`~qhPG!&NGt8&h>2d4P`Do1!uJIPxW)TW9!L9~{e?Cy; z`6EdBlfe=7v-mReCnw5^eZcwe&fx&};LP`}!x}IZy%}l+VJvVQs+LCZTx41A#Oq2c zQ>~+DL+PJ)cAd`dStmmL9|HQ=OkpIZ=|?MYgv|BRI?Ml-gtTA3h%x=kGf&BOfXRSh`tX&e z4`K~FTU3J%j@z40C|4gl?Zy)$Lxq5G6PZYQrY+e#fRCHGx4VCkuZe}PyOFVrJ8-_WkV`a)StTtdxW5^Zzv=$?cLPZF8w>uEVJY^W zL$p4^+Jhg&_h`KOhsz08$%`KjK_zaYfDGJ(-Nb+97#V|lGQ?~P=Io^oli>_iK zNL|ge(Q_$J+0Sb1J2ElH%|qNd6Xi5D{_(Nb2-;pD+%wn! zbvB5mU8=fs=)`aCRfFF-^ffkC;foQQnm)ss?p=8~Mf_oEqV>!DvC_rYPe9dyHmw23 ziVQzIOTc?5dK&>}K6P@7rY8Nu$FNe}SdK!+qsmo3SE^fYW8@r0jH!9+u5LclP+5T(9GuZ(oQZZ^yA4l2R6D4+n?a=H1pY}OWyr-cuMV~ z?Sy~FKC84p66Q3(OVF2}DYl4kzs^VF@=@L-9#6kNGSMfRK;=KrSQ%R&ov@~MVO>w}bGs>q3xx&0$!oa?)rTN@w3I2wbqK|@DM@KdOZ*NcYw$rNoM zst%vd2I+lTGIJxtBQNW&Crn7>_nnrCSbtMw;+oc-NVeTklrVITG6Af1B|0W2Dk}hj zd{37Z9+I0J|F{=h3DnAnwYD%bF0gIR;%EYCCk7kMi`z74M#y57D@ui3K@FGtG>=8G zVty&&6qz&1V0w`Gfm)g1Mr4X_F-4GT;4{yvL5enlB7C*SB|e02xmH9FaWqzG9K zlee9<(CyLE^_YKLr-87qhV0Y_7>oD_lc}VZ=HAPH^*v;RUP13Jo9Aa{$y0+W*qDc* zntZ}igBtdy;X!Ri$Wad=Jvl5ZnjHv$<_;y{vO{tFW7=B3$`&UYL#oo-jyN^pP|xqg zU3|IoGU{BKTAVE|R3L7U17oT;k2-{Uh{#DGS;n@Kem`$fKPlspkBqHFheta(2!-TiDWE=qeX( zFU}!2yP^nLtB;w?3Y<&nk$JP*;zw>Z3S<2YP|<7T*3B&$2YsK;7^|Bia?O=;UZaa;_738juv{J(k2K&9 z?!73|tS{&AYjjy0Ei!WbvVrhsfNl}vk|FXs(3Z_M48)OkI|GpWH^sV45L?we0aUZf zO5D<{h>vpfV8^V48x?3TSoZ#Fbc26uz^*9EEuGcWP<3> zc?yiHx0Ya?^Xa_|G2UoKGkq@Jp*k=6kuiEMD6-`ZWeEwk9;b1Rs=Ck&aMU>>-MXbN z^AT!VP~t9B9Jf=-4MoQlPIY9A7G9Aeg zZLrFCyncNbh^O$tewf#%){xMEpi2PG1?4!9<<)ZCX)>tDG{M(iweAsy^Tn%;nr)JY z*;I}WE@x8RTM|ZsTt%o#99!3IO|L5rdurfK$pBK?$)l5 zSVZnYh+cHo`>k8ibZ>1eXULLAaFB@FEIz)FuJY&*#tN#V^zOVn= zk^k2QLwy4ISvGbcdbqNcypV*rr+bWzRj9p}jT>;5j<{X7;9GPItH@4{k;l}C*Y^*Vm1BBq z=%SQ9M3#K2(X}ZSGz`SmQyK})jWXYnao(kw>$PFvIqke}0eDVVf;Oq{JQ62FYT5E+ zL~N+0+wnzhAi@At=CK<7)z|QXU`y5M$=|9c=jD*H2ws6CUJpl?fzas9>`GQ@plw*E zL-AsXs~SZDfRx-FFDuZGgVWTA)WpSQUbw~fu-9d6w=v8FRc^U}acmiFBo8cpfTz_JZV zHyMphZkkInOeajtG(@ak|X#G4GaeC@XsZmolaya#JN%8$@z zai%*IjXS;oD}7>yj_uA0O`8KVNmyOg-`GTd%uMhzvkSu3jqamto`QPHyOEGY8GDmV z4Y6#l_IUIyb8qiiS00XdTjMqd(v5C_V`L4a^P&%Tsx=5g@#I`h6xHPhlK zIEhxYkSiRg2!Wf7+DIVs0)d7lv`aOb!n9FI3Ck5ZQdYEZses6PU5ZVp)yFTC!rt%e z{ViLLG&Q$@*G`f*da9m?B#v0(%yoT{GC#IrbLlZ^|JXb`^En7}oG68ERi+76EM3dt zl)|oU295**7tqzxmCRbGA0=Z5^x+lXh{LsgfTz57kLY2tfEnCR>gg$|Q@r*{^YDF+ zO;@q_4DUMX8>MJBtSGA|JPO?b9%7J7n9($fAb-O5)89sMcE45obCBwe-%wTiED^gQ)9R9 zik$Ra0VCA9`(P8W`}2pvXJ!=7OlkA{ND5{8{D19*Kr5gx#VZu@K%oQaO^qx z(w=Q?Wj6#_l;EBHLrpNJiA!rot4dk(=$I0e$e-uh4@q6nt9h-|J*9%U&JTt4U0Z&{ zlbQP;uR~lXwf|{ zO>2Jyh5Rsyie}z+F&2rkt$9FUtr_BAV~;UespAGqMR-QdV^HsQI5u7mdAEE;m4&2sw!vk3wkIhNeaoyg7XFXl*MBdT1 zPE2)AE`f6y6e|1~`yjrx#)!B$F@i}9OcgoK1}&Uoq#LDRGI|zB#QuOhCtMXV5B78S zQXsUWt14@3mbxaq_}{<}<&GPFhK7$oA{R4VHy8m;*WiDXVy(5s8quix zijC=F3W?#S(#xTgFB^h({hfa9*+XA$UQ+IC8f@ry;UqN(=|arueqw$yzNktAy^Hnq zj)CAZ1#x$rC^`hkYAUXTt~9ty<+LH#Pt@6*TuX?Gm0`2H98$P7=gG?PK1lP)@s{3Mpv5Q;;kJ7iZWI$^HHwgJZ7A= z@730BafN-v(rU+nfYD^ol9rhL&%U)>2br+x?DbTlQye-!Hj!s#a`TW>aT3u1>Fo^k z`tv~Mw_H^Z{y{L2lfdKz@dWYa=`R#Te+G;1&#Wu<)ZY=aUd`FhXdh+w?W^IAH{W(Q zs-pF+P~x!!H`AL4RZM60l(ZB`x39#OqtG$} zAlyL{pBk&Dr=wljZx`EjTf!G)+TR}oDptz3Dv__=RGwaqlK=cEYq1IEG#nbC#_#dK z*f|$g@4yK@T08D?8E###eO9j>hN$J;XV3#Z?0{8dgmkU&H@bZ`G=~tMO>!EM{H9*qV=_Q=d)kSG~nMf?~E~% z*>S}YO36a+KG64F3n9+d^H^-+%red{gIgPBRv4652EmZjYB0WuabWUI@Z&1&gn+?} z$agz_3j_{@9A>`nc$N<J%w++m|3L+Z?nDX zcuef_RQz%$`M3QXn946>HB5Y?NXRia@*PeOa!WhA5=sH&XMTERNHp%KHht1z zHjN}bHo;{N?)eNchnz3hz#$KVD#5k_*Gbn$g5*dD5}Mp}ZM;mbwnBT@A}Ni0w|>r^ zwTG56z!A+lViI}h#*q>Rt=is}g(NJC8lr7{mn>x>ivJhSoHZ;eTAgqppD^&-q}|Wy zKV#0C#*ZGHK9K?tPyPrNRzlg&VDHFUt0j&A2sii0MvK{PZQV8o(}~u!qui1jdRee~ zq(;COpvE41-Nc(4Lpe?JR!LAt zzP4w!!xRLC!mi%yo-fsWFTo`*Ryr>8p~kNy10eICHfl*7f+gRK<1yV-LIT=fh^D30?6hDg5o-1S^k{5>5d zlWlMvkTY_Z4#QO8T?L9a@BJo7jB+?K6;G7nN-SAj+}3BvyuH;B;C*o8UO3ldc}GF{ zdtJ{ty42snAaok|;$jzLtZQX~U*XQ90zr3n~1E;2E1O>E+wzP=D1 z@@|Jl)uM<-G}x!kT%#1Odro$?@9@v>3_Xk3X0(TH;jwcR2*B17w_8~vII%+tm{opw z9G9J{mo@!VioY;H-+aLQq7iFp-m8 zQrEXN!R$eHUq!H>=ct%AVQ`-L#~8f=f7$olkrh$5HSI5R-U*Jh2!pgEzR8EN$0FPN zDimJihSS;$183aP8?iV&Hos?cj^1%?jjztnRm_{XZ^sCr^|2f3p?%UI6CXY}UT;7o&QXv`D5q^(cPfS$F?Z z0c#}*Ar?2-?eU?ust&QuUr0+#3I9nYO}OcW_U__m2d_7!LKHZhYz2oCe%p%5H7q2f zHeY6oIyFbK;Fex=j5{gO^&Y_BT+~U<#yEu@N;eWWlnolfj_f;8N*+W)k*omhQR~g^ z#k8-d(vzo6rKWeEoz5A@BT4GIbJuTi&h5d5p-FTLlpuOaE#30=N&5M;IOl<*eK^1D zM`I2TdzIx4_k%7g+QX3w?Z%yz3Sij8F9EIWe11LvzGMHT%t&&AOj|?^Mr3OIv^V48 zQE9vD)z#P7Q8_!;m>G<+0@w-aV>|`D!hUp9LKyI~42dWH(sd?7)aEOgwQ!o%*j!0U zh<@^<=_XTk?a^Z|aby)QR-{Dw^|}>)f8P9DO2cJ#X)s^ILYFA5H+y$))l4ddA61AX zwq|Viuww8SluZv!vLe$5>^u-8-v2p-ghDr#oT4FHSng;lLogYkq|RXB1?O})zm{(z z!uXnZ_XM?EA7PY8Skr>i3a`f7J=2nXFN!3f8aDeFQVq+43e#BqaZQ@5knFUtNv{_G3i`FCB*lUswqBd|Yc*>* zO_+iseINq9_o?q|wx(^iMJ7Ht^Xy!Z$jKCbDS6Q1+`}+j4xQH@1gII>4>8W3WhC;x( z+1cEW)@A{m8Vi|zl`CFf%(;Qo*!pQ;=Hdig;dsCY2i+R8&arq@rd2=ydmIYNle!C& z)34Oo)pXG3@_U4VC2Js648>`BacG2cH-FD7q8b3|MU$s~=8|``k@O-!@PGLoaS%Q6 z@}g^;Y=+isySg6_&%#%^e02E~=BJj`&DX`E{JeAkI~cJ$S9wG_w|j57_J`3|Ut!<< zJ4{{)!FMwLuc*|AoLo}O>78m*csZwSy#1o*k3R%rr9@JwFGvyXD=VEu=N3wqfC#nQ zeqK^cw7>u&;@A}b!9YKpob=L{>wo*x+T#=2-=2|Aq$iiK%47p$bz8N^vv zw&=@w)4ocP6!|T(RTh(CFO`C#PnHo>GOe-V+`5*tfuyVeLO9*D`zRoOOf;U#5Ow6 zGwBS(ePT+DK;HpCKO7~@Ul7deC!;j)j)hHo66}Ak>yqDJ6k`v)REfW&i>r&C_r&<# zbA}9ZrxU(WZRrU4%EGfgxBd)IC>-;)k3X(qmv6uggrLdpleRf?6x_hvXUqp~u zxWB%gu2rzP$LD_@dBs7dAY+78Gj#{$FLDE93F;k9X$r zRkr$@uha%^O`4vD9drgi5i)c*WATW#BkBMVS`4%33g2k$mc%#Uf8BStrQHooyi#7X@$sj32k{z zu-C7vH*1S?wmJo~#@1~D-MjL6X=&kP9L?1ovBm;6VRj`3evk{lx?SMV_ier9T|dn3 zlx1*=y9WL&*Ika}{*W&)*e8sHDOxXF_D*bq^>_9xO5EW;*^!xP-Z`0sXOCK~PlZ3? z>Dv-nq)}K$y6=yk#$@KeO1{c(>rK@1+v@YiQ7=RvBzt?Ey8bTxbB9r z%ilCHNF_w-sR8Vw1m?Rca6wN|PpdoD-M28-b1zPJ!gMO7^ye}CX7oWz{4hN8xuQP| zKg4dMQvZq%YF_HGVpTj9Z7`EkFKO0*%zKeKi!fx$$b)@-8T@A8&Nk$UN9vuU-6D;^&LnhPE-KjKinI z6XTm@ZK~7KGE#5f^g|FM?e9OLQi%8Q`g#xOJdy2mdO_#tlufQ-OG9ggFlCL}OWo`v z6hyl3!7$SzyT>n;Rw_lU?B`vxJ6y5i*1B_jqAvsw&4}Wbd$yJSnGjgX!KM3MnnFR2 zjT6eL@~auU7!&e5l#5skpD)40Q$pT87W3C-zSlOshqrDD?Z2pR97^;Jujy|~5Q(-? zx_ZLu82qN&ExJjP4Ps_x6^UQblSJ*KHZ z30hH(fXZ=KCYly7^ek#&K{K?XWg}-DDDJ#m}8eyq&A;lk;<(;7~ z(W|ugqBZSr&-N8xt30f5$|Bx&n8X|tqyFA6ZL-{FIvur7^KxHiBJw4ThDr~}BB$`3 z*-xk&oahKLVP*WaGOc8$P49#6bFC-bW6g2nh+e+RFmqf~igf}G=W=p6RBn{G>@7rX z0@~7ZmS&V_@>`{i!b8(!y>wrcijUPWQ*TU+#^jdl`Yjh-Rgf*Hhzrb7Ww5AyRVXYM z9W$>pXX&s)9#T|}FO8AGCReRMEL?g?gLCRFHnLjQb(@^u^fzM3F1`U8bXR{A1uT{#(5tto5??uE&QThw79Gh7Ps%XS*1J%(8Z^1dU2lj%fTtu6()NFc+c@M?C zbi}c31*tPXmLHxAS-hK?x4^l10^HS5z8x0YTG39ViVxk!9O)h!e8+8Lh5GJ%3))m! z%Eck)&2GT!lW^~Q^0Z+vSrvU&-#=%q4rVT@-fRLU$YG&@Bqo9{7PJMmJA~m2b4&;b z;6O_4@`gWq%8vavW&^$+67Yn~IITz*kl!`Qm%R3m`(SzjN_ml#l5d|i?t=%$X%^TG zUu?Sir8XCBXX1kN|-tG*}Bn*;i14P53di|hp1-LI zUBpdvPHB)!h}*jCl^38Zpm+YKafbT&_J6@1?i1`S3MB%OzB{?7N(pkYu+d>-0~g-t zpsYPD_a6Zf$Bxep0hV6J6vU(nnHdZ(E1)fz9ag)UvHIDt^U)~0lZFbS5uyZILY&fZ zzAtD$rGlHJ>&fk$82%g-__NtAvWY*ud6M%q$`(J_(;EvYb{jT&BfLlb&7n&nH zMr_>4ZTFV^ezedv^;_T~F0lplHd?>Io`Dttqt(S!(IHlKN(crW8H_X&E4`(1l~>pQOV1(jdsY784*Kqj)Bm%?kke0h^nINsm&!%!&u#54{s)5;wHWH1OwLf02-f86@QNXX1EnQ)cY(*C zAtlhWjbs_PyL4~#^c;GvExPw%QqWi>369T)>dP|(gbW*YLS#O+b z^r+ub!aNY1I|aa$H@wTc{#TFmzOJ*+`LfsVKI}h?BWoD$LU#giOgbmReKTiu{Ct)h2fx488{ye z@~gS5jO{LRrwH~Zqu^aa1&YdqtVmAJH`tc_;OlX@9dBKGEEyKlI_nz$p|>%qZOG|p z-cwUZm+N8INieYVXn}^h;7{NQ)>|64;_V3&m$GNN-ho3|%LEx<#aW&?+8{ce7(*GP zMjtI+>h_KBfR*8G2Di!=6|=QS6XFLE%WFDQ`9jT>z<9tKbw z_vw};)6c##P)XeKhgejN5ngXSVDIH@WogCBocZF@K~9v2B{ojQZ8eL1v=}E{ImA z)l%hD*ct*wD!lp{s92jAPSXYq3NI@DZY+NqB>#w?gZ6li7CBKoD#m_DoIgH47MF+@ zTTNK^R)BK6PxLUbDR|u>bawFSlK@VU&!BwN%tA@AhYEjcAo4F|OJ! z>~l!M(wQlY)AE$xnf)CHV$u}3)NeN3rKWuQ6dRm$y;|4U+w&x*^&suyujCU^cG)ozb^I4B5>*ZkQ5)o*lV~l3d;mSSNO2Z+w z5rr<>ekuZ}(VzNuX<0%Z|FbiP1dubCPZRh>v?1AGx#t>pR#ZlM%BT;Aw^i+|+pvWW zvpcYBOGAG|f262nE!x)p_S%z96NNC1&lPOMs#Lzc>&H40IG+bzmLm^Zp#$XUp|*=E zZT7Md7~lnke{MpSHx>BHw3gSxzR{2&IZy4e0zY_czGnKC(JxBJIr=Q6qRpE9bLcp~ zrdtbKCS|O*KWVEC_G|~(wa^?Ir*nGnvp(bJ&6M9teJ11Z`@RS1eA6epI$Ep;ZE1ex zSMT>ib}F25s!?+TK|zyjTgca$CH!noHM%TP`?4K3cCOPOCma{ku{=+H}XQ4&Z_2VKb&@djKN(&_N>Rc_Y|)(`y%aY>Mu3rg6?N4(!I3ZIn2y_d3%b0 z4I>)LRQ`MelaGWYP(C~*C95~l5%wo4zVcTQ{ABE4O`pJ;@srn+kC-`GWHdAt*zRw} z3n{RuqT21?&|mWEeW;{fS+3-CC5kDF1RUQ?Wa`m=jxPSgK*u#uVLc2w?#eVR*?BDKl) zaOBwnCGo1vsM`2>lf11Qobdu%310j(v0^QtBqu)d3siEUfb;orl=kuQOp4Yt!*`t6 zl5?G&AAT~Yj@qvL@)7g}_$U`n-XXLAY#s_1BD9lI-+zjW{3k54tn*5EhI^y!Fgv z+E>n9Fvt7ioA$lgk0LEM;P~dmd9WAnHn~yLz5f!$t9B~Het<;3iqgVVHta&=f#rhT z{Wz)wnzEGlg}4O|o0D248?7bPb3)dV$`rpxy&V(!Mvr+qKdWva-*mik9=qvRpcX9` znLD{ZB{eSb*(JQan^PnYRu^_Y=%~5AslX6j8$4Ig`J+*3Cf1N=G3$vywC-uiH(L*U z1=2mU)eS^j+Wzc(C$*kdQnirlY25Znnc#_*K-XnFgGHn<_{-Vaw?;od{>bCxOLCdXHI>`dx3M90HQ~AG$2gE_ty24_uX0yZh%!Y>4 z9VBd3xbaJ$9vEj|8>Goseo`BKm=5hwFrSLy^)<3^CromcN?o^6-gQZTzZ;|RJ1rO3 zPKExidR8cBD;kg0j(S80I`MQ|lWMbUxqi+&-1`L+9(u1|Nx7e(BV}%PQ?{EJQJn6V zp1TKKgaw8He0RsxewqbVv^)3E9S5i*9?u&31-iViN$-U z27|N3Dv$vuM<|0Xr6dc}&`pSR8Hh$nWlvB&zs2b^i;_)c%vepfNzaLDnaZ4XQeL2qnM8;ve5K`a`It1CB4EPx$l6TGndD&ger&(mX8 zP1uxhaLimq)D0_w*rJzO)<@dd00eDMbeK6t}||a zd1W^joDMokyr8P@5bUhcQ5QRo6mipU1T0Np*I^~dS?s|JukB&(d^rt&@XES^174w# zAX@I@ByO~*$QfHnO4*ctPxz{jG=OHn!t2gbvsN``$qD!n8_!oaQxq1|p2)dhnit23 zpOPyf@kNwx)^(JxS1|Nq>Ila}jFT~nNLQ;!3Gxuc9yD>iZ*LWGUO>Z4^#j@?p*2>- zG-;kwd@CR`0_=pmQfX|j=lNysehrs17`<@%{#>;t(@ytb?xLt;l=%7<+j&8>_Fu0J#jP!^BN$UsKq73#5fhH2)3 z?*oqfG+*X_?FhC=lYL&*QrNVR6$9E7gXX)ghzoS)q~}@f8MqN69V4tPjYL=f+khsG|(Y;ODXIQXgF93xC0d%r@?6 zONr}Tbir&9<1;s#TZh-q(A86OV{(PW9KDMJiww5zK9)w$C&L_m{@h3jpc>JD(pEGR zTM}lo<~Rv-fbEYs+8AxlUY0R(+}K-vER^Vx=e%fqVwnE`tZwcwD}z&vRrrgY2Y0%L z+UuQS$~#r#^O;WiZ>rgvxUxoW+B9MW5#60ZK*Nvq(aLj%5r!GDZ@|tfeRve4AN7UX zv*Z$8!%b0#toG#bg%HYL(#^R(-*Q)n#VKUKv17~dpPofN7ck~!RZV9f(6r@!_1(ZpK*$NMy=Dj5zHSq-P4xf9_pvh2wyHgIHp0( zOSVfo-2o;`*^e~L1Ub&<-!4TD&2InxT8W7$1a7bbN)Iin!qH?4<(tZm>E5_TR1O)l z+h1sDl)$PbPwNsf$eb1Fktu`KgSg^UYee92U)YuOG_IBOX!d|}<&6Vvk+Oo~hddVK z7K?uW%-qt8l7)iutn(W1p-%GxfWBA5x9CPsOF2Zk)LTe#`{#GgAUWhRIm6ZFK85%| z-Qg4=UscxA$&60aS?Y#T>5UHPQg0h!;ycr7U7RHfW;xRx zRHOARU$+@@ZSX&zOSLtcx0`WA-G32Nto9JvOP9C*h1In?;YNO=27V)sFAE3bBC(y&so#LZOl zgda=417%HxaRrFV_;N^m)bb6KN4b<{p2umBGRr5Mvf%fxTIp_Mska13Yp6fcI-jaD z_!y96Il=xf!tp{E{}17KcL*=29XBV2DoRN43CYsY0f~u37GB-`hF*^IEzoo%VOMW} zGr@IYL2@(>rBl$Tg-tX5jg9DkD4WaF_`1_IIK=y%Bvn+9IB;Q(gd9a1GwZ&6B;8p z!JFE@_l$0uo87d&tJ5fu!f_X>S$Ui~-}qX0?U8Kq{&85M%RYYKt;FA98yz|h;0Tro zFZU1BPV}6{tW8MEd9n5))=wp!qhURf+Ij!*8W2+}XjLp(0oX@;!h5Z6ZHtX^(wm3H zeHS*s9cS5Mv@;4>l=FU81aOA1M6|#O$@4coS?~UJFHa$CD1`eU@>KAQ15M6bSZs(A zD+gTy3Ac&}Nvmet8^;Ie-xY&=kI1u#yE-2vw8}>DkOu?Uhi2}Q$!z!+D)A1F64^;E LF9q2D-{gM){9db# diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ja-JP/err_reg.ogg deleted file mode 100644 index 27ccc93047420a7eea499c709475a2cb9a545da8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10168 zcmZvBWl&yAvo$V3g1ftWa0~8E*hqi}cjv)fgS$HfcL)vvf(CaD?iSqTbf8dbsZ-!=!wU9#pz%@YT&dBc(1rXSbo1KM+g`JJ<9|ZCHV`^t?Z(`~s^qw<* z&$08pC)vqtERF2nC;q#z=+AfDyZy89KOe=RoFRrTqV8vFD{E=(Y5Kmohns~50KsG| z&tYLD&ovq8QZ?IpL+4*tKp#I0aTWsj;lczMOMT=Sq z#*I+Vkj@`~Rv~y4Ds`lYF*IMm%Oqc+#r?b1!iy@LNy=jjGlm(*^E*{F^K`MX4~4;< zcK8?3nor8^ zL34#Uuq-779VwyI{j5K!DKSe+sQvFe2-`s08)x9rPnEY(aNFnj%)B~r=+ZtoGZ`_4xbC^?7-EKv{pwi@ z4Kgs7w^IzN;NRb4WX=Q5uv0`%JOw|#axm|sfphterg&4njV;=^ z+))-@m$8NQSAaHr;aWFZ{Ng`+EU`}7Kgam>HNRtetGPG22%SY8-9eDjy@N8yth5Lo zdJD@y=ipb&zCKPTuk2WJ5qw-FfY=^fh%#i*8yfzh=tGPxQ?P_d`jHnyYvH(f`rV}H zSnGGW>h|c#RbKG~x=-?LkypEZ%q3ZL6n{M$SMFP;eGWJkRkTG;MFA7PZm{WVO(3m0 z-#0F|*TmUEgYlKGR|E&B@RXj^nBTND74ye1AYZYuKgH0dr&&mwJAK*Jq{1GkIR70* z82dnnb#Ariogp0K2@&2}pj+hQ5qlBGIJ=Z%-!mA(&Bfd(WcT+DwaOnjEul;^Ji9Z# z+WlGOAdwg|DxWWI_`36HC|O7mLj-0F`p!5lPdsDE;C{|J)NbG}ZqMD>+ke+G_Euy}uC zwf2=8WR{|(aYHaDI+UeE&lid+i!V|Q@-W95*@JgKHz|T9y2lxX#?9DLQO#Z4I?M+e zqEy-iQN@w7IZi>CfAd&qt}-=f`$*WL=ADNbv+eC#jr684<{~af1vFIBY;IfSvKRO~ zk~(C`*Pbif{W`mW)1=+-!ETq4?9V_*kQWX%8C^T_jo#35r;&qGU_hzHpz=nrmpNSE z{m=y*9`ftFEFV%qJIjDU^(-dmc6xX-<=S8~zl!OOE^5gZeQJP@c0a}GeH-buqzYOa z)_E0#Rrrr?;LHqTKcLn%Hp5%uhtjtxYEXHzo-Uk09@`C7tCEEeT4YzKtI_ zAJ&S0s@Y*~vNC8jJk`COyFwMmh7wf`3}*#U#`xU6SzYsFn*_zmP|sYw!I7484*yyI zc9D7)@QrH|I8zG{r{Ccx(W4`-zm4qZ_Qo1!{ppvRb1vqE{AGS>OBiBy-?d|sl_H7z z*$>~hYq{{Gf;fg!t%lFlu)I>RY)}P(phy3^>J7zH4 zx&LkrFU*Q9wilW@Ut>!^@rv_S()I5IMizf0v%k?7n7_j5r+L688JW$)?6W3!*}0Oc z0^69FpQ%W@a7ss{N2fm_cT`qyH@D8iZBp|OdGgEtj*(CYiPzpFt2(gztvkMLyYA-a zs>(Tsmcb{!Qpko3elPK4ODoK(!J3Zs@qB0ZCS|06Y4Q8#JJFBDCM+W1pj>oZ?>6>h zD_l0<7*k*EW$f88r&AH;wpm%hyhf_H%iqBRTT8wFQZlvzG*b`M=^C#A9onj?kH>A?iC$;?*JJWGVjvdvT^9PugOEF*ZCRk{41x}TK~S; z_dz=N9!Q5o*YqAzf>zn`@{4t#BB()!&tr`)Qhs1Y z=HZ1nrHmVAM$;tdCwdSL^BgYkP<8yY9yo!-Z&h5 z(*tPM&iz(d(h%JGXP1SJwO<7<+>{&;DgC2f8QH&E8knuSaKlPJEsurm0IG^;SDjUQ zTZdN)8BdnxfoQ-6`hG_*bjnRW{{6s8pG#V~6vS+F5j*Diz@2Yq%OOS)hMsv>%X5ecy!H4P%ry)-%x*VQ-x58k^W~9r|ZeWv|lX!k;7;%4vU&F{! z4Q2YzFE^|OHtv2ZtlGkQiJhCA(mNeEbC=ZIV-5AHY#IiRRdn9sFL)Qf2^x-vO<8D} zaq@^~`Zx^sGApZuQHtTU*#{j<4c&w4Yl&AT6mdOPP6vqW|G=~Wr?v4%sh8@LuD7|4 zzh{nC!n&Rpp1rV8Qyjs)2+<37F~5-})rOZLv=QWb^61BIs9A7#l4j4+livWn&hwKI z4w6FmK@1Vkh^nzAq|L<;r;HBjRV}p%WVVuW`CtAg5DFzPHAY{xW`Z-(v*+nH+RYB1 zUlpoEfn8V!&Bc^eI_FOz6l89L-h*635WQIT8uy8(8rMkfP1P+a4*GXqpIuW!@}9{c zo$e|NxNlJqQ7~HgjbiHe1owg;IpyfBs&DLQA%8iH`;2?+^d|;ZK}!d**ChIrx^cQd z27NamjB(XCcg_S(hMEk4N*`~7bC;jx`4Qp==WGErNoCs!d*9C2k__Ia3C|f;3QTxH zxP1Z2JY<|18>`c4TLCrgp{jNY-Mtk}1#*$OSD||d7v6+|B-bTM^vMH^sgaj!1uK=k zOlc3CSa#)Im2uc!oU4MXMV;JVJ_@1g#+ias@2L~r}a3HrnK2Rv{;5L z&E(i~`CCDT{$JZ;x?T_y#Uq= zoz#rQp*|rI+FcdS)+3TPJmZ@726fw&N)?_LJcntm_2{I?YW3zgCi#gf2e9RP(ZWny zTQN=b*2`a*z4a+9;_a#8B8#9YCRmjQ4|(psT*Jg~Ip;%s@^)Sq;aLs0=5Cb_PHQa> z^sJ=@Cbs<^&PO5z)j8!EYvV`96J$NiHdk2TK=T0 zkaz4Nk+&S_czG_$?a6~mIs*ljvi9t-`=ciT`E-8ARDcXCIUgObE!r7L-%TU$4 z@pZUPG9ko91Zpik(Py^exO5$H*3-tKR<^mlO!Ati7s;9(bMh1ZjVw1A42!s2OUHh&cx{r*EG^I znjdjnQNQhmj*`XuarGGw_ie1;zu4)WQdTK8n0aKAfw3WelN%6pn~RBAEDX6r_}ZNy z$-<_j9YT^oYsGpBQ<#1(SnlZX$;}M<-SW8T>btwgZCT)j${{z>{TJBDiJStraH~;o zlODM~ZojTHv&oT$5l{-!{QQ%1;9| zus%-2_Vw5AO&9|T)=ECf?9q`%e@~+MP-xJWdP1+#ih|S!Kc&Yb0kLRYEonpIQ_rcF zBYdc24_lNDr7wCrvq6OER2R>A5(nk0e?B#7Rm^yh(HDt1T91eo%uy3m5RJ zmiL%}4fZKBU+(!Zq~bK={6p6j@>Gh3Vmu{Rqdm3PQGz0IYCuA5n*edU8G%J?$rv&| zNI%?qirLU3;*m6`S8~dMWO!9nq+J4L(-^zSVCoe(l+mf%XIn4HQ4zv_v|a4a}@Dce)I7=6d7edXO--76qPEdC?OkhNYb!L{#r2YjTL!Z|GC>8m!rc*d!VWv=WDk_f zZ_b^|Nf#_I{)QO9>05}J^iKm|k%l=PDDr{|Ff^hOprpQVJEx^a`bXa)+f>5L18=Go zxA2oJLW9%?82-GaeNC%g$ne6=3Z_S6BxE&86rjiyuC}0e4WI|ao}75=Fy{O$OdUqV zE#eYHH7<4cId#9=b1c@edeR&~nmMR$Dtt;|ABAlZBsl~qO9qKXakSb1=+-n_Gb?O1~vT{nFH1A6&qIqJUyYIeLk^u zG(}Jn0Htxj+9&tGzEdDrt})L_IKFsyr1d2M!%ak}oy^tXvX;KMHstCL)sHv;@|vD) zd%ig$OKJos(6rT;?o+cg^2^1OXYb;&hWlrKyHCH&MKZf{@6*fw#m;r!vSc7C>v(@S zX&}{TYKAH|y>zB(j`6^~75XDQEFC0-c5}R{h>~8;RG$GrUg|q>Cy>HEN=I8V#gct^ zdSWE|-@(*^=&;4G8SOS7v6_2^^%FeKI6L~cAYbu5CTAP~8r>upGNHJ(cDWEaPYjJVrD2Y9Iwk~ zK$gyr(HEav;MQRR8^T}1<$i5IL-YMbT(c<$UkhR}Pm``VNPdg)-56ZkjV4E>^!>t_ zd@>=WZs6VloQV*hvJ-38#PkNQBnBAq3Bw(0LVP!73enWRQN&?(v{NI7`K5rp_YvIC zC{ZL>UiSmoU6)P%Q~udvNHA0;&KMg`m?SP=*z3}Na43^1@1Y~4MdiUDf$#7nfp7fj zz~xY;=PyIL*?Bo1PWV2+BdB&tuJ_jHmZ?W5Edb(OF7gE0r_N&WGR>DQC!EvrZe;U3bCQ?az z-lxivSl;^b8hj4dt56U6+JL}B%>ML~VZl%o*q9Q9pVN`i-e($E6>n5dvWiRFw>~nA zQaDaYl^$=?Ds=W;*jatbW-}A=M)KbdxJ!K4&iXTOX%^xri&nezdu9&t`D<;@Y{Tm| zQm_Yhr%hCQ+@lhK|m;XVemxeJVDcUAM2oN*gY1X_t0wjcF2Q*bvjh%-ieLy2evgbG>y$H#jg-R zSqbFGNSOC0@cjTBNi+)Z^YjNr;S=C zXvL#))$Zndv6tWm-yBZ&4^#r^$(HdiF8o^i6Eq?ojkt|BkFtf{?8KuU@!hU##L-5s zU?G-CP4E4tC7c9Xnxy&;L7QL!P9!$HlrMGY;jDK6O>AIL`Fr2FzvLiF3~c_S+gnM+ zxrfUdh7!|6Dkx5Vo{D0MOCH3&@t}=Yd6eavQ3hp$xg%4?PEuGA)D(qT6+q=tNz4>| zC?wUH%G@Lo-6(P?oNi1d+?u+*dQRVBxyAGY30tI*lJ8l326?r$Y)n#O^)8790n4G& zH5uT{9rp*Dz19%%sQ7SLFbW?`H)>foS;yE!syGsN&I|L+L{)@2S#1T>PmB-{?{a1o zSHu@0{`#zMs1tW;gQtiV)b1@}zv$GKX1}fCZftA@za0Hh__$9l!AWsl`x!F1_jPF3QP1|uHhu~h1SGlZz9hCW$Kz~5JlDO3QR;nVgzDm?CYjV zh8f}TVA$5vWOUY4B+N^~NfHITW>2{!?Axqne4VVyXMv4r_eA%@p3r&s zQacx1QuDlFs3>a>Li>KTN5Qie;7pH)ZeDuRNjvv`jPnuo8QDmw$dw=?3q{a&^T z5C`%hO_Ok4vR_sZI477Ge2(IjwyJ91H#pVr8U?dW``+FycSep!l@u;%a;s<|h<`IC>UMM}G@kdy zD1ec9dLR)>?2*KRsW*n2>@;pV645`aUN7RIg`VPlVup}J&{^JdksZ(H3v@gISxb5_PQsvMW zj~!8s5Uh+m3cv(tNmqVayYqSwN?^>HD*H$5?tmFRQpJn^pZgcl==#K%Q>%qrG(l3bTKAOxs_3b}>cIgNw^Yl)HJcY&EGFQNFo%!PW43TlUw6Rwfw{q00 zUfttazw{R3Pn8{nxnGUO`i9;`N(*^Q|ZS<%ql0DAd=$UxvU zf%-Vh;YE|>0vE#&0$)g5YW{DM4lx&t#U>mlHjm1Y`RE-|cwu;OAC&|fSq=*n_fCof zW8lwf7$!Y)^}*t5feeNqh;SaWBJu3STS5npI%+ZNx4f)T>h1h{iu9gNGU*&Fbb-Xb z9G8rDnC9qjLg{lgG19BKqQL1byJuT&Tr2Ham<8EqvmXtDrL%Jq^h@x*+BhN{8l#s3 zX4L^U^J!6*nGS4~=GZ zhrSO{GQXO#8YqZY;AwXL-}|INj~Ev_h<0#Wf|kzI)2BJ;=e>F8WjGSU^G1wz9HwQ6J;)&u4O z^}Iiql;n_DNkmsMPEaID*QGTzO*_oU=5j7a$en%zli{BjT!lNHQmLL{`8*7>2DEX} z4~{fgE-Oz0r?JZ}i4&xDc@jB3?gWM>qiVJ09jLO#x~vtIPq-Y+ckE5E$}5s2QSM7w z4zHjcFM+G)ptu|Q8IeP?%hOg4{DN&h@(RenP4b=}co6pLAZ7xTR8}{sLH|4TwFeY%ED^bndFB(|?dkth4FhI?sz@~8f?Og_v7XD~)U}LwlU>3h((^#>t$X9D9 zI9wc|rZ&EEt?n^*g8O<-w!V+MeVs;yaw>0!4T}jl$JvKIpIxM=HuJ_N^XB+PyB?=z0G#YnyII!3>@TXeLMSDkeZelq>JaRRQJy_T64`uu`RWc zj8Qd@q~|bp`iKSKi~y!(&zwAn6uKEqPDD_YGr=!@g{GeT^Ybh_zb};ll_x)_H82mZ zcScVxqFkUe6&VqIe%gX<`KU7AU!60$7A@In4N|gY$uun}6bdeZUzNSPL_SzfE&qul zW_cM+Jur|9Wb|`Z*Rv#7`8q8>xkic2SyFUaK zvr_XSr4lV^r@ReU3_ZjAzAe5*2Du`8y;oS%F+Zm>Ec3l#+Vg;u3xp@i6!k;fQM2T} zZ;iHZe(?ncD7GZT)#bxA0%JBGgBPoC>3R2cGH1W@N}Wxu=wvfW!l3reeB?ra80GR# z?3d(e!t^8zNb-SydlY23$1b=?dnCzfq0P}s`h>7=&p{q`p`Rh`N7lr?_|I+!hpK~v zNW`Lcul5F?+i_ft1poX&hQ|BDjyWTZR-w_FeTAdKWBn%kcQ=E5?%rG|XrGFg&pZN? zWqUBn3+hOI_GEBLAQ~#W)d~;d3hAjgq^U1Pe=ahp>${5f86IT_^GOQdQ_rAd++7VX z)jkDX9bg*|bxkD)>=uSVX|uf8QPEDFhBt%QMsUS5WdQYhr1;t8d}YSCAM!4yEhsAY z&=tiPF-j{>0Yd>PN#; z&Vb9L*wzAi)h;2{Z!OKI_-PzV2gSvK+msT*kGnIBJtHVlyl)cy`}2?r$I5N;iWdDKK^6L7PM|~>`yi;>!~S!z6;drebH>`HYA6evXSOy* z-O1<=&6e{x(WkFk`|anHJ^J_Gzj_D)r0MjaCm?R`jM;aEL{_D%(Qbay8N) zB7!C_ZdB!kzke&wvF_31V_;~!0q5`NCsm=)9*@Hv%YNp<47rc5qZN_|E!Ati^jKPT z_ydO)qfsK!UXn;!BgY|frLPV~aN1_eZY>F~L{L2AlQ|YW1sgqMO4aezJioA-P;+c% z@BN!~!?8TA`_~6JLN-`KjdEog>O}&?8pv*A4|}ms__E}^VqQ}DL+!Hr+fZEX#~{k7 zR!C3joe9vytF9=W{oHgF;^=8oPIEtGm1=YWr)S;kY;ZX**TH4JWj4VpMy4ZSop(wp zYVJ9V50Q)L6%xh7Y~B*8xzmPan@W51-ecKTi#?Su9LPdUzVJ;pS!zxNUoOW3ZXJzi zgqrBj9PFuo*}*9$*Iuc1_FV>(f0gsEfvx|TnoxCAu#rq8)t$7iD0u9q>mt^H_!=kz zE!zFF@;_V;qowkX9QiNT!@v8F7|uDU=3p~N2L)axT6RtfY;0gxj+vqFO7eJI)YtrB zXJN2rF+9`=3#s|9YN$O(URbT{whylslC!IaMDGJ#p?Gkfhdzq8EQGZfeF{NE6d|Tu z%!c~|Q8M)EGx%^dPfM15?$+j)(IiMRXY7+ln!@)r(rj>?Kd?*cJz1(qd}*%#rr5m_ zk@XlrV%LY^EKr{ocljK;KP27_!T=vTd-lCucv#X5H^ly#2zRIatn!(3;&8x3ZK%ld zufxhtk5mS@?ptZTDjITdp81PsD3>XxFN*{N$Lznm4K+Z9y{iC(HbumYycQt@OP1 zU(3n1laA2?v=Bx{er;tC18|$?z!~k_ z`X@YyhX&ADA6QB9m&Xs7?DpZsQn`nVrzU~MN6zo}obJ4J8_@WbSPU)M%8PdkhMyhi zlSbZ7ywJ`WQ{E^Hro)Rv$2%|J#0{?{Hreiq?WQO~+7LHV2RBEnF~~`Kj0742t=vpO z-S|@s-M|RWpFW54j~Sf<-}tNLv)QZ3B+-)FqNqN&*lo6VF9?;{&Jga~C1(^%9h$+*v`D7iV(fU3R^?h3VB<|fco77)W!%rTh4R-i6C)0+W z-Q)>jhCUj{WAv3TZySKbs=vvvGG`D15%m%G;>F`(GWX@oE!v(?|8j6j4Y3*}tW*VU z!bDGGi@P9UdLNpo5~cN57Gs_uV!2nJ%uLZm$)07NqpsX!6 zSS}L_2-9qE!cgZ-o#2wPG8)eb;)%G_7c%CyLH=ANDt!G+R8+qXYXE9tS4C#t(Ll?>wKMdLU!!^jmAAo8iBsOEjlL#scuy=~lAk?`g ze2KTrpxZ7?tqzRE%cR?^tK5EvQF|j&N}q;?x|HSXUzmjD)&h2HHcGMi>n$12z7x-|)id6D5dL$HT`<-OkDu1QG{9 zW&eZd{KfyPzc}d6D@6w$1(NxT8(KlU@c(3 zfW~SlpgOO?tl)HkgN&q6U3qyO8HUI)kw)2Mp;gW?`N`9=CD*W}@bILy zcfe-G)`9EF_xrx-ZEup(z2qbNya$uC6?x$uXBVol8@0*hZLtoch2U_Mc*q6ir|$Vl zxN_zY#NY#G$=o+KV_P$YpbI)>#Yw*$&u*)NkJ=ssQ&RP7eHsKw>c#VXy{+qF9b}lZ zxuyOraYFS41~W}<&EKKGwqke8*{e3kq9sL~!(z+x{!6Pf*Oyr7?e+@?Q9tjoz=|}8 zfha_|U2)K*qUlN`g&l=@fnJEmdI=X}l&{)B$SN7ARq_Ba%0O`8_u7wK^%5v^j`}Pcb?nlzA_Qt@_p^}6+cKY|77mD!xG*?pT=>y@hK-- z!T+&Paz?w~`Fc?YBo`7yWzvV`Q;-=G!Rr#^MV>@vg%3EhcLk_Bx`WpJ7D)&xBJO$1 z8`NN-lrck>Cnb^Wp-cXOk#05kS6_+jYAS4w0`(4m=N2~dX)_7BCNM`5yqf@@b$x%8gs zXun&vM#4FT-B^du1&uOb%d*Fp6);W>Qyg%DwO75@?-4M+l`PuU_ZSr@aNt1G>U!G` z$(gMTiQUEWCKSVi#D0w~BIa5cc)JRAzn>QgF!ZN2Dqo45+iE9)WQO(0a)u|zN$>)b7Ds$yNH zYwenTBq<^4Sl3A$*jEf;DO_-8?btL4@Os6}GnRNV=94}vQQma(h${)vUL!kTZhSQE z-5{^i^d6nWX*f`bg4g#5lz%*RA0*DiwzJ677WCk4mNzTI@!hIQYV2vp?@-34(#QuG zchknc?7}JjUcK9vwsBrJcH}*P7)i29Hsg;U3RT*h7A0v7uS_cswpFH3?86@>j`Ffs zW6-q%d+mtNXX)k$_TtidM2Am)oM&PlGxXpvXgCyDg-R!3{v4qIMY%m#6h6CHZ8Tl& zK~`L%Wu-^lSfF;`0HUbZxy#B~=GIB3Zc8A)y>s6`Cd;LvZ&P~Jx@116Vnl3`-LHhg z!?EfjC;UYvo(rBxniK4W=3(dEoS@;RJfsOHh!-h1V<|R3bFiGUz(+4BJUMOC&#>X6U39PE^WW0 zTybGQTO*T4xyC^fTR6E*zsU#`S6{JI;EsLvm@54WeAv=^$JgeC?QBm&i*w;HxjXfv z_5>xFmggK=lLr~{>9mVrQK2e*jmQRXs$HAmSqJYvFh@;oVDh}F75HM>pUp+YIdqSM^<5B%(B-gb4 z3tHm#3r4={&4aFmbq@1y3b?sWR~D5Mte08JWVL`9d-5qkVi815lB^?P2FnuI+4oDdEuNEt<=3Rhpk<%3rN(rl%^u|$iPS| zk=6Gbb5ylYD`LxI_c8ZgNr)Z)P7yecGr3MI_K|uNomo=EaDnB~FV{KnN6na^HfTE{ z(lIjp4q`FkDTQKT7+mqO9C#NWIBZxa3U{K)ZCSwk*EXS{e?9hJ+r;>DbNOo@6YE%n zLm>_(KA~O^H(w85{{R5%(1N&Bh!F0sg6FCWnOQ#-DZTW0M2?Flw}PH|xDpWefDA~i zrscYjG@34aBfv~Vig3C7o)bM{)tzn+9VEPh($wgD$+ z=Z7LQY89Q)oK4U&4lTb;%5{Z^;1=|}rtDAP$Wi71kjLJkRJQ8Q@}2~h!aKpo5?T7c z2j*xlSQZ9FJfO0i3oylTf2L&Z3%=>c;ry8OSr%uJQuN8x-`$AeI>TbO9nU@|f7hRS zQaDwC5viS;;{2z6t#&22=|6@ETgnMUF<@&LQj}9W>ol)e*W8$cn0}G@XpWF=6nsv zDR?ZP_oURluX+3|#eSbR&Q%J3O`fV-j~*ud{fQ8DW9qJh6d zii)FQ@F<(NSnX+4t<#f{y3Mwv%yR(~ z&=)?3jTBPV1gCrD^1hvtF^QYS=zv@Eau@+{U>-PKix3al6-!6|yh$`%yyd1@7grfh zxG}B0n2^_5_Ym1x`)2=kcIScXcI9I-#{{04rEQJBN z^x2L#$a3;g(kc@NS}!l~ITVKFfmy9j2{ktAj#?)zVZoWI!8Zukt;RdAV@bovQ;y9H z5~yA}cy@EwdhNjo9P(6|3#y)Tr!%Tzod#hHXyNkbT0PmkKZ6kWf*cDK^AE0T11udX zQT!lyd!9{UqKM}|1HHYCdBtdcqcP!3oQY`kyFyfBltgsVVKZf~2=s<8r{w|U&Z4LZ znM-Yh6ERwGPS}P|7_x#R0VBxgO)Tj)2Y%DN)zNO@^Y?SNH(7XfYXMj&y_DLpS!nf5 z?NmxWmJ|DDL*%cJWyUEMR*l5^wZT1Wdb5=i6`Zj{ZWH$$F;$HjdOjl0|WmWiq=H zao%eHTe<|(S>%-vz3l;q1htAoBW1a8A)hZh`j5(xdqxE{X9`nQl|^@_mXOxXAIBU# zZ~NYo&Eu@MGc~dE3~v7@IWAV5Eptdb3#EPjfiXO`$u498W^0Q zDO~~qNp5Klr*T(wrJgsHU^npMzGP(d0T7XGk^|dnCV5mLbNbkGrZRHl zP>zGa$k@o{`~J>UsKJ3mT%qpo&|((6&169b?9}dHg_gUzn5H;e*I!xF<=!+R8Vfn! zQkjGEfBTBpP$*WkCbXb8ILqJOJ7RbT)-0UD1%K2w(m=TE*IsUDnJVm`2uOY7bIu^k|5!1mBIw^``tJsd`NxXeKD1xpM|wKE z)Rht96nI8X4j}ubkNN{d%m{H`SZ9yRaf@Ou`OH;)XVZDEA~nX#Mh*_MV6X#Zb> z3*N1wFmjFbk5Mxp{h=31`CTM=6VLiMqe@6DlMnRbiLPlwfIGQG+h80ByWY(ZI1@Dk4V6|$$#mAl~M z`pnm;dL3aCDBa@6h=_AdxNJI;^oi%|OpNILef03??vF4L?h0Tzj9F&&mBxp2=Dtl` zLRm*wDX<>Dc&nv{!F>i=GX&RI0e7%fhr?Y$WaFZW8=JD_(Ax%(CI zV71Yid;43#&R(y*O72NtQe>eS|L7oFn4v^O58?DA{jegcKKx4abu&mNA-20}7V*|$ z_}1>xT}K@Ilu2PJbrClABifo-!QiB5*4--r1oW2c6$Qs)2uwS|H^nxSEuF;B`S4jU z7idCS(287%UT6iO=u0`h3Q6EFQYbL*T3! zi{b!=T8CcASDg8(gs7cJuab(`hJD#$e)J6PpNjKXI%0le{Q>8_7;}9s+FG}%bY410X#7^ z70c*x$D2_z{1E`1x9{K@1Dy^zhxg-#v|6Z&wa)U|+8-V`=)GJd2dPJB$91=bqRQj} z5Xzy3m5f>Pn8~t1E6DeqrPA!+<>KH;6}`8J;XVI>UToXW343GbEqeO;_DhaG4QJ2z zx8@tkRc0T^RgzQUQ~eQ&hzp5>m0o&PYg*&N&XKn`tIfaJ@!s`B!U?9y!@VN zINCaZK(e54*gq1zzw-abUpeUF2A9jL1S$TN8`(a2Mt$+3ZR_tOEg>o+Dj_cZSHW?y z96jtk9UOfWFF5-PPD1X2l;Co6vGcqz{ySKy{X%zvzk~mNs-G??kPZg(a1XR_4YrE# z@iq1`(KG-^MA%jBzgPQt5Ew1Jl&avLWpVily}5Ihda(C%)6#5FgAa8&_Kc^Q}e zc+pWEQf!7z_#=Z{n|CSVsJmmr;~u|X&1JRMCJvOGVZ@uc+KY!d>0q>ui`HmX4_O$9 z>8-m^9y(!Dg2yCKMzd}J@w`ja=~Hj?M5eli<4-42V3E$~>`q{3_Y6nEYirrCj-R+} zO{9}pVj`D${Jfig|8gj~E&@TjP7>v7%|=Zajak@10ebH<5qUIN{S>r0tMOM~{ygEb z@7nD=)(4Igf69zfL#*H14myu0FipZg1yH_$mVvEbUgI^X1~yZPm>Bun0K;fQTcg%z zcS4HW1dWoeZ$m`NEV}B|9?X*vpU^TQ_yLXGwhs|Tol5kHQ==D3?B*^>%|uwVR}5ub znpHnrjG@*wC*w3HDJppm?w}rNZGh4;s>=cC!oOGfAc4ndmI75orc1UwCFNr zx80OpMl8nkvDF8hda+Vg^UA}9Z(R7FocM73C|zGm&^YbU{oatSZ^>*-Y54v^8uOhF8_SdBfq$eD-syQERWS@iwrrd%eDzCEg1Y zsxdGP)onN|s+pd$ajq^96h_2QRdzRkD+=#VXb)EMtn-^j+pXt=e^m&AdK{akzpt*5c(7l|3qq&-yg4+0wmLog)152E_McobN< zuSPi3$lcO>76=q1Va>JFqBsE$9@&yFDLei@idx5p1R{EbJGqbw2Em&YpE|`3?*!O# zUvhpbpgNb;sQ!rfrIGJxUEM@7tNlp?{1pAV!63Y`|6l-~3nk3QP2+iU(rY} zNHgjE`oXu+AKT6*t5D-%qv$wGeG|uUV6%zgcBiDcOnM$YHoBKGSZ(ETz5S+`B1S;_ zdBdq2gMPP{tr8nm#qutVvIc`%(vjXK)~BqBxIEBn4UdX?qox(KX+|=6CS+Ecmg;zU z$thRgZ85DfG|bIQ5~0ZQdTPmA$?>k* zQZcmK{61r`T`{RJteZM2L{!ZZEXrI|o8JkEbg?*g$EAPF+lMFzzJIhSRbb;8RDz0@ z@UQ*q?AU8M*fiDC6W?k)lZU-3+yjj~X@Md>(Dau0jF<8BV5JQzrbx-W>c-Vb=?Y%FO8loVjS%#> zs#mGy6xKKmzc3lDoG0%r=Speu=~{*U5-Qzlpti1-hPoOEw;}0)|Gr9@Qa>nqlqg)0n&AMsdaXU;4fpAN)LnOTGVk449_%oLodP1|zqzcc%B;N; zcDHF*@zHY|)CwYtE902oP?7Ip%6LG7I8BKvZco=gGudMJn(F}U`mQ5B{c zQdyx~^=v;Lqs7bRvXtu6vREF5MQ1$}n%7g!xD?+ym186P2YGE}fW^xCOKch!_MCmJ zw{?xl`tlAfxZPs)gtvqJ-|7kv{o8Z@Ru}kUe~h>>K?nB=ec_}V01r2il7k6I2{Hm3 zfmy;2ZhgRXXrRlznT?LgKVNxB7%QZP2lEndLbQ@(+dG{MQ zuSGUAy$Z9Q<8w7#p}~%SW&wzfjb!g)4>pKcDQ|!;C=C69u9}J-_bVr=^;}j$R9=4( z(rUt|P4_K%ZOLV^%$^3ut4lTG{ycJ;t88*EBz**`Gnxf;DmV6-$bLEsQlPJrL4jIp z{M0^Uf3m0K33>>2yS9*}UkN>~AcWnL=u|6%K=G=<_tQJnL{xfxmx#1Z(0j zyYZ%w2)`dG@0Y8!A*-f*0qz-40PlNSLInZNEYp6?jHz{ZdZBBybcw>qapj&^^$Tio z-(F32^v!#I%Na(|0uOjPO&jgf>^*1Lu(po;gzo(ZaC z#4T753_xtUx*px&HJngu5>?NNjNtXHP_DXWQ)|a=y$D zns2Ug(E6c0blzMC@eTM_9Ha){zo$8udh%V?Al`d7s2M#^&lQ!ptv@fo7T&+#pw$8^ zGE)@&(3Boecl%WSB`S`O;fky3mr$Fvf`*H7fhrLqk99oP@~!Ne8{`LRmHBJ3ehs*l z;;GOy)nLIL7I^=={q1dsu{_iP4x2OM_Om30(HFBLf-c zE*}#E-b5K}9DZ@Xd5zk_@m6EP>Ptkl3@KI#Ak$PP+*?UYqFPsj;t8=?>#qX+y7!r4 zkX;lm7lhQ&U0#)Q;}B`i0yisLnd$@^gr6kyY5Q}ge%yYg#a=~ET$FJr(BqC)UXK=z31CCGaA;`?~ss@{-3oKXJPzXDq~dGf(SI6-CY$e%`8A5VGvZ} zKN5|9^8auD6jXnQr6a`2!qP?j zZw&G`#v}4K$U|dqYwq+n@xO(ozW>$zwSR^G9jf@Ks0L3)-qyx5G~k`BwWqDyCsVCA z01`Xoycf}&RpX8rdt7Ln>%miHApedn$ndG4uXn4>Hy`I`=R1Ln=o*ircJVQfjfh$> zBrh+X_bsU(y`l4$b0~lsl{e%dI3Y1)8E4+#!j8cnE_6p)vQ1XZPbCrhO*H`muTRB? z-F?TFlN_pj>#%1mw7M3+{(&$=`y!j^)Pcl#;K)o2SWnkEhxXSEi#;hMY^0(M1XiSE z4sH@owPm5HEN%)&6LzJ|YEM7X2SxZWt6v|5U|`hEa39yumaN;A=47u)yF%4EJ%y2l zeB#!>;;5mUkLuJ-+W3N;-8U#CWspCv+v8K3<>gHm0mlX9E^E73R1g_voy@Eu|4N_E z24BtSi-l-A+}~GP(U=JVvd60`Tg7B* zp}W`2-IRxwTw6ecOt)@C)JjX26<7S7P5GHJ3XO72!_d=6PgUM0T$y%JmjoSOoII|z zv=S0r_%YaUfwtv0Q&vQ$1Thc1MggA*)!qq=FBZl4dt1vopI#P(*H1gidKLu2O5l4lm;2E%O1q@(pyO&d7r;j(8p$v^c1z3H@YDPcb~G# zK7^CeC%4nBRv&RUZ(E;?(oyIAsCLvMmG4~LTAFT4s5RC3u2Ps8l)wE=eoYlsgoG%t zJD=sce-s*_ztulkk3(#fIn>+P7>;}bAfy>6B%OORBc^kY@#FHzFxzj~PHF|=OvF2y z&*YxJnWSN4m!9@thXjvs>SaZ3w>^J|)|ou1CEynVret?9q>~KtI+9V!iBv?AUX%?6 zp?7Eyd0O{9(y_0g-ns4)aN$2hWqKo335L+)l~{EDjzsbfHJERI&$_v-8v_RriZ;~W z^Ki7)rY$DBd~VQTf2`exFlkP@KXxV}1wS#QwNT%Z6K9AGZNUpSXEZ_g9_v&Hp)Cx( z^$e%-8nKbYmI5dG@EOIBcIa85Jz~}~7eL6n5}cbU9oA`(prPwFk?=Jdw3!7tQ&z~E zFJ;bHNQ++5sX4t%4KIu51Fd zmXtl*j5&g(QHWYJF@{J<5{Z`Zx%j}M$Q#D?24-cM z#>Y@u$F5SlWuwk;%oj2KI4PHcSa_mGt?q9Et6x8ofk|@Za}x#_ehYt9!&TL?j8T z%HvRKI0E7@peti%puZ9=T=&N?tEt}J`g4otBWC&Yfl=1j6Z+J<%b)tkdx~?NNtMNL z5?l4mdS1XzIm&96B42_Gk+zvGxCEu3#r%F$g}cIXim9i2jnzc{%s;xH36@pxnc1P4 z0Y|I2LNTY+lyg4wU=7#|+-ZD(4Biy?LEAyTZj=-{#}c@HA+S@*X`QllM(fW?Dn>fn z>+|8UUD<$7!-0@ykmyykCQ|7BoBr$83;2eo9#Vz}__b7FW7fIi_vjkW21FBq*gOKY zxi0_xJXc-k#B5lBhgjix`xE=}cXGjyo!mRPCID$%`3-<$OEth9*!yK3$m(-e&T~**PbQ=*8bp)kNSLmu1IG!rJ%%Bd}7Wp`}t}- zzh947T#=1N6Ggqqk0R&ts?|5B&wFY)RZ4u&L#KDJ*oS6K{GXfwG`W*1i*-li;oqy_ z=+}n&B{|CkYat`J1%xPIoiYNM7PEJM3*f+v8z#ii6=j8^VD0G8yfLHiW>%Fkl znw-3Q{E5MPb`2}1P_euwM8j|OZ|09Dmi#Az zymyP?lL4K%{FT9e$liAwM$>b)1#Wy^T)VSvSIZaob+0&l(2{w(pADH~*G95BOD6qG z?MlTsoa5%np7boWig_rfc6D8`GmuP4T)X>ntuLG;O(4HT!EXBuOXkVKDTh$XMR5Mx zIUZ7e;Y@1gY!)Qt^k0qP9RtEFBM)YZMD!VWT z_l-o8j0q{*@G7sdWK&-Mtk-ENS7I}F8D?E`+D}gNC{DQU-j~4xT-5~1dg}^#jj~DK9THD;vu0d^g=T1%Pj2F3_gmb)*Ezm&qAPu;_ za1+^PA~>HQd%#cHEOzTAQsbAN0eXo;-`5*EIi`UQq9%6b&sVGo=?5h!OtK!Q-ed=B zPd?tpll)at`}}=flgu#Wsas3MgQ}K(2718)&u^WaKMg3E&j5r6v889Dph?c0uV|ZU zWj!X<1uWRu>V7liXq&vXffX6c-c~TE{z1WxkkX!2wY+JnniBUc+R^*$1VdMR*5xru zv3n;)vmK9OSQl3gbOhr zG*c%{1-+v@jlJA>-L1X{1-AO+?dS{}BA{;jBy#AFqO(-s?_jMG)+OnWhrQD-2I9dv zPO4?c!gfAc2hhMCNXP9x{Ysix8TU#;Wn5w{TDZpA$3zL);o-1#8t)GZK3&co0l~9) z*O#=z%kVygS?pRKok`iS#DM4zh=L~-YCaTL2dUO;yZ7e{HFNSY4Jc_B70PD3N~XT= zS~B5=sM%J0SOJ%0eEy`eKS5p1kb82nL5XZRo^5|F)X>gwS=`g#ic~w_#bi>VweoMRS*V%Q-xdp{<_O86Uf7-Ce0FK>{$RVIB3e?&PuDC%wgSeqRU|vX z&|uA$-(O)XwfEkfW-MFx<$bl^P{2P>)PNbcx%&jF(AL) zSQrP6ZN<6A&d*d5WQ6WvuS(Blv3x0b5sM<@1)}kUAw&`DjSdV!3JJaYUFu56Eo*gJ zr@=J}5ThxV@SMy@5BLz?JYP)acrJl`Q$AlT7wDAfp3O6s-wiBEzofpPES+!p7C5%v zm%Cp?S(zqkgKO!hsfThdlWR&$+Npmzo;GBq{nUyJS}U=_!OWnKE2Qh`3H)_jtG$si zz}h||OhjxFD-)0B9dO~3I5)(QVCri9A@Ze511cHlx$;T>C5i;YrA)rKM}c5sV{b|= z(}_i`e+W8m3c5a3_BN`QP zRjLOJwPvLEDGDc#%6-hkHpg3X^PyEeJl`e@M^AErtpeU?eOvf`n}LIo4yN||BjgGL^Qupf5s>bbg1&i(3B6MPEM^DhHuJRq)OH+lGdOOWHwzkeKoaZXH|eU zri#uf*JArbzy9vE7-?wp@-?jJFud*7iV~x-BOF=LE*xx&! zebniEB=_k2UyQ-U|NCZeXOhhgnP9g&A9PyqU} zEL~gvWN5Db9g%niPY1z+m9*5>%D!MU_IY{k=o5y@U8ijVipAY^^}`cQG_C>a$L$JH z$IRB9{rO?M5;8ourBin@-Xgz8j0&Xf77=z&%Upnga#fCi1rDtnMOc-V{ z`D&3xWs!GmXMW&x>fIH@8D#-{UALR-bUwT$L4M8;_5H#0*<^J_N!*)!`qIw^Mzr@C z;@)ojQwe=;fy_BKmyu;gpfeS(kILM&@!*I+Y8H2YVyG;Wthe3M4Fo_l!SBw2kz z>*7eYZbRejmqJMeQO_&d0Te@3Y5;M5%-uHfI?Yd7Eud>0yJh$QppohnKm7x*v1+W8 zFCkiH`qqB{g^r>$7$mSSXi4WprAs*KGR3>8~N zZEEYOmy>pA2m=W2o!XX5%aT^0`Ga~)`mxHw=Ux+=LE@l@2OjfiAs^AOy1;|N7ujZ% z-HJ>TYKJop-=N^-2pX}(I8n=t0!P6qBJDN}@>A!kFApacY?VoBz7q%6`YD>=EE+Xt zl^cNmH%!ujCpD@jdM;Y$88>h+UHRbj61});G{3EHk*_cjyw8%m-nE%Fm*w(6FR6Jy zJUbFlt#?kMKb`AZt~W4z46a1b5nzuMJnwEA{!<`lm8_a>IRxfb zK)=ftgt#(%bTDPemwKU0bjzJ}T~?MAEI6Wv@3%IluVF3sx%1$cJ@25T5pImvOya{Y zq62}Pfs1JuUHQ^3GlMcg$x`6x)2>PE@V)*|&4pW^RXOaQk(6$tE$nmU!ST0}Jc`l4 zUj3NV6KYc~&RD&5P&z;~kx3Yti7YAZ$s2IvTtI~c-^skhB1od}e{`N1Y4%~u-p4djlSm6JCgopL;anZt0rM37?>Ol6Cn>tteo)xRQzp4BhO z5I14zMog7)V|8|ns2{zcyc6K)k7c5ZQ=`JIr}syap0z`{sw3HFq!9AEMqRZ*9B>w0 zVjB2jONQ($@CqwK;^KiLM9KRf@ec!4BR$OS=G1TBy4M@X4*-{^&it<%v6gOWOG*8c z;Ud~w<3!0f8VCD3aYqHyk@mrN$8e8uO$kw94piyFo3dk^n}e?P=Dwy(yhetdxSQNW z$TEnZ(yMLxo&f9drUf}G!!HuAtMJ)|5FFT7*G*<L4296wd6k4dy?l_PH57Ap5{Uxl+_;J>Hp0&_5( z4gD$>&1x}EkR)*qQ!S%9ba$s^rKQv1`$M+>ei@Nm91V0n8uH5iB3inFFRP z{$$JThlkHRj7SBH^&_tX^Hy%XUHp-IKVj19!>}NYs;5NO-5d+ef+BOJUm9TguwUQ^ zH@QC#>=XQYnK+OR@CfV;$m4-wAs*NUon?NjUl^g)R348S%QgTSapB@p(E^`9^7!2P zf(*~kKT;VGR0jOoi{vt*@fgm!q(h;prT z@VJ68e|1jSlxAd;a~4r2X}ijwb>jJ@F-9D{n@c7}s4QwYo2_(-XNz8cGYWtR{CzR* zt1svEGnXUq*T_$DLyh)|>G{%SQM(h4{d%WG!vjg(j?4Xa*kW-t`OoByTlap`7qn#L zUyOoI$Vw^qUG?j-av$I))NAMK8RXPFp5SsOw;0C_au%vf#z*D&WG9ZW+tGnoIuH~% z3~moKD5iC*W;NXP?d(lCvJnGSixn3M=+Mb|pXlz0YrT=8#4Dq}n1%$1xo z{cFMwcA{8A!L-!elj)?-5vHZe3ibC}|KT(0uV4SmXSBb3rg>>Xf#YlE<7Z=Ope!v& z&&^Im1RO+|9CXmS_s0FPCl`5_JLTkj(I=85ojF{@Z2ubet94-G(OoA&31r1lARL*7 z+4=-Z6cYg6{Q&ox^iE#t~lh+dl%d-^9B38IEBTy3+bhK zF#|pY9tHmy_J7wN`0-6EXk$Go3^VzaH?X&7ZZ0(5{IQmaE&x}D|G?=-qI)s%n0UVU z2C+@7#XXC!sbovq)d9Fq#;xTwCC>gp-k&o|UkN)8AM|_DB1o5XOl8=heZ{^pkxovh zo9DKsHkM5&HU;gy)nz@5{xikwuCs~P)#}h>m4!rQLKewCRfyQ>=s`jss!v! zw-7bOXo8w%&(K5r*CO9$#lAMh3Un*N8kAro@z|1%jBOekSh-Ags!pLlH=y(7y+;FftY=X5CAV|+OA1=^tHj=kH)^TiHUF^`^_P>#3R*l)CDyq_IwZgmfiO*p z2wFVXDk zI)N3B3#_9Rg%g@4Z_`NMZi-A zAg8paC_LNYorw^|z)^Jm+edZ7TzY6{;tyeJ{=ubko-^A5lzr}D(?UFaHx=)T1quxH zJSd4U%k?RJvpOlBA0R_R_3hW+CWOT=(Yc7GOQocgGE&Crb6MhJ)KLA~VD_HvBz36~vd=g#%ExMO zmtDQYgei(Pjy}Y*y`3wO5T`sAH~sj&V4HkSbJ&Ec_qRZ}xE^!z_KuF1))1WRN-+vh zJ9#*&q|tEMID4IXM0~i_hRX4db`9dju+JFLWSo0MHaK`5H`T!u4VA-F5mhS%1^sUGx zMHL=@QF53jxbvHCpvEJ^=!gLe09~+f|L&W=btZL&kZ6I>J)3YoSo(uSYTEGF=9eIOF1Z)>@Uq*DwPwLc5Z)5^9D%lp!BH@f`1&36%PBdg?9n3@)GTvyh;D!ulh$bfbA{_zOSaL7gMM&=E3em#br zUkPNZ<#4VtHdLi3U1VU=MpwyNx`0h=4hYJ5ztoupY>!@26PzO0S0X`PD#?)5M>mU- zvH8C4I~73bZp7tF)jrsEwV^4-Nf08Fn$g=vhn@YirZw4nz7%?B^uE-kW)=rcr3FmK zbV>yE?f$i)aVoW9)zqt#1gw#+->ug1e65ix?G+8_$S~WH(U%<5YeC!wB*vzvL~QNi zA+XP}-x4zBWv(OFPAa+h#eU-K=Dj-GuR5GYr-y@(0a+ZFLO2F=eL8KW*~FK297$Tj zz!jIh;A4!t0-gFsc~@-4rDANQww(;)h@p+SwK-=|beRP`yC@L%d`{lf@`6NW8IAL1IX(pEe~@^sW>OS7aQ+Y7K4!PnnsIRNeZPu zREqYf{#nS;FI(N!=HZiuSoZ2c;Gb!?c_qC$aS>HjWC9eDH#)w@{dS4YZykJFYd~nNVMF?InkxG)zK2Cp zq#T{n!fBV0KL)MOK2E&pZho@fQPyf)KWs8ki#lv_SP*JjWOzoI=+BJY8fYDvGt>Qf zkH^!Yl6+#(Y#y0TRHQ98#ZVoa;~s;-cMhtWr@QC65-1Xs-uhlQk&$e zS(2$|puIhlZFNt+rH=FBedTuE`Rni837=pIONHY#LHZ4=`12ay){Qpyov;wK%K?@# z_l>t#bI;+q=Z|E^i?CL>w2B5j8WIpkhVr+B=s2SOm#!)hlFY-$y+!24=!()4fCR^Ix9V ziO7xIgd`ZB7unT$Y6Qvg<&j*?cE!&0nn_2Dcf+x*2j666Wz%Z?B=mgAc1z~9w>vzB zdedh>$dD{Ncw-ccw*ggZViKQy3L@Su@*+;n@kp5tj=2+4I-nb9W) z;|K*u_S#m!2$wp}O9f;!A`1)jbn}xvDN*+&{O!FeTHrMo zrnJfh%mX8oSYMMRl`f<=pO=w?rD>acnKKDy7Nu#w`#r7fKgwm_ymd*cHlb9Z_I({x zmAbbhS}Lk?@9Dr5!(b) zRDEo);T7_%VYBcBE_G}1di5QDP{MbeR2m$S>adNA_|qsu#e>L?p|3}ts2_}9a`6T~ z68*WA#u#nHzQP!A-_O4UAsyVhd-r$G;xg)nBc2&nF#I!TRm-{4Gn1Y}>b{+Mx)eK! z&S*^nQB@@Mo85F!wk#+Qlv%r2+hV&w9hJPIzf0OW&I!~s;d zpv_1V(4V@(LV+FYVnuaYx$h`8sE&h=Is)$Twbo|zTHAoCKX}^z?!=_^A{KVE#q3!; lZBYulMU^~r+7EqUzbF;@F0QSHHFsr%xfSKoHq2%2w<5=-b=O6wNJ%7hghF!} z`%kno4yTUODVI1dtDJ;MkLQ%bI)6RqIY-~;d7tO~zTeO9_j})$5f$YRfkFP&=jYGO z*S52$!da*WBPl(V9?6P;LT#X(p9n?;M&RQ|B2c?=LZ{49$59upr7iLx`~6G1Pj0@4NB@$la>UG ze;%32(NaA9sNzLTQdx{%_Vmo}f97oIT{wdvB}HjPHnhf5<6h$>?_^eC<4&3@o+AWfFo<)fJ|HKc1O3_?qa6#;gh}&0mas$)&eYg&efp=P^a_F^~`em>TxNT z+22bTnmRtLmxLX@>VtP0os+A)-I{t8GI}u@_%j5HKu*QXM7FvHcEgm@gS;FyH&bD{ zJC{c!<`t)=U#UA(@^n7-P3$1Nx^Ds>_?hg6wQa$6e7_@K=9 z?&LiL28pIUq05eL^#R8k0M}fpb(oK|BOO6%v-=-dWt69~Y~!^PH473*ysQQoo9qhJ zt=S0d$-9>QJ?6CTn=FaBnzxf`z1jOy`}Vo`SH}vf%CcgYM+L*MS?iLI8!w8&D~=ZM4k8x}e} zjXnZ+>4Bm8-n!ABQC-9of<_w6=_xGK8!Q)2JmGjZDsGawzK&bhFd=Uk|-Luq9LMPy!tpHy6m%{ zoN+4@@izH=lTWfvTUmLbDA&kiBY&DspHo)^oU&_ks^ zoez+|H+9EUPf+B_=d4?b9QD&OaM;I7AzBxFEdBjD>{i*Z z-~Ahhy6%rhpZHNu^6u-ys?IG~%%0qEcrT&SbhgOidS{j0m$~^&6)w-nu&&-7`Pc#D z=smTx8D@xB9NW#Tw8!Nl1C9=cnf{v6B+z_y7m^=Lx>2HYa=$oYM?#Xm<55e$O$TT$ zS#0h2CFF(bh6lEV_|;K0xjRcA1na>4rdwe=x}hu zEzacO6=x6mVzzJc)gP9wyBJHYDh&N)nFZU7ro|(pCYLWE!%4bL2U~MWvT8!}VX=Kk zrMVMb}(LesEc!cS@dy6{NA0 z2C_5BFN0pF7XY5euNkTkpP(L}9~;wav9hnNohc0SqQkfiOk3p0`3EPSEk3H35@FxP zorM_FD94maWwmITa1Zf3C2&;E@6PwoU#4<-nj4ju#{wz8H2a>_++-uFUwzoni156q zct49X=z@b=13pnm5>k;X`*}ADyAq5BdYFY=IHEVRr#G;(Qr+mxhsFMHT+jcm2({S1 ro(287w4AcAt`c-T>)E@$>r>FJtK=syeA5^7>r&Ch^;0B`i~auqfP*- zBiLY;X}f{yfBIRb+40{dErEsHTpcd z?yzmzHL2(G|C{@!Ze{CC(Y+Fsd`}ECPJsPcX zYp*2j<8uu+N}9ac-G6%e74CG)rSFn^S|fy6^7WLid=RSL{YQ37D_hx5VawIadD9wY z)sN)%slMH2=e6?1Z83g-$>_~DcmG}R?^e?LTP0kL$21OEr`~XicNTszOK5su-}=7{ z$M~|QO*xU>tSrBWDP;cF^Qm1*c1H_bTfcFvDLQpH^)4H$#2dxg3lGgYzT` `QqE zhBmA3blKhZ`~1Ck@-3HR6Q&k;_5ZoR`=Nb<({8^_uH|(PpPteWobZ41_ZG8TDH`*+ zYs!Dru|HK@Q=ORIEU&bqtI>W6ORoo?4}(B))&At0*;nc`=I(20FTUFnJ89*%4_rT& zZvFZHw){!ceuc+uKiL0oocT-o*DUL1-IKpIT3wUgy8ZMO&E^Nj$Nm^P1S~IUVV24E zc-bhu_Obi*O&8ymil5qcWtX->cC(V=HkQWZfYtoVt3Me9UU_-@yGuUjHv8KP_bp_; zX=C<;MMouj8^^I5yU(tUESjwqYj&-);2}5T%NflA{}{TaoSz}8;mEV)*82*fAZ`K0 zp!nEl$4gdEI3adsZK25h-&x0lYSS*6ZSdQ6D=%U#$hNIFe8XK9+3e&u`ttZh8GH5A zpyl^W9gq>R_B*#s>!z?QHSM*sU#D_CS9m_pX{*qEpgpRat0qbrd9iCr{G8Ca z>mSdzMbjpEoR9z9<#VpmfZIge_M`27Q!TmIv0JwBoQuw!XXR@mnQBse;d|R@waWVL z)Qg(u+nOS|3@2<|DN%5!UALW&bJbU=y_^dhI`U56`!C<3X)EYtoqnZiDaf+^HOqDP z7KUkbl&)L6WMc0;?G>&HBJ%p*j;^2i77WaEH4vzll9h`POK@gc9{RV!sqa&Vikd^6`s6)>&@ z1=VgatcebcUD;J`e2I@=N#;Li)7;rSpZ(P`YIVsi z=zn%IKM%)}j2r8Z9f@=iJO5CzUy}V~<%yHwds$4oqp~3E1B--|8!mnTrf)tzgveCE z4<``3`Gz0PfOx04YPzJtI&)X=&f8I)-7FvoRr2q^&0Dv-rra=v@%Mh^xY4;aW{U_& z;DTcB;V-?9ELvaGJv{=nMh2=1YBBo>hx%O_688Qx0{jCXJnD)I3~qFJSKalTNn@i?ytmb~H38jrLgd@rj<(A7)uIU&n zbhcc|wUQRGLO9hZ97~-4dd_pw?|I(mdB4B!=XZIY_r(MUy9fyj{TGl`Dq3)5_qB$B zq%je((Y8dtKoH0X)b8~I!3gmGLx6(-HMBqH76>K4ael$kU?Ah*cRI*GN6S!42Z0a} ziohX;1%w9@qfmes0C+k`z|>I=Iq4q`6#i%|dZQKKfDkkmEamQl-zPQ7jYtUYJaQCT-#8s(%KP3{4T~x{Y>lt3B^Vy|yJvNhIb()o12JjQ(ikddjn6m%+r6I(O(2MQisquzho%y?wQ1 z{Rnls2j$Y3mc_x7X)3C8Wy3Y)@aK>7ZScKC&Jf=bh1UP(Dp|LqDewlk}4ompb-*txp{l-FS5IrbrgX*VEFU!5c| zp|U%mr&GuAJ!%8qucu{*ITnnUD(R}^B9+^bir^~oY-9WW#kOUqZf;(uUUHP?72Yk1 zqa{awHWp^fKuBu8N2SJAVUx%-4VAX=lEfl?e)cLcLTobBAi zwE{U6a!SXV&KC^KJZZ=?+BuhpeL^vsj0_^vR5hANPKOK*pxf1FuTH`ag5lJ}j&_EU<5obMHE^{nIzP2FytS%VhPueK(h@ZxpXWpGt^>IAz zKU=F{m0uy+?R%qmXAs2?p81!yW!q7!b8=Xz5GmzL zC*)dX?kRh)=NTnaWfQnpGZDw$2LyYQdZ;mDX4tjwtg4u$_E8YN`}Uf|GAH^sQg5xL7`&Zux~co<$cC6<~E?M!qovh zvFEgvbyb2ODB-&>UL`{fx?mod0jx2gdo!+C4GIPc&BBYI4jb5571jb z5$R4b(;C1R+yMMRB*XxQG8uW^Dn|lJB!ScrzIs03eA!h@;uk*aPhGL@D2>UZbNB@w zQvm&(!ps7ui2T$~>UmFpQC&aP;2`hmW){$!T+YJcCN(X!_zMf@O)gJoanlq){jvie NyV>PqH%}3$e*w+D;Bf!| diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/4.ogg deleted file mode 100644 index 79f515e68835321485904ff87338766ba25264d9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1426 zcmeZIPY-5bVt|5G0mc_WO!J@<4vfP71*OFvsfj6!j24UsV!=xMLCWC(q?{4R`#J5t z4Wlhcc}QYP*- zBiLY;X}f{yfBS1?vzkgnL3rlvFQ1+se&)33 zjG+Ir|9qz5ZdxmxJ4-)hf90{=Ht(9U){U(b*K=7OP!INhk$6Y?UD^W~>4w;AN7qk_ zd%-sG*I5xk_E@W#V$+U@{hjzn&7kO|sW`XG*U|6c{*>~Z;=sn+?-xvQe7QCmkKJiW*N2mJB+X*N4 zW>x7qO{`G!m)>HqCu?uz>wkS-mqapIX6IGk{rWS*+nat1r@KbvAM9yQ9CDS5FGNX0mf`^P4(DdbU+r!Uc4cDG5@15?t=aN%a_z|6z}+&g4bw`NKhN^H zdDmu^?P{%zJkI0t=Fhy1@{Od0-?-gUVm-a1asBs= z_!k#0JaGL-qvMiBo2cki3tNx4^RMg-8Vd?^E=28oZDrj#HMM1)U$c+x)fJ8Jv)5jW zWHMV;Ghwq}UQ%|mxFBndh3!PuVtsxYU$&DUU%eN*x_nBQl#<4Q1I*JD5}Lowo!ow= za>)XHj;k?O^I~6b`1yH-{8aaY+1bpTZGV_de;L##^h;>{U4G&N$Ab4|!T-HYw>_Ep z+|@%#n#zp3gk0 z4rjkgx9G`chH@7PDR+Ibf++;@rixhEAmo5Ni|l4TeuT(;6PWxC<|8$C58e3t04RCX zOwW3GywH&;iv+e*b7VIQ2>}H!B}#r({Bux|aa5@~V%P4Dib$-j&(R#pR>Zz|3s5nZPd-E5@g!sG<8GzWN$+^v+ zCK;J#6{2y9;MS8vQ;pnTyLgXMd*wInZ*P5}(nYjXP)RQLvW@dZCMD{|27YZ0{@c@Eb4i{?-&S5-XQbB#QZ_^FgD1G}ApMz)IgZ zes)JA3Ldn~ts?A%K;z^;VhPav*dYJEhS^5RVrtP!60t*Bfi6SMBw8#)+mI+ zM*jk^zLYflPRMnaw{8}Vla+6JNGiKkz6*GmD_kNmH34WUhMR9* zGIXQWeD+@f+f_AH75|YbtIA^~b^SOq|Ap*6Ly(e4Zm9?pr6 zJDO7DBM3C=)>LqcvfK;Lrp1z>S9nj~JIf*00%37@Zc08%=2^f}%C1SR-lYLETY1_& zAb!ewq`u>U71^BT(1gY*DUcKPR5iF{WHJI)E1mV{BX>q(ZmIPKT`Pl5*UlbusF9Gf z!-8|-DQy-TMeQituD~{B85LWK_Oa8?-@~Q9Vo)uZv=be=criC?N-?^#1a*{eu(&rR z5Dmwd>&>0l0=<;J7k?F4ZjDTk0oTH!Aj1Y<|^jZMue z^v_p?EAXjk`Q?P`yj<%t)Q*Z=^tISUNBcE=Q=9j20%EpFX^zd{@k4BP-K!G?V;|@^ zuzb(cGv5_e1i5k>BbGELl1nMimOe4CIwduKhMITIxixpqjCM0=x6>C;-n!n8_j+!a z&bdf*Yu5I}!Y#@AD;A7Vq)oqIUNH&0|E0sVxuVe3byPOrs-_{#ggT-D+yEE~T2loA0WCXGAZc}1Z zd208Kb0%^DHby~QXG(Vu!e?RIk2FkMRfXOWp)x$P9^I0xaM8G7YAB}wJa;`Ig|Xlf z=p{yI>$ozQzx7~J6c|OfI|ExVlUat@Ad?d==8n-ToMuYF>%4aRARqHYq@GsQqJ-$c bt`A~a;O)oYeAsHI_r@tY7xRc+|2O{w2tUZ0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/6.ogg deleted file mode 100644 index 84653eb4846dc71f303aca4cb1621700bbc237e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1516 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 YAiM>X1@e$|{tB@`F&D^3l||zL0E3l><^TWy diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/9.ogg deleted file mode 100644 index 9060b2138d59ff88aef6e0e9c4ed2b22c247a96c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2430 zcmY+F2{=@38^;Y}sVs>?gPFn5*v3f6@`fZOTNI_lFt*7g6NRykEJ>7oFO+4C?Ul(<>vW7BR zMP=6^0bE$T(=BJLw=SSL0UG)wAfjP6-7&X-jsGUrYXW>g>?YnVD)#rxtRNQWio4_O z?Tz=sdwP2MI5^@+FbKN}_xy90KQ!ND689lQ83~JN{A#ODU4X`H!WuHJqCRJ^KQ7DTjyjXyy%j2E&35%Zmw@k( z_zuYnDPrsFirza)_z&Kaasx?Jbgqq_qS?En)t{)jo39Jk(R3d+bwG| zISK*YdA8y+wo*f>zP+=Jv6f`~V&u)HJZ(6bGM;oRvO=J8jYmF`ttmIbJWz8n&opG& z&;CuLDNRKeN0No5a5H)#93rE&**DdZ(CQs!3!+mXpM9dcX+dy^gG#1kg1UdG4aHDJ zdjl_pk<|1(n$n{lW{CR!B_mS4>RjoAZbQ@F**bT^(h@6Dx8`rA{gbtbjOFE4xM+vK3$&0nkVA+NUhJQo6G zV%l+c`rGv8;7+I9Nc~6-9abT`(8WlI&ME+%v21vaBgx6+l46uv6uNYq7z;Lh+bubB zTRoc)r+gRUr$-)n@0J!)+8$q1$i0+Hl-O6I!w>P&np^8O67TVzsiY?PH0&!0bm%+o zgKShVkLG#~A4iEWG_T&9&+f2w9%}D{Ogh7c(O_i`|fi#|sL{|2WZ>FXAOZ?yR1OdrIM5d%T8DXAkV|RD zSv9Ks)aI!d?6jd4X_wlx6*o;M zphwMi_ZKBw9XzyUrSx!OMQd3~Oe?NzQ2j?tsQ^wAg0sp-qO^V;#Pk&Nm(;~`eaLbA zycFyTpO&~x^h#D7!L*9EHcXBuzGOR>Pu5m6QQoY}_8E;-tu~I||2pmbk9J?S&G(eQ zh|5;=PL~yUfYmn~Ng77hzRrJ9U+t6Ydc#@v&C{`P`vCFQ(qk2tCtZc20^EjNm1j$y zc1jk6+HKqux4nmRJa@mDKe-QWrhh@ZaNnw7(>k%F#(GZvyec-jiqS&c{D@Z~f-H)- z2XC=XNK=h0H#6x17jnETJb*q<lE;Eqh3Vg{RBhEnJE)jm|nHDc5LVqzqD(cd_7Y z3|ad;l%tjPBH@yXkQ-Ov>2{}3=vkZjyF$(jw+Hf^VRg~z_d>|-(5tugm6+Tr9Cw-^ zn-RQa!i2C%ttW_${_oY(T3$vLDZpWJ<#&v4{(RFc#sxlG6q?Gk`oB_LWqcPgZDJC8C<~mo{YnaR%^AnbKm4aak=~5c0 zmzw(C*1!5yu~o8u{8F32QwfF3oGSr4RznzJ`)Ku=k7bAIWad-vvEjj`!)^x0OY16m zPAN}E9jI+yBp6QG)OJgwF;A`r9O;JE=erd0eF8q399cZ^!S{`|azodn@2a*PVkg5> zubENJij-xz?kRYo8;W*M^R?<6~EJmm3)>UCke@RU%Cx_@MOa_X`1p(Y?P6|U()kNE)*Di ziFwW6St+l-C1$euAtHfY@oyPwTSPtOcPJv2s+iNH*0)Znz zp$eV~39Fw$w$yzq6!G45EZ%n|U*fQg`x};JID>;F|2r|=ZD#eEYj~qc4cUhkiKL~@RvSLT9J5%&a^@WUWo7vK6ZHgwBpBsf}Zx`W6hxvJXCvD4o3Y09o zgu+&)6+)&VJ@JA(xDw{}8?@cgMA&DODQ>z447{q+ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/activation.ogg deleted file mode 100644 index 1af58afaa687348b8b2b657fe897c4e4c25e0d5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11193 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 V)4_lD3$6dFb!_b4-vF)k{tr3*gEjyF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/err_pin.ogg deleted file mode 100644 index 508e926ebff82b4987de03a3e6dddf6c1510a87e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4725 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/language.json deleted file mode 100644 index 1d65bfb3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/language.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "language": { - "type": "ko-KR" - }, - "strings": { - "WARNING": "경고", - "INFO": "정보", - "ERROR": "오류", - "VERSION": "버전 ", - "LOADING_PROTOCOL": "로그인 중...", - "INITIALIZING": "초기화 중...", - "PIN_ERROR": "SIM 카드를 삽입하세요", - "REG_ERROR": "네트워크에 접속할 수 없습니다. SIM 카드 상태를 확인하세요", - "DETECTING_MODULE": "모듈 감지 중...", - "REGISTERING_NETWORK": "네트워크 대기 중...", - "CHECKING_NEW_VERSION": "새 버전 확인 중...", - "CHECK_NEW_VERSION_FAILED": "새 버전 확인에 실패했습니다. %d초 후에 다시 시도합니다: %s", - "SWITCH_TO_WIFI_NETWORK": "Wi-Fi로 전환 중...", - "SWITCH_TO_4G_NETWORK": "4G로 전환 중...", - "STANDBY": "대기", - "CONNECT_TO": "연결 대상: ", - "CONNECTING": "연결 중...", - "CONNECTION_SUCCESSFUL": "연결 성공", - "CONNECTED_TO": "연결됨: ", - "LISTENING": "듣는 중...", - "SPEAKING": "말하는 중...", - "SERVER_NOT_FOUND": "사용 가능한 서비스를 찾는 중", - "SERVER_NOT_CONNECTED": "서비스에 연결할 수 없습니다. 나중에 다시 시도하세요", - "SERVER_TIMEOUT": "응답 대기 시간 초과", - "SERVER_ERROR": "전송 실패, 네트워크를 확인하세요", - "CONNECT_TO_HOTSPOT": "핫스팟: ", - "ACCESS_VIA_BROWSER": " 설정 URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi 설정 모드", - "ENTERING_WIFI_CONFIG_MODE": "Wi-Fi 설정 모드 진입 중...", - "SCANNING_WIFI": "Wi-Fi 스캔 중...", - "NEW_VERSION": "새 버전 ", - "OTA_UPGRADE": "OTA 업그레이드", - "UPGRADING": "시스템 업그레이드 중...", - "UPGRADE_FAILED": "업그레이드 실패", - "ACTIVATION": "활성화", - "BATTERY_LOW": "배터리 부족", - "BATTERY_CHARGING": "충전 중", - "BATTERY_FULL": "배터리 완충", - "BATTERY_NEED_CHARGE": "배터리 부족, 충전하세요", - "VOLUME": "볼륨 ", - "MUTED": "음소거", - "MAX_VOLUME": "최대 볼륨", - "RTC_MODE_OFF": "AEC 끄기", - "RTC_MODE_ON": "AEC 켜기", - "DOWNLOAD_ASSETS_FAILED": "에셋 다운로드 실패", - "LOADING_ASSETS": "에셋 로딩 중...", - "PLEASE_WAIT": "잠시 기다려 주세요...", - "FOUND_NEW_ASSETS": "새로운 에셋을 발견했습니다: %s", - "HELLO_MY_FRIEND": "안녕하세요, 친구!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/upgrade.ogg deleted file mode 100644 index 0656a7871818b06f4669148202006a44751ceb75..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5335 zcmY*c2Ut^0v!*wZCelG_q98~obPy>@RZ38#cLRhD0)h|-MJXSGp-4x1?+KxYDpf&x zlioXs1i0b(!SPY~AH?Hfx+sL>gxl;dFAeg5o;$=dWKoAOzdce@&bDdQb^~q~V zZu+sYtjZB}w=)ovXEznFhaby2*O__sFa!c)2Q;22^G-#|<89oI!GNfKof%ByqnFYS zS3Hl}|Di?`!0LLREHhGnWNc2z3iT#Er7G+MAt{bVo=%<&F{a(e?8VUK+&(rR1eBb73541w_h5hVS} z^m}&%J*|j2Uq1Y<@aXu8KA0xdhgsb;Zz+?}ql9zF?IQ6LMM_7Khk`bB6qsY=qlR;R zvJeWAfJDtk-G5$NmnFW?o_JhGajCVKi+#xN-R8|6%F?fF z!LTV@d;0&MX9a?KL71Y*WZD{bE zyD@8ABZ5rgWPP-r=w(rFTo{`n=+fgB`QDyu8Z&@5Ic-OH9rtF$Rsn=lZ|ojRpQdca zs?ip5N8nb+gD67oMgyM8H)Hk6O7qbIhH4De!06t3{4Sof7PP*%=LMLXph?P#wMp-m z;Mk;~O9-7_z5Wa8x77uowbzOS=^OWFBrMU@=rtC))l;fK@+c8YLf5>z;R$^k*`NcR zqA8M~aE5P5Cb%8sL(_XXW-geuzlosFHw+ts7S(Hab-vD(GIks3Jfy1ZR`YqXX8obw zQHrs}n%zfKCyw744!{2sOWz5o6p%@ng4S2 z>yI_BxELLWuo79vPqdK;6)|>iW~rGx~Xl!YBo<3NVtcafpsCe-;lAR*DOHU@b+@SSS5@%#Sprv_^iO%$0Q>VB{Hi{MO$q98PN;-v7t3erGoG3wH9DrKpxG{3kJLN`Z za~a+>Vn0R-#Es(mW|$_7$2nS>a8_sgG$1H##A{je=s?b&aj`U`P6tMsNvdce08qC% z$Da&0tfOj#QZ7+)r3NO3HNwA={5$f0Y!KSn5wB6oyDu z9N~|+IFZR18A>7l1P3^x!j$Eug6a+VR(^OVD$f_SQ<<=@vXWxA#C!iS+?j&FIQg2S zO{O%!&TM2Cl2FO-3#^JmVF8leIZE%d1<(-Z_l0x zvTvP47`HYqspEDI2BcftAT7nfDE{8aq?>NKhp5v`cWZ5BeT_)9WSvUj7f&U&TXT!x zLEjQ{Ws^q^ZxQ0FYNu)HKZ(iZ4IY_qdoK|Rjj7N$Z)**wZgllHyXC8?U6zSD!0i}# z+cP0BE-s-?w(&ky%!j(DLYU&XjGHmZZnKN}nZrJQ%H*+szZn10Ny4gzu>1%L9B2$X-@`-uzL2|KZUmY<0tR$t=LRFei(U+2i%tL8q&{>#4a z18=DMU-l)$y)`)D)wJHOu5LaqUhb|=KJM;NM^^`2-~&RJ@|nYPCoeZ?PS}IMyYkzn z=oBh3c|g&Lq>Q2xdO69f9*hl3jWYbaOCiA|p=V}LS7ZTDUd`^@o$y$htBV1LLn60O z`W=vFw6f=yRX#@UQgMqMxD*$!sN@i59-mDfpRd!4)(WaLt$Y&T`@-)K7!MGo)-dDq z-N$?=Q~uF%I`J(^arqg73xhBwy4r}g!=r}=!rqN+NFiCq-LLW`EwYEy^`pt(jU%^f zJ$Il_1oA__v@wLmm&JltGf=}3)ivK=hvo&BTwg5<9F#*excUI%Tq%V$D8JTxPBng< zKkmk@q6bgn>A0zpSe2O`9~E= z%Hx;W`El!pEE<|)^7lV_VjuSM@_N!_oEq(=xlvD2&0q+&0kNp6W+TsAoi7?D%?T895ols(={<2UR}m`r_IVN8blPiVU}TG@X!9< z%-17{>fAX&&eA2jpAf?X^+`RYvwiz{p`@`lhXluA${bj(CxJwQ5d*=s?JZSfutuNZ zpcxcTb66+t^S9VRt!o)-; z{XruS-5T7z#xi}4`gCcJMpHZ??XCRwXs@2u`o;CfK`>Jy&9?*-qne~%ZAmKpzp+L4 z_|UsNQ%4hciqLZOz)_23UDX4Zu9vU}!R15%f;OoGfYNcdXyM6%E zMc~xM)E7M9O~PNmVrP!HE9ptAU4~K}vl6o<31)4_Co)32rq?`&-Fd?I!RU6lCbRds zsons8Fl?1sAe6d>hI>$uQc*wqIuot>O>VE_N(ZDxCn+hY8?r(DY^Eac(B@CpkBxd} zfp!ht;o++3R&x}@EA|Vi$m0{-XeRw~usm~Yu;?iAf{A^ALwg}7u8qvFEVD4W=q`Cv z)7o(p0qmP#CH_D`KZ#y9by&TftQwUYOI3MJ{Bc?mQEToJGb2@JNk@t0hrRWD#e*e_ zHiP;KzMdajOeVOq!^2&tUZtWGKHj4S-|~}56C&rnTfFz!%#i8N;d{!nXB(t^{hoCr zvs>aM3#RSkaoIA%v}3u9JgTBLn4j^&dv!{U;`*r+HApB|M5YiAOn03*&LKEoQgU3? zV-Usj-qHRpnL~;m>vJsbZvyg{KiekRcM+?5U?R3@=%SUOYOK~|pneU$s<$AD`OOu= z0qT;&JnQ5)G&)4cYqLbjH@a^MPJxY%$m0Y{N6XOHg@}9M61pE?k7I zH?)eIg3fp1EZwv|&XVDYGx-X59Yy`I-R??Rq`z@n*tfQ1Nd0Q!{`WLQXK2rf*o7(= zh5*7iePR+xu4Zzg5TeZ!Rh&?;?WbV{lG=--{zv3z$%^B<@WT5)STw!3tCTZFZz1>Y z_Iz+@K#Xn*lYF4S9^P`#Ijsxq%BN4>0jm?9b6EV+Z9+S0xMOf0xsyQ3GwK(lwqCAQ z3ZEJB4aBCm4%}0dzOK!GG>z8DStgzP#_6Sr_*J8-o?)>hc-@9A#FpA``!N*-1#HM> zQ1=PzO_=xVNh4ls(Jbm??eiwDc-~46ODk8uzMqJ#cs}wanxt=NiZp;ZacLZdiw-VS zdt3@^vz8eAQ8;a*GVj$KGP|X2gyb9Ip3If=_-&Fm64*6?vb_4_eay2`?#|#j@_kU7 z@gojkf40CV7NX-hYAi~$7o%Hg8|TkKIh2*j13@ig_mS+N*@{CaX8TkL;Fm;S%oJ%c z&K(zTiMx!k$5JwW6PM~jzW`x%;F`Vrt$?%Z`IxatU@u3pSn*G}#rp2T-Kn@0q5O$x zhAGMn6~%<5`2@ZllOKA54Mw7G((86((rj+uj~%f5ZQx8Vu0Zo=fWcIn1^Ry2Yzpoi3WCK8an1%gBmsS#Rnu$2aMvGc3qB=A4%B16XHp_YDcd~E-!sg z3rSi-WUa;Vl)K+#0bjY)hf?bkhn-eYKMp*X@)m@-rAge7tN~Unbi z`B6fx?I&sS&NwdEB3w3!n?U5_s&BVaU~SHfN0iGcbwgg%u1^$}X)JHx!#*a zek`qwXZ4)r>OU+^)W!X8xqee46X94IIzwAZ?F4agbFz1T}?0%uO!Gkatl z+sT6t_^k5oNV9L2c$s|eU`{QGvp%OWygaZ(ocKZEfFAzjR;d50DbB(Ko8|2v;K_E$G%>w?kyWKP${7EF9R9c~yUEzTOv*HI z<&qb)Lk8cVM+^%f1c=w#t07){ZPL}s@`;B1j6y^kRjtWEPA<~)W;D5&7@#+LMyQD+@BBdPGa0fm}JXA z{HdaF@4Mj($~!~lHrZJ<-&rrX&Xl_?F{Gse+9>|vh;)8`)v*qvV-~x-uGL`{TA}+! zQMmBnLDB$+L0=RmnZ;R(y;V%GFBY*zEFF35Yzt($Dd>eGDkMS8bb}~b&|z2J|Kgzp zao!A{bqYVyfx#DOvc7zhGTKtcydh{w|eWya@84|O=193y1{6p zNpWS6d75caczfCiuCn1neS@H3?t&QG{B@)|CP}xm!a{gaUH+w#;=7|@iN+Z8G|%#C z7*!P32Ed6|uJZ7iE(66IB3C;V@m}huSzRaQ#p;dNy8Apc5n|3l;`C=8TveIArXntj z7k3G%X0OjgU^r$1aHGr=Jojl~+hV^R-1wKeJgS`hFH5T1OoJD!R2)Pum%0XyKXa;~ z$@r8EEtX!|-tG2yR<}R>CPY2f8%XgW>~!dAG!({TA~1lem46gZb&ghVx+!LRYIA7eQ+`T;axbucd^&jqlqvT=Ot)C|Opi&nqoP+OFEwIzJV! zOs#%_AwIz%t5dF5!}wWxGK&*Fn1^=BpftzV93pou2Yh6dTYOf~jP8#3Kk^^-TRz@SN<~8s2RP zjPf>V_Xoep{UX(CD%z(v?S-Pnv-tMc(*C4l%zk(Ewc23>xq2N8J*ugD3U?PEgrvQ1 zdwRjG*>pVbM`h&xO9TDC7IiEm_cu1`81$DlkskC{Pn-t&8=E2iw-u-T)w9q5^k3sv Rd;UEKoc0&CDM3c=e*jN`1A_nn diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/welcome.ogg deleted file mode 100644 index 59621f4db9c527745c6307f339281ce5332cca02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4566 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ko-KR/wificonfig.ogg deleted file mode 100644 index e1610afe57afbc538b551a922c9e686e4befdbdf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6474 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/0.ogg deleted file mode 100644 index 2a6fc026ff8fdc3dcdb0d7b355f5ec729faa55f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2176 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 E-@@s<@c;k- diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/4.ogg deleted file mode 100644 index 3a3ec0af0f01ff7db729fa909d20d070e2e2a3fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1680 zcmYjR4LsBNAKysZLd!$!+%Oa4Jd87J&f~Q+Y*8_!$uevirgoJ&3X@z`PN9E=n@yJ# z)iNoYJZp6+vNPpM=xI1lQ;6Je_qx~r|Np#R-|y@De)xPo--p-h8^&aYgS0^Z#wOb0 z8O<`8VZa3&g{2?l1|{xI0E6-1*4Te6VH*2?Lt_U6DD+cQKiEfOkJ!uP>H!R8@1Z0Q zS7%RWR~HwJ!yFiiX$($6;sGB(V*r{f0T5kLDf{9%K;l1z*EKZ*J|HxOHJfr1W#<~~ zkmJ&>vrp* zo=-neX4L(=kW#2jHh^REFk7Vl_1YnCP=m?3XOl{aS^FrD=nZkp6c1%$?j+_;S31U; zAbDU^Cbb&zU!-&E_000^kBJ?B=ilvSI}f0z?x>x{i@rWse3hy9$30XM>}|L!DVkLW z9-2gKyY(6oXZ`s8-QMKUtIMIOn5@`LI-6&Wk~9SSk4KWvhF^gag?`@;F1{;@D~L0F zYx5*tNTtVsj+f-z?p7sYz13-&Z#M}ooSS>%T zGtZ-_Yo`i=&ux9}Udd~$F1wOoD4ncTd3^AV$=^OV%`xiT{S27|Pd}pmY)eU{TXio< zbt_0l`ida@<#dW<)^yxo^yARVL?+$Icu^9-bUgW@EFCXxJE6Hp8M0(;arTU_!8!K} z`Sn!V7&+$Jq3V<9;YhE@r&&L-To+K%$M0E>A)_5dkywOYMn>B2zhoY@4K$^Sop-H# z43uM~eaS})mrPDuI7U#}(-MAc&CRE4sKIiqyt%KD-$=DF0~*;#tINwAy06;)lGZWc zwjm(thg`d;_V$-mCmTBM4$$5l8FE~cHY4esIyod_L>cH@2OIBj8X7~y(SG#dxKwj5 zK?A#mp!^DH;PXddkWWteJzd#1a2NF$XW{y{m%c8j%^R<*tTRr@qP6T?2NwZvhi;+- zYrXrhSG(fIpFLM!O&8fu4TBIvmrcbPRr8aRAcxhdwO@UrmT;@DRG~cbGNj`zq$25A zNhA8?4x;g-KAG5;#U59EH{D)RX+N5^xiB_NR|IYd?PHKU!!~gR1@k$VRlw0~c?Q_~ zFOx#^Dk2)I5=f$8x4hni*M3e@6~bY-_b(=_$S8VV57DU0LUA{oOXSGAR&Oaw;IOHb zy5U!LN3|?Zh2&a~i7M=}ygwH{{DSh3%_>Vs`mz|4?dJ7EQy%1o#VQ4xXKw1L9sR_R zV3`?;`Jx9S}B+sY_GMc*Y#@`FtGA zH2d~aBFs%FuqY3uD=pm+8&}!9%_eXg|LY$KSa`afbIlt?G(R=uq5r9kWwpu^$QXHa z=2;V24PPmERB`+@SntiEp->z?bI#)Pl`R*W=c2LDt~q{5KTrmtYblT^%65G!=Fj*! z1?5C-bY{p~HV^>vqHyHKv@id-&H~O1eH2PV3RYnGqsJmLwd{>d9+Gvb(0De_*Z>x; zDUf{;@BU1{KR}v5H?Q_V1!EHJ-}+Yz`IhKmwf=3O>byp zb(c-w;IXaB-G^VQE_fW@!MNTId0O4IbL#o`74pHuDLt+CNZQhGGKt!F4R6=G^k7Sm z%N%UBns={LHB#ft=9zp2X%pV;`||O$AVFra5U}0*bBQEtJ6^-qebtV!+BTFh({R~o zr@4Xb0{q!JZ;g<@AKH&8`t4)xJLC1p!NAh}R!}_f?ZP37Yp^??+TRBLRc?-Pv|>nF z*I11$xp;{DNEdFo)i%h|zcR7L8-NewQLREl>+At9JX`yJ_>|h~|5N~JQvdaq8hd&F E4F!<`Pyhe` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/5.ogg deleted file mode 100644 index 3dd6c067c76334bb2cb8fec75b36872dae14702b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1565 zcmY+C3pCSh9LJ4v$#mH!m$ERdTt_pr&ATQcjU}U%OO)C8_nJ#Y={giAy)NA-tWkz^ zS++LYR9L9ga!;ibl}jln=|wK@)_KpH_jk^7&h!0!KfmAadCv1t7>oclb+vz^b)mU|?fWScCRrFZa zepXcSK9V~LN1)i++5&7tndG4YVJz^2&sB^x}IRXAAuiCit z8b`{kEaiLeEb_?U`)C1dQ>1kJr-s6DOUC`o?TTF4Mf~BL5muMRbS&ZrN|zjoH{weW zJ`I<_F{NuE{zt19Hj2}x^PjFSvWdJhTOUz?ReL0-cJ{xpem0~#{e-?{1k>7|8jc0>g1=3Wa^KGx31%**^i3Tv zA|G7gF*}t|*&WMorx1oY4C1Ty@yQ0|Ygr;i8^E*t#OA;SKVjwP)s(zdB+bl_V%x4f z^V5y}>w3LCEwUSyOG3q_4r}mDW0|yK+AYh~#~MmH%WSGm$~&DHa9(x(a-P}USrJ?^ z^+9^ZKC+5_ly7aV1{DJoIDAxFBGo?haE0=$T+rnJu7xev7=;le~pR~X`!gWKvS_il> zlt!Xp$J^)4OdgPug=sd!*ifh+&&glE#eQzw2|X66F#?g9q&={)+GX#QeYU<)*g5Je z^U0~rb>7;nwX`O$j+iAsG0&>iO?W8Mtsu-rwZMjq0k#1YAv$}NVpwp#t9`Fc%cziv z7&lEs5BtDa{EMetHs9B7sf$jp@E@H%{A2lrs@_w0Ui{AP&z~<2HlZG)mIG`kOb=Zy zM{MbDN8H_o_w0hiT1d;l>c(+iltkC&tpwww1%`ps#viAboh+AI_NLWf_86I5N1N6c zGP5)aIaq)VgDi99$huK(?B~(_{#PxJZG}de<8-blamA*ZcgaJ$Pih)~J`r^SII^w_ z(L75?`RtMU#jwT0z!B-|l8%}SVm!#cPUZ0{fKaidXN0u`rK9Ofc- z6tMufp_?{mj7p^BO9#S>?H>I6p&SjUoTcKvbAbN1 zHTxJJ-=?n4(yIF~z)LUCwq8NJY2N430kDnM{^ADPatEZN-}aVNdG|UWuT7$<%@9-u zg7$JOCH}xcvg=-yQ4Cyihxkah>sdHftIMc|0N-;$uSxNqQH8VcoZpnbi2!J5wWhYT z?tH+7Ad+jb*x%}SCvK6-{*L<}tJI6!^DrFYccoHc7xyhiFLq1Oi>Fjlv4npB_@BW` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/6.ogg deleted file mode 100644 index a8e3aed68d5f9705a4ceddbf1d923f1e2f6f6dae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1661 zcmY+De>~H99LKk@%=|1&mNmZ}W6dTlMrR3^4PBjInhqQUMed|xCZSzFnmM5fVQ zoUq%lPB@&3Kq*fwD>@-2HpyM-MJqk0?MlTq%D+tZv8r^F6Ta5YCQY1_l0j~_GFzFTH4Pc zU`DsMNQ8D6L-h|&ssocK>z5K&dt4NPvkf^Y5c4gprQi}|0(bBI%@6w)vLIeT^M)D0 z{(7+rge@nk7`A}rGy|oZ5y>>Y-*YjHj^%Or{=3}3j4%vC=h;`~-089)2Y@uz~) zaJGPp3ZTO0$8fGe1qfz4@}9dCv*j3?NWgFg9#^jeNe@91En92pjVM$!Cft)|Zn}>! z;#el7CFi|9_sD)mEew5%?I3EB?mVck{xUYd*lw^e&DTTsD>A^{Y%Wbd(0;VCaZ+ol zzqZOJBs_R=49?&E%?=|o_SV;8DWI!^FOEozNg!;X*s%-bJTUSnb|z8dDE0*!ljzBl z`ZL<-8c>~&l|`7$<9ME524|%xn_XC`9aXgM6~Hy!B=x(W?Z}MdJVAWv8aia;%z2-F zd+y*$j>PTQjFjTgfuL4|$L-`i&^@5Vj|zTxvqaw*zIp4abT{>Mibgi;(Fo~x(zz(? zkv`et+H}#({F)j<91U>I&@Bphy2sJ|W}lXp^j0`k@#BgsK!1hj?0ua>4MUB2i2O!DnJHEb5N4(rj-*>FU` zqh_F+wK6{H`AnEb!-c~r-q)G5q3^+znvv^>dRKVwVJM&xP-F2d^4f!6(%UZkhi*LN zc^&dNL_H|)r)Gfx3Ey#Hd z^-_hWE&wC6g%u9$Y&A>>AjsCh=Q~O1U$_VW$FRni`QgZ#IZq@5+9L1=YAp+LzItuornf&V7la-%2^t9~- zK48VCE@7z2m$1?)aI!J0Bw?J&pM-$uvr<^;%X$4X9$U6MIbfqme=`wjE@_!tu^SXXO`La_Y(SvD&Bgs`%NXsJf^P%ReGWQ#{mXTzrx|( zUrw)JLOMGaRZ{IM+j^ogH3YP*d>|WjRpuA+)AE#obS8o{S(;f^yyBOECu(%1cXkE0 emT#~;@tZ5@e~JjG{j1L?{_85$e

  • )8E*VB>`3-oH^M}?6 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/language.json deleted file mode 100644 index da0e0e21..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "pt-PT" - }, - "strings": { - "WARNING": "Aviso", - "INFO": "Informação", - "ERROR": "Erro", - "VERSION": "Versão ", - "LOADING_PROTOCOL": "Ligando ao servidor...", - "INITIALIZING": "A inicializar...", - "PIN_ERROR": "Por favor insira o cartão SIM", - "REG_ERROR": "Não é possível aceder à rede, verifique o estado do cartão de dados", - "DETECTING_MODULE": "A detectar módulo...", - "REGISTERING_NETWORK": "À espera da rede...", - "CHECKING_NEW_VERSION": "A verificar nova versão...", - "CHECK_NEW_VERSION_FAILED": "Falha na verificação de nova versão, nova tentativa em %d segundos: %s", - "SWITCH_TO_WIFI_NETWORK": "A mudar para Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "A mudar para 4G...", - "STANDBY": "Em espera", - "CONNECT_TO": "Ligar a ", - "CONNECTING": "A ligar...", - "CONNECTED_TO": "Ligado a ", - "LISTENING": "A escutar...", - "SPEAKING": "A falar...", - "SERVER_NOT_FOUND": "A procurar serviço disponível", - "SERVER_NOT_CONNECTED": "Não é possível ligar ao serviço, tente mais tarde", - "SERVER_TIMEOUT": "Tempo limite de resposta", - "SERVER_ERROR": "Falha no envio, verifique a rede", - "CONNECT_TO_HOTSPOT": "Ligue o telefone ao hotspot ", - "ACCESS_VIA_BROWSER": ",aceder através do navegador ", - "WIFI_CONFIG_MODE": "Modo de configuração de rede", - "ENTERING_WIFI_CONFIG_MODE": "A entrar no modo de configuração de rede...", - "SCANNING_WIFI": "A procurar Wi-Fi...", - "NEW_VERSION": "Nova versão ", - "OTA_UPGRADE": "Atualização OTA", - "UPGRADING": "A atualizar sistema...", - "UPGRADE_FAILED": "Atualização falhada", - "ACTIVATION": "Ativação do dispositivo", - "BATTERY_LOW": "Bateria fraca", - "BATTERY_CHARGING": "A carregar", - "BATTERY_FULL": "Bateria cheia", - "BATTERY_NEED_CHARGE": "Bateria fraca, por favor carregue", - "VOLUME": "Volume ", - "MUTED": "Silenciado", - "MAX_VOLUME": "Volume máximo", - "RTC_MODE_OFF": "AEC desligado", - "RTC_MODE_ON": "AEC ligado", - "DOWNLOAD_ASSETS_FAILED": "Falha ao descarregar recursos", - "LOADING_ASSETS": "A carregar recursos...", - "PLEASE_WAIT": "Por favor aguarde...", - "FOUND_NEW_ASSETS": "Encontrados novos recursos: %s", - "HELLO_MY_FRIEND": "Olá, meu amigo!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/upgrade.ogg deleted file mode 100644 index 76bac60187551c9e3b1c267fa8569ef7994ee257..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4051 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/wificonfig.ogg deleted file mode 100644 index 784939fdb93e8d15102ac2b413a1a405cd9fc645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5471 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 XL==)RfoFjd|EC80-&)MM81R1psliy; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/0.ogg deleted file mode 100644 index 67fd181e23d808e2d299c3fafca7c8c980ded615..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1958 zcmY+F2UHWrAIAwZ3*|gG<0IU`(=SYf(_-Zr>3bfbt*4Fn z?zMS5?_eJc-k9Tgb3B9r$3!Ru`g;X)I{up&*~#HJag_M$q{s<&;>Pwtp+2`G z@f-^4?q_*c6HAhU2yZDOmO8Zr5A!1cw{8|j&VrmV+ulMUU@mH`u~FiO76VG$r*8IW zji7~K<3x#0U%_|*L$cZ~97_Vp3%nrozi_6Pft4d0Hv5U(eOKyz0{$*In>Q(ril1m~ z`S3nVa$qgrYFkb}1){NPbCdh^#zFM*P~8gUG3}!=lL<8iUBx!67}gr`0x!a_BxSWU zP>fo8_#vP?boV{^M_?I2LpT$!>tqg)>J>Igq8+9eN2EQN*|=T~y)Jva4wbfDp{Mq#<}%*fvpbrnKj0gO`WBnk6P};O zlGIc(V2>@XCKtVOR*zkWd(o=?Y+6JH80SDc5)VItWwWa#GM@$VN_TX{#)QN$Q;;k! z6UjFb*lt|m9k*U9)Y>~_8_}BO@lnBr)yXPIqBNa%v`)Lw5RR!(5(=O z&m>e$_J1+Qk`!Q_Tll<}a(ZM}e;Wo9;v;r)(vJAZeB{!mQxsvc%fd4E`9PgO_q;~R zmvH@S54@u`_Hd5qwobstkQ<|>h%fh5bl)YK7BrFR6hro^b-(^R=Z)X9zbN@)6Tu9F zV8sb638tF6tB`51Tn?_hD1nX|_LjX1rTa{DqC+_KjomMNvN@dmL!mJa}7z3dr+> z3T;PuAmk4F9zVI3(gJ!bl>!y4Uh;Yd?676h^vbkX7=eQu#TY){-1K^2c2IFMzcjGJ zk5E6Jc-!}PwpD2Za0^RPgwymX+WRy)=28<`F5qcPx@_G2o(1DN{$U;o)s4mM#z$0I zI=B}0#f|Ww-rg-moF0DTR7BlWjPAbJUh;420WTd2K=wK7n^aU-YH4a=MYBUuUj|zg zx`mJAaxp}k-nDFY0pJ4JZ*_I;u~nRPs#1s0JZn2NOy2Z4U9*bb`rpDHPnF|(Cu@jj z?AFZ=Z2k}h4mwgh$e#?szV7m|O9^a~tLN*eJBHN-My=CBr?;62ZQf~z#U%^Wkj7Ri zEwJZUlVaP9{FX0h*zy+wdiODRR)ncG$yia)iE{(s$&nVt`Wf@%F<+Xm2`p<=?T(+g zZh2_X-8+)`Qt`)9GZ=gznLHUzF76)@L>g?T$Z1C0R=j z$LIp#3L_hH&1QQK1z(e{Vlb7hTkg<0B{SMgUGM0w>SopMbL_??q(alhg2#_BTTWTIkIR{s91+VtReU_!=!@1i0_c(V! z`NFRjaR)AY1bX&1Gj=236d?d6R3E;Q+#4U-yGuWtXT(nR{GKwHC`FuIJt&2L?gvyx zn(Pc;_WfOoaPrA~wTO(2k)wR5^4TuP53{39Wm@xDNHsl!f*>s2nS%TK()doLz009K z=g`O)>ER<-PssoaRGF)LxIk*$8Gpz2P}x8lN_%cKM^jmpum7+tHVcT}(}}#ECE&b< z^oQO)*P46VASl_&t%83I&4}+wNmf5iU3Syn4gU;N!Wp`L|ML~jc0u)(nNs``r9emU z!xuR&LH$MTDhH?q!8&u6f=7rJ$b0jN9bf(wl6Q02k<8yAUY_7vbKq}1R4mDUKxl{x z&HSh@0(dK&*FGcjtBxFwp||X3+^|;#M^sYB5GU;C1$)^yv7}QFzM=vf>*Ol({Sa7N z2@z9~Hcd4QJl!6GfPm?|J46WKsa~PoyC-Ez5l(5Wdw&YEhWFQqHv%)`xPm382ODp( zHT=+bN3f(5kbfU-8n2PU59j0s`oj|ElHN7Grl8a-3C)tv`lP=->cp|lek{*7U5wZs zI<7YRzo}}w&7rS<53kAGx4(ynQyl|n#PVorY97zTp^x=#3f(-Gm!tkODlOx<`@G@! V960Jf?AX|Gm!po2GP|`s^bhu_kv0GT diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/1.ogg deleted file mode 100644 index 291be6678ddbc475a140b40b6fa5402ec0507eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1870 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 OAIbJM9&M0Eeg6UdhFkyu diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/3.ogg deleted file mode 100644 index b93d5c190d33f03235d975c935fe162b4e491cfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1566 zcmY+CdpHwn9LJ4jB|FE~Iiu2C=8_c67?qVsk6TR&~0MLm4j$k+O|Fww&L@plHKLNmO;6$UaivFFMdN8|!>CfKx5K3}!~72B z(#6_T1K&JfGGnhCnqh#hnCEF%!>SR}eEk=w51$t#gnc;5gc^`yg>q!q2G4QCoos$x z>9ZJGU+9<*4+t?GR)H(ATv}| zBKeQ1TV?_B=y=>2|A>T_Uqfvdh}2@`6$|NBTg7GeOvdDz5eL&s*K112E~O72AY77o ze6I-Q$?Bo*Oo0$xRMHYvRbI_!};4NX|8c*b~aFd=fc6?FdyFeb-iV%N9FEw@~ z2k(%`mfcQfAXGR8TE!Xp3X*Ga23g<$JqvgJ=j`KN>Mmw(d-OO+h;9mjl$3A%(!t?5q4dP7aB zTw}YR1$_bqXK@uDP?hUf^K@Fy58d1AA1ezPd5U2Zdp))%N@gkI*gDxLRoGY`dE1-R z%e1g0%KBTb+oY^!t{Un|cwat=4Bz}1Y#2@5cy~2a2Ax#ECAoYpFpQqGTdlx%a#v8% zw9b}>I(?-CBfd{-#&E8kDGOpJTa~6^NQ_>p0lP0_fa~o{>tjjpatP)b%{B?4^Gei* ztM+N&z|6S7%8UA%&vtZ$lNritOk4`eO%*_gz6DCYH%@1o8tHa*gH7$e5LH0}q^v0V?g` zCa}Ee;2kHIoOUB3K*)k*n|#`@xfT&3WU;_9QxFg9MSA+JJ#nv|M;M-+bHl7#Ie0#G z!9OmDqM`yP6f}pMS6E%8=(-PdQ=jSMw~zud1OEGwfVtK}#QDC=KAtB5pw}%|AL;1; z&|TuO=*OBmf#s(j?AM(l1x6g55cDQob*#eA)d163t9$MFYDUESI^tL@@19!4B+}gi zGD8WjZ}TW}@FHx;i?H^p*}e6`Z2&N|k72r}kn zTKHIm_*pXHj!CVCjt}*93-uOX3WvU_I+>Q@Z!uw#veyxn$2AD+lBYw+3;i)t-p0tu7>&PC?%4edn=)^Z(*tU!nt(}5_jhA^5TUe3X!g3N8y0-R;{Fbz}eCsVD_fv0w P|JGFGwoJa}^Sb^8#u4Jr diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/4.ogg deleted file mode 100644 index 3feff21b3572e2d2a7ab451e10a016fca675c026..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2149 zcmY+F2{aU38^>qtTSiHVvCLu_TSR6CQz}ftTQ6gYkQiddHe;+=GL}+VB3i_Vkd$SZ zd^KZx3nNLAELqN1+ws4$J09i&bV($~_Z)#+K zG%zwW+#*y24Ikng>W3#`1fH+JGeQeYBXwfnxlqBx|0K3-5paUoO1!nH*FN#kooBrS zK!kg6C^0ZN>|DV4V+1N#UHES1P#40X?rFD$#lmcNf?GBgiO4hk@oP3p&y)ZINk!-& zCdpV${B1Q)8IiO>$^s!SI1=bo+cgkw`qZ+HS0x=wiQc>!&csYeiSuLoY;w>Sy%4He z`<7h^R5b|F;`?qABS!8t<6HS3ijxNxK5ZywwpE! z$vQY%f@tG`jPV1x4<9~(c*tvsCf$O@>3}_D^4UTwZn@#`xAj;c_rBWE0s=N**L=EkW~*kf5!H$d!g@mEit)?I`Ss__WSOl^$=H#{KBvDs3#XH zTdp4D1@gv9>qee~lOVoEJ5!&YI6ex^QD@)s-*dMAXNqygylw5Zu7I^Usi?qTMfD4w zvjnOpgoO+ux{F-8&lLrhTx)&)myUGWhBCT}dO=dAr-MJ?=U^lTu3liFi~An*$vQnZ zx#%}Axq0E51?@xsADFx_iT+^+Hj~X^exL6gEZxi)NLQK3gRExp;*b0EYR4(+3|&xt z?X#yX0Q;`Dh(OhXF_#Wr>hh#rX=!100`y&C$6_k>Yp7qD77BC8@3EL_EL~&D$uvFM z$~R{LpQ(p8b0c9iwJ&xB#z!-9s)lpf#W6u;hiVnPm@R#U|Ednw{;}>(z3k8+awb9- zZZ;*{d8TH%fO2B>vR~E<_2*b?0u`>oQszi(N*_nNK9*3pOrBOeg&c|&)meOz`L*hZ^+7*sV+ zW@*W`>Z6}2y?kP5)5zJ8#OF4qrbd6b+Iz9?nQ{up29Dc#|_s?ao6pKoMVuR%8MuQSGVq~VAGCmpCQwruaZFF=qzNN5vG6ez}%G|F|o?L zUCgPyu8<_=S8A171FR=Syve@V8@(>E|E_5IMreuL+dA=L!P{Psu=&gV>!sA!;EpbF zBjFdbCN}#hKkV;mX=n$fC>AHn^0jxijmcIKs8IN`z|S5fpRGw~`3dWe2U&zFE6<)Z z2JPG9FQjl@S-2x+_^B)8h{y`X?U59L(d!G?-G2t>X==cYz4*1krgsJ-5|$@q-IOJ@ z!YAid-Jhbn?J69Rj5hSvBC10a)p>d+?_4LA`UuZhbkmDW;jdxl!- z+drWkcD8boK;oaTDq|Y!9s}Gz1?oe2^@pAjGiO6yQX-EB-`{+pK)-Qf zNA{_y(e_v*WH(U=zQaCoFVivfWxr#L)OzHAMK8l6c1Y^ zI<24J>-HqB9M*9=Tvm4@n;)=jfT&*nkkd*(T(#WW?SeO-1K*E(#q}~>$;H-z%4OE5 zaGRX!s_I;h$2VjFD&_86&~a%V0}eqE>l|%#7h<|2CrZw#>bw6RB0;DdnPZ< zD+OpE-XFcu_@m!gw`okw*s^`)Zq&?BlewCW5rQ8Syf~;-N9L|_M->ffqQXZOK(UH# z9iPS4=c1%Kg_if!13a%dPj{tEab9Pu)ha#fB z;%Mvi{yb~6(CDOt*FJCLcw#nW@l(z85lQgrv7h}h{J4T7yM9t|391E*lZQ2^BAvRL z6V^)HGIdAVaCQ5gi}F9L&e01omMVVkU>h83fYvDN=hWTXnfqfHBFf>naFQ$`lh#`3#z!%ueKyVY+|;J6)4np d_5p6YD^S~J(j!p+msg;-xvaeHdk`qpzX2UG+zS8z diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/5.ogg deleted file mode 100644 index fe56930fa0b5db0518cb05cb9902919b5644ea12..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1766 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 Lb~Ws*1Qg;Q6vcmg diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/7.ogg deleted file mode 100644 index 9ce02c0200ddc96586763c76dcb1732d4556fc20..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2318 zcmY*a2{aViA2tk9_I=A>hDk!!WEs;m)z31L@KU*Ikdp35qe?knmP`01mrEB;A zL~L<{APa8~F91Lv(CGF{V!JQ@H}>TK7DAYOp9UE3%N;y?f_Pao=RJtm^fc8^scW7* zxvx0N8s7fs055O6F^fa9IL*^6Qd9nhuV(;j;r|N58(2D4>=)kOl*&;vCn1C(p5X0+ z!v|dR#QS=p(O3*gSojDNDqGj0l;cf4{xP(sng*ir+;cJEbR!so91KNA%Y$__iT&9q%`k-nX zs=+gl*%Kee+0Q<)pj__7jLQF+efoID`+31{qnW5^C$Y78H9w4w$=t>x$En`ql~999 z`(>v;@5eh)ZL|BRHg=mwUHPh$dNr^%K@ULP6?=6~{fIBkJ;!`j5O;Y3M&YNASXW9;H%`aZ$=f#kez|?RQv1Oxo zcdd+JCp&(#Za{rvMNCkI@VjZ%6Lt(Vhj)jcl0n{$?DTu|e*MTTqUe?CpY^V}FDlRa z22wP>b~ry2x1R0C7Ls>S-PpAMdK|^itYU^W|rL;KJ_{mh9s{<4LPQpHJxc^ zZ)oDD!hr+p)ag0g3zykJ4z5q_JwMV%u3;10h8D*z>~RwV*!?uB+OJ&_<#NAFz5A4M zR!lhL!o0Zxq)wWu0*n(Bu+<%mLvg0y*k(;z#&4rQIdoZl7q|sdu94C{LnmNJ%8=SR zUoPlJ=bi^)ViA$v;lkRTr^cGH2impZ@h*<;5ONZSFwJt+BvYZ-K4}w*^HK=XwM{@sYZu!5#qSBrbyLmHhMs@yMBRMZRPMHmtvT#P zm<>v1OurjPc$i^GV30w`&-Pbz2YMIfQ@%NJN7!@wwARF5wcFD?zSgJ8vgS7ucVa5#z4+_aR+THx8P|hmgeSer=lSncucF6)_FO&UGz|q zmu$Y_U{#n%{iw!nOhRyYq}rI-!2!o2i^!B!F<|j z-b{T5yhQt=`jA(fbx{g26WN^WshYj2Wya8M)#|8FkWMxNg`Xp%W$L$m7tJHMd=hV#Z4(=I=3B-0yUB8(YkZ-Cpnjah@n;Ol`xoiBMS#Ut*h%Crr2?Vj{98vfm6 zXm&ppLsFC_l`?{)RpaY91XlH4DG-e8WXpMLymb`538H^q3ImVEju_k$DtD*0^~+|S zLA?m`L6$SN$XZ6T<4E9%Z~DE!3?6i_1LEpE+og`juvWRg{xWn5DC#Q@9yG3O^BF^u zQPf|B$0;Pl-jW`J!+2t)&k0#(@;@ztUwuA^(%&u=&a@F+5mfP;TQ5?C-f1Bk;{xyA zS{lQ04`B;dEU5`1u5XreLf+0Ap3BBRPIy4md%?E+N^ha0aKRY`QP&ZxVtql7gskf( zU4C;j7n5=W=q+Y8_soR~+QiEc?QZn(lC{kGCsGz}CDEU4zhL1D_DN$U8(bX7h_NO~ zk2L-?SYlo^ckATYo?#bPAxa*9s=uf1MFTGR;*O&_=C4xc_Ub)c+X@$#ub796^ZYV7 zVAbX?kNahE9IRAMKTL=#&|U4si4&}!15Al^(k<<+J?Y*c(bSBaDmzMjeb{J0nNGFT zF&XoD&DrlbB0{{F5(ke+Iio^oP`n>L>Ke{WNEs1EPP<5-!N zAcrp*1gM7)4&PKR;IqlO&VHU{v;5qhgq8g8hSGwijG&HxY&K6A95t}i{U6kU;rKtk q$2`cU2`wMcve19DIhqGq7CO*{X1CmZurAGR=>S_1c(4l#b^Hy-i8?U= diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/8.ogg deleted file mode 100644 index c5d3184e97faeef1af28ceec942f7a2a7c74aec5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2000 zcmZWqcQo8f8@7vBB4MNVUN=}GVzYXWo*=j`7Q5QA+A3Fx^3y`Fx~Rb+a)q!3SJaS% zsJTd3Bv&sHksB@Qx9l{XwP`Unfz`s6mD(K_x68ES0`d7H?d48l~4kRWdmQPo~ZtO%FnM zbJ?odne8LecgW9GQ>fSUA~@{Myi4u2{Z|StHHO{ZVf55G^8bqbh)V>qCOC#KoEO-c z+IUfo2hDPV9#-tp_3#Pa-DCE%)QayLh&buhVAE8=0+QlMWp!Fl>NH+(tH>Dn*!jQn z)!n4lgDmno)2p3?`oRq2K(=Ft&sar=P!FiDXpHv`Plyt95I$F)_4Dx6<>HWxX}ZVy zK)a{b?0#D))l{!AzJ_m@NOh{lLDuCoF@JogLaaF($a!yy9NmwwfRtEU%6jVrUWeoU zO3b>g7{7_p{&mj*=sa9@H7Gl@VcMsqf0Crq2Bot)==Zvew-q_*?hzwKXU;CQza=PB z4xzGNJSionlxFfmZr9Mw#lZXG#AEFM$uEF&1XOo@N*CL+s&LYY~1IQzWuzOQqk>#?RI^J*uV@O+>6zN2(xl*4hO3CS(|YcX zQ@(57XNOM5v}a1U6n!PbJ=jlBRIU=%K(2&|V{NBZMb0di_qojOL7%@_4@NmDkz_QV ztWi(+mgOm66uim5R^Ak=)w&+~VY4@*xfs^kRmXSTV>K&v>sfxLnZuF3@PU>-tgv$K zS3<3_O;IciEoGsm*cD$cwTlIW1R2RfAqGd`kvcr$$oLo?A%=6;)`4KB^9&pQ#;%x^L)wUTcG~w zr6R=VbTVhWpg<``mR_O(-waI(1{aCfn_h{+O2n>Q+pGF(DDQwd$&e^HgL$tSv8zo7 zEye<3qDeVZiK>n3$9GRO&3o$6;r5Kk>ThhWwc-VzkkIYvDtE%u7c54h$JE_80H6GQ zu_e7I#c@)Ah(Pl8JV5f}khjBpW1h|(YO!2;Xmt)(b!{i=izKHxNRVFLyK&_W!G-p{ zWYp)!rNO-$6Kt^gLvv9C@jfX#1x3z48RL*!N(%{T;h%RAI9>oDX4^fCHCMoV2R`jzPX;}5R_{q6TK1xp}GYw94T%f+zSXQEweZCjgF*%21SH{uLkkn*d2*#)Pgyjmi;V zR&+!d>$aagxL1;3;qfzeXrmj^iC{N?mUjaJ!g^9>eGg^&T64nYofc21&9e7q{+yI+ z5_JG`7fxdV3DHbW)wctF+sr|C7Dp;8S^dD-;Yp!SyGk^wF+81(SUMGq!)>cR+poE< zcpFt>Ns9HSe&P&}9&IEB{}KBoTUjJ z4?OSXrAb&=^$oX_~r}3Z8 zm{Ef(StIB5iToytZpjeF=7&GixDeNmWPFFJJD7$Pr?Qa`M!IQ26Hu3w{|M{;7S{~E zeArvIbgohqtW2(mCyJ8_YdNjY&&nB7G&2hYDrfOu$1%XNOXoaxjEnf<_qZd2F!^V3 zPbX~6dsxKXYeO@ulhb5w{9|Ga@ZAdw``5(iX&IT6DafcG41qvq0SIdGDRc3?f1 Tj69BGJwH1?o29?#|3Ci++H$MA diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/9.ogg deleted file mode 100644 index 1d156c7ce9196acd5afec43498a85a79138903e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2279 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/activation.ogg deleted file mode 100644 index d2d91fb84ef38965013a812ae19f879e8a76ce37..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15258 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/err_reg.ogg deleted file mode 100644 index eafcabc8c0db0a9c3396615d3cd104f078e77546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9224 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/language.json deleted file mode 100644 index d8ec774a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "ro-RO" - }, - "strings": { - "WARNING": "Avertisment", - "INFO": "Informație", - "ERROR": "Eroare", - "VERSION": "Versiune ", - "LOADING_PROTOCOL": "Se conectează la server...", - "INITIALIZING": "Se inițializează...", - "PIN_ERROR": "Vă rugăm să introduceți cardul SIM", - "REG_ERROR": "Nu se poate accesa rețeaua, verificați starea cardului de date", - "DETECTING_MODULE": "Se detectează modulul...", - "REGISTERING_NETWORK": "Se așteaptă rețeaua...", - "CHECKING_NEW_VERSION": "Se verifică versiunea nouă...", - "CHECK_NEW_VERSION_FAILED": "Verificarea versiunii noi a eșuat, se reîncearcă în %d secunde: %s", - "SWITCH_TO_WIFI_NETWORK": "Se comută la Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Se comută la 4G...", - "STANDBY": "În așteptare", - "CONNECT_TO": "Conectare la ", - "CONNECTING": "Se conectează...", - "CONNECTED_TO": "Conectat la ", - "LISTENING": "Se ascultă...", - "SPEAKING": "Se vorbește...", - "SERVER_NOT_FOUND": "Se caută serviciul disponibil", - "SERVER_NOT_CONNECTED": "Nu se poate conecta la serviciu, încercați mai târziu", - "SERVER_TIMEOUT": "Timpul de răspuns a expirat", - "SERVER_ERROR": "Trimiterea a eșuat, verificați rețeaua", - "CONNECT_TO_HOTSPOT": "Conectați telefonul la hotspot ", - "ACCESS_VIA_BROWSER": ",accesați prin browser ", - "WIFI_CONFIG_MODE": "Modul de configurare rețea", - "ENTERING_WIFI_CONFIG_MODE": "Se intră în modul de configurare rețea...", - "SCANNING_WIFI": "Se scanează Wi-Fi...", - "NEW_VERSION": "Versiune nouă ", - "OTA_UPGRADE": "Actualizare OTA", - "UPGRADING": "Se actualizează sistemul...", - "UPGRADE_FAILED": "Actualizarea a eșuat", - "ACTIVATION": "Activarea dispozitivului", - "BATTERY_LOW": "Baterie scăzută", - "BATTERY_CHARGING": "Se încarcă", - "BATTERY_FULL": "Baterie plină", - "BATTERY_NEED_CHARGE": "Baterie scăzută, vă rugăm să încărcați", - "VOLUME": "Volum ", - "MUTED": "Silențios", - "MAX_VOLUME": "Volum maxim", - "RTC_MODE_OFF": "AEC oprit", - "RTC_MODE_ON": "AEC pornit", - "DOWNLOAD_ASSETS_FAILED": "Eșec la descărcarea resurselor", - "LOADING_ASSETS": "Se încarcă resursele...", - "PLEASE_WAIT": "Vă rugăm să așteptați...", - "FOUND_NEW_ASSETS": "S-au găsit resurse noi: %s", - "HELLO_MY_FRIEND": "Salut, prietenul meu!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/upgrade.ogg deleted file mode 100644 index f4b5618b5893d4218000b236710d7825396fc04d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4479 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ro-RO/wificonfig.ogg deleted file mode 100644 index d536cdcd9f094157466bea9f7de390af99d14cd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5552 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 R(fYrvjb6w9S`k_s_#aABe>ngE diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/0.ogg deleted file mode 100644 index 8b3d47b5af6f715cd7733b2d1e52ed1db883fe16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1661 zcmV-@27>udXJ=CY0ssI20000003gSt*Z=?k0N6^VNpG! z&8;ftapRW2+Jmsy95~FT#Mc;5*Fut)$*HG^d3qr=g?7t7LXcPj>y(r)XrcPqkD$JN zA=C}Us&yNa9|6hDG^p5dC@%!6+r<@(@@9 zJ1jO^*3h!`YStA!;gcL?&bdQHwL6SdA+`MjA$JJU_3dwHhZB=}@?Qd$qQh>N>^H&I za&QpkjNH>~&|feMfu6mWz*qx2EH#)c>KFg5fC@++%Oh>n3jx$uP5BcZ>6N33G@Q1L z6RCuxhguUvlnFiEnF^0?14#lZ;SuR}W(YXPY(Cy2)a-ZP-%VBxW81)310+qTKz}wQ z{!R84#YHFd^W_eyDyQp~n6wT$F~a|i>7nTRVi3pH%8Dzk=5;*KR-OF?9@p4qGv+nC zT?rW08J3%~)wBF!%WuuUTzFUl-J?B9E|)4oiekxL?E}w6FMGMRUkT`dJrArKXaconFgf&S{UsBNXhSbh4zYi=U&i4m9-Jy;n(!f{)Noc5M z##eFKjzP}6%{g?GW}N>?e{+PjAxBa28VvdCy@R{Dg3LP6s1?&nOBs~-!{mbFB!|H! zicRvt4CoK9iS5!^hmhOo_+xDRCVf~V6vdlT=oL&na(IU-`W@Ir6r1+O?BsB8o}slbL>(uET*nclR&l2IP!peKZ23DAB_hGTr zxLD|O${Z^{#o--DmzvqvFb@%cH|Jv1;A1N+Wl19gxqDhF=N=@|wYtzj@5u~y;lQ$r zCTNhzXy69!Jk2uD8Q&upSb@)rG*&+!<42eJ~-?{aRV2MEyakaM;*n zL7`^z&%bV+rf}MP62MsM$bJBa4=L7>%6C__S(L#)eb9*?FvK&?{UiqKeQ23Bqqx;$ zQ?N&7gdl(e#RqUhq|WSGD_1Wa+UdgmwE8(_SUftV7~JXcN{CZMm(zhU=puDlZh$kE zo1P%nz;HA{K|9kQqTsCI;3_M4l4zm&YyeVHCqD@k>RPA3TN;uk;-Y4u&+TIPKzo745x-qHh8u z&e>qnSn&&@gV-6Y(VqWuVagA8*JTFw`jTad;)7hZ=;2~y{}E^#Bl$z5~PWFScJrP7aTRjC=^Jb4uH zeq9ce{5+ohoc4S3vl`hA(EWl78HbzNILH)6{sduaEz@lWY zSPC_*xdl<8d{SbrnBa1qz~>;g_&&U`9GL^ovoOPM6U+O?3EM1L_-{VMjEf-kE>#^l zt&5WCl!zR}t8SR@>u|s}`hZvhVY}STipmcdVYDPexp^;}L43=bfz4taV5A;Q3n(fm z?FPw!SON4YFyq>R8cZJ=oTRVj`dvM9DwDM*cW6~1b~!o*fme1E+fQXB0;1(Y?SpHo z+T4&RiO+^lXJ=CY1VqFD0000003gSt*aH9n0EJ!Sy#W(8>I*l diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/1.ogg deleted file mode 100644 index a9a3b23365d6833baa7d08a2a5b461f0985c2a19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1847 zcmV-72gvwOXJ=CY0ssI200000003L;6951J0NB9ay8#nVaCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G000000000009))60RR914K7>&0X5{ z$YvSs$5;c+HwN3eF%fgHCzMFOyR*lfh1S;ts^s#^Hy+XPEdb%`V&%YDB_c`GJ2uV8 z>_|I>>1Zvi&vSh@QF$evkrowA)^qf)G0#fMSOc{w2q^tfN+G#J?Y3G5(ZAphoTX%{ z-5U^omMWlG#Gx3cm)&2am+eDHi8hF(;?xO9^LSr;kTF6q`+IMN&9)3Ue0#uH15Qa0 zY<2^h5|l*Jf4q)>SOZQ<+YmXWR3(i-X*BjP-M2O!N0&6{EiUQj0Fw4b%1esjJjfeJE5FaU z|NeN>#hVsh=6(U9sbrjZFv1KFSOZQ<4Ja{QNMWFGz_(`_Ei-qJ`lQglmO2Rd{ zY8q*XmLsw|)(q(#Dl`BOSNxzeFKr&0nJ_6-Ak0@gLl!YoSOZQ<*F!$3@7oREYWlC~ zW-!DEMJ>qL78X&4WjTfBou4_`6rhN(pQ>HqjU1X#`Ij_`q21APn=s zM$FXj>x!GH&U$5Nz4bnF;&g8BT4H3hN<61#%~J!yiV(xGcf0Q|gCbgl21uDcF}-ao zq8PJ#6utF>(H)518%1HzPFE8@7cfm6<UK2!ND|zwhio6}PtWGU>(zb+dT950>hd1{I;R;Eb5$paN-r8IKNg-Y#UuaCO5FOwc+YCVUA7EDOEp}catJWOB;NESnc!?v2N@%TMR9J z#=%=f#@qXfiBMARK_X(7ELuzbDBa#(JO5g7f+XNghKsnB-nHB9bZ7QduYD*VMGd*0 z-NFgJVicIseJ`P2!vk3p(OfuQzvFELVJYZvl7qzl+4WkE^ff$wkCBPlNOIl5fLQDG zeRLW_vCSKLRQ|kcv=;u79p#D5mVj6Pc}H4)LIuMeufp+5}Yeu;DxY88usV* zIUg-b(m_0sy@Y=GVxl|W-qZsbVCb9TxEgJIes0%LJaH4nxbI)QO!CHadL*N}a4sNf zF5EUbX2~+HR5%gdvOoAThg+xvSy<=yFmqHRa5lP`dD&iNoE%T9)|kPNIslcqF+&Nh z??(x%4>s@DlCKXD0~%#dt#!=0;z^xfHM3!~!IU`Ao6@&*C+2DGd*%S{eV_e(uPJNA z0*ijWWc=W*!@UPxACB9RSjQiY#Vc&tCa*azWgyUYyT>XVZzaaAw2L>GvbW9h-Vvg8 z{4-n8)YD83)qXZ^G;Wi6+U<`%e)wPLtbse4H&}HK`QvIgP{~a+z`Hb3v}dPn_F!Dj z_xzO`Y4S9+?p1QkZiWbpgd%>}FGPs|!QLiNSOGG`;HWCxX_X8azmRvP!9xKA6paC9 z3C&DM8#;UnbI4eI-sC zXdrWmC%8Wt9A#%g?ra=b(+}Xc)F=8O0^;L%x0}w_o$iz@u;fqgKZA{|TV4q-w=_JY zPiJRS00czD0000000016>=Oe3003}pnkfM~SOx-FBcn*;A{&{f6!tMvSre&$J(~Ik lL%`wr+VIp6SvT*kON6D&IFL{pd^YveC^%~!wItM!SWx)VOV0oR diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/2.ogg deleted file mode 100644 index d2f6b4dcea0f424dba97c4226d857d4b6978a9c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1215 zcmV;w1VH;wXJ=CY0ssI20000007k#HumAu60L}LEOP$4IxIOn^($(P^i@t|!c;fW2ORq0LXI<4 zUg|u`bDF)f#syS`N0Skc;oW{JDls{9*FG2bKA-LZH1trCL?J*}=l)}N#Hg;|*`HUc z%*$Ck%&Rg3g;>BQ1AG>`wp#CtGMh)-{^vjlkhID(eCmVu`&Tcwz5wX^H0ah7)}S)N zG9a_Jrwn~&XbX2XF!T+{UMv@F#f`o)rL$q`{T4yPW#MKa3?Rh&dU)zh| zTl3qehF(3LdVuD=Weo26GNBD5M&#$*46@}J@Z=W|2wYjx;wSa@%rDLkpBE0W)8)`! zsx&R0#pUV^{G)J!tsZTfs^zi%{UQ0qE8KS%7Fb(NIM)zRoX{4whP| zlp*tOfLQDg4P#!{2y&MCQ3s&Tg@H*BDTmyz@w)L-Ou+eFD*`>RH(3tS!4$jreCDc{ zuD*OCNu?-Vd!EAT1tLP$VTw@5WTLkB@(4*`QeMMIl3p)V>L)SyZG=nL%s} zLw0>|IX^J}H$389Z~;AnFMlmQE!uZ>q%2FCkp_qpT`UH=<=QZKSTC}xSMhEgEa2B1 zBx4E!+@}q8seNM*N|fT}4}}ZsDNAVvXZrl#ebK*p)l(M`SnD%;?2z95gx!~$A8IBJ z3iG-{zYIq$+*jnw;v78X8MJ+0IRSVS;$@1$N`Nm+Bi!u4|<| zSi{Pc<}9Q+{tP5=tTi)s9%}H#LEtHZ6~jLSrG{JBs^ickgK}^zHo|Y?v(az) z(ub6W`N>n0c5%h~3;dY%D9c752lX!?Vn%?mq{$t&Z`NM}NptWDHDS@!oG9JS8j?T# zhA>eI?`0n?@z>P5SPYn=g~{wdy?a=9+){Oe)hMzK1f*KhD5p2y5v9)$_UFCPvA}{& zk`eHr+G8*8co|(vw(I5@EcuCt1}xd3s6ZxAM$ZTKfLV9zjKlJVCe808AXoyBHVcp(zU$m-k>DO_qTzAwXA6h1m8uBswUg#VLMcdq=;w@!uwxKsMEJTl!5v8 zVL5;~Z#LYurKpti6)#1BSselU{*LM7MMhdIi+>SIGqB+t`I)I;LG;#m{ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/3.ogg deleted file mode 100644 index 744ae4e5489aa919da56eebc106dcd75fb462c2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 854 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/5.ogg deleted file mode 100644 index 9c976d7fb786cb1101462034974e94aa083a118c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2106 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 JtkRyZNd^tp^|k;2 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/7.ogg deleted file mode 100644 index bbb3cf32ad0a597d1c17301be74c702ea12c6e39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1103 zcmV-V1hD&0XJ=CY0ssI2000000CW@@X8-^I0Cal&2LTgLaCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000bQBtA0RR91up2-`0XYW;S z94)^VFkr{OULf$<|E!!l{pcEuWeX(;Smc6M0#rTH+<*+oh&<5rpPd*ynJllOgU&U2 zk?B*H!xRm$>(-UZl8zZ4rxvRr4vd^NGz$`eY;-Hx?{GGTWG|=_f<0-Sy#vySmeqE8sul)P4o#5 z-bSw+`Gw@9MciRNXWpxJoTs=luUOQ83p+E5*Bt*v^aikOvHm9ehZObR26i_fCq3n9pm%1I%L9fabfKHJ1TU zud!H4mWVAWzZpUfW^c#DiC|dkE6|mgeT()K%mjFAFV_c*+lFQ4GvIszp&hf9pHmq| z3G~%#=L;HMvTLL$K~o^_Lo=F&5-mUsFr~vt^)nxhC9^U4Y7Vvih@xTC7lq$>b%ly5 z_CoC9CUY^cQz%Rqf3vg>?~*#k7|Y;T=r_=`5C_s}nxMP9hUFQ}u+<+h#VXnLDTw42 z-CcK8s@3XI6v{W!GW8%T{S&SWiYJlZ=P6d&Ggq0v;+kJt znIk%+X-YHVCP&093&9% z+S*e%*_A0s)4*5-U&aMpp#a>hpF)>Nab8nM)EY^BP|H$6K0)(h_{CYCj_l*|+1` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/8.ogg deleted file mode 100644 index f73c590592e788858cb7dcac5fcc48d238b3654f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2557 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 ~7VE1_~kN(e>3Qf+G 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 D(anc` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_pin.ogg deleted file mode 100644 index 1fea3f6b1395c2e4e0e3888bb70e4d26e079b698..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5773 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/err_reg.ogg deleted file mode 100644 index 3d585f9eb52b109f726702b9d274b5badd9d00ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9221 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/language.json deleted file mode 100644 index ebac6069..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "ru-RU" - }, - "strings": { - "WARNING": "Предупреждение", - "INFO": "Информация", - "ERROR": "Ошибка", - "VERSION": "Версия ", - "LOADING_PROTOCOL": "Подключение к серверу...", - "INITIALIZING": "Инициализация...", - "PIN_ERROR": "Пожалуйста, вставьте SIM-карту", - "REG_ERROR": "Невозможно подключиться к сети, проверьте состояние карты данных", - "DETECTING_MODULE": "Обнаружение модуля...", - "REGISTERING_NETWORK": "Ожидание сети...", - "CHECKING_NEW_VERSION": "Проверка новой версии...", - "CHECK_NEW_VERSION_FAILED": "Ошибка проверки новой версии, повтор через %d секунд: %s", - "SWITCH_TO_WIFI_NETWORK": "Переключение на Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Переключение на 4G...", - "STANDBY": "Ожидание", - "CONNECT_TO": "Подключение к ", - "CONNECTING": "Подключение...", - "CONNECTED_TO": "Подключено к ", - "LISTENING": "Прослушивание...", - "SPEAKING": "Говорение...", - "SERVER_NOT_FOUND": "Поиск доступного сервиса", - "SERVER_NOT_CONNECTED": "Невозможно подключиться к сервису, попробуйте позже", - "SERVER_TIMEOUT": "Тайм-аут ответа", - "SERVER_ERROR": "Ошибка отправки, проверьте сеть", - "CONNECT_TO_HOTSPOT": "Подключите телефон к точке доступа ", - "ACCESS_VIA_BROWSER": ",доступ через браузер ", - "WIFI_CONFIG_MODE": "Режим настройки сети", - "ENTERING_WIFI_CONFIG_MODE": "Вход в режим настройки сети...", - "SCANNING_WIFI": "Сканирование Wi-Fi...", - "NEW_VERSION": "Новая версия ", - "OTA_UPGRADE": "Обновление OTA", - "UPGRADING": "Обновление системы...", - "UPGRADE_FAILED": "Обновление не удалось", - "ACTIVATION": "Активация устройства", - "BATTERY_LOW": "Низкий заряд батареи", - "BATTERY_CHARGING": "Зарядка", - "BATTERY_FULL": "Батарея полная", - "BATTERY_NEED_CHARGE": "Низкий заряд, пожалуйста, зарядите", - "VOLUME": "Громкость ", - "MUTED": "Звук отключен", - "MAX_VOLUME": "Максимальная громкость", - "RTC_MODE_OFF": "AEC выключен", - "RTC_MODE_ON": "AEC включен", - "DOWNLOAD_ASSETS_FAILED": "Не удалось загрузить ресурсы", - "LOADING_ASSETS": "Загрузка ресурсов...", - "PLEASE_WAIT": "Пожалуйста, подождите...", - "FOUND_NEW_ASSETS": "Найдены новые ресурсы: %s", - "HELLO_MY_FRIEND": "Привет, мой друг!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/upgrade.ogg deleted file mode 100644 index 69fbbdc046534d465bc51b4713c21c1977a88fc5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3396 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 ahVSiZzKBg(41TmxaJ}oHxw>;YC(4M(#%4YM diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/welcome.ogg deleted file mode 100644 index bb5f05c237ecccdcbb4eff8e2c3d63cdc53daa1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2327 zcmV+y3F!7uXJ=CY0ssI2000000C~m#R{#J20Q-fBPXQB8aCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000dBy)%0RR91o-#G<0XZIj62D<<@6jKz?y~jAP9cCu)m^vRT3E#C5=&^^QZzw-wY?rt1APcz(B6c z?jv;HzDp$YF!}ap^R8GWOX)T%${w)Xb~l_pY;7R<&4GJsdB`Ldv(>Rv$7DOy8A-q~ z_iqEp(@m}q*2(e3E@FwM-Q+XY!8!ua`N@fxJN8R$Vk(R$52-&FOKM82Mc*XEP4MxCc6TL1KkIkSh0}SU(H;S7+lC1ufnoT#+ypPczBw^xC zoTIy(W2oA9a=ZZ)%#(oW<>mm3_@+>~&z2~lZcd~eB(Xn$SO)S!E(E}C(XT&7+o`aq z=g-$PJTDy^?rP+rU?_E7l{S(3qq$QJYAstX_D0kl2&3|FD-L1 z7wD{@D?6=;SO*D!BDh66sz%N-t`W{^3iz`D)iEF4V@Ggarc(BH0L^w|{2%)dB!DG} zgEiUEo*- zDF z!w%{TTiAJJjB$3Sq6fiqQk3Gz+)0pQnBIE0WZ<0!t%SQWgb;VyeqS zDGA6}K(x=dZb~t$b0)^{OY|R=6i1D;}_wXfKsd+&41OP z3!kUCVIs8z7dZB@Rf7fC{VEC2r=;TK<&CHB;1v6~c31_NCq9t~rK8fjL)RFKqBX?> z$@*dm4BT3%?OU?$!x@Sj;wE1J?w;4=H?RkeNu|fneUl|7hPB*lU}k|YAu}XB0rTtP zEs6zA&{zg32XOGw3k3IHaGZZ)DS2hKt*t3DUxegQ-BMaVyJ4w#7hMCBMx%^KgOI7g z!pY7A**wqq+T2MN(sY`VncTXVPAykSdsuNhG2cXGV3@;kfJ?b>Sl~{0|6&@9Pfvra z`U&!XlW1eYxm#O6v_8ZLsF=u*(a>EdoaPp4xXgvqAW|Y2=7BiGWK))id)0t3Y3O;g z5B7oFF^H%wIJ37f!-Tzs!sjABx5gU%O;p~a7uV`#^zNH1r544~>LKrB_qwAN_kE4D zfLQHGPYQPjT_Q-Tt41>`B+G%xo~Gn0TTjaB zCLl9y^k{JgG#0Jw<@-beFSx(TBAfCMS6)XaSs= zj}bE7al3mmM>2C@OOFeFPX7>f0}%4txpfs$9YeaBCb=PZ;&!b3RX}WF)c5(<;-M)` z^y+FgGn$uJ>s}J(@|g{q4Ivj^aM8S?@*FkklcNGn`+N4t55QNYZ(qe3;hz2BTIEyS z;DHqOMVadhJ`qb4nhxQi96)3rN;%+4Yr~DX80k(;MX+~P69qd493c@s3HomI|G+-k zrw0Wlco>hAO$P;u$c*O)-ziCqE4xi6&63qGG)F{rD`uQ&uO9*`BYRlvrIqPKnZk;b zT^D#+CS&W}V~Sgjo^^VG8{k2rS*jk2{GXgTD=xNCluPF&J^R=mQF6`N$Fa~WkX{93 zO==eYzULWv#-J;s6z7`pS{-Co?#Vl$>{#uzTZ-%oewsWzg8#$Z|GcQ3aLuK>1_sdzLMfho-#ykur+H(j zYLj>L`&+wA1ZEEE3Nn%|JaLU8G^CFCPiggLA zRiG3S#(l+$yoCp6s|v zYr;)jW0YKWado6qzVbse6ayuTCbe>JoqMROB=p2n-3g2bQ-ZZ%QA8&7Cu~>;b3^@N zKU|>emDuKyF#?e4kB6^2l11T2SJeV{I3UN4YKEAiO|-zfHdpBfs`%JLbNG3QAHgB@ z0N7bl8=ao@r)=luI@rEn{Xg*zFj(e2#=494cO42z9Je)U>8R@9FeOm<37KzmIfHA= z9rVi?zU>R*pc?nc8(v_bP((7;+ zOJa#& zQxpB|NPL}q9R)$SBDSOpx~yN=LUdDFbI;~NO2{v^i)!H3d7Zf*qAuz=(V z*brlIvz{z*Qr?+cq0zR)f!T3{bi4j3nN!smCm1p0uAedDh~+h(?aWvMPD>n+Rx?%7 xe`p2tOiU;v*m1WNRNb$mUlN#$&MC diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ru-RU/wificonfig.ogg deleted file mode 100644 index 0a26e2b8ff44848a1cf7f01d0aad1f9ba421a8b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7563 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/1.ogg deleted file mode 100644 index 8974741301001642cddbd3034bbb78e74ab3ebde..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1940 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 WdD!~@`mW1u9_s|EW9+{9X7@jA+4Cy^ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/3.ogg deleted file mode 100644 index ce9635e2f89b186dd28ae68e2f484389650a6307..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2105 zcmY*a2{hDe8=pZ81~t}XnTauI5|X$YS#P*gWadLtqsBJr&sefIgpr22T1=TDvW7~s zjF`zXw#lb*o0Mz2*_C}s)ZmW3?|h&8ob#UZ{NCU1dCq&z`#k68OeW(%BB1}qWSQX8 zR_f}W@ChvM92|bp!I$I%2AhE!i9aRITk`+KmK-cZ_c+~-V9b^rPaZ=)cnA6ThGK-Aw~#Y37m`Ns0DrF_Vc~xoTQvxE!q{rO^{7yCZJa*Jde`1CgGz2PM!rh}i#G}<=Ah4AaBM&*1qgna7k*Ey~ zRcaF~j;{kr?wx^GG+#L*t6Y4aoUgQEu0~&GI4zVdHxz{XX`Ijz|JpTo_n0&j+qXks zC4zAbT16U}@v9me5dZBTM!_5FqQ=5sEz2Fss6%h+Y#>?ns z7TCL0x~LT+rz6Q+)YMWk({!dO>mrUrs4uSz5KD^>F%Ryf4{GmeEaJLHwlh-L-oo&2c}dgiQjG>3sTr~ zK(3?|C*_}!@bZ25*JBpNyV;ZoC1dvMfO^d;;vHLgqIdlL2TeZZ=8+k>*wN~k0^K&* zHh`uMXFtd5@@GAf44JeBB^$^chK%Bicnm7&ufAUtlh~p4*2>l{7UtCRpYTq$I{4!u zZ+W#wP`|m1mhO!bEp{pnl^@wt{|##xrE}EPO~eKrIagOyNpsC_1ZY|a_9mVX zUVMj^ob&Mz%lWEBph}Y6nXUtkZYMv4=cqJ3JWfBz0jv#%N93EPRF~!IRUmTcs1?QZ zXGR?iTjbd%?HYZvoD=58E&iW}J@u&TkHpxsPtb9t-*y<*qf2V5`!2P^!~mMM1_vuq z*}XBD@N0h-sVQnHu#Z=Mp#f>y{oKR%oXXI~dhv)6f)kuvr>a!uIO#nx`m%#+ZmfqB z5SilTRT)iTh>zn}WNws#h`?)8=L%Y}+dsSP6Swcp9GP zofJA&A-3_-uh#8jZSIMw{K5G!>i&J&ESn$^}F6XM{w1YmwL;CD2^aqBIhkkiAJ5nYv4a)kE{}g)gX_k)-_TL2+AnjMn^8!e0C*g`kmerN?G~ul4RQFoy z6#lp{^b6#=WGo)qn-t$Wj9`8uoo7{Ooitw^@^B+zS>2SXQ6kw{I|K!TU2<%1_0?2R z{HyJe(>IEJ6M`shOQC}nhUXeOVP7q~5UvRl&-d z+7V+STlj4owyWbvCH+y$kke0(DCf;MH1nm%P5i;qhGM5N)U#>B>@YW%Z}z#+La0q8 zKtm#~y6fmqJpA~qO;Su-boR0Ni(3z~<9*i3{#7g%6`jjkTpU!>yPqO;(6u?i@9vrC zxD9OOz_WOa%{{`>&Fnw(ru$|ltxhTIL%(lc54p-Gd@nLY#(0y~vNcz3wd`DC@;;rW zcufl~_X}4SuDcm0MVQUC%3Xw8hag<7DFc?ZHB2{qF2zpQ;sw(VCFy@=zufbhM_NvA zj7p*`_dQz>OXNoJ`R7HJVk}J`BZxodWfjs#>W6 za+g=`jd?Jw_&*jq0nvZpZEWhoV(0%kA>wV<-q|(3jTNG8l{rT9|L7~k+t`wm+be~L F_cx*o+dTjP diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/4.ogg deleted file mode 100644 index 3f8026d656473a16326648c72d442ecb24bd6bbc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1893 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/welcome.ogg deleted file mode 100644 index bab84762a07cb0bb83e74f166a67fcc0ac775888..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3786 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sr-RS/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sr-RS/language.json deleted file mode 100644 index b86bf0aa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sr-RS/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "sr-RS" - }, - "strings": { - "WARNING": "Упозорење", - "INFO": "Информације", - "ERROR": "Грешка", - "VERSION": "Верзија ", - "LOADING_PROTOCOL": "Пријављивање...", - "INITIALIZING": "Иницијализација...", - "PIN_ERROR": "Молимо убаците SIM картицу", - "REG_ERROR": "Није могуће приступити мрежи, проверите статус SIM картице", - "DETECTING_MODULE": "Откривање модула...", - "REGISTERING_NETWORK": "Чекање мреже...", - "CHECKING_NEW_VERSION": "Провера нове верзије...", - "CHECK_NEW_VERSION_FAILED": "Провера нове верзије није успела, покушаће се поново за %d секунди: %s", - "SWITCH_TO_WIFI_NETWORK": "Пребацивање на Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Пребацивање на 4G...", - "STANDBY": "Спремност", - "CONNECT_TO": "Повежи се са ", - "CONNECTING": "Повезивање...", - "CONNECTION_SUCCESSFUL": "Успешно повезивање", - "CONNECTED_TO": "Повезано са ", - "LISTENING": "Слушање...", - "SPEAKING": "Говорење...", - "SERVER_NOT_FOUND": "Тражење доступне услуге", - "SERVER_NOT_CONNECTED": "Није могуће повезати се са услугом, покушајте касније", - "SERVER_TIMEOUT": "Истекло време чекања одговора", - "SERVER_ERROR": "Слање није успело, проверите мрежу", - "CONNECT_TO_HOTSPOT": "Приступна тачка: ", - "ACCESS_VIA_BROWSER": " URL за конфигурацију: ", - "WIFI_CONFIG_MODE": "Режим конфигурације Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "Улазак у режим конфигурације Wi-Fi...", - "SCANNING_WIFI": "Скенирање Wi-Fi...", - "NEW_VERSION": "Нова верзија ", - "OTA_UPGRADE": "OTA надоградња", - "UPGRADING": "Систем се надограђује...", - "UPGRADE_FAILED": "Надоградња није успела", - "ACTIVATION": "Активација", - "BATTERY_LOW": "Слаба батерија", - "BATTERY_CHARGING": "Пуњење", - "BATTERY_FULL": "Батерија пуна", - "BATTERY_NEED_CHARGE": "Слаба батерија, молимо напуните", - "VOLUME": "Јачина звука ", - "MUTED": "Утишано", - "MAX_VOLUME": "Максимална јачина звука", - "RTC_MODE_OFF": "AEC искључен", - "RTC_MODE_ON": "AEC укључен", - "PLEASE_WAIT": "Молимо сачекајте...", - "FOUND_NEW_ASSETS": "Пронађени нови ресурси: %s", - "DOWNLOAD_ASSETS_FAILED": "Преузимање ресурса није успело", - "LOADING_ASSETS": "Учитавање ресурса...", - "HELLO_MY_FRIEND": "Здраво, пријатељу!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/0.ogg deleted file mode 100644 index af94e5b59ec53b84e722856926d8ec198adcbf6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2303 zcmY+F2{@E%8^=vEmeCNx$yS45$})@!St_Pu8T;5vWXp_^egAZdu|-qX6fGEJ!b#cp zEt!#J9IDX}5#wYJ6OlQi^IhMk`?}uidH(PJ_uTJ&z0Y$!x0R2NE!P3A|Hg7xmCfEX z)NpzmaM&s^EX2gy-3tKF2DD%PiCFF7|BF2wz)`n%832I(9&YFE69VD9F?SEYs)=>`u@916(zi%*eij8nGOrF&}~ILK~!7-T0fwtC`+CqN880u z+Db#>9Hs?$4I>?ZeYi;*xY4D^>l^9EJ)Gn45FIC773p5JLui{i=Ia=~Ng4tR8@p2W zvmShD8dDi=VTu`&;Gyhn{*WlC6JfB^*9D*xers}Yu%4lmPCPo;W1b$6x0wo=olm4e zK(W(;^qvu)Uh{m3VG(gBASCR4`fOOO4=cz9VljFm{Q6Umg&m$JOrDq!XnsyG5|1)opS+pmYIq_8o>6nBubh!+-5fWwoJNwfN%m2{Ue3fVX32O-G#yN(y_lG6+tbmJK{f=sR6KpnLan*MVeac`KeE zcdQv!c0tW}0Oi-xkEu9ey!#2e&}L2*w$+HZmxpm*$R#T^ANlBULsC+}DK^h5zzcqs%=v_T6KqS7 zduOc9-mQamX6A!~LNMqtDtE!_Ys=H9pog{7T-e6TpuvUl3IfTkQEX5Ij5Z40P3y?! zY4~XSB`urj98=IZ*pQ?q>20k*JLow_Z@yuD)8kgL3D~##xM0ftbtdP>N!R-s$X_{_ z2>zq|du`E?R11yBLZP;mQvNw?ZnaR!GY05eE~u_viFBOD_W_El((m|%=UsWsg;)GY zHGp@XZd@%8WtxW8403awFmLomJ?V+z8W7H3ZSabq@qb?jYTx*RCqQAf#$C^yjPLd- z6PV?ye!`BMRt0GdYU|R*5O$c+8rVXfP4U}}?FLQo#M}7oI$H|~s=0@6gD-zR@-Mq? zq@B?hyQyP%V58kD2r&Ud_htGHI#2YfN}ZbHm+cY;n*KoXJpR+(`Uc^09i=y7TG@R- zT~UnwZB8OxOUa~<_IX5IGpyqSWlKGlECH%v;>>n?N*PZkj8dED=)KP$P6e%x@X0I& zm`h}sLNYPTQ=DCcwb{N8vh{AI_TA)b_|zr#s1tRPD9Dv8-Ey-{Y}WmmDqU!GgfR37 zGmmiT=MB6RV+vj@m>6f7iFfl;W%{arPX<~ANz9EyxXBGRD{ndti|!gi0ZOVbv`|TK zg`CauGJpf~D4rlC0kT#Hi)GMq^kZsS8U5!vSLsxE+}g+V=7$NQR!23*XV@p0#DZ(N z8TG0m+htwoj0+|`g7GVt#>c8YN5-B4x>p7hkS@jcGe-t5;R(`51kM;RUGH98*Sz=I z$*@?(Qp)_<>QK6P@E_8-d;-zVCfh}Y!o8~26aY#qGhf}$!1rt%KyWpq5|eor5CsqA z&RTIEnFh{3icu36-u&5!KzD$9UF+XQ1mujvrvU`sfPk|qoZwuwvWZ#jkVgsKjYbH! zA2a@!!p%EPEDExm$3og(kUFFCBlxiCg)}@g<<3b`d1~517EgDvD>tn4!&wTkPIorK z)=o%+wRZTcEm5YsKf$cudzm5-TTE5M+ABNqO-Vn9#`eg&O}J{wkQOUBTO&(+@apf4 z)g-mPZNLT;&FhluVi($vA>G=>lt5MvUca^HQTIRLAy0 z5qYwmwjLh%i{9r}g=*{l-)qUz`Gw`^eQZy)&OVl-wD;#78rkm-jcD&%$yooj29Dn6 M&Wi4@fupql0dC1Q0ssI2 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/1.ogg deleted file mode 100644 index 3246d37c658ef1629acccf864b852a6c3fca86cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2228 zcmZ{lXH*l)7KK6Sp@q;pDqyGyMd<|TT%`&`niT0uD1rt;jYtbsPy$Mcps2u;B1j8O zfzTqs7D9;-svu3ez=eC?djH;DYv#<%{?1wRZ(I5L+R>e%`>zZP^Ps0kflu0J=s{M& z;bCUp9=GV}HRwBB|3R!y@&D-*r$4z39Ve3Lbx-l@9=>7hCofk$B781El`bnmA&^r- z>|}Wdc_D6jhw7eqUMC(@^TdQo-uCxIoHYJB7}kEmo#=G%>8C0HM$14$4RtMqi=UgL zV?>TW;_hwNK(rt)yB0;Hotn07oj!6yP&A|7er#^Z23SJ^T!#ZOsc*pQsz_MVTrzVO zE&nG#IBC6VY#sxUK6H|4csFDg4-7(?Y--J$t#gvi?|B}65fug9?Diyr1JRtEthrd~e#r#P+`%l6g_Sj#;#R-a7nj_+ zze_7(O@`lpV3beN@6~+83q-VJKQLLXhM)5cZj@N>-LP`rzbYSWJQZA2-WUEThjh5TG|_>;G(KplPp2;F2&CRV_l zLX_xUOy$w!y6-f55G4-(5SHQce%Ev|SdCD^GTltHn~d`EW$;zulrEWs)+5o8Sov{f zpLgy-B37O8bn}}3X%0#B8#}%c&DU)&y4}ekh0m$)VHG%XoX-%V-ePvv^dysc+Vd`5 zyHY5-`NSn)XJ;AdDCrJHp^qmf6jlA*H3NYace8{j{}y=o4Z(F1B|nU*KRgogXl_F(VxxvkgBu} zS?A^MiF=Id6_3n|fA@tQ?3|moow6YegTa3t$rm?vYRm8X*p5}eZxC}Cl8Fq%7Iyle zTqzfL2nvRP=IL(T_InlxvO6fZ2EK?xNe?PiDa%!5^L&G;4Tm$mjx18IiEew9qJL{+ zRYp2chsw?4lvy=y>d^sTJp+7NwA2*?=GYq(`xBD1*%+CHS1&(MnquUI3N*o2+a#fN z6WSjM!|Rx1w+hb|KYI9f z=XZ2Xqn7)e&j&B>`3I0f|Mgh5)M=q^$>8r_-HpB<0VH2h(2}x!*!NzM9N>%1Z^-SX zR?bM#4NLB&w!cReA==$ePwA3Wlw+X~XkY!w zB1U`+xu^0;j{B=EdHXL$@LI8FcRECs>xx5ubFQ^jh*k@H0!2*hW^-XPJ6dyt;P3+& z3i`qYx}cl#Vn=yEThS|DF3nGV9gG18%(@PQG96Ir9=d0a0Q<$9SQ5L+=<=I+G8CEP z2NlG;tQONg&tR4k`^?l@x&*@~A`+<%JJ ziW%=I;85&&dz)G5^I$gq=S-hJZwrdj*_tJ676?)vv z7?4MZ%wak^#OZ*KMtuC`UaKw}9w~&a(MM_)wZM{$>|z=&8AH}zYZ`Qv;Rc8#3R+A= zFe%IV9Ea}BV@PAaQ$#8(#zsE2q$i+KI)tq7r5g8;M8hPTD`+dm zh&B;z6o{-*9My7&hX*b>TQTTK3APaM@6jZiB%!}3Xb};?d4nGd0rXpm`lag!qf;G% zIxXzz*Y?9}59-h9)7fg%2E!wViiRwA7YyvlZP}uU$Sq&ot`T!#q!PHEk}QlNw@HCl z3vs@DY>@#LiwE^fDJ2O4xfHZ4Z`7J8Uq@)gh*~*gyT7K{AhtA+fKpX?xfa2%V5TZw zE(ccXEA9b$0T-$&ve=r)TE~?qEi@DI(!f^NJxzW3P9Kb0W^k^~Yxln(vG| ivTetE!JaD)>Y`Qa9*b^Br?B%K9~~c2&Ytf7zy1vZ)hIdu diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/2.ogg deleted file mode 100644 index db2a251d034ef72a24b7333c4206a1d2eb69480c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1995 zcmY+F2{hYT8^#kfhGc3lwS@?(CMK4)X@p{Gsj;T^(h5S&-`FW_jU{TQRlziBEkz85 zSYki+r3!4K=*ak<0Sr7?6U@!*UMEaiA z);go5jYc033cNuK^bYbNh8plZZ=R=pmS<`!1^9af@e==A*oevFcyUnp;807H*U@5T zrkDJKt_FtzA$}3TmrafI0FsOp4D?k>zU&z#_n1yKUGc%M4;oJ?(zxVJs4V$!6X&Rn zchw#Et%ec*J;|{-ig3V=sGg!GD|>8WzUor#*c=M9jgq=f^g{oVTOn8@vQejLjE zI|_iQ#tUaWU4>lY4`fhl`M4VQ4Pr0)l;1PZz5T+UfW0zf(@ z2X*)z#$=o{iwM=PN_v*QVe6zx8!?8`l1o+#T+e$ERsbu1?OP^VbHZlvtjE`~TjHdB z-&BIp-&cJX@;(c@5LVDARAb|*6(%+wy3!N$!BuliaG9|5)iw$`{=it4YA*l-oRII z+IT)CBlEAir;pcQs#;lcP>Y$xhMJ ze9qnF9=D%0Z%GMdICw2?yJ2A!D-fvlsO+N2Lgk3AOk9E{yTR0uYX|@&C3yW5M4sN0 zdM(z1w5}ZS1M0j$@~7=art0R(o8N`>^^IF~quRDqU>msZfu<|q3v`baO?G#Pt%-BN zHOZ|RbXy-+F4~RwLSraJVK*K;(37;4W~Ra5f&+HdCI+h$jZ@4rgLwC+*0HlRW5=>D z#VhX&v<&CY^)*c|_#UNIex-_QK*b*h!h*;%b7EOME zP`4)TyTv5W;?b8yZ%(Cr;AheRrDYTB@j>0QazE<1CuN*lw;+R-15&XbwW51hCae|bp64Z@VR5M!q z`Hqnse&!AD)zmwM`ZRND`ut@qWO~bT_t+PmHwmNNz;It;d3dRKTx%!N=J>g)VraU& zr$EfAeD(f2xa0MGDDHLXw02%su&$ef;rlfDqs|jRx^hhKD(d~)$-2*_fvk%1L8ru-DH38x9mUu<2Z5JQ+TJeDQiS_k?Rm~=sPsI0ZquP&r;^%nglF4pEJ!w!rYAz=81 z1SK4EyRh)%FndM_AR*P-EH&c>BPPo7`7<6ld^z-#0hjejK|42E&wF zhOri@DqSmIiR6do>Nh?LxxNyQ+&3M{Klm!7F{Y^M_EcMvBO7wkN8m%jX~moAh(ujm zHeUn{!eBwmClophj;sepst+Y)yiD`XxA+`piduDXh}@|6ZG{`RMO&5#c3sx-3JZk8 zXR`NWVV+Q#^i=kvvLU~{htpjgoz15N9pQNwOD%u|S5!9t)mze&u$r`JDx)k_GjswW z6)8aZ6V==zNvTT&G57@4Aig9G3#^40oyU|X>9PvQRChfydUr_Xb z3@NV#mi_VxyC;5QoSwTh#3BL$kfbG#N{sHgNat}pXoO7~r|Ome(tQIR%ncZZTcnNnA zThHO=O}R*Gg1`^F0QmpG(>5@;f2l*IawRdi!z@o9a*Op2XYv&0Fk9__J;c(&v4?iy TseiEy@?n>!4rQ{MFu4B!9h#I; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/3.ogg deleted file mode 100644 index 5bfb2373e76151d9646844bdf798e600a13143b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2018 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 mn=Pz!ER(HtjzB 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 NhdZmhvj?f-{TJ8OWi0>z diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/8.ogg deleted file mode 100644 index 318735fcc43bb42917ad9aaa35e087dc8344e1d7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2028 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 T4)tVQCO*MFk2;x!i75X80}jU@ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/activation.ogg deleted file mode 100644 index 08a507d6936fea967ccfa59520aff0e9672aec8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14059 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 U7jl0rJd`bBKHNWU|G)Ns01gl6<^TWy diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/err_reg.ogg deleted file mode 100644 index 07fc197bb36d72fdb08f49025f7a64ff8b4b7e15..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8675 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sv-SE/welcome.ogg deleted file mode 100644 index 940789690f239cb29a50b68715a88147b4608582..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2490 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/0.ogg deleted file mode 100644 index 15e2544b6265ddff62967c5c33fe1e990ebeaf53..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2279 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/2.ogg deleted file mode 100644 index 057a6f360f9060680d1a76f9278dce201bf37b47..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2086 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 Y%iP-^{*#-zxBCa0&%OIcCoSv$7iG5=zW@LL diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/4.ogg deleted file mode 100644 index a35befc90f688591d34ab1bdbf1444a6a175f43c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1919 zcmY*ac{JPU8Ws^;jVi)PYYUM?Ewx9eW$fBPD583sJ9gz~D~fPyi=xyX(`iK0wAE6X zSb|zoTSKH%gxG1PqeInL+S}H&)nTIdo;&6}=R4P7`iNg8_5f>ujj4ef^F(NuLI8HS9U*m6jMLJRK8}C1=(iZ!j zd_ZtSO#G#on2Q%L5dL+}&rlyAtE+$}y^9p?6ru3+^UnGv4=kg*wbKf{n9T-a=R{}0rinpV1yuENrJxIMW&(fpJyHG? zGTsA_HIJbJq_i{q7xA;>!ch?WGEr|!leJ1L;_PzU8fLmvut^w_qwvI`jf$z{JX5!P ztJNhElsLO9zsRxzYc_4-ci-f&Z&eV*Yz2q}bHVxuDC1&5x}0Ga@X%i&a}6M?qO=zq zQ4uk)NLR!e3}=%AYCuXiMV!{DY4?w4l%R8}{}&!QY4Beg2;0r_Jo zKdZoIO=V=Ml#;VAj=Jknukf2^Vs2ENz5Gl`=4K@~EC2OmZHX{FPOw(T@K(H*_?X9U zw7<_ew!{8-muC#7D5~L;HRcAMRK+(9O(hPbmoVkw#1>eZ%{l7%Xplz7#6TcG)<9PU z7_4gt`^ea7ZhO&*trAJw~%nZmJ!*t8a_ zj{szhHpc^mQ^ifb{>gxM@jOY2hfpmg^8_8!L(OGI5p~CfyVdP>BtKb>eTek5ZHid+ zt!R1|y!44$a8M^py*`+h{iU^s;`d7p#z2ZAPLSa1Bs};qY$oXfkJ4!AbTHFg7|cqp zD`3>7##ivga;BsE0J4^5Hz9Mnm+X zJTl257BIlfQylZU==sLZd)@|Pr8^#&iS9kKB5p@q8CpE&KRUMO(6oU-Q@fX`o^yJ+ zzGf=1wJSRR$Xlx;U@pkI0%QcH%UZ?}mEjuX?0hFyfpey}Yvc zjqxn9sgbcX8Fty^TMu)F+ENd}mnG{BsTVLgfEB?f!}aC({gEc+;wOuJy-+nNsSUk7 z;r*nd>_(ZIQmP<#-L?_wKdUdF@U z**|^j@`7Rbm|2}-u0*0SuD3#9nR#EZ?Z1N+c6`ZryQ?M@>l~uQ;R&}U>4MI8$jtAm zN?Y*Eks>c)d+4mw>Ugz#Ub?-;RXTGf_lD{;Kt`h*x_q3R3L(0dM>J2bpxLCGvRkZ` zC1~J3)rW{{bCPy}lw-js(LKpI+=kpkxu&Fq{*(T3jBS|?!PqZVp^NHqPA2HxvRiKO z(ZNK>5AU&g!0ajIfI$5Ym4p&oy0Saq$s=7qmd)oa&{;o;7OG=0K}o84lhk}I_(Xie zm&zxLM*f_kvO`nI7`gY<_KCZfR(r&c7^r84A3h)Xu;trNaQsoFn!ArY`+ue`o@>y2ISPbB4j9e@Xp#SV&6o=ECk(v(+Pw z_Y8Q6;mF?4ivC8j4YgzDDcH;)S&KCD{a`{VO0R-ISd%9!d zMN-RvI-n!F{fu43-vmpCr?-ag8|xdr-I@xEs6p^1CE807`rYW3T@G&&=45)HnL-D zKpbwV^*e61s!*w}d@SKgvUr+~g*P^Yt2A8T=u-7L);jUSmcOycSrtq=>@ctG3>oc9 zDF}O>h8mwQq519cK0kw@!RpZ86s4Cx&X?v5^LKhXyb;(o+Mu0_QRPY-SYok|D7k4A zQ?nH{@JHUOZ?e6n#wJ0$0++k_p?dZnYQ&hEp@AJBqUP$pt!+ig~+X_g!nHBCY zRPSqL4S@fK53uYcE9<{F5yE{`M=pzd5fGw{T T_qU}Ye1ILF#2r{FLbyKx=lNRk diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/5.ogg deleted file mode 100644 index 8eb3b5b943d9cd78f77038752d515a259af48d49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1961 zcmY+F2{aq%7Jwz8!6=Pgi`Yu2B@&HLYA>NJk}$N?zDDUZLv3wIY-J{@Xsc>@ifZj; zq=;QcGGeExrB%x_)T5H2k5=P__s)BL_niNnd;k00`~Ua+=l<6@Bm^e_6!?#LbJYh9 zRjWb9Nr05|jcB4nkY6AGfChAXA0f_%_Y;5p%yM{eg z0J*+b@WFbWt*Gpyalmn%rqVy>u36h7WVB;a!i=iIE8KhP6}HxO6XdCP`uALl=0*r) zb!F`sZTIq7vzfm=P2R*#Ej91YhEYQ4c5@6I@9v|i)baI>RnX@qrq6r2#O23(GWJ++ zc0_x=v5MWa*floYxOF$Feh`XCwIFm;BDE7W7}el1PqpEV+bd^aIE{^u96Rqk$HIt0 z{!!4Z{H|b{fQ)Q)0BIXu%_?v-Lz*$S*POPGiQW~Pwq4M$rTp5XmUn^WpS}OS#R~dY z-H?dU0*pIoEnI#zM3=TPO-4$Zw^60^GOrswL7RU*AQsPstxIQ$`_69T=9!6(1hR_C zgBNc-VITKpr5+eP+I zM*d))JF-C_D=O3CFWJuTb=pk*iETt+h&Bd3Ny5_4&Ogl(>RY2lK@pQ)S;KaFK?KP5~hY~=vsMX8&AmcP+`|0Be7ljFRT?t!*_b!GbCP7$-PS19~Rp;nx}5wJaFgK-Qg%^Aw-$T)`5k)W0H{m-G7QqH-3af zR&=D&Y^jZDj*~1AqKIPC1as=XbX=_RiVS-aYzt?A?VDfaD-MrtmJ23)0P@C#tK|OlmiW!YI!H8*by)Zgo&$mkEJ}qawIGJNDBTk z1hN{G6cJ-`+KN>n?I{;ts-K{9=Ipyv)`e-kR7#RnVSR1)0?T;EH0S(tSy%3)!ghRk z?r-4Up(mfv;)owXq&jVYz=70k#F!1QGOd~ zl0r}D2Ofa8%=17lvds;|duEW5;n@(KxS|Z)t+5r?`zNoF$W29mhmmKjM}A1f16_r< zKz$e84viQ?-|awCyGo~XqVX=`I@tZfpd{m4 z=Yfu9g7C@}xcVSPGXZ|1tv&Bya^eZ}G1V7i2g$4RCd!xkaqbePmo-#tTm#*gJi$2n zPyDhJjkV6*@yj3LsSF7}T-5YuX7S8hZ&!mTx!w46=YT7OwI#RV6() zp}NfIS+)8b+am~Do;SzAY7sy!p1Tz&ycw2nRqG&#i?(*b5ER_25=b5CSf~BaoL9&8 z$M3!>HM_qHn>Xrx{MEX^9|ip)3y8mxkKTvUS`M57V41;g^fZZ#QGPec$w7~oBhv%3 zMLiXYiqg7m)TXu{VM%2IW!Z*>LoveFOFQ21lv7h48F=` z9Hk*Z8@**y=uc1Z;avb<1pkLVB@gZ?Ye;`hi$aImt5LkwMXkjv5x75wz`!!*VI1tY zLDU|2|CIFooiQG;bSWNBx_Fdtwck}}<5Ppht18EW$dQ?ud+WsMHU@z#bDW>C(SDD6 zhP69A7;P7D85wNJjsP>G|9Y0tRa3t8h{yml;~2~zyUQfilg74KN3%+B@{glYbu_C$ qe6@aqkOi2hy#F(T0u z3l9$)8d{qF8tPE~3Dw;m5J&=W zSv-6cV1#gW2LMz6@11{2EU5DT8C4FTARoZe7l0;J4s-PgV5LM%U4tI{0+ENxLlhLK z3J_%>eBmf}guf<*gHt$&DusjydwaT}D2e|mtkXu(QH)xcx+#g(1RV}XS1&(g2>drM z4<`p_dt*IWBt}4hHc7O~X@y9$FnA>X>+XNHkxLc<@8jMr#?vFsU zwe6gP{Si07Wcby{u|t-`^)KqO3W7(6W^c85AAcC{A~fIvfEpwuMp7ujQaic$V;k)( z@nGeO-~4cq-;3plj(Bj9Z^e(1(2&l;@1?bJd`bDkt$E9VWb6H}V`@#<^5H?1(=YD$ zMy~}$%aTOfXxm-CI*vk}dOaJ?r*Ez|23ab3GOO?$_cVhzvcxBP7?Bt$VGKJ)5f)+G z4J}ybP&i)Hwl9G48RLL7Po^*BSKWT$S`w(GpCA5m#-G%43}500`3KjO~kii@<) zwQv>L8@sl`jM?;m!^Ww>NN^n3l68^5DT!9Qx-8>DjNBt)G&CLSq|bJ5_71VNY9TQ~ z;&t1;r;da9h;XrTp^jD*3BDeP`FLWK`lXflpcQ`j{+?DzF8wj|l4}7s<0$>x z0xR*L7+u2YZz=-%voNN!*K_pN59_<593|A^ihM-96Zuf;;u*$xQBTLTiEbC1Nmk?x za(`Cz~YD!{)5Z;if{(u)2X@|TwBdkCz*{`OOOI*Yi1z2gSS9#QxYa|-&WUQ ze)1h(qU?@ASF|^GtE6^nvER6X=m>-m8ER1>4*sah4nR z`m}7PLu1N>&d5V){smZNL>0T2Qutj-;)~x?_&ECH^b~W;;2etPHHR}J3`({@VTebG zo^ICDHD;b?FOe8QVQ^`ZE(yj(vg@cjul9iWaehrM8kes;D?Be%4P&M|5@}S;=l>J9 z8r^XHa@TQ3W9*vs3zn#iSp)Z+EYIZ_sg3+3( zvb~>*O+sHX$wXo#gkmgu&1(^^O6$JL;o2-F+ssiQ>A_xTCtxpslE1$Ku7&GP-FUXh z`PQu8v~xh508H34#GU{H+oEaaJ7{TmHS1bP8T)yx`=aEv@&tgLf$^UPIanX^uPIyE zBRV-TS3`Jrz$!?Lm`M6(!!juH;rZ?=D(00(zF^0UR*gQ1pzD?9nep8t&x@sXG9_ek zi;Xzi`f<$F!Awiiu<8avog0pRP&tZ1@8H*R;L$7~nbPxtlli!?;n}qb_(FnxV+L1> zN_R-b(wx#=%H8lQV#kJ@6+|kMQ~pvtx2!o3R31FpXEfw~<_VgayRw%_pZMH(_zvCr zU{JexjAyz~*^mSmlfdOqo>(y%^G~MohTpnw!`WEacVHE&3!uC;B^jc?nI^2xb(y5vN)>Gl)8tgvmz z+a!-0hSdbI?rHZ4*o{I^+j3d>4Ch%~odhB%RvpF}z z=(XU6@mP?kO8h~~(+o|y!5C@79){k~o?g56MVw;jVRAo`?jQI9o4B{z|9_5xdVbCr x`Vr#K5%Y7#&{5synFd-}*^7m692Zk5=t5aMWcMFU|F9xoXhT64v;;qL|KIidZHWK? diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/7.ogg deleted file mode 100644 index e93c9a4df9626cb7f4101a192523e3de3f6e066f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1590 zcmY+A3pmqj9LH_bacMa*oXn+R#^g4{(p)N(C_+fCAu*Q_UEE^sb2(*nT%wufHsPQl z6GqJRa3Xi5CigCcDSFQN>*<`czR&YM&-;D9pWo$qt$ls%_`rNWWZ_|+v3m`3v+)7J ztgnWLo$~SY27$1kcGvHS^)CLOc5x8k9NZAkK!&@xy{B&&6nL@njJT|a(a_hxXld;d zvcT~P@(T9$2{i;VFCfDl0YVHS!0%EpQ24zuf9?~21GL+Ccd6;#wIoqjclWU1kQdWCIPm580$9Q=(`a+U6J71~dr3We@OsDD zUst+Pt0@U+x$~6wF}B zGI)I4wkNT1MducF(19i5RYf!A%*r0I?KQv?l$8^!)@hRV3YO3Ch!XnJ#lOVnAm!<0 z>udWhs@DsI-nyJ7N+@c1)U>uoWl`rju^JY)OZWvLrw?2YxbrE=#29MFKD=?(wvE{1 zF{$R$&oFoC!OadWh8b5>?le=O`K^?ogYc|+oPa^EiHVXl7*9YV8KVBGNOm}uA=gBy z)H@{GNF{BR#and-)||g;77%@g=`Szb`h3P@i_)O4sp#Yy6gd$lG!nQd8mcXrzzm2Y zx|mP}1Rl{_^Zz&-U^(}jyGh^VlEkmeldma#oU}o6$Be$7LFSD4->`CEoI)$+-t;^D z+%BWlCy)D*5l_un=W|Kf(pI+^DGzBB@sG#vUAKN>SahfkHP#tlmL#*!5FJ_{j8b|f z)z;g!-}%v09xK(ay9J(9-;Stg7FIja`*yr_?<6jH+2Pel5ftTXG8s+dYQbz5KEJO6 zz7$ni5gwDK8~-db+q}lE44X5`S9I`B!yC(O#u-103RPKz%tz4TFOsFxM+0=E7Dl61 z6zYbRv)WshuhfCH#^$mB1j=4y4ifC=**`_zvYwl>}na; z=J&;*l6}&>ZEfF-6*K~Kk!dx{^O1DQ9Mf?coDg>nb)qHo!tlq~P8UkXWBp`9IiWy3 zDVHLW)&$h1iHXtZsF%+4qr^`SsHRf(pG@t)5pSAz3H%xNTx^@(c&tli zK982DX}Z}e3|ZTofKIb;hFSK{f^ANH#!j^*#3{;CaqS0I6_r!jDLsq6Ue+Q@y-~^0 zoTubIH+xN$Vk7>&F6mxh@B}FZCG0pm>p|f}ovdnVBD9!vGzG%0Za-d2L{7bTMsAu+ z=$tb>FZaTImG<(m5Sf7E7F$!d(Gm!zf1lD3p^3XyrTm(iqUz43Iq)^p80B$HcPF|N zPmo0@VVldHpe?ud?D)|{X6u*jMwSU25X$iZabA90$%)h7?;1JwwffYVh$cswCbzJ7 zj^;&jos{h!Bp*#5QqITcj7ye=h@`LsApYcY+>S_`r{xfyASx;p)DK53t-}QG&T0KJRu?4QK(bQjUPK9qaogx%L1I_iyWkALe8Ix}t8#dPI8@*zTo9(AUO4pP-8VFiHH2KC1Q$c>jt==9QJ>gBaX%KvViAFi*>O) hm4L(YvK98cDd2c2>#rI7#4<>{I{=P{?P)N;{R8wb(24*6 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/8.ogg deleted file mode 100644 index becde0efa4098f89e9091352def4ed52fa401fd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1560 zcmY+A2{_bg9LEh)Y8Y3D=D?Vx5@xJpa;(By;&CjR9D^}({T(B@*5+umtYyhMA96&F zF$^K+NUj_;D3WS2iAlL4mR!4kJ$vZ)Jn!?opZELu{hs%It-ZbN`1tw$shgTu$Ng;$ zPsIvy%$gb+Vs@GA34stGoun^{^}haJ?duSbaJf3`5QBZ)p6neW44zn$!@RWdYC39o z9B$u0f$MT0CCKyg6$3D%fEoTQ7~GGxeV;sjnO^@O3qlv5HiS9^vfq zCeEmgl8O5KU27auPEgpceHoRpq|1>xx1wr0xGMD2AD|%>(aUj6fG}@aC6jcDJfm4V zqIFB@aOX=|AyUaBG~HVuVKN5FZ9I0p%%U8>!pnYRJ`VfzO~_1_*%-eLwP`ojTnU#D zVIl3$PC|XxvRw01xyOk-&ApyRIK6fu7wWo6f{~jCodFs~;YONMC@+Nls+1A0S5c&D zx4lp+?(qoi&o!;#`KDQ>)Z;UEF;(-~}`46&Z^@kD)=f+}GQwu}5xQu+)mkh<fMVY2 zw_l;qt2X!7Wmw)*c__t4Vc%>n%lZX*D+Cj z;!9bJFaB(Vhr3zwU(LtYGjtLv`|kM_2|kfxXn?PgZ;B`Z7@gttJ2fWk>Hgg&u9vUl z#(89$dZ>MzPxyQ9k7DIaDLRE_>S*3rTB})FY?FFv@SSb3RU}At$k(n?UaVQpG#D>2wrn^fQH57`yt4<`6`jL$(b9)KoD65bnk!BAxswwl*eUWPs zL6|xeR7qYG5vQG8XPB=35aXv+re)R|z|>%>F9`)`R0A{wQs5mtsMOix2-Id8tJ;ea zrR+ox8DLrRa~Z8K9vQ6rg-kFAST)Cp_~w-h;^D;nD7E>@xC9sGZQ0 zc(nCr_uQ$cJL{_yLY?Fuz4k6<&#GIuQ6sYv=nlST`VKJ=T~(ti*?(gsJD~t8|2#Vi zwkog!_hU^G!Qm$mtr>?eX?r=Xq)p2qHz#jq=cCe#Pjj^L3imj|2sOLiZx;!g@F;6H zN`g^-dQkbcVxwedg|W;X;;{UWjCIHA4Yxe{S!zjmfw*9RO-UFM{0=Gpw-Q*NaCd0w zp6Pls0MJCm1P3BV&x&a)8t6@oEi!rp2Yk`^A&yGNHEa~XgFO5<)|asP6}1EifZRVo z?7S_Zn6#!#_@6Q*b@jg@!a=uClW-sf=|E?tJwgAV3-W=q{_4R_R)+3ZF31PmhYbhs H021MEai_xH diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/9.ogg deleted file mode 100644 index 319ef67a35bec843460788fd9cad73de7059f716..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1646 zcmY+E2{hDO9LMb>vWKS7U@S3a>`S8b8nT5!WmGa|Vw82L>E&QZ)`T!)X&4WKHrq(1 z#yo1K(IUlj3ME;}*2pO9`;Yft$NQag&$-|G{rrCSch9}&dSbCYLLx%{#&}k`wP5Nu zpP((QWL5EK?P^?kPai$WkaJ~}); zA|m8;pgYtE2pkav7A1k+%NUZqD9|gqJJHyuW3$!vj6)^_ID9);sgvp|GhwBBBF@oH zZzQEhR*$7Z&_m4`%$6-qt;o<@!Ai{E&%a2{*N4?7S91@qj2(Tnu+fkIsD>mHa74{L z;3ehE=O!w{zOvN|Q7B9mz<%sfOpuS>WlB|rI@0QuREsQL`E_oi7lPLt z7VVikFTdS3(fbEkm}{bsIt}&_QrII~f7D39zrBuG6SJ%<}_(wKA4qApMoq z-fBfKLO|bf1lx8@7G3MQxS;=|-_Gk3$|EJ>aLgfEQAtt4n9hRkz6gT9xj#DQYGX&& ziYX|{MTlEj7$R5Gm()^H1qYa_?C$jXrz4CU= zBz%2n-#UlfpvRBkT;Du+)(}3}B%u%pCTx^-`1W#$sURGqzn!?8;C;Obe9;M7A#;O& z#5b}eY<@i5{QkDR*)PK#dpzuMqHUSw)?dJ`U>lbV8H_DSzm#x^nkEeiga&RHXMZF6 zpZR=TM=fo#c{VpJ{ZSla_c@nrR;(kQtQ_{%_@g38d}T4L$Ho2n?dJtQLVpM~g@0JJ zpQ7YvP7W!))GkJ!9^qXxadKE`QxRciW%GI@*-hTCX-yn)ulC)yHYZt#b4`9DVJ;_9= zb@kKCQntGj><|eQXc9VTuDkOT^QWq7l*_3Blt}>127$yrZtkCM#1X*|T4>+TH+LcI zg6wbuyVk_ZOP~i9X9v!&y4+UDrM4+5&3RPs9-y}nx+#?w{)(;qZeOcYhzv8iLzPw9 zNoti+@_dO;Dz@f(Derx#<4cRjhP+{Sd>j9QOzQ3!93ribxMMU%3iFj4hCjCh7pTSf zG$xXI71^1}oz+^5z2QV+sWN69?l^U?w^(bUOu5F50T~!dEgxQ9Afs9V`{3rq3jEri zv)|?Xt&!ShnV*ohDC2mG(uSM|rK5RLs2f%HZI+j{M1n;!eM&uU(uUT6GpX;h)LBgC zUCPZ-R}~Wry*HsOLS-p5E{+;nCSRg`?=mVaGZ31aL3|TW;$?{4vo0VI6}NGjjvIXe zf9P#*IIw1SAev61TQ%!Umk-;5+K;NpeM6ykynI#=IeQdw}({F1)vMfWyg^N-4n3~Fidp~^dd~6fS-vL8SGm)tk080R|Da*ct&VH%bSVQoUkvy$Kx)+Ya>b!;)rr!Y2)fsV5zAinn?FgCHp!FXlQ?90OTcJr^c0RLCo9Rh z)NQ`Zgg9$DmZRs{fMj#R+cn8?kEsWLdCHc0-aB!ko2EarQc?S+0`DJmQ{93C&r^{2 tpJH!iXJxi*~$WXi_5sNHS_6x-v3xYZ()0TxAp)i_TO!{0nY#c diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/activation.ogg deleted file mode 100644 index 983e4d8bc41ab1f0520428e96c96efa62320d085..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9627 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 DbWR!Z diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/err_reg.ogg deleted file mode 100644 index 042c47f26a4461d44cd881c9642ed9a77596ddab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9745 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 UMgKi6l>S$5{nvlb0ZIw}KeJT|DUs|W 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 VpY)HqWc&x)n)+wvJHqb3zW|)5WwZbQ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/welcome.ogg deleted file mode 100644 index 0b32b808c298845b422ded071884eab442ce0322..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3788 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/th-TH/wificonfig.ogg deleted file mode 100644 index 984d2176acc5df7560ac8721fd34ea52192dff09..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5596 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/0.ogg deleted file mode 100644 index 9ab9285943756a53b5aec653ef006e0229710927..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1972 zcmY+F2UHVS7KRBWK}1H1NRS#r3n)cNfY77{PzVylGSpBLLP-EY0f8tWy-1>zrKrRi zm=S{vBvfIMfDu84A_&Tgg(@Wz0uh|x?%8$kIq#fz-~ZkF-nr+VcilrnJ%xmY{$oqL zzQX;j@52EsK-N7vj)V#h2m%010o^{|5%+!kzqXG91YT;)rJn$n`#2^blq4xQITH{c z0yjE=IALUHxKAhxR&XRXDkzv}DbTP2&B#n38mUEu2Sy13|DD*TOTYLML^iNA%61KO=xbh6U@ zWS=1{4_o&_%gw5>29g-#v^JADqNi(&7;pY|gS?Xo!jfby-dAUpeVC1D7_2g{)|2Qc zkn^ZcGup$Gl@;N*T@dMc#cRbXeT;s_XVa$WKgY!p>LzBUsxV`*2>Id}TGJuqnQD}6 z=hVk*qAcM_e~0|;PIx?7=D>swUQL1EkzW>X{3+d&adz}G>O8we=fiwb$BtYpo~#W? zhqc+iqjY~I=)qG&BkJ9p-#=EI+jEOvrJMUtji|9Fy)N4sq6npnMM!Q$a70%~{)q7i zd&Gj0X?Cj=GU$5P!W&KyGnGF@P5ShYgug0v^~_%PlJp+AJn-)}F0l7$b547x?ZF*e zz>`%W)J;ZWqUYjGE5?PG>BkGmD8gUz@#*d4;O2VBJ=Z=;*wd>_ZOtW*rMmnQ$a^khC*r12{>38E^^i7yV zpiLBN!wO=7WvggB8KTy18`|5XkP*H{hZjB}?m=?AnX7M`CkkL0cE;ewtD*&tZJS)7 zuV@5fL`QS9PT5}z5iD|W?b~_c}bL~b}H)ePv}W1TCU;DktJERo)(bYDj50=YO$sw!S&z=mx9!v8lpodZkZNLvSfyyr~>dR#LS>ccY`% zmru$MFZEdR;0dzRDi~(uOV5nmU?EdU3F{YHy(2@sSiOE$T+pcpiZ-WqOu7PFdqtFp zQ;63dvwJD>2Q?Zk(;%9g3Rw9&o5!=?dy~chn$zpOLO48GQ5k`Zcza{wZ2Qu67fw<& z?2i;Mye4v}ZN)xcpm6I^k_6T=(Uti!DA4CRw4?OKvZIT-;*J4AyyHf{K{5dC$AQ$4 zR_TW3b8>hS1NRcmx{F2Ww*syS{ytSW9(suPq|IsF!b*>BUK9=c@-7-Q_a**boLDso zj(CGdhRhGrHIxH4Wl5FDKnyo2r|7~fRK4)_OtzSXipx@vIr7QH5ChH@KfBWl{A^F; z{Vtw-Oje_BvDZueXb>{>=4>#oyvcYPW_d(>u+YN4>L9;Bj;eaPmVo#TnGbcPm)!tM zK=?XZhKSQ1&S>77q$!w1%^!|GWbs}Q_R2#EUL7N0aL!c$J<`o7PlzAo6+^d!)c+}B-UE{*n`nzF4 z5Wn0V+h!{b37fty8&WzOGzPxHn6;Bpk*wo1`8z@%nLEM8YgwRyMAm?Jcdd*@>c|HB z``8lA8vQ=CzK<;t!S>tk0$x~OA20HM@DHKc>uc=)X#$V+BU>u{qbl%zh^#VNWB&~g C>5(D; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/1.ogg deleted file mode 100644 index 131d7749242c631c1589390ad04ad1700c3f6d87..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1983 zcmYjS2{aq%78XmB*3#BmYE5WVgJep?T52sV6-%ksh;;}}*bcCXIGZ>>0ogxN_HB~SA-g(bG=RfCu|NZXw-*fMO&UFe3auE;|_^>JKc{Ex7C2cO5c1L1?BbUmGJp7alj zjts|!;=%&MZ~FY?We&pJL{ONrKO0;;>77`doIDzXxNu3X+imsi7 z^rOd`(~VgL)Fwtr(a7kgJ@UT1LrQLblkBT8y+w^YGU8+s+L@u`6EPdvZ<=-aGY`5Q zlJD4WZz4{d4!{zWmG!k1|6r4A6PCn&ks4}lcI54JL;_hHH$FY`jH)tro5w0ZvFGbK+3D{Zpf%0p^*D-*S z7W&ehu2dq3oPOq2c8!#W=b}*fVV~Ji~B4u5h^~F4W4`? zDA%yTTiGwWnk7%)`vq2Ozvm9^Jx1wTQq1Bt)`<+c*Srun@j-9g`AX1m(y6BJ6^3x# zpaT|iaHg~BX9DZ~)^1AgyROE!!0F=|6CS|MFIa*Gm`{sD6by_N%rX%$!+SsOS3qs^ zu#Q&k_ayxTaiL2+mT$Ih(pSK#nA{x`}d>5_U z__Dg3jyT2QLZ($ly7WVq&L{UD)9MmJKBX!+lNKOD+a*|nx@t?AL|#*M0twI46z%Hg z&b-Wlv({MpmF)ggu6Jf1pK~z{(WGbPcci=sHF^GaLXNmEDLn3;3FI|M;C&FkF&3JV zFs(N1Oh1`k1k!$g0q3<-1H3$`QR7Jm*6lot^mc&7+X-}G2@rL9J#l%X?d0A-Tdz`T zM$&4ZUAbL-dHhH1#Wtfvwp)!Gg-ugm?{PT|nU@N<>NxjYR?X0(&+o?VwgJ=RigFhU zxXgR~T}%`F`bTMr)y}!>?)C?GUA)$3W5(>5w^ly3Shi60X!I(7ZYnLDhzX+>I7@_k zdaUTp#@f(A3Hxh+STJCt0*$w1BLB^!^PaEKCK zkIc=V;M-jd!JFMsUwKgrJU2?-J2i?(EHhX5XmQ$tmMB+DGV zKHxft(G@+PtrbO#u+(LHD!7Ac(8f|*{U+ACg}S}#OBP;a{YZnkm4$uH^0>5j+;(4Fpi3)h5oQ$Njx%IQTrj< zP?+`)gh*br*fE*WI=Z^n{_FFEI~yX+5ELay7Yc! z*12?vFM@?zzBy6veGgT<;$T$Io4v9`Yl+KC_LEvdCj`cv!zMpXZVCECfO>C-z#Ng+V-6bXl(ZHZ1A+2Fe!vC zY5Bv2<;id29)MO3y6Fzp>`EdM3!ch-c&Trp1XO1yz&=~H=$YQ+b95%(3(!-Wk4)p- zDn4O-j#lSSgI4o6W`q9J`4poH)~sUOg5iUwc9HzatLlT}do1Tq!&u2NuoRHS`N^l; zaZWPGFS{0xZ+uo*-J|!8X?oq}_oZcw7^5#DW#&)qYivgY`M$6e17BH%YJ_lm0kd_s zm6jiS#_2;`_X(YEh1Z0)u!K`GV!bz7W^6_7UZ$#;jl>GlS~D%~>)U})z%lvQmeD}B zV#^Fp7`daYO31OQ6Uc~!&RH$Gt*y3=va7nVLO{l?9>%rKB1uTfs1fS_h{QEAIgC)K z?;A{*IP!ggecxb0eAoTu&YB<$c33D^8g(d@j}FNe=%GvwbNTpC^o8r;66&LkO#Thn CTdGw6 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/2.ogg deleted file mode 100644 index 5e80f6e3f9411c6bae222482ab4b95f554d6ca0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1699 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 M(fS1ys%z=|3wA(;WB>pF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/5.ogg deleted file mode 100644 index 30d093eb763bbc6f6d7d3eaff7a95b68392346f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1868 zcmY+Fc{tnI9>zt)uDy1(M26T(ZB>aZLRE!oQ~T1fMrtCK5^Ai)4^?W5MwCX&P_@+5 zR#iHQy`_T;rI@ysl-4@B(CXku?|tsL-{(2cbKdiQ&U?-u=R99RV4xEpKi_|=BQwl) ze`-YAISG;`T#BONNqzw!5E8`p`i>Cx@&DC64&o`zSb{}{43#5wkR_y&QUo>jh6Ru!usn~*^Nh@RrV%Wd>>tM4_@7`47LViAe(?UKR@I&sOL}=z ze+mvEM^Zz*eO;|i8R$^}WhMT_9L~$r-Brs+hx0zDd>Im=>HbDvmrNCy5hWZC=B%Nf zEp5<+9MP@5H7Qhj-o#`r?IYb0%nm7QrU}Jp{x}OCd7CYYU1H+cmT1|$ zO{pOY0F^&+OvPiSwu+nA;f~UEv%zd)Or2t-Gpt%NX}F`tkYK)o>wYyo_fKekkFM;qWZXnKm>D=j$OR)a3j!_)bv%^i=be=pkEm3ZSW$4FjEh zL#DLdMTx`-^!R?Nhk0$dT@|pTknzB>hu-=EkG+r@n+@MtBb@dMDjCb_X?4!>po9Rd4y>Jd$wf*p_N;BzBqvqgxMMk-fYlkHfCE9s8D1U1s zzLn<9f$Iy%5N7j~8nd0=^iVQWPD-%bZDffCa?z4OA)jSN`p_cr??k)JtAiA`)pMF( zwBH-`dPD)>8Vsj&Df*FIPg{?}=e;1W76j+z6`= zqe3F4NsLI=a=Q~TwWXXt6wG@anhftfuKh|~a3ksO+%@GM5cB!f7SwBnQtN9ACv_?h z%?|nS3u4mJ!!MXf!s-dIG84pXOs%9HV6iCRQ@k=VUI^luuJq`8UbeZu1^ zdpQD~7QRHPIxV4>fB5Crx%3e*Bn5FUYYf@NJ5nQcDO(&LclIqXIB1nt)s3_6Bn^H# zDxci5m*Y`;{;b^nL1v0QwyvhA0y^O(OfQ&pd9_|3aOxZ3#}U?!S1X^@kw?m+*F#e@h!Dx)2*1eCabnz(QO9 z5dsb__d_{!DI(^5hCCXuiY4-%wUuNML=1{8|Ui{SmM7W`}=Qbp$>DOF8 zQHh$q{1=YUrcnDuPywPcOSL8 z`98j#)j|Oz<%B7TFk5in$tUi)#P=dCM6%FGMXx%J5g5MecTGxCg`#NzHPFTgy(rt8 zl|0mCJlnl8>Hy?F^!k>E$wv4hDZt@FLeFA2X8$r($D$|3x@EaM`Sh6^yIe{=X$*<{ zM`eCOVkqGM(+6C-3=;E?ciRMo`QAW%$q9cEfM+k^bQ8`-~&O`&Zq-H VJcT^SHbowEn<5Wh@W~A%=HGR$Qmz01 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/6.ogg deleted file mode 100644 index 95a6f6d62551e26d093ed17fc4c1e9c1667510a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2014 zcmY+F2{hDu8^?{kkcP>UnK70jO_v7Qiff4yS+Wf-*+<5{-i$3XT)fI!(@-L`*v6QI zBFkK&ize|}vuEFzkeK_|`=0lm`<(MX=lA)4zt3}?^Et=QPv{u`ssV-rWq zFq6=Hkg$1RSjbgRR}T$6QR2BkhAK9&4u_64xA5+(GFEzBH zx+41g`6CAm_&ojH13Wx~wE@i?(9oKIh(`F{atiUXS5k9nj=N^|% zStoA=xz9mrtIctYEJlApz!6S~^Nd8UI=@`}^$eQQ?GyPxE}nKaM}c<~l`ygYEVeQX zaxaM|5tS4x%orfHDcy`aZ#}YL2IavvdRoA!rrS3jF4?=piKYAE-Qbjp^(aDqP@i^6Tyw#55bU1Pq!F~zBv<*hjLQ*;Q$w( z7pz()MKl_nJ=^%&^>odXE$(QUd=T+bdXT%hNYOWo0D+>_)X-N_cX19K)Jsqswmsj? z&O&HuN((W_3r9d8>(Plf?c{oq++B?n53f5qhkIk5$1Y!Jxj`36h;~?(sBK7l?(N6k zmA9dFhaq&a12**g5_W`}?!;4frVNRDn_||94yr9}Dq4;z>1XVCPH7_P#Rr%N?a!4A zr!oV(jAlT`opR_iAtW3@R=TzjnZzqhubJN=_VC&Ruk)Wm@*aWr&!D00)VUGk2FEUVQcjA5*v3MiALGbVIOZO6=^*FR6sj$;7=u zjU4GJFmfv7GO>gm+uf=U>#1Z6VUXQ$*8}940OuN(%y^{CwRKreUkjv67KZ`MK zyQ|(38#Q59aj@tbI<7!`S|aSwP6zRaouh~2WM$HlcAm&^Arl;7*1Ic^tXoqgI7bxe z9=s{i6Gam)h@(gFQSa&(W@!3Gnq*{MLS*6yQu5X7(ja(D!OMl(R)xjhBBr3N>8dj3 z#PNXP-}%iW+EFbr9Oh+lDLKh;CV5hUfg@O2o*`^x%{M&F<3Di;uY zp^8}N0dFsc)3Uf^A33-2SU}g}Xeru!rT+w6~` zl!WWPF5PuIUw$}d?liBhVGB84QSUQk$fgTxN}mGMekp2BTzjCEdbF3M$F?y242Rw7 z7REsZ9I5Rp^QNNfVb`!u(}N_zOl)1^S`s9BjMPBU)tzT&yrpqm$ADy^0gJ{2yf3na zOq(^FU99(pTU(Hnu`y0k)>VES;Cri0>o%k%M`PJ~rlBp~9!qh`2sd*AE&}3hZOEp4 zx?R<8D4$#h(S+T(?jd-w%7OYfs}JW0d*DBP$YpOr0%c^#$QY)@cQ^in?w+R(liSXD zhvN{#&}ob08~t^;3s1_@vqsx&@Oqnlq?r`SD~>CDN>xD`;c)Jp&we<9JhIMqHQIBB zP#8yj(K}F4l8@iJK8`C-OP^K{HtWq|_`gBv80+~}*TqtX-7T$)N6gquw^uy+_1W=FDe-{VeQ;_i>9(}Ehk&}{+eM}_FZA)h4=h6oR#uD zgYn~{*Kh=+B=v12O`EN*W)ojtn-@jJ8+LS!V$d#Oa-&H#Tf(BGVRS`plCf0Y1&z|T>HNm7|a znUhymj86cE5_XY)yUh!?eY1V3Rw3$CafSHeI48Srv0g?Q-b7h!(jZo2D_CuD?w!_Z zB+i#%GleJVAGo`YtYfqwkE>A{$Dcx4Q6mcjL$6N$sp~SkgI2j!OWD+FwEE$kOY62A z1&*SWx+>Lc_=1(3>>67P<>Dbs@D+2$4G)F$;e6r2W2C!o5mUDr~L5?7_}-d2MLpD_(!V5uk9@ z8WYL8^oW zsOmM?xF|x-?3jiAm#j9Px9ZCQD#^Evfrnp^PeP*9+YB4YSNtqo@2l&i$}NF=tfD&GPih<(k2$$>i2F?Ew&L$Nq#*5?N>A2nAVb}CjNG9&nTIWBg{r{A*zSjA3 z3~{zi{+vQT#}Egw6f7j~bDjf&wG?1yNxl!>V4)}IjZRiCz%1%Z%MF$$0BUFT(t=o9 X1c)WGA!F?ybpd8k-&0vL0c!snqzS_5 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/7.ogg deleted file mode 100644 index 9ba5ebc94492e921a2b878c7f9274fd0e1011d50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1818 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%0D%NHO6gzZ&wAMY<-iN zU4o(93lDrCyEvgPIy*R(X3AenO7DGPc>-xH);5jZl{0omawY z?m{$w?FOb^y)_~7Ipon!h%=dWxE3|(Yrk*sUdx7EZL~i5g^W1t7|xrO2Ur7g;-ZRo z_p9#*euc6&_J;A`(e!gL&y)(l1Muo_&@Yh-y}>`8lI)^v0P8Y%RH#bVAMSN0p*^Gu zd@XN!`XV5QfGhX)Sbg4_Hx-lSPVWkHzvnx3Vb3enB9&oiU@vHQ(13V;NtP5`aYv7s zlIlB_p_b(r9^9hkkwT*Fz5#o|C98U?nq-Q9*Vip6hc29Do;&am_T2Es31DU+VwCz> zmF4=J28RQIMRwF?-0ARwq%0}}ss%JRoGET(E}xIDO1vOFI&EH>rgnYH+CIJ*QzcV+ zrzZr(5OD}o_NK+7gw5OYr5as+43h@TT1Vb9Dnknb?x-1b(p~(x^mn}$8f}DobPEqI zUAE0;*qI799@OCsj%NPu2pX#yj7y%o9QY&4q{b@1=EW0FXDUNaR}n`~kKa2Y#y|P+ zHWbJfW~*s8T#2<;5Ib5D+ZRIK4-R#Xpxn0-L)zV-uN84*@LJ=YdGtjk@XGCeDLF@` zdn0|I=?V7d@Y+x)`Z>FP4lfnC%NLVBDDO6-GIaHSR(pcY*Zz{#FapcjYW=hyb_m`$ z0GiM{iTa?8A}nkIYlwR81&8b71+XNRHx@K>;{MQ~K0XAQJC4IsRsM;w|6q$(u=xLT Ha)kXiX^@4U diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/activation.ogg deleted file mode 100644 index f8bf34eacf7edccea0761de6f8cbb3fe4d062b92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10808 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 T`=;Ukw-wU*uV3cz3IhHghYN5x diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_pin.ogg deleted file mode 100644 index 6e5831e2d64fd3568a3c39eb589c70175ac9ecad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4456 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/err_reg.ogg deleted file mode 100644 index 91fc7ff5a098ea0587ea68c3a73017cb5d70b191..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9495 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 K5!sry)Auir#(WU~ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/welcome.ogg deleted file mode 100644 index fedd21c26c6de35df2f3080d7a45b70666cf169e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3010 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/tr-TR/wificonfig.ogg deleted file mode 100644 index c898adc079438b2ee323dc17a573bd2cdfbf4005..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5432 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/1.ogg deleted file mode 100644 index 94bfed5fbac2b4b2413dc398342f632ba0cc92d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1902 zcmY*a2{hZ;9u`|rv}&z2sKgSnN7NeagkdlhrA7Nh5cQ|F3St*zOqJL|+d;)vTP!bH zODwfa(Tt*uRxMpnCaOwXLu=kk`rdiZ{LZ=O-0yzh@B7_*&$;*KMj&AM`1$@DLyP^Q zys7ENE)yi}77-Ke7>El1fl#1<%ikn!Jo*2ECkJtn<*S|>AZwo714oD!=dS#KBL*Rj z5atLYLqncIg*yVT;ll$0qpZ0cp350oa7iOb=vDu4ZsLE8?fSVoZt#qGn{v*{qDXmr z1ji7G*J7?m_+7?ZIHBMGSqTCnX-w5=B59T$I+<3wzXJHV+OBggk_+#9J+%3n!oGg` z<7#z@;P9~VP1%wn|7h5&^>)kWkZW1%883Ahx+_Y)SIYTlbHm7>EsE@4NV>FOE zuJh4mYhE%#B!|cOz_zY=L3s-kmd(=U@82PLvK|opFF`8pR}oquiEW=|W|}O6QM`T% z`;WPW_efSv%&706pZ`Sy(55czc^q-|WBG0&+iV{opN4k5Q0F*ksK`Ye+BP@c6uMJE zjerLCQI)vhHjiGgs`syx7~9g`&QbE6yjq^Kuku(O0h` z?%878SP-^J8)P*ZYMp`n)Nrd|iSs2JvyNim=xqesK7g)+<+Cb`$OgzTt!~A14(h9C zUGLsNfW1|bvwCj}8vt{~YD8P*LSb0QBSyHiPoEScl@gPfa_mn%^_1$6K3WXvSC@KsTGh3EOwD_YmU!v=-mFTqz+OLT!Irc# zSp$%vTD2`Mk7d4snfEJma(Ynezf73!^ILROt?L#f3{FAn#`L_s6&uo7tn-=%1o@{J z1k^{E&S)=Hkbu9Q9w`jPSBH?QB{zSiluLNBLgaV%T7KIZw+pNJOSI9SnD^F(>~6Os zoc_pkYirYgrshI*==2Cc)=+1uzfN5Cj6L3|T(h@)3xR432*(yF9!y0Hqi|OPH%~4w zdTi3N41N1$MCE*3(szPbhYhQ(cCsBa7x;|v2Jly_ik-NKrAVl%>@())!d9=0Fgb@j z3Uxw_@mT`pHY3}sXOKB6;$&k3khP#~YgYASGpEf0JpCf)I+pr`dMkH2hOR771ok+K za*7jTAdWdR^45B^N4Ctor1t_Jj{olX2*Q}+H07VGa%g$3@>DXZyTf15u$1AH*)o1l zD$e_NRkitvS=WLS-RX$3iZaLRzsc>xQqbR(!P7;r@GiDxkkZY$F?rY;x^e1)WrdHv zct&zI>Q2y0usaPf7uyh@-WIrtX{i4>{9ph_r@y-k7nx37$b6ExJG!FDRPI^}k1vA< zdEfs2Qe|!e^W@xIQt`yhTNgACkJmhN+t391YGH(7`A1(W5xkP3eAAbEP_3LIm&J9| z4ZC^;qk+eDa~fs`AXuOf1#6lMS2oW*vBa5o(F{M0%2q(J;Kh%)s$L;yZX(mo$O z56+&AOP{qb`DsMiSL~r5N@LREun(9Y=+#mvJUQkWB}33p&dR;3P&IsazgA}W8HfAE z)rB&0H6(S-D5htdQXKM?v0>31SgID0QD-WDV!o&!h< z;ubJNG#%z4IUz*>WfBxowy9=! zd`j&LOM4V0>Ij~{(l~AYHC`++t=>YB`xnTZ61f#Yl^t+L$F|~RZwN*g6T9#L_#wSb zNU$$badOrw-@ZAwG9=R_XoVla=GnqDq?Zq*G1$>EczK_AmoDqvVtU!w4Ew* zQQ>Pild4+y=fV9y+ZESoqu{al(J`+9`bo{ysU7y;&?q4AfBf@@qbwI4$t;%IW`Aoq yf-~da`pvh7Bfy=$iQ)9|!{JAbxZ)$J6-L`figMB4iq@Y$%5u?>%zsAijQ$&42wjZ; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/2.ogg deleted file mode 100644 index e6226d538578c7d90fdf8f893d99beed52445f6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2026 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 Py4@*N+q(7?qMZK(^*Sf> diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/4.ogg deleted file mode 100644 index d3f9d7fdc40814d760b1f7c2147daa5e617c0877..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2327 zcmY*a2RIvA8y2H6>Qc3dTeYi0+|ZOz#H|rEqxL32>`|k%uGDBLHA2N6zfz<|iIk#N zjViUps2OUu)>S3F(fdFDuix{W=Q;0r-}8OvoacMaYk)?Z(9zTVH=4HE=1-@xQFGhN1cRd&v zJPzufT5vQ^T+cguP8Wj}5{>8>C2tsXjO;hd9LqzowbW|rNYZ9c8g6<%RwGlz=|2s# zWGYx1#qBx1>$iAxLAcPCiYoXjAT;)U|6%jHe!}uDPc~5n{>X=TG{bK~fiFdT2%;y1 zCh{;P)PBmJt#$0gV8zAL(~*IF?0i#@Rx7cD-@D@9i~B?R2r;w7XfmenQ|8Xo5=*6Y zyp0~}_3k8sy-BeQ0ov(+q~OQO0l8Y@9A{knIcxY?{^(AB{Aa>Lmn25|q|QxOGG}$a z)v60C#k* z~|o0jT9)@HOkXz$4-(tK3$DgRkSuu3t>B0k)ykcf-+J&opx-6GUN@r zErU!-v?%yT#}VG^?CQkuqMbvIZ6t0&Zj1W?ooGOre#RybdiXb+b=0LBkwIGiy*a6A zFv*_Wy>?gkmWfVJM3EDCIYc^e)ICt=jha3vqcCi`8iN(P_@-_9{I|7kykg$SMB#Fw zzZM5I^0u}?BbQg6XlmIf9$#hoKW;%cQE-cK;qV7W!u!2Sfyls*7Gs0n#?r2d#~RrLa@1>^^!dj>-)W{dHN}LRjT7O z?JdO`zD?zcp;&c01zS3l2AR7nc51_!RhOw#l>(;6cvlPgcH4$cOvl;3Ja)eDzf&sA zO1N(wDobt5X^>xIEs1>)_`>z!fO(^^a*ts5?Y8Z>HMdTMU`jPY#;qZ>3$N(KJrA+4 z2$YakjnDnrD!H#-9)Qmt*pRab@L|1;Z0{aF^W3>3=IRFU@+>n`tj2QON*3w0^cIA( z9xDp_GjG9<>-L&ERc6as;II@eE{q>yq92p3`&)rbeGwx`yz_}SdriE5ES2kNPkeI^AZ+aUlFjMJ zm!KG|#D%&vQPOpzurzxIN_eos6=i(71gjQ0WhI&&eJBODZ zm$uno6&7EPw6DS4vB}oyTq=x3I&-_PNR%_{A*(uZ2^xrgX66{Udb0MO+t&$YgXNf; z%PDVYEg?ZLm3c4u90EH~7v9t14Mn#Q6vlXR@MR$y2D|R#0>Ec;(;rpnrQno})@L@M zQcnf^45+bP^@|C}inguq1#m>fgx#!e!7#~vy+e7qbf7p$D*mr|(&s=8> z&0F$)Fe~P?F9RfY%}%^FIuQjJ{c2X;-Y#7_o$AiJgcBV)R&5dSx^mZzjbX@YXQH5_wBH$1%Rpf;>%^&|5u`Q| z6~Cyzs)Kp)zVe%?{*9b1XAG800Qh>I5>oOb4(S;WoM2@rLD2uB$GcG2 sX)O((VsYF`r%*0L=@%^xpJGdqN~fyO&@X4G2{_Hx1e~t&CKU?%2N5Do>Hq)$ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/5.ogg deleted file mode 100644 index 712b0a0adafe486d1cce9e4dc430bb4f91833a90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1989 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/7.ogg deleted file mode 100644 index 4f3d5b2ac12174398315c6e95183f774e137b5a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1678 zcmY+D2{hDe7{+J1$qY%{ioL1Y~nOGuVMmTqH75yD^^jD5SdA)+!2q8VGr(u5E) zmMjhGs7#TRouX30kTTu-*SY8BzUO@Be9!m%-simMyyvsS;m&~efc~wC9@FZbtFMvm zC|JlYC@ciy?coImqrnede<5}|_E9aRl= z^&LVIINkvl1HHV1j|1LCz|+tLObwY!ex89qcI;Z1_V1F5T-NA~9g95fXf?tGun zh9}7*veBD)7yPdwQU4JmwZ{vbMvF0D<>`Ay%WpR zGz`sXZ7|wiz>|>3lqe4<`c>bpTHA^5e_s;SPAV#~VbX?s6hU_+>%5i+=WtcV1){emD8{+TB6?g zR@kcpxehab8rB}U-}V@k$j#L&BQqBKt*(1K5$tAZ!x%tkqN(%sS`6e`6uQ6Q5SVnKzR zL6>NrD(#jGSjWL0Ce2^Qf{S1Vnmt&>Tb{#fh+FVwM@oTUgV1y7Ou_h%Jtw~eDqTh6 zNz!o5C%k3MEq>@toia;2vmcV4Xn?NrS~Fi3aQv>GHM_Tn9t@qGcK8|LM!oECoaCOQ zCWc&*P^tsb3RPaSCe!$DZ=_RP->|R-9bK}rSy?>hVhJ@j`0f`2;X=ydDG_U_d9-Kn zL^(O0+1z|RD?_dD*!y>hZYNXkTo+hmJuxY~YBjRorUHu$nbcb1@Tp}w!IY|@&yeL` zm@DQhjYsh$aVQU=q+=9?-CnCGuA74%7;B>~C#v`x9hc&sguI?%Q{%=ew=9LS!?G24 z0_fe$)zWg9O`yA51&!~DJ^l~w!Ki^jr-!!$5#dc}^lz2$5^eBXrLXH5>}CPIi_I0* h+rf{@%_@mK`>WNY14ZpoqqS=^M$k0&42sh7 ztG&uw(jh?yTHffpyytoD^W5+Ke$F}fxqsYa>0{oCNPP~<#EHM(CIgc?K`5-K zsI2AUDI!TpwlDm-{RVY8B|R9^>ESl2TrSq+c$*=Sf zZr{)PeQ3MS;mil!G~*YsA-K zu{u0^PqNOk+0+T{f#appxGPA;y)-4_m^5_fc3G>GJYr84-@TDp~%5T+6{$ zrf#F%IeDSGyG)&!T~VQ|vc{W_QkR+xYXnFd0$Hg>_%y*&U<}VI!Y%}|G2ge4-WK0M zcyi8ZIBJu{_^)aS-m$B`yB7-Xfh1E>)l-Fp*V*Mg^~-RBDgFLjk3ZifIoP1E(o!vs z$!7O)=L^;AY%625t_8ghz&LmmZb{d+B9oaVE-hnUPD)+Dw5jB1D(ReGMb3;X^uWq^ zt<*qyaR~@RS4~->zl(6RZUU+v(9YAVid^r2 ze&;H-?U`!QjndKO)jMa{Rdu<|q~O#l>Y0*|C%CeDljnM5`cAix^Tyeb1Z&$+=!XN^ zOG*%*?;hzi=kQF;KrvR9>ca#-gF#eZ9mF`sz_6Nu01}vI0)f7(=G=j#Yw9X~k=^G& zU&xQY6ic14mJpjNgCW#gv}cVzWvbwlm<%zeX4{d9z$% zl!2~uCpTO`VIh!gAUH?0gv?TxYl)c)_~J!Z|MNr9{$yfT4kRhp^o&D}HYMu{T1z&) zxw0*+rW?Xi7N&3DV9Pr(dVX}~d2Y`tIV%CSm#w5&t2tnMMkfg9BJg-)#$?i7vIr`j zCh-|XEiJMOcAQ0F#l*99vf^B1(7zT{#N9{K`(LlBrn&(zc0qX>y@^8)2)o(DZ|fQ* zo3pRr&LXL7D0-Xbz@tY+$J>BFY69cs&seY zFdJ;ZInLhX@W4yq7Zin+lqNbrMfGkY)M3{Y2CEk|b*pHjAG&TgnA3N?zO0GFvcf#Rad##Fn zeyRIgyOmBGT-#|KG;2DlyqB|gi4eKOw}HZnOXKjU&%kE1mY8Rn-DY~D+DpeC@2YiW z65B}h_JU_vi$HB1JmulMwgqA?R*$6Lns#Fu@>d@ovFMkatk9dOwgg+I%j?G0Kp%{< zk0Hz{z{QmkZOt8d`%r3KfL5dS{WEL>LJDcl$mcNobhMmG(PVT|YxJf3b`{TBo~#PJ z!ZpK6q+owg?3_f_7uidEm3*fLk%L}O7jWz9ot%ZZPGWP6?JL@kC@$HdRWU4zT73F( zS9d~cl7f!Z5B%w0#4jM^@$k(3R9|NBMK`Z%FO8EDIf=aZrRI~ zQPaPqoWJUERU7#;5nu{GZ6XK`3C&Rk5A6{R_^PB%9hk1eZ>h$LD(Q@m%_;UIQp1B7 zP77Q9Y(W`c!wC3mpiB~Gl%;3@h$D6Fukg8okpg=?)xVjs(UM&IK24`)|2yhsrZ z=0ZnXWVx*0KT5OvrC?}>p)aaDD$MrEvH0~m(kD!%39e#MF1uWbQ?NVEwXNI#@IC*4 zS2Sobf+RWCLqKbXZNl-raN+F;9U2t{TTBLHZhkDiD*^w zS(nLYf2Jc7VgJu?{4*UHX8;-mXBLFN?+`us-HG2fOBSVrYV4$lNW>K zX20B7QAT`wXL?H0`99b+cGwg!>$0#a)qd_<%A|2`VzE+ZD(&GpxLBWUt0PsgnXUzv z#cO~m0mdTx`CYjq+p($u%Jv9gC|G6%Nxnj*w8!RRj8Tk$q1%H)4qYYOkhlp7&Hj%{ zq#na3)Zj@ri|eFIQ-l9wpTf6CPO?woloM{1&B-n_^?!BoK_^|BI+59)Mj81h3al}a diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/9.ogg deleted file mode 100644 index dbaf9d6dd76e573eeaba4d51d46d37e6c415990c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2146 zcmY*a3pf*O8+KU4r-NgT(;Aj$+V;tEh>DoucdRB>O|jS*CbIM`MkM7tmQ%*3gpflH zi#e6k5|yu{&&WA^%pt=1r~kkHzn<%Quj{$r=YH<@y`JlN-^YPKa1jv``LA`I1YO^D zW19*RMCBam3Oygr+x zl1rp(f}v@QjlU9)?5n@#t_|X9i=Pr`^Jw~%;_=q-Y!MU4%`OCa!Ug8M|4WU^rjbKB5_|`~)ko#yZ&mv5* z2K#gaa4phWr-C->Yzev@iGkl5CKG&(V`Je*7H0>G^Uy{QsQ?><&c>@S+86B*W!xjhba(*Pa_2?fJ)>SrlXqu02AXS?6 zlw(R|l z?6%qfe${x8fU;m0SVG0}s&n2yW@<=aklqc`H9j{$VhMytj6nkXzHwHH;?Zii*&)>m zuiG>67eXJ^Wx*o}x5ykik**D4V-(!qwcb1~C;CTRk@-wfTzYpyJ!|&N*xuvD14G{<1=69%ktEQMks{Q$UbY|XU>WT*WQE3Vl8TP1d# zsBE_4mt+8ogh>K{Hf?oLpHTbC$+ewTz0N$V_LW zX%rYh*)PLB`1K zyS1~?NCwkAaTLlYA(>Jy)^pflTIz=x~{` zFrXRPI3}yPMG$1*Aa=l9^y>`?6OOv{+Ywcl8K(*8zNmDvcvbfwv=F%gVPGQfyB>TNnM{a z5>sOoywIZ}>6woUb^9G|KL}Sm+t{vx^nx9Mp==}HDhviT_oLLTKiLb)!HE8}y=e*l zaqS?F1F5UVaUapO2~4!0J5PccQSF-)%Ab6(T{(vSd>e)w{tfi^wGY+B@8$(DF5Pes zMJ7>~D^g}t@n(-QLwUYbnTNvc;w+P^TPc7v8I=p0^ze3h_j(erDHfL6+~iO{5f7KL zB}dhKtMeqqil1c2hupt=J(?ZSv?zSIT1lwe@c88v^V8=+kaY&Ha4fY!Yi1DO7d68B zU^fanm~o)3Q8nCT3^Z!eo5*lc)CJb+>8*$)1X2K8}IZrJzvwn7b1hKNeJmSqQtaf1*nH7CC=meXZ&HCbnOz#mr0Q;lg z#M66TX*gqLWKGaJArP}wL-j}gj`s9c$d!%MN$9&DHf=E|Y5-(|@OE>p- zh794>HFr_E^Em#J;p6Et<(pENJ=fo;etSODX;$i?r^Cqdmla&>kbGUx4zXPP9b6Cx zw+CDErgTUH4ZNP;LGL?$j6A@L(H|4<$H)^Gx)ewA!vIS?Jv|~_ZQpjb_Gj)LEt=}L z!b*^7iE;^Qy#!=wG1?>fPKB!Yc)q~Zo_{Xd`EC+ce$*#95-r&o*3o&E!;%Bv?Bn+k t#ecya|3`6)3q8M}j-R<{vOhtF#KJGSMNa&ml!WLfZe<|9=if%0_#6NL diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/activation.ogg deleted file mode 100644 index 446e0208cecf0b456cbc2b9049a3543d6809d7f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14195 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/err_pin.ogg deleted file mode 100644 index dd7d40241401a5ed7d7729b8046986334453346f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4537 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 =ofY)LDm! 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 Cz3-3! diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/language.json deleted file mode 100644 index d844a383..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/language.json +++ /dev/null @@ -1,55 +0,0 @@ -{ - "language": { - "type": "uk-UA" - }, - "strings": { - "WARNING": "Попередження", - "INFO": "Інформація", - "ERROR": "Помилка", - "VERSION": "Версія ", - "LOADING_PROTOCOL": "Підключення до сервера...", - "INITIALIZING": "Ініціалізація...", - "PIN_ERROR": "Будь ласка, вставте SIM-карту", - "REG_ERROR": "Неможливо отримати доступ до мережі, перевірте стан карти даних", - "DETECTING_MODULE": "Виявлення модуля...", - "REGISTERING_NETWORK": "Очікування мережі...", - "CHECKING_NEW_VERSION": "Перевірка нової версії...", - "CHECK_NEW_VERSION_FAILED": "Перевірка нової версії не вдалася, повтор через %d секунд: %s", - "SWITCH_TO_WIFI_NETWORK": "Перемикання на Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Перемикання на 4G...", - "STANDBY": "Очікування", - "CONNECT_TO": "Підключитися до ", - "CONNECTING": "Підключення...", - "CONNECTED_TO": "Підключено до ", - "LISTENING": "Прослуховування...", - "SPEAKING": "Говоріння...", - "SERVER_NOT_FOUND": "Пошук доступного сервісу", - "SERVER_NOT_CONNECTED": "Неможливо підключитися до сервісу, спробуйте пізніше", - "SERVER_TIMEOUT": "Час очікування відповіді", - "SERVER_ERROR": "Помилка відправки, перевірте мережу", - "CONNECT_TO_HOTSPOT": "Підключіть телефон до точки доступу ", - "ACCESS_VIA_BROWSER": ",доступ через браузер ", - "WIFI_CONFIG_MODE": "Режим налаштування мережі", - "ENTERING_WIFI_CONFIG_MODE": "Вхід у режим налаштування мережі...", - "SCANNING_WIFI": "Сканування Wi-Fi...", - "NEW_VERSION": "Нова версія ", - "OTA_UPGRADE": "Оновлення OTA", - "UPGRADING": "Оновлення системи...", - "UPGRADE_FAILED": "Оновлення не вдалося", - "ACTIVATION": "Активація пристрою", - "BATTERY_LOW": "Низький заряд батареї", - "BATTERY_CHARGING": "Зарядка", - "BATTERY_FULL": "Батарея повна", - "BATTERY_NEED_CHARGE": "Низький заряд, будь ласка, зарядіть", - "VOLUME": "Гучність ", - "MUTED": "Звук вимкнено", - "MAX_VOLUME": "Максимальна гучність", - "RTC_MODE_OFF": "AEC вимкнено", - "RTC_MODE_ON": "AEC увімкнено", - "DOWNLOAD_ASSETS_FAILED": "Не вдалося завантажити ресурси", - "LOADING_ASSETS": "Завантаження ресурсів...", - "PLEASE_WAIT": "Будь ласка, зачекайте...", - "FOUND_NEW_ASSETS": "Знайдено нові ресурси: %s", - "HELLO_MY_FRIEND": "Привіт, мій друже!" - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/upgrade.ogg deleted file mode 100644 index 5a41be8aa85283e761b3357272e61edc9d998066..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3642 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 Ux8L`MyMM6+^w-Q9uU-8A02_YBi~s-t diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/welcome.ogg deleted file mode 100644 index e04ca00e65f0f934c049f787590eef9f8294c808..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2803 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 E4KIx@RsaA1 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/uk-UA/wificonfig.ogg deleted file mode 100644 index c1d5d9037766b1626bcf12ebbbc66ab888862bad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5981 zcmY*d1z1$w(x_a?wvbx=G=2;?)+v(!_H0{4Fm0e$8U`x?7xr3#mhi+3Jte6o{BaW*68TM z=v}7&5z+W7{(s}II68`&*ZEd}{^GB=j)k2kA?l5)g}1FBACC|ZA207;2?o?<<6`A% zZR7C*#j`^3_(V`lK4vEeOIOsye-uk~qU2EHuj0QSW!?6)gG@-l!^gu5>gwQW=j7<^ z;cO2Lr6MNS+Xh7KJ|}wbzs3XR!Nm`>_bPA1ixEkrYqfuxd7F4nvW5#S!7@J1JNc#p z?(wN9aDj#rQ{oK28yeQ{$|q+HnmiuDIm5$z-A(0b+z0O_?Nd%>uz(FjJSM6E-g@(4 zSwQp*Tg#fO_sS^fVlRB6g|r4D@VLZa&`?%zBsiew;xoPYk8fU#ve^$mD3g4@;WTq# zm-0Zi2@0kdi9tD$8amd`>rD-tN3nj0jB%jVE-KIAUW%2rm}gj5fI*k}OCoaSku_R+ z}jfRmdx|1Uw$EMY}XSS z3S?_pHmRAgh-)@b&~fLOpT$Z|ly8{Lbppm~lV6jbn25P>z+60XUgzgwcoiHZkES{% zz~C@UkB8HO1J@N1<8+F9Rts#PGPtRFs`maBQz@FWpPe14<%CCH$8YV(b%N2 zG(8vtm=*{oXebEWa@uN1Zpqu!6g1m;WTIQ9J?D8`pD8pwn%dV3KGGP}w0- zQBkakX znnC`y8}4pZmbawW_gHrHW*q5c>Y}LavBO^QmY2PF$s&K9MADYe9EB$jE<{r;Cv?DD zP8Fx>@O78lbuC(D@fHyjYi>T7+%13bI1eeZ5eEzU^sXdUELYX(s}d)Ukrgh>x33@k zrham1S(X;QVaYmX-#^t6#!~84kvO7Vw3P}@Rn_c zP9Q?|Yzww<)pOg+e#IB3oKxU$w*Rn0htND1JwNdA_wRKXiL|Gww!Tj%HGjz2`-s<< zl%AVFdVr9ss=p97Z7$U$jIewk6rbk3*ev zC32D(hv`H9xKT%I(}@SH(?mYw=ek1535dYfkSfOK3pmVM(jojZ> zibYdsZjK6_7^Z||4_MeSyqD<|oYCmk+OoC+p7ZvCI(cb+ELsNepMKK6u3No;*0fKq{nEUufr!{VdM?t|;(I^sb+YR>ysOO5MsU;Yda9s8VvPi;Io;w{q1(AOdFI;3jyMa_7|OS5Uf&A@jk zHk#oBqclbGensdc#@&HB++4Il_`9CU%Kbf_z_ zQ+3q-!0;Ntvr;r2pXF>m3;p85Eu3sGb8VGEryRs3=_f@K7f1&jxde>V7+%LYZ;a>l z1)4lOU*eL+be_ibJ{uiiHyJ#pFN_Iq13hHhpXmJtf`6kKAp%;q!FD_(t--)WH@1$;pvuNcGha` z$ghQVgRzaCpI#b2n`)t<%#5A;F@|5Zl(uS~b^U@=uG0=_6yiU(_Fd&MC3cf3cH{0m zaddb?g43>oPW;*1PS*(EdQVYv&~UIsi_}-01mPJm#K{mA;+Q7+)Q%tAmdr*TM{Blx znqd~;Y9h7GcriHFsu}VRQU(S5h1GwM5)*aTC@?jOw14}3Kz5GoY)dnaZJG#59pRFOJVe(^(nPU&bhF zCqINN2~EhE+j%6DyQvLhWf9~uXfg^ zP&APZ!I^&?ysLnQvavSYBPTv%z|{~Ebf#$G^%Zm=*ekdMxmsPET2|y1gcCh7-+))O z3EyV<&VRAK1yURPpn}CCf==gg`da$h_2uX~5)J1^q#{ofzNw8UCs-kUCNiat1da2% zVxfOhfISY8pE|}p-y6_QI}L?&v=nMhP%|hM`JJ3thBUaEF{vhWRnkufjxCe9#&Og< zL&hySH0|BrZz0)QTle#gV)Hm$0MO>>t>2%B)8?7}L1`>*lmenFoM`xHo#(hM;N#Nk ztK!GfRngdrnOu`cXueA;YwsVF-J9k*Yq?{fpo&K#U%D9B7d z^U_TsiyxuD`R;f+Kl_!gSWTm}+D3_M_K&sj9wEvdqJu&5)wY7Zg)o$Vg5cD)`&fI> z4La@2Hdl8?21-nskM(m{P-tMq6A>nAqIYxE# zhj0cqQvkSuW+$wLW=s#^uDqZfd`NT@$2{~48}ECdzMat5{&8x`bM5m}(T)4>YT^0* zaWxOU3DgzoQc+_il}xWFOVlDX70c_o!EYwls;9+f=fVl4sII0E0#}`@CX;#+@7Af} zsP-pCNT(8(rCwhaR&s#CTg4t3UJr|}lwcR{{e1Y6wf-P&=1s--BilR%XTl#90->Sw z%)(1tp)(}6_nnbHbQ*Tb437PdOlRCIL`}RL8wHIPj|M*vb((flBF;YHm;QeKe`eEelahDSgi%Lf$|6RQIVWA z?5JpdzsRZtyV{UrYZ(wNbKslE1)()aIZOQ*;{lH~nXy{-XA_6Ls5|yQ-h3X?9emCZCKJ<39=2d=-h{U*U=T&{bgIe++J%AB(yyG#4m81*WKJC?Qn92P zFS{6(Qh?aXKB|Xlt176}S{{5+rnqRTz1?h~_Er#`F8Clf=VZ8C1qxn77CAy^kJ%Q1|fsgJAQ(6wrlu z{wA^(y0=zBij$qwHFx?1lnfR1pnfOJxw1H1*=dHqo_5E$ zN@Hp8V1$9OefjtKn~dc?eK<+xU50g&9i9li>-Ka=6bgYsbr)Rz`5O2bl|P8JkJ+N( z^TS66g@+@03kgAKZ8m7g-A{EfAv69F&NJ^QGH>FYvp5pAG?7r_KepGvEf!msFzH0` z8x0u6Qa?@uDM+;Ag6*_q#k*XMOSa&}{u~leJZLeW({6{_99x@rYUN7S-qRCF*C;bT z2bQ@fWzMfx16e59&*38Jj?GO-uyY_uZd>%IL(v55Hx_&TC^iM4G!esaXFWo)S{~HP zx4%9YZxD6Rc0vbp>;2GxOHh5MUrehER3KvA-n?~BLdZd4<+|*v1~IsBvOoY-aAs@q z8$bGu%NLP5@XQ_O!YnyKgR^d=5GJkHb*J@7DuQ<%+K*+pR&BftN zdEOHOx>|ye%==r&=F-OxLr5lmtQ2h3d8sb?%uDEFOu)-b%$1AUR%XnjXcKPIDu7mq z*pD0QbNuir0@y#0-1Xw0I{I(%3P3@!R3!#FnTLy$qq~)tyB*Zi%iip@rRCo&sJ!fb z#z_}sk^Jdf(yV>^{A!@+?|01OseoUEk*C6t(y@zDM>Ax6hvVD4J0XsRC}6s8y84IJ z*jiiTKlp!CXwz4X&gEdbwMgcXy>(r z@ssPdH#z%$_!69MZFJA3i+el1Vwxk0Xv-mcJ$3|fuvYq#0fYaV*wenmO2*kA_({rFM*sgVc;>j_(`nPjfd0L^f zTsHknVyk)8m!?2eWMD-|X)Y@PB5ARbWO%SXuYukeaqZ}C67 zcC<_$!X2c1xnjD6j1nnUUC)^63O^n+_-q;hb=bHHCh~+Pe+Z|}AndTxV(}V!eA&0P zD*sgj&@Jf2%k&G}2NDa*K2|K~hK4dRCclqd(B?!_m!Y)Y<8{<1al4o-P?g=cEMm%>_FW<7Mr_ z;wLL_iitgpX@WEz(mo!UFBkT6;u~9koIes5_fCJwzsbMz_pgSjn1o<-^WA(~kXwK8 z=#<~88)GW3obs~an+6p|p66L-RCAiCM=J+$zW|j~*U(}>uAh&F&_~2cwYh^3V!Yzz z_z0*Jt*mJ?>!(M*o>~@i1RLpjws)5J-f2P867kA&<6!5J7OMNj4z3HlQlX8UOLGc4 zo|f?WPM!HycQA~|A~^~*do$whr;dfx zh&?DMw+V33ZbA?FlnWU?(R1&Uc& zB}rk30BI@;#Pb5Q4W^jh8jEA|J?yR1*u-L%R$&}LZ%1Q)mEQ*P^tlw!?9F>FBrI0) ziL>0Uzw==;r(;S}GXG;#S~4fwa^O>D79$cY3KFzUNv>#P@n4Z^6JWOMJs%FfW8*@5 zkaA|{v9M1#M4c#8F^^872nOGuNj5+6yXP9WERG%_4UBA?Kbu6b0@}98%*;BB8j=EI zA~98|y*cK`7H8&nWgMx>)U7DOc3ph6TSY3gE59)J#nA-6vc$=wp&)wk?$M)dWl@*a ztv^(L*}PrZ^Sqn56GB_*Axj@w~PUE*Qflcj!$iKO8VWRWLDx&(%hoSedxwlmrJB=5Z zu*)i8e>mRw&LdnumLkhG4`^H}uyg#Kqh1d2ZbV)lAI0YH1_dYt{`xKlv}T5cT;+H3 z#XiKl^gyZ>7ksMg$1|IH>Hs{ITYPnba6L+Igcl z#G~@%af`~2JR8}s?`a*1O2L2!Ne|x(zC&wdD%>VX! x)5uOo{vS2;Un-C9^#94C=znp`wEjJ_OzU{)-+CL|kN>3?Mg41Ld(!d9{{WFTVw?Z~ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/0.ogg deleted file mode 100644 index c6c04183e267cef70837843feb763dc29aee8508..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1446 zcmeZIPY-5bVt|5UD^J9Om|h(V`WS`%3rdSUQWH}c87&wO#DbOhgOtMoNI4^r_vOWO zD@I$8@{q*zVjiG~Phwe`nW3J!o}qyONQEpAr{*Q+r=%9y0_Bo{a)y>bNkfI4%%psv zMzFyw({=;Z0RhNhkfXdN3o;327v+~07Kb<*`WfngL3Xo>0@E|SeYcd&x`cD9D?ggD zTt0t5);YrA@M96iY$I8z<+m(eWJL5HF0s}5SGmmQQC;OV&v)+ccZJ^4UfFv;XSwpp zem;hE{dcRcyj`>}=1p=XPwD>;yC)k=2=BgQbbag6r$TnAJtr48q-Hm(D{d`Lc&W5` zp-r}?F^Am^>pS|h1D$%-R-`Ftn}~}Xt31%i`R)5jiOG9(Bu?$E6kVr%`_KQ~JJj=7 z1${kNx)e85Wvr_deI=*hw#WbbR9?rJ#Na7M{oWoA{C9c526pLSb?2_kix18$>9POV zWPI-3-Rx!swLPVwW%i3XetW#E$r5{i@EMPEq04*sSE6T@El7x*ztDJ3!Stm)O!qZc zGC6#a^|qB;b4uGJ-}K*`p6^>L7h3#R)i}nu_;LR3w?RAQ4~km<{~sD1efDd##P5Hb zp4!UUTTZVzx$Ufir_h7YSN_1TRNrYl^=Xpmv{sk%=M+Bo<}VH8b5=eVqI*I-R5a)N zUWJjB|EjUL z@3W)x7stzRTsNLlbo+iFueTlV$uqCRH?7_KrR~hY%q6>ZKNQJ@)qMN0`vG1TWsy|;HkX}XoXsfccN zv#R=ne{)W*t>3cz-Wsdb65jb?d2WK{hWxXNsxE_e|t( zRh+f)XprTuaH~ZJ=P50^+IYlzr>dR_r?PSDMYc$m1U*qP<=kgZ3EPh7D9-cJlAkNT zF6DL0(Ttb-FIpsj%UxCj^rMXCGKn8AKHi_dXs1f2?7W>e%_ker{kwPLtcxN~%)uz7 zM*QM`wR_ zvxq2X@PfV9>K>oeelz8q-)2pDDF@4w9NU&0Rd%0zFZ7hRq24l)>GIE)?XUs~sw?E@ zm1ceItT))sW6*lTCc9aHpJTz>yU%Br$-nt{pugs|-xH3EmcF@?1_!>VHC?&h=E8ow zkI`4DRDI%o&b)7BKpSP)FDyA4^rFHp;^#rFD+=bnj$Wxq0f{MxT;(^loA<8w{MM;I zS%bQcZrgoZ+BL@lEEo29QCmg4j_0fn*3*BcF02mpdDH;3UXYLdM5zSdyXWi98odxy z>HfULi2Y>ciId?676~agT(Pi0;aOxi^YTJOwy*FzB-G;q;@sP1_|JZ+>>EZjwaifd z!mCW;dluCpWV^mtSRi;SL#%AFVQPW40{KX?n@f=00OVO9tKB;VSr*7c(s_J~1&X;B cuUH}Z2FOEFd;1Hj8-RQy*=HiiI)OY30JSNHxc~qF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/1.ogg deleted file mode 100644 index 4774b06ca00151808b9a7f1313df23b57c2d2dbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1635 zcmY+D2{hDe7{*P5Q4D1rvW#W=XJ4uzOO_HLLk1!HGBFaFLK5yY7#XE0dvOg48OFYi zDK|@{tXH-|5qIR))U^z{?qBDgd-a_2o%224^LyX(e&;(M28VOv*~Rm(I{O;3wzt<$ zitt0kFyWUYtpj}nAP@t{6VD$AW*h%c+c*StyTb_P5R+{j>x+vN0#EFGuLPlWwe+=g zb#%4~IdBDr`CkkOykr7q{$Qqi6byBdp}~F^!NMPnc{5u<4%Bwz?V$+mD*^kw{iCA@ zmqUYnUHmO|H9+Bs@=Cit$mh;=7ECp2u8R#<0v>;VnT-@cjiWvJhOKj$yIw6`80_V# z_V~#EAZU~KnCfWKY`@JkhbzK&-5x5d$5~KZBi|tbg=BrTdX$tWS=#$fL5k^tm_uQ@ z0G^0MDnTt^o3im_3yOw~ROP{9+$R4w!K?FQ;nltTsV*c-#TAFC8)NkrXS)~MXfp#( z1$R&0G&0?)sdf)IA#%Crky7MH_Lo#Mqm3+pIVL;=;TN0sve|IA4_v>KA(q>QCjvn7 zY1Li}{n2xDDSx&yj29cc1btRVYL@wJ4YmIzR~t>pKc$vxI92RQ@vJX#Gj9O;7U1_} z8-djc&E%N;1(j#gjCh%6>#bdlIxfpthHcc5V9lzQ;Q_Yrp9h6}OAC+i-K27-S-8Lp zb-i=U7Dt?oDHRW;^LM1Frj(ZXJBdcvor^Ud7oWecLRkv4QVxWRO)wCPd7c*pj@+&b zhf+ND?_0_&T1jzF;9kpnPh0d7@S{9_=`guU*Y$$l$$umga*{z>FLXYx-te?U5VgDC zRoF&}w5mNE{ZyjND?KL>u^7@+&*hyP#}k!+YP>{S>ek0^S1g@AROy6Aat6%B{-*Hr z4=$9y$mBq(DU|9WAFgG1(0F{_=ec1`9F^B>mXD4`zy)&V*BT16mbG59`aYJ|Hnln5 zI+&AjYDq{XNhk4}r`^#ITH=OJyXko>#FEo1l>AhGMe=wPo~R5oL!#j(tqnEv-*Z;W zGa9YfG2KX%wTl@vv+YGh#Tmq07NJ#w^)83S5ZCP2EBKh=+xLhv_Sp3Wm8!4VsL`mS z$m8<{oA|Xes8(d`3dTPA{)5p9Y*O^HB|1s`M$9`lf{1uu#$ zr=DhsSF8l1axD~79eLG{MeJN?Aw8GSE-ft66 zR8(Ttr;(Y^5CV^V8b#w{7ZJL_Uj(5;Lc7MS48)1nxR4=?!L z6o9t*(vp-JX4Nm7v8jV3Wmd?=sY65DCmy**v@r&tutj&9MaZ~^u63Bo(z-?vg9a4U z&&;A_nqIn9AWCER0aLuV8{_KDi!tRsw-RVEY4?iMdDAAlVsU$a4a5`W`UfnS@4=if2b^5BchrHYuI55`-g;|jGG_!oQ$(E1`JLfpNNA- zghA*IpYn3&B=sA@knwa`S*g~EG6MJ(vMQ=tE#F;ebe1B<6#LftYpfS*Sy^E|A^rl) z$#$cU9nq%*QEeQzbIsfQD;-OcLfeDJQ%&Jcn#-XP?s&%k6DJV?2RLnH%RtSn&F zqvDz6B@8yRyG!OAj`4wP|){0cYRVMs+{_lq47`7;D2{d+`xDz q3;G>t!C`|Pm7p`&$(CVvrl8wVSxYediDlm1IRof+u-$cr#{U3NGV8bi diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/2.ogg deleted file mode 100644 index 592e9a445f87191fc78169e24a1844de3a2d1360..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1857 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 Bg5&@I diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/6.ogg deleted file mode 100644 index 8158cfc24e9ef1a7d67897df107681fe93dbcfec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1786 zcmY+B3pmsJAIB|q#*zpp_qK_(xemE?B$xlm9FYix7&hZK*BLoZMH8FrIXlVGa$IsN zmosw-n`KLEg$J%`99D0{e8W@pXYmV4GD3V*dy`38e?9q z+?^u%3mA}sYZRH}h{FbhKo+2OzpskxuKxep)j{G^A*YD~S?}r|*btJ8c*PkThc`nT zm>ZytjCKtT@xVm{MF!(yti>!y%+Qu%h=vkF10%&7zc$``i!JuVwcB|2Pz=EkPX1Cv zbVNjKOiXkzF4WuIP)`q_sA__q%RA<&Jp5#blfj$H@ulZ-)9c9D-{J4kt)~sR{&TwoXyrLu_6E66TnwpZee%bKa zCG{qp6XPjl;C9seQ!yFUD66$8-GMiBP%K4@W7|Dk9N=9+g1?9cmm=9p^@%@GHN8rx zOZpnY$FS%hWC03HJEykhP5Y)`bn3z%_Pe%j*(e@CPC*3X~-+Wq9gCRTo^A3jA{Nn!P*Y#h42GsobaoqdxV1`4{? zW`Smj(k7NLo=PNyCzhZLP!KTA0c!CMWcpmCvE!SXw=kc+>0rI`(-G7m3A2ybILC1; zX4Kjm)8BRqYYTOe39{(yKk0GnmX(1S7}T@x7(mm8$fWtdwGMAnhLB(|%S>(jJ*lA+ zbxivaI&|ei>~^9?K2O;ApHH2+07YAy!v#VWg+j|ejS~q$sE2wiuk=fnVRltW{`%{~ z7$34qAW;b6+%=DVYO~!J&IgF0iAH}Z zb*7>5;nl&?&)-RpH#wa|JKvh2ToDu}itnbyX`8gi7JYmm6*nZ5V2u<&`J&2CS1{

    >OqgeksvbVGC<4dBqFprc=EX)Cljuso%eAthK?K(11M`AI# z6bYM5=|48(_gCLe% zSi|gcUPy3)OS(zu0bKT{&m`WTy3&nis#|aT8zz?qn&NMi#Jz%BNg^1{*+1(>&kNmG zSPU41kxce!EG<{LQt<$K^Y}_HlW~_9K;|NBYdOI9MBdy~j=Hzai?^%GUCs~Y@@#|v zMN6k_X0iK2)V#Mlw-Q&nuWnH<3pdXrZq9HQek&fu)!XZkSeb4}dMe1bIb-P;$6Axh z@C+wdyX(-&2l=oul%diYw<24z9vDp1D z=@;_D80Fk zE@cc*jzE!TJh8;EI=^$hBsMHd%$u@oc41(PgTXc6xy%fmC9a2hz zmBkr$RH0g6=d&anYflmJ2=>?x-D5WSG>G`RkvG}-a{3%Bdr0Y^{@7M?!D5PtJ1qVy zID$QJ^Nz#M3%ZF{Qzm{TdU$~)8ut8ja4dOt>J;{a^8B3|ZItT#BeVU48C$7Kk4#^# z6qM(VgY2Fm+7HuMw)TxHPJ;ge6#GT> diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/7.ogg deleted file mode 100644 index ca03b3edc25fe2d0eaa4cff57665f6425aa7e58f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1967 zcmY*a3pmsJ8#lLgVKGETF2gv@YNZyN=weJm%w=w6=GsrUxgB?!TyiQ=Elp9%EpfJ? zrI|VCYzNC_>7bK{lT;LvliPpm|9}2}|Mz*m&+~rX&*y!g_xZlx=li;ahm+*w<^E$h zK5<#*a^pLdKpJjmW22oyDIp-xevlyWhr~@L|F6m9ASueP;N%< z=3eP7H);u{=V26%s%OtA-<^Nd6P+B|S|@1X!L}jeL(CkG#0IZ9;qIiSzA*7K<-YT< z*CGLQT>~A0&{4Zw;rGNx8eh^DT@O$?_UJrcDKdj6X~k7|19Su;-Nu*R zna)M(f<_*La6qdT3GkQhIU5j6-|m{oQAqcz$qZhSo57C+T>95*mt zX)1(TIJ1B5ucbZaVI^K^%825?o0TN2b;=>u#VJmFq)AjZogpSy^mlgg&n=ED!jP!+ zBIF4`p;FR*?D(b=qstc+kE}gifqEGdYUX!}@*Ne%i<$&2In@42@GrQaI>jQU(D!~K ziV|s6)Cu@(9ONr1k0v=Omuk#GSjLiLgJq`;FXc6(P?|1cW-BR*gFBUYqS=dM(Pr8_ zJ5IZkQhU^1DQxK0_zVW|6`-5Jn{C7^BZ5@5tw{|I!*48iM6W)z7$_%P-bZBMd=B=N zhP}0?*{L-{N``8z<#Sn?7AtnmxzxgeRSDdTVPRDUgQnNLhFR%-WQlR~62k3^zPp3(Pf`l6+NBo7U+8dj|FPRV0 z=1ku{A*^+v%BwV{o=#)X&W2&mQ>(?*O!jOY$5pFvc=z3Sh`)ysik$xOF0hLy_RqUdWO>^3f%#LzG_BnN^ z6kOa?;i=|3sN9!6CCU7b4X_MJXm9ya7}kbL9%#eMo`=cRcQ5_AZ|wMfW$eK23TRB# zb%yUSgII8R=31R?-T7X1Xv!i`jL649my9x0o>@-Jlm@=SyTWO=#`4u^p-slTx4HV`nh_F!ZeY9*A+{o zE*PGwt#Tax`*iNut+Qzb+ji2jGGdS&F*zkX*j;Py+nB|mm~m%+p19Vr@gmTJ7*94iy? z4-tSr3S&nc%H_r;8?nC*n@z)aV!Ac}*Z}M$QZdA$N-29`ER?dv-(zxVYWo{y#wq|L z+4qudBR+i$#8*DB$qO=)sAOtN+t=GZT@!7arSBuXy5xK%Xt#V%P9pSaxLVAsJZCw- z{_U>^JodYk5I%^qZq2?Q4Illp-=8a-hOceWkl#L?TIqn=?6LfD%I9tl6k4nmz(r;T+_wEq)(~VPRd*#iQnUjCqKfKKLEL#OqQoewkf|uB*>>t=CHNI<^EoyRHQ(68;OWVTmpP diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/8.ogg deleted file mode 100644 index d359674ff42b6b3ca852d27caf237872c152a562..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 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 UDAe{`mg9C;p|*A2!=upu1;{)V;{X5v diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/activation.ogg deleted file mode 100644 index a3871b8cfe7e6be2c35e38a3633249068cb02d7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9747 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_pin.ogg deleted file mode 100644 index 16e42a0eead3b4b5fb7254eebc80388905948cef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3806 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 TjV(9E|FtQ>`z!OEA0GREOGOp9 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/err_reg.ogg deleted file mode 100644 index 00b6babb0c4015c0cdd4898a2de0af04bd284131..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8213 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/welcome.ogg deleted file mode 100644 index ae12cc3160d9a4f780722f48ec90c6c01513fe2c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2929 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/vi-VN/wificonfig.ogg deleted file mode 100644 index 08c3cb5aa7c55b8e0d8e4df56215f3aad132a300..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5203 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 BpSb`4 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/1.ogg deleted file mode 100644 index 858af34c5d69cc84ebeb82d86cffb330bb3d38e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1485 zcmZvWdpOg39LKlDv}nl4HFR=op4o`mP@I%S%#eN@mzd41rN&4`%CR`+GTOSj&1Jcz zBo!wdBr4Ly%2DPz6iYhdxSr`b&-v@TpXc*DpYQwq`n;bnF*MW@v<399pt^Rn&DH56 z1O-+ho@PW7C_y1$ur)Y&{||(?iT|ff94vhe34KUlyG`6HC^T9@>KqMqgZCGLCQ(BS-knF9D`rwl#jZn{uUbG z8|wpj?88_fR8;{`Kq3FDuz3zC^KL1hU)b29@VCH zR_@)%8nPOk>kt`f^Mu$1(WJ|e;XR8<)f%o$>wL5}AAn)42V=JA9@!%_*RCRNkq_K=wu#Ub2`}UQA(>bk1{Ny$QSS znsaVO>b)pK`e;xKRht%boFF7b5mL97T+W6Wik)L05~qHuIIkYlRIG^%Y5)05(CXJf zDhpH;M1ZZu+b^8D=KhKzG=@HR$vtOy)vaCJfft|dMVaIPGd#)82P*T_M4W@?p-g?< zYQWsi+5~!Yh0Cw`$jJ9TkxFBkn?LF$-q!+Q9qY)&{hCSgw8Y1qaHQ6KQjVH+Y36F1 zp96d%Y?h(9F>M>?{PELdBwJ7CST3o=*0JUF-SBj#u{&(*!EUz!opx+B+r!4=p`&ur z`o4YDOxXwm*&)E{EYr&#kVH}9=%aj#bnE%}1haANRdn>B1b@gc;uT5oaOdm^p7Mdm zBTDju$U%SK4TMcr+O4I-7vl!uD?Ud0pG?joE*a(bat)%HEq?31HrX_2_A@NwnZp;5 z3OH!pmP^%$x6~n;Ren}UR6clUa_6uP*m!pcV;!0pC_fZ z9sAP*bKDW#C71DK;M`2NpmrLg)So;tbeZQ#ssC60+RLbvir>EL9VGO@{0 z;lciU3$%!QIE1ImQpBs*mOsDdtmKy z!rMAPQ#9dhzXHv03T>BpPoo+J*Lqb%o#d(&Schp(-1eJ_MrZAZs1?=;*7@=N_bpvW zN#?dLT$k)8ZuwfVd?+v7Mn6SUR#c|+8T2ez>3DG1-)`6R#kHb4R*Gk|)bLR+>iUqL zfP&WdyA4YhQdo$-tQOHXot5r8AAAU{)42YzfGw~`;HmIVr8 z@~XUVjmAJN$*bECrK9-fWr9erWcX~=^oVI-Ag7}LQ{qeSzW(mZ$-+unUc$Mnte01C zdtSc|XshckYlrJxf^Hdv68#jDrM>3nbJ}u3!q!&>dG!VWrmw(>up diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/2.ogg deleted file mode 100644 index 72f53aa14f2c83e125702cfe2448653f2b53b130..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmeZIPY-5bVt|60gf-eArgGHuLyW@y1*OFvsfj6!j24Uyc3>s`AmwlXQqBnECAZ2r zG1`KZha{#K^8iJB63f!e4E4T5vJ$8c2tWpd9Obvi^r3*CPfBWRQG#Efo~DkOw5VtVLtH!K8JSGSov-8F#1=Am z?qrMkoP6>4iXIEe2W+=(nR zo6Y7=n!~<9NyRoJH-gjLI{KgJvLl^&8ee8rzDoYKM4@G3+WmchPx*9jI%J4u)FI^CE(^zLi z?|09>1eJcRWY56;dn!CGE?C{Qp7G?aKZ?(0o?@T9Ho{~5?s(Dahc#2(4ul#+?ht0H zKXvl|^W5YETB=M7%U^rO#7;f@DTLc0(kkJ%mJ%QHQiZt<8_t}H>2HX5r*S()o>|fT zdWUSKf*e!E1itU<4@m|s`C_M`qnvsm{D$`PGP8uIjUo$=8&w=TcJ<8J)ZcpqCw;qa z*mvMaQhL8eXZw!pWv0?%D`fL#99+MoTJySYn);K%9mgiv<@(M!Bpk&0AmW_?@A`;C zvt4$Ir+wntQ?M$MF*9mcMh@G}%Qcsx3Y;wYSeY4jshhKMEMfWn-+${DspP9%XB&l{ z$+R$M);dI)UJfk{Wq;v1`;k-K-@oe8!k#Qq32#4K6WA@xwFYE(`#hC>&du^7$&MGl z=$ibStZ?9Wl|~tBwB+iwb2eOTKgj10d6%1K;?X&s&Zc)VMgOLpaL{^iK|uAFBjbna z=NcK@+n342q}qzw&EhI)5XrDV^Fo&G%9lgGxm1&LbkC|DpB=OzGU>d+GmorO`70YD zPX8;OXnwnWZt9{>FS_RL%2X5BnfyUB{@8^TY!f;cYN0S&^D7ojilb{@0FwKh?Gxw-$5CFXTEasPH}`>{g^@>oN6-Q)h6kTNJX; zElhEe!Gv{>VoCdoE0@e%bJEQbJ(YtV1{S zJ}ug5dSr>MW{jKe#wppVW_R>wRK0ewo3WHH_wIq#_rLjKY#Kw9|0>t4G(9|ZN5Iq5 zhYJ6CW%CP1L@>P8e^7pN{)fr^AJ#k&k_+l-y06o>a>hyVDKR^lR%)FVtDAPWvTa@N zOtp2T0ujut3JP19dTgifSmCR3R)Wnk^yHN_`3DrXPS_SM`1fnZZGn$*d)R+!MKGx^ z=Km_5%2{$CVQomK8t0|i=V#|8c@_(ESbom(o_na-ytnUQmT&a^gar|dUo;Iq@K;23 zU1i_Fc0|6->eF&t>$D>;FFyE^#MqxJxaP(Lg$a+>tX!RIZO8R^uSS_UhYV2Hhm18g zO<&jc?0!|c;@H1TzF#N4&Ph9>kr^Ms_$jW)Y?3_dFZbR|oqh$b-@mmLunGbI%1$UW diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/3.ogg deleted file mode 100644 index 848af1199ecd546398fba5864dc9210f92080630..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1503 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 G?Z7`qIp;_K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/5.ogg deleted file mode 100644 index 92303588b9367066dcb9bf76b90a6a3eb7675f68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1512 zcmZvWdpOez7{~qGWrPTGTUj|;X3O0~k>%EzLVo0$Tg+w5+;X&tHNu)MClr$;<(896 zbk3+KMlKyR3(5U56guoQXL`<+j|zU&^N)wqnr4fZCTe>sM#gMR?{G%g?NuQ(FDn1K@0{;SKkA z>rPIZo}D8GVLl$)(eyO#6mt0jeEd$&_7Zpxudbaj*1^QlSOa%I!DqrNSTxy9>wzOsp{-p1ba8dt>s9T3B1Io!EokT(n_B=MPiu?Jwna= z1g!{s7=62tJj{q2tG-(l&LVg0lItKqO>2!^C={Mk=Bi1&qZu_X`$WmYApn|h7^@*V znlqf&rH?_9yVI5=m-P?$Fi@0r5B(-z+fwMaj6vDX_)<7l@^ z4ryaogOK2S&vZ8lV~VLgw&d3q0i2WbLC;X)K7QvJJio70f3!6RIh&)_e%$3l{sBA1cJ;h>X$B2i zGfb+&#%HHuaQ;dg1GBe3{<33>@*z<^388-tu9M2xC{1Mw>D{+Z6&(@s63JM1&|zgA zC)UY8AMp!p2O>W@V4@!k1XEjI@P!|77jdbbaSk=~s%Bc<%Eqm(TGE$3k`r=RvbhyE z7OWwTO*+L{mH`)z;i+?jcyl+8H^rYa5@^9ip<$hgv+rpx2mGLY*Dfxlc1gHRvKwF3 z9ZUg`PP;SLEf~?TG`z+8l%vMo8$~aIQ`4e zER&bjrLpiKLw|WQg7C~2!uce3O4p2s2)Y%5yIlrLSDIibsdOJzc8iJKQ`Uyf*l#_q zGO=RSY=g)%!A~}9>({VNvo&q&JR{6*lwq0R+c;f|giDOgv+Ww`GE@oF;XQl9fzAzU zX?wnrH8QacRj96Onat9yDA7{gO~YjBj8J;y3z4lK3f6|J*v^p%NW@b`il-HkBk?I; zwV*s^|KIesAWD*U^HiX_+F*n97lK-pCz=!Y9k__SYr|eU8W8-33fWqsWnnpHmnZw6G z88s@i2$8`yvLyp)>uIT*k>m|y)?<-uQV{fOW(1V4fa+_-|e9SsMUwMl_Lv*j+ zpK^rtG(RYh>N#m7eb7e^4hk1wILwNz8dRHe*z&};uh;jv1HvkoTm;P{pSlOX4N&vhCvi(<8}ZOy?Eb%*WL5LR9tF@Rvj3N%|oC zc_cfkiv|MgSW=j??qZW_Bu9?M5_iTUbG5AyYhQCO%NB#c7oQkox|Z11$?VX>xv*V4 K9s>5i%YOh`cCnEF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/6.ogg deleted file mode 100644 index 9ecb5747b9a4fd1077f68e7ef0cedd7599ad8051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 zcmZvWc{J1u6vt;WC}y%XdX_Y{vdx$|_GP?5y|M4~W5zxVqR1AF%9OE|NkT+<h8DJ6X z;P6lrA5Rh(tPQ?t@Ds5<#Q)PF4(3eL%U&^H>>=*pNe+c_HWr={zM2@677Bw#9}=fH z<#WmVGRfx(mg9MIJd6&<#2^Cwy)JVOe+ENFsyG}+hrx$WjUr-Z1RWgW$zc%`qNBUJ zqN+9=4uISyHyLxXBi%_LIrrSU3vCIGdrxBJ1K_IISjrKLP$$;3(_%d5D; zoKlB;A><;m$~K3M&=XbrtGPHbL#8<#(N6277p@sE7Euv^k}Fw4Eeu&nCn&uUo{((w z+_31WuDUKSdlz(#=!?@i*ewJM0kUWMFp z!4CBdDvqr@(eI5FzyZ^i$n(%`le1V^n4f+rBF}auTy4|JZr!Iz5p5kCeDZWhaNh^J zoLgd}5~*l)-I1lG*8Lr$4j-KE(P%@QgxN_`K=^*XDXLbw6m@HJ8UCZrK*7T?9^F?+ zAslfZah7AcIPMO$w1V4LCwXuO#B)I_WvG$Y`p+CI8)Y6PLrSD(Mb>kG)e|L@8iTk9 zkpu4DVXp4_6CpguS2PB;Sj&tZ7n0~%ifgX1o#<=DfmzWXs$Dq@nB7~NPz%c1yPOZX zvhy*Jbiq`?hCiHZjEfQAqeI5|d)#wku1&YYEayV{AsePYft4Xq<8cJOsWQxU)v7n*03fI#;r!d4eMi(6?E5sjW zPSWl5_nyH|tmRf0I%hFcx~H6Gvr*58=sF8We+PA;=)hWy9-fGi{6Cn4$D`&ioXi`6 z)irhqedDw9IHog`mNNiYy1EoD#|`S%C*#X{Wnp%ZzS*|#@PtKT-&QvhhW9ewf8mc)H*r1)*;ek;$KM6_ zFLo$@e5|td>1cWu_iVuOZj|cr_cr!_XE+O2mleWUKtlJf!gzu!=_MLnj~_9mY;>m8 z3jxKA4U|crVCr6NGKz3FT~fSl{L++5D|AQ)mKqZNVyJA$rrh2m%PHeeQPPNZL`6D0 zadb&;Gz5t+FFYOFOV4PA^+yB823^WynuymV>q|=#KC{2oB!Sg1Lw*ZS$ly93xPJkY zb{1Nmome5YN)Gg@fB4iW?_icF z0^^<2^Ze8e1^v9+a|;i;pk?j*Yp06d`h5*EQkra7Y&CUD+Kw?+#zxXgTTRfyYtp8J zkZ3?Z|1~4MUO|IR-~lQdw%?0$b;QdAGJ{Jao5BFd_qgeq5CMBx-O>-0wXTAY%;Bf8 zZH>R^rNLA&t6LdA=rwymZx&<$@TMYqPMd3?U)nFzuA(PBEQx;`ME829z1>K=ilL>9 zrGQ8Tt`qS4hFrVnr+(ryqsc@pbF+$H<$i>e?l&MGbfxP|+YLhYbNne^J>>i@%vbtN oi*A*XYAOt)NAZS0006x1c11JoH1|IKj=xGOf{)EsM*Q#cACYaY6#xJL diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/7.ogg deleted file mode 100644 index 634879966fd604d7a12ba9040a283e83a6cfe41b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1652 zcmZvcc{J2(9L9|$nUNB*GZK|CjD5+j#g>U7KSHyZm}`u=gOa7tSdwHnbj#MQOlruI zt?X1+GZQW1=1wt#j+wG{(d3T0=l*q{bKY~l@Avt<&w2lPkm2DdF>$ef#TyLQ*%~`+ z_<0}&Bsng|4UY)}fviC(4nGj&7XF{MaFFPhAPM+_?6+_~On8i}Xyb)Bd&bhl$jZnB zf!HE6MF&s9MTg-j_971_@=R<*rU{ftz($K6{tR~N5^*AJ1#f*y?Jm<;J|L8MffC_y z_yollebmUGXVs)@Bz^H{^iB(5Y%;Mc0{v@9+@`G;8a>x@1K@=C=V!wPbSe_LJN2vCQ1#a> zeusSw=UTEoA2dg8NTzJB2S?r(E0K@+&C4kG``?~?Y=Qo^sv4ru;9;X*yw~}QFewO2 z;$?~OrhWMp{+%7w9zLOh$h^nu#(&<=eUjaGA~V8nP<@kmvj_O#;f?Jvj61nF2w7(3 zUko$vH}OD-mka3HnO9)IUe zF~InWR^EO^HmLKhAO-k<@wOP>biF-$);D?f%kn(+!W6+9Ir`}Iw&A&1_VwJwTFAL*G2xrO&gEf#{i3Ppt^|6mP%~aWyeV}k2bzi*_|A@d!+-e`7`55EgEx6dxVAfFIj_=ml1DZ&PZ*HLJ=Pbxo`*EDX7vF zG_he5+hDAGzgiEL{c0%p;A{1;Ahpgjl6?y|JnMY89h!!h4e1lNwhd$@OzM!#Mro%V z3mzpWCauo8@EtNy{%e=C2XVdir)kF4x%vkEpMC*kVFcv#^_@lCMD7?gG+AbO4F9Bp zo4ll%PhD|rCIot^#-@_p595p?Li7;Kgsdo=aS6Mt{<(!96~yF@;iONv!Wu@{a6c z zI4luQtHdI?Mwk(~JI_kej>O7{68JwVD1ECz#YNp1KgS57a_>qoF_#4>g#A5XzL)62ZRE* ze1g40NIv0cuIJ75bPTzsj&e`{F@$^gGnhB6nago?5Pa|yPTUtNYVQ>3>q7{Pv+=;A z5Qg%Sk^m?Q3x0g#MIk*zMOtWo{2PC)%a`D*4R3FjnLY9#hlbrk3n=pO%|iOMFaZCw?xO2lzIRghjQ8d|IXZgF zy2UxyO6?USloUxj?e^A+cY7TyTY<N4AZM8O%17 zpU-WztqejjT_)(j6v!RD!N!cLou1zv?bxKC;Uh zIhVEVwqn;6crD-3HI(+j`9_Hqy4I>a^P6$>i-~t;a=dNxM{GrnH8Ukk6XC*mLljfv zd)bOXq-n0q06u~x{VoL55@RioatQ)BB@N3qd7b)3B_O-p2<;`k;ON_zIq!td3A-Ya z24X}Z8GE@58lMeZfKM8fLJrpEU+js@>I@TD&fjGHHKzWt9Mh4$lD2W1?h6}=Ars$Qf6l_vTO`CA(cE$w8wuec6(j;VcC{O zpYD3ixR<7NalKuYDdAL$Akp?fhj(Q=6OM;(*8q1~3i~#S>gV2Ar5^>fQ~M`&zUGX_ zP8I5q9B7>k@o|p4p)m#EWIp~oh%Qrj-*0RX<{*HD1tRm@7S~*RFPfAL!wfHId0fv} zCDtM6=EGB1cRUhZc+JM1$3L)yb=F26=cUg?z&5>%^{Hvk1abG%Sff!(E9Om1Y7a23MghHFy;iPMJdEdZOS|>9M z3fa0x#m(@e0Z(-3$3pJSZp^e+zZlAJs z`OZB5=(q15cc}EH-p<+&D)f-%FHDhHGAZ$1w*w=Q2g&+%L4f>$samCxl;OJB;gx%; zH~i|!vtT@Yo;4$+(Qwn_y@eG#q?#Y?*^M!(sg;7b0-(jFlOQ}fP<*2qT3|}ZwKHW8 zZHB`6_k-$(u2bOW;PD7u0;xfR}O^g(18Tcx_qEx4WsadWS45B=?jfzvWP=(k6H4F@|E;P73;x zYUQNM%ncrrwhj#zU+jKb$&3QY1!ggZ^G#P4gkF3UyZy{ny9#)DVh>BFEt=lCIq3+5)1z5S4{FEwGp8?8gkzo znye?~^3@Xt>l*_$%ep)gEdlVlMbz4wTQ-~Kgv%@T#a`unnUh;RmNAs!4}e#H57*CD UI=q9;2++Ev4Bg$;RQ})PKM;JEKL7v# diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/9.ogg deleted file mode 100644 index a7769d9f05064f5a97b85c3944b23043dd6bd569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1421 zcmZvWc{tPw7{?96xTPWGKFSQMVT7@zamJLZarJYX7>ql|u#TukiK#UR>7dBXFfy$p zBHArtS~)6fXBDzClQ9|h?C9BN|Jv{KywCH#@Avb4pVu`k%w0%W=wCH#;HZ0Tvb{3| z1a*x|O2FW8As~=BC=2}^aoxlJ(;f~IOny5y{h*V3xCbsQL0YhJ!VyEwkO&k4X=JoV zs0j)m6C4|Yk3T8!f(0J(M}djdj3S(m6$HN@1~X{_PN2QRdrz@*Xj}WdeN%{GQ6z5< z7t~RdmZBmcl(%~r&6g219yz$7h=JUDlP`k9T*bCUn!|Ck4mWK|d-P_g>DGOwOzA6w z8TFswbWRV$+pHTj!6pC(X4Y5otF3a5k3F77i}dUEnta}TvTf|YMlS^|_EbvA~c^eut&I@&!c zW&m8^_9DGeee?znx*Yl-gzgx;c9)x{EC=gs{%d_obu2ufx?Ma0_7d;y{XFV!2<`~H z4W{{u@g)mb-o+01ZNm@o*0m9}UK0rW{vo@3YIjD6wrFWiEvQa?@Qm=as{WB{3R~F|L9nN?R)i6C=E8tP0bhN_XWd2&;{Y>CgI)Iu#K;Am!&c zk}+!S01Lj9!}yk1g~?ih-gBrThy_7qKR$?uNz%6mq++q%k)?aqDK^i z%C%Th>j$E#J`ifX*Y!#t%99;gx8tCLT7CHNjvOE4?2L0^3!F@?h#3=8n#Y#>vU%k8 z{rcZYE7|$LmshP&T7PDffyqNTzFLwVc}pU*^Ngrr(6NymuE6`MG!SQ}yqwj@t2E&G!^xm9E^a3w`k=QYKCG4|1m@d#=3NxAG^ ztzoN*cd*4Ma$Qg8Z(i_eCku-)KD|X=wUTT^!8*8fE!=V))KF}aAD>7bh*qx9$B@j& zS3M?_Jxfq19@`qd&`+uWgm%-W^9c;Y=tX^ZJ|3HCG94hR%e|>1l-Fsl;;m{Mv17@~ z+v3BBTM8H4xi#g(FgpvyKufn8E~MdN?~u=^>)bhUNXnLtBcjF>*Vtve$ONRYzaHhr zh9+jK;5Yp)i;VkSMv}H2sT)mKjn0SX_S8SFNo+-QU)uCv=@<94eB0J%;9#;SqdLr6 z4X3bkKDGqHMKFIup{rRCzOXnTuG2Y-ePUs^u;ToT>3EaTT{Q@YtuBTlhMlHXSh`jv zZYa>{uNOmUw-#h{RCktL(Y~$w_W{Bx;f4cM4oST;!bQ03-Ns9@ZCdZGc@YkVYj$WQ zlYqi9lGh=Ue4}lFUMm3N>KT1{k4t--8WgsaZbA5<>V#*Z6;$I@DiIo!T5|`Sl3oJS z<8k2T_U9aBRyvZoK=pa{JvLY0q^-YLmi>-^+^|es2D>!+b4IoDEykhEngECs5N}qX UA-d^sgJAHprsUSv5C6aX2js?&@&Et; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/activation.ogg deleted file mode 100644 index 33291af68a8897143cb53d62d7f90a37ad2b7696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8402 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_pin.ogg deleted file mode 100644 index e4552442a897d7326828df53ba302eca27701638..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3538 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/err_reg.ogg deleted file mode 100644 index a3456f121449ea52f36071aced78a6572608f4a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6747 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 Bd_n*K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-CN/wificonfig.ogg deleted file mode 100644 index 7ef88e2521bb6dac3f5813d952e4bda0685cdf40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3155 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 BpSb`4 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/1.ogg deleted file mode 100644 index 858af34c5d69cc84ebeb82d86cffb330bb3d38e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1485 zcmZvWdpOg39LKlDv}nl4HFR=op4o`mP@I%S%#eN@mzd41rN&4`%CR`+GTOSj&1Jcz zBo!wdBr4Ly%2DPz6iYhdxSr`b&-v@TpXc*DpYQwq`n;bnF*MW@v<399pt^Rn&DH56 z1O-+ho@PW7C_y1$ur)Y&{||(?iT|ff94vhe34KUlyG`6HC^T9@>KqMqgZCGLCQ(BS-knF9D`rwl#jZn{uUbG z8|wpj?88_fR8;{`Kq3FDuz3zC^KL1hU)b29@VCH zR_@)%8nPOk>kt`f^Mu$1(WJ|e;XR8<)f%o$>wL5}AAn)42V=JA9@!%_*RCRNkq_K=wu#Ub2`}UQA(>bk1{Ny$QSS znsaVO>b)pK`e;xKRht%boFF7b5mL97T+W6Wik)L05~qHuIIkYlRIG^%Y5)05(CXJf zDhpH;M1ZZu+b^8D=KhKzG=@HR$vtOy)vaCJfft|dMVaIPGd#)82P*T_M4W@?p-g?< zYQWsi+5~!Yh0Cw`$jJ9TkxFBkn?LF$-q!+Q9qY)&{hCSgw8Y1qaHQ6KQjVH+Y36F1 zp96d%Y?h(9F>M>?{PELdBwJ7CST3o=*0JUF-SBj#u{&(*!EUz!opx+B+r!4=p`&ur z`o4YDOxXwm*&)E{EYr&#kVH}9=%aj#bnE%}1haANRdn>B1b@gc;uT5oaOdm^p7Mdm zBTDju$U%SK4TMcr+O4I-7vl!uD?Ud0pG?joE*a(bat)%HEq?31HrX_2_A@NwnZp;5 z3OH!pmP^%$x6~n;Ren}UR6clUa_6uP*m!pcV;!0pC_fZ z9sAP*bKDW#C71DK;M`2NpmrLg)So;tbeZQ#ssC60+RLbvir>EL9VGO@{0 z;lciU3$%!QIE1ImQpBs*mOsDdtmKy z!rMAPQ#9dhzXHv03T>BpPoo+J*Lqb%o#d(&Schp(-1eJ_MrZAZs1?=;*7@=N_bpvW zN#?dLT$k)8ZuwfVd?+v7Mn6SUR#c|+8T2ez>3DG1-)`6R#kHb4R*Gk|)bLR+>iUqL zfP&WdyA4YhQdo$-tQOHXot5r8AAAU{)42YzfGw~`;HmIVr8 z@~XUVjmAJN$*bECrK9-fWr9erWcX~=^oVI-Ag7}LQ{qeSzW(mZ$-+unUc$Mnte01C zdtSc|XshckYlrJxf^Hdv68#jDrM>3nbJ}u3!q!&>dG!VWrmw(>up diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/2.ogg deleted file mode 100644 index 72f53aa14f2c83e125702cfe2448653f2b53b130..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1250 zcmeZIPY-5bVt|60gf-eArgGHuLyW@y1*OFvsfj6!j24Uyc3>s`AmwlXQqBnECAZ2r zG1`KZha{#K^8iJB63f!e4E4T5vJ$8c2tWpd9Obvi^r3*CPfBWRQG#Efo~DkOw5VtVLtH!K8JSGSov-8F#1=Am z?qrMkoP6>4iXIEe2W+=(nR zo6Y7=n!~<9NyRoJH-gjLI{KgJvLl^&8ee8rzDoYKM4@G3+WmchPx*9jI%J4u)FI^CE(^zLi z?|09>1eJcRWY56;dn!CGE?C{Qp7G?aKZ?(0o?@T9Ho{~5?s(Dahc#2(4ul#+?ht0H zKXvl|^W5YETB=M7%U^rO#7;f@DTLc0(kkJ%mJ%QHQiZt<8_t}H>2HX5r*S()o>|fT zdWUSKf*e!E1itU<4@m|s`C_M`qnvsm{D$`PGP8uIjUo$=8&w=TcJ<8J)ZcpqCw;qa z*mvMaQhL8eXZw!pWv0?%D`fL#99+MoTJySYn);K%9mgiv<@(M!Bpk&0AmW_?@A`;C zvt4$Ir+wntQ?M$MF*9mcMh@G}%Qcsx3Y;wYSeY4jshhKMEMfWn-+${DspP9%XB&l{ z$+R$M);dI)UJfk{Wq;v1`;k-K-@oe8!k#Qq32#4K6WA@xwFYE(`#hC>&du^7$&MGl z=$ibStZ?9Wl|~tBwB+iwb2eOTKgj10d6%1K;?X&s&Zc)VMgOLpaL{^iK|uAFBjbna z=NcK@+n342q}qzw&EhI)5XrDV^Fo&G%9lgGxm1&LbkC|DpB=OzGU>d+GmorO`70YD zPX8;OXnwnWZt9{>FS_RL%2X5BnfyUB{@8^TY!f;cYN0S&^D7ojilb{@0FwKh?Gxw-$5CFXTEasPH}`>{g^@>oN6-Q)h6kTNJX; zElhEe!Gv{>VoCdoE0@e%bJEQbJ(YtV1{S zJ}ug5dSr>MW{jKe#wppVW_R>wRK0ewo3WHH_wIq#_rLjKY#Kw9|0>t4G(9|ZN5Iq5 zhYJ6CW%CP1L@>P8e^7pN{)fr^AJ#k&k_+l-y06o>a>hyVDKR^lR%)FVtDAPWvTa@N zOtp2T0ujut3JP19dTgifSmCR3R)Wnk^yHN_`3DrXPS_SM`1fnZZGn$*d)R+!MKGx^ z=Km_5%2{$CVQomK8t0|i=V#|8c@_(ESbom(o_na-ytnUQmT&a^gar|dUo;Iq@K;23 zU1i_Fc0|6->eF&t>$D>;FFyE^#MqxJxaP(Lg$a+>tX!RIZO8R^uSS_UhYV2Hhm18g zO<&jc?0!|c;@H1TzF#N4&Ph9>kr^Ms_$jW)Y?3_dFZbR|oqh$b-@mmLunGbI%1$UW diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/3.ogg deleted file mode 100644 index 848af1199ecd546398fba5864dc9210f92080630..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1503 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 G?Z7`qIp;_K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/5.ogg deleted file mode 100644 index 92303588b9367066dcb9bf76b90a6a3eb7675f68..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1512 zcmZvWdpOez7{~qGWrPTGTUj|;X3O0~k>%EzLVo0$Tg+w5+;X&tHNu)MClr$;<(896 zbk3+KMlKyR3(5U56guoQXL`<+j|zU&^N)wqnr4fZCTe>sM#gMR?{G%g?NuQ(FDn1K@0{;SKkA z>rPIZo}D8GVLl$)(eyO#6mt0jeEd$&_7Zpxudbaj*1^QlSOa%I!DqrNSTxy9>wzOsp{-p1ba8dt>s9T3B1Io!EokT(n_B=MPiu?Jwna= z1g!{s7=62tJj{q2tG-(l&LVg0lItKqO>2!^C={Mk=Bi1&qZu_X`$WmYApn|h7^@*V znlqf&rH?_9yVI5=m-P?$Fi@0r5B(-z+fwMaj6vDX_)<7l@^ z4ryaogOK2S&vZ8lV~VLgw&d3q0i2WbLC;X)K7QvJJio70f3!6RIh&)_e%$3l{sBA1cJ;h>X$B2i zGfb+&#%HHuaQ;dg1GBe3{<33>@*z<^388-tu9M2xC{1Mw>D{+Z6&(@s63JM1&|zgA zC)UY8AMp!p2O>W@V4@!k1XEjI@P!|77jdbbaSk=~s%Bc<%Eqm(TGE$3k`r=RvbhyE z7OWwTO*+L{mH`)z;i+?jcyl+8H^rYa5@^9ip<$hgv+rpx2mGLY*Dfxlc1gHRvKwF3 z9ZUg`PP;SLEf~?TG`z+8l%vMo8$~aIQ`4e zER&bjrLpiKLw|WQg7C~2!uce3O4p2s2)Y%5yIlrLSDIibsdOJzc8iJKQ`Uyf*l#_q zGO=RSY=g)%!A~}9>({VNvo&q&JR{6*lwq0R+c;f|giDOgv+Ww`GE@oF;XQl9fzAzU zX?wnrH8QacRj96Onat9yDA7{gO~YjBj8J;y3z4lK3f6|J*v^p%NW@b`il-HkBk?I; zwV*s^|KIesAWD*U^HiX_+F*n97lK-pCz=!Y9k__SYr|eU8W8-33fWqsWnnpHmnZw6G z88s@i2$8`yvLyp)>uIT*k>m|y)?<-uQV{fOW(1V4fa+_-|e9SsMUwMl_Lv*j+ zpK^rtG(RYh>N#m7eb7e^4hk1wILwNz8dRHe*z&};uh;jv1HvkoTm;P{pSlOX4N&vhCvi(<8}ZOy?Eb%*WL5LR9tF@Rvj3N%|oC zc_cfkiv|MgSW=j??qZW_Bu9?M5_iTUbG5AyYhQCO%NB#c7oQkox|Z11$?VX>xv*V4 K9s>5i%YOh`cCnEF diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/6.ogg deleted file mode 100644 index 9ecb5747b9a4fd1077f68e7ef0cedd7599ad8051..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 zcmZvWc{J1u6vt;WC}y%XdX_Y{vdx$|_GP?5y|M4~W5zxVqR1AF%9OE|NkT+<h8DJ6X z;P6lrA5Rh(tPQ?t@Ds5<#Q)PF4(3eL%U&^H>>=*pNe+c_HWr={zM2@677Bw#9}=fH z<#WmVGRfx(mg9MIJd6&<#2^Cwy)JVOe+ENFsyG}+hrx$WjUr-Z1RWgW$zc%`qNBUJ zqN+9=4uISyHyLxXBi%_LIrrSU3vCIGdrxBJ1K_IISjrKLP$$;3(_%d5D; zoKlB;A><;m$~K3M&=XbrtGPHbL#8<#(N6277p@sE7Euv^k}Fw4Eeu&nCn&uUo{((w z+_31WuDUKSdlz(#=!?@i*ewJM0kUWMFp z!4CBdDvqr@(eI5FzyZ^i$n(%`le1V^n4f+rBF}auTy4|JZr!Iz5p5kCeDZWhaNh^J zoLgd}5~*l)-I1lG*8Lr$4j-KE(P%@QgxN_`K=^*XDXLbw6m@HJ8UCZrK*7T?9^F?+ zAslfZah7AcIPMO$w1V4LCwXuO#B)I_WvG$Y`p+CI8)Y6PLrSD(Mb>kG)e|L@8iTk9 zkpu4DVXp4_6CpguS2PB;Sj&tZ7n0~%ifgX1o#<=DfmzWXs$Dq@nB7~NPz%c1yPOZX zvhy*Jbiq`?hCiHZjEfQAqeI5|d)#wku1&YYEayV{AsePYft4Xq<8cJOsWQxU)v7n*03fI#;r!d4eMi(6?E5sjW zPSWl5_nyH|tmRf0I%hFcx~H6Gvr*58=sF8We+PA;=)hWy9-fGi{6Cn4$D`&ioXi`6 z)irhqedDw9IHog`mNNiYy1EoD#|`S%C*#X{Wnp%ZzS*|#@PtKT-&QvhhW9ewf8mc)H*r1)*;ek;$KM6_ zFLo$@e5|td>1cWu_iVuOZj|cr_cr!_XE+O2mleWUKtlJf!gzu!=_MLnj~_9mY;>m8 z3jxKA4U|crVCr6NGKz3FT~fSl{L++5D|AQ)mKqZNVyJA$rrh2m%PHeeQPPNZL`6D0 zadb&;Gz5t+FFYOFOV4PA^+yB823^WynuymV>q|=#KC{2oB!Sg1Lw*ZS$ly93xPJkY zb{1Nmome5YN)Gg@fB4iW?_icF z0^^<2^Ze8e1^v9+a|;i;pk?j*Yp06d`h5*EQkra7Y&CUD+Kw?+#zxXgTTRfyYtp8J zkZ3?Z|1~4MUO|IR-~lQdw%?0$b;QdAGJ{Jao5BFd_qgeq5CMBx-O>-0wXTAY%;Bf8 zZH>R^rNLA&t6LdA=rwymZx&<$@TMYqPMd3?U)nFzuA(PBEQx;`ME829z1>K=ilL>9 zrGQ8Tt`qS4hFrVnr+(ryqsc@pbF+$H<$i>e?l&MGbfxP|+YLhYbNne^J>>i@%vbtN oi*A*XYAOt)NAZS0006x1c11JoH1|IKj=xGOf{)EsM*Q#cACYaY6#xJL diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/7.ogg deleted file mode 100644 index 634879966fd604d7a12ba9040a283e83a6cfe41b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1652 zcmZvcc{J2(9L9|$nUNB*GZK|CjD5+j#g>U7KSHyZm}`u=gOa7tSdwHnbj#MQOlruI zt?X1+GZQW1=1wt#j+wG{(d3T0=l*q{bKY~l@Avt<&w2lPkm2DdF>$ef#TyLQ*%~`+ z_<0}&Bsng|4UY)}fviC(4nGj&7XF{MaFFPhAPM+_?6+_~On8i}Xyb)Bd&bhl$jZnB zf!HE6MF&s9MTg-j_971_@=R<*rU{ftz($K6{tR~N5^*AJ1#f*y?Jm<;J|L8MffC_y z_yollebmUGXVs)@Bz^H{^iB(5Y%;Mc0{v@9+@`G;8a>x@1K@=C=V!wPbSe_LJN2vCQ1#a> zeusSw=UTEoA2dg8NTzJB2S?r(E0K@+&C4kG``?~?Y=Qo^sv4ru;9;X*yw~}QFewO2 z;$?~OrhWMp{+%7w9zLOh$h^nu#(&<=eUjaGA~V8nP<@kmvj_O#;f?Jvj61nF2w7(3 zUko$vH}OD-mka3HnO9)IUe zF~InWR^EO^HmLKhAO-k<@wOP>biF-$);D?f%kn(+!W6+9Ir`}Iw&A&1_VwJwTFAL*G2xrO&gEf#{i3Ppt^|6mP%~aWyeV}k2bzi*_|A@d!+-e`7`55EgEx6dxVAfFIj_=ml1DZ&PZ*HLJ=Pbxo`*EDX7vF zG_he5+hDAGzgiEL{c0%p;A{1;Ahpgjl6?y|JnMY89h!!h4e1lNwhd$@OzM!#Mro%V z3mzpWCauo8@EtNy{%e=C2XVdir)kF4x%vkEpMC*kVFcv#^_@lCMD7?gG+AbO4F9Bp zo4ll%PhD|rCIot^#-@_p595p?Li7;Kgsdo=aS6Mt{<(!96~yF@;iONv!Wu@{a6c z zI4luQtHdI?Mwk(~JI_kej>O7{68JwVD1ECz#YNp1KgS57a_>qoF_#4>g#A5XzL)62ZRE* ze1g40NIv0cuIJ75bPTzsj&e`{F@$^gGnhB6nago?5Pa|yPTUtNYVQ>3>q7{Pv+=;A z5Qg%Sk^m?Q3x0g#MIk*zMOtWo{2PC)%a`D*4R3FjnLY9#hlbrk3n=pO%|iOMFaZCw?xO2lzIRghjQ8d|IXZgF zy2UxyO6?USloUxj?e^A+cY7TyTY<N4AZM8O%17 zpU-WztqejjT_)(j6v!RD!N!cLou1zv?bxKC;Uh zIhVEVwqn;6crD-3HI(+j`9_Hqy4I>a^P6$>i-~t;a=dNxM{GrnH8Ukk6XC*mLljfv zd)bOXq-n0q06u~x{VoL55@RioatQ)BB@N3qd7b)3B_O-p2<;`k;ON_zIq!td3A-Ya z24X}Z8GE@58lMeZfKM8fLJrpEU+js@>I@TD&fjGHHKzWt9Mh4$lD2W1?h6}=Ars$Qf6l_vTO`CA(cE$w8wuec6(j;VcC{O zpYD3ixR<7NalKuYDdAL$Akp?fhj(Q=6OM;(*8q1~3i~#S>gV2Ar5^>fQ~M`&zUGX_ zP8I5q9B7>k@o|p4p)m#EWIp~oh%Qrj-*0RX<{*HD1tRm@7S~*RFPfAL!wfHId0fv} zCDtM6=EGB1cRUhZc+JM1$3L)yb=F26=cUg?z&5>%^{Hvk1abG%Sff!(E9Om1Y7a23MghHFy;iPMJdEdZOS|>9M z3fa0x#m(@e0Z(-3$3pJSZp^e+zZlAJs z`OZB5=(q15cc}EH-p<+&D)f-%FHDhHGAZ$1w*w=Q2g&+%L4f>$samCxl;OJB;gx%; zH~i|!vtT@Yo;4$+(Qwn_y@eG#q?#Y?*^M!(sg;7b0-(jFlOQ}fP<*2qT3|}ZwKHW8 zZHB`6_k-$(u2bOW;PD7u0;xfR}O^g(18Tcx_qEx4WsadWS45B=?jfzvWP=(k6H4F@|E;P73;x zYUQNM%ncrrwhj#zU+jKb$&3QY1!ggZ^G#P4gkF3UyZy{ny9#)DVh>BFEt=lCIq3+5)1z5S4{FEwGp8?8gkzo znye?~^3@Xt>l*_$%ep)gEdlVlMbz4wTQ-~Kgv%@T#a`unnUh;RmNAs!4}e#H57*CD UI=q9;2++Ev4Bg$;RQ})PKM;JEKL7v# diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/9.ogg deleted file mode 100644 index a7769d9f05064f5a97b85c3944b23043dd6bd569..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1421 zcmZvWc{tPw7{?96xTPWGKFSQMVT7@zamJLZarJYX7>ql|u#TukiK#UR>7dBXFfy$p zBHArtS~)6fXBDzClQ9|h?C9BN|Jv{KywCH#@Avb4pVu`k%w0%W=wCH#;HZ0Tvb{3| z1a*x|O2FW8As~=BC=2}^aoxlJ(;f~IOny5y{h*V3xCbsQL0YhJ!VyEwkO&k4X=JoV zs0j)m6C4|Yk3T8!f(0J(M}djdj3S(m6$HN@1~X{_PN2QRdrz@*Xj}WdeN%{GQ6z5< z7t~RdmZBmcl(%~r&6g219yz$7h=JUDlP`k9T*bCUn!|Ck4mWK|d-P_g>DGOwOzA6w z8TFswbWRV$+pHTj!6pC(X4Y5otF3a5k3F77i}dUEnta}TvTf|YMlS^|_EbvA~c^eut&I@&!c zW&m8^_9DGeee?znx*Yl-gzgx;c9)x{EC=gs{%d_obu2ufx?Ma0_7d;y{XFV!2<`~H z4W{{u@g)mb-o+01ZNm@o*0m9}UK0rW{vo@3YIjD6wrFWiEvQa?@Qm=as{WB{3R~F|L9nN?R)i6C=E8tP0bhN_XWd2&;{Y>CgI)Iu#K;Am!&c zk}+!S01Lj9!}yk1g~?ih-gBrThy_7qKR$?uNz%6mq++q%k)?aqDK^i z%C%Th>j$E#J`ifX*Y!#t%99;gx8tCLT7CHNjvOE4?2L0^3!F@?h#3=8n#Y#>vU%k8 z{rcZYE7|$LmshP&T7PDffyqNTzFLwVc}pU*^Ngrr(6NymuE6`MG!SQ}yqwj@t2E&G!^xm9E^a3w`k=QYKCG4|1m@d#=3NxAG^ ztzoN*cd*4Ma$Qg8Z(i_eCku-)KD|X=wUTT^!8*8fE!=V))KF}aAD>7bh*qx9$B@j& zS3M?_Jxfq19@`qd&`+uWgm%-W^9c;Y=tX^ZJ|3HCG94hR%e|>1l-Fsl;;m{Mv17@~ z+v3BBTM8H4xi#g(FgpvyKufn8E~MdN?~u=^>)bhUNXnLtBcjF>*Vtve$ONRYzaHhr zh9+jK;5Yp)i;VkSMv}H2sT)mKjn0SX_S8SFNo+-QU)uCv=@<94eB0J%;9#;SqdLr6 z4X3bkKDGqHMKFIup{rRCzOXnTuG2Y-ePUs^u;ToT>3EaTT{Q@YtuBTlhMlHXSh`jv zZYa>{uNOmUw-#h{RCktL(Y~$w_W{Bx;f4cM4oST;!bQ03-Ns9@ZCdZGc@YkVYj$WQ zlYqi9lGh=Ue4}lFUMm3N>KT1{k4t--8WgsaZbA5<>V#*Z6;$I@DiIo!T5|`Sl3oJS z<8k2T_U9aBRyvZoK=pa{JvLY0q^-YLmi>-^+^|es2D>!+b4IoDEykhEngECs5N}qX UA-d^sgJAHprsUSv5C6aX2js?&@&Et; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/activation.ogg deleted file mode 100644 index 33291af68a8897143cb53d62d7f90a37ad2b7696..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8402 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_pin.ogg deleted file mode 100644 index e4552442a897d7326828df53ba302eca27701638..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3538 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/err_reg.ogg deleted file mode 100644 index a3456f121449ea52f36071aced78a6572608f4a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6747 zcmZvfbx_s8*Z=R8hAW-Y-5r;1q)Smggmj2>H(cNnQWDY)(%pz4Atepc-FZoA5FY)0 zfAf3(dCttv?w<4BGdnx8=QT&u+WIx<8R-8Rr-kmTf6GI#)-aer)5+ac$F5% zB>yAP{3rka_D>G}yW1{aECWmYlk1pTyF&hY)J#3Bgm}52T)aFy{}hyehoytLqlKl5 z#NU|t-x#mR-ykoIosF5}--G{6EZy-}_t*X<{&y*%FK)beQWBAHF9&y1Cr1ZcS9`ZW z4*-d<@7;Won1a=}O-7r$nD_YkEwVNI5zk4TbBTXktL6UO_v0VNz*i?IkfS&}u3|c9 z9k*$jOtMiIxYFe&0+3X;Bh9Doiu3tAVwc*w`3iH+Z`G?n z>d&%d(8IjI&q6um51Qy?XNyepZh*CCC(~OvGf&z2MukPc?oXXBS8}ysLK>5W8i(Rv zY@Y@_7Nh69JS(fyo~p$iw(_}bKH(>BJ@D$mKXDkebS8T`jJ#VNoXNd+KsIx(5~2CY z%-MBgWKTMDjwF`qMGABSzjes&d4U>f9}KA6gk zA{>$i_S#up%%Hvwo7M!f&xsus$OO8V4Essr#LY#D`ux_ZC>om_@M)V?) zJT#HYKQz}Zr)b>ZJ!x}#Nfg1fsGyb6e%}$L-#r8d?CU_)XCDb9FGU4q!Gi7WEb=~0 z2&JQ}P_IA3+s;0Z6sp9`Zt3U00E&cC~(LIJmlj^`@(Nt3vsA-yb`K8=NYK ze<*<(DG1(-JF|e!#Ka67(;m>B|0o-tIq}p8sf_0<^rWbjMH`S6W=Wl66bVBGrKA}= z9~D#!g4skXmB3{iw4m>>K59w#J*N8_8aPox=Pa ziXPj>HC%%T9*1*s`q7sAs9i-Rri zYi=W{2PrzvW8LjaPtTt;A}EOYUNC}ji^T5WJ`YYp`$`IM??6Q8N{0aQMoD&Zq%?I# zA>N<51nxs`CdEc!Fz+dFVtc37K+l7g62!m*Hln-DGm6g}X{8EUSa{AcU4HVG+VBf{ zel*Sm%VIl<++HfySSWi#$)J_(;uBdm;aEMRVk6gJcNq;I-{rE1JMxQ=Wqr;sjLXVo z+kITXl&J{zbnU&}*N3T0om9WmGHGDzF#;8D@t3xjoxmI@zm5ICJbErmoDnt|pq^%d zVLTFX+V=~b^3dzWgSE=By#R+i+uZv($|v|enD5$X>$MN{Pmd@seDT=d{uSoKn!9yn z3#bM7VHRghtZlwQbI=b0hVhrVZBhEpq^XZVNyn+ zlris4B0_sMXt>`WIy_Twq9sFC2hxAlO-Y_6q3~HH3gQ_Z`WZI6R;yw=L~i;g&0#Tq zF+)wwD>P|r(vpb$LVbm`mw09I#6!Z8xP#V|SoiOrlZ#sRc~B+5Nz}4uKF&=-lZQ!4 z7C{GMLR5O8`ayaaBvkZHmFL)Do}hRHNx?q$RT2_h&C7VhV=dBZOtME%iy_aHSI=`V zv<2t06y}rF+8{L>(v_)>k0ONV*qqPu-73xcvfbC@ZvTpqx@^te8({y^a9SIWy!7zv z4Yat9N*aiFb>P9VR4_Fk!$^MjfMk2#Zo~q2#~wJC{&c5L7URQzKfQX^o2g4FCdO)4 zY0~4jhv$YpFH>=R@3I16iRUNN80-D)a)(tgCv!O8)5d&p+t)ay_aWA9N&t~~ zQw~ed7KDKwT=cmd z;Wmuw$aW7S4Ibsmu7fzN;j!f5=tLu{V`zRtu(**jO6Bs+t>9;eDqQ8+gHhdzw?F2A zmgxy^JO9=()w{t;9+BTAGZf|0ORaC$Ibac1B=ybp6+$l{=wB7SJg*{yoF-%M9mef`AxneH-9K$v6whe1%={91?I zrQ-aWwXe8u*)`Imx!bAN_4tNhj(aP|yCS9P13p?oEYA;P5>zcMdKAy_3tyy=rvA(2 zB%b5Q5ELcDT{^!sn;q^S&9)i$I8C}s&H{ENa-O&-%nqdE&4iLs2;R>BA{Q3$kI(-_ zF4EsQgR_AN&pPa*zlWESlkQtnUl&LBm;hkcB-yWmc0;kJRHA~6;nf3EA!;PPSxdeB z=x!^Qy-u-816S`G1=9q+(d*hB5x%m-uoOrYD%sm)Ir(x<^$Wf#k-Ml{t7vCq)ey;k z^wC!=k>F6}gZT@JKEfj|k{0#G&dFbKBfxHz&_f9bC*Ed})>u3Ed?9L3d+|#Jru^3Y zH}VkXi*s{VSjj80!$g_jfB@lON1u=1x1L1=(qhH@?8Uh+=OW#W{zPEtqbj4E*pwVm z$Q4VU)&h2F{Z-<3qa6NTpY%gT7ib$6S5sV&%k0`GzGb!~J7iWYv@CxJL8=~?^eZMu z$fxWA2eWZ8_QY+scWi7>(qXEVEJsFo!KbImwAC5w0cFDecu>~QJSK3SuSqJ)12CXkj$QYRO=^nZG0 z<44L6S{DjJ<7p16wC5tlTI|L0{If1TC^>&Tnt7hHJTz;t2OJ7v;k&uiS=!Zhbjcj7 zq+vDi*oZoH&k{xag5;VJ zvO#WY3j+>h{5pCW3LC2YY}QKTKyCbb)GOht_t@+fn_DTc$Y^n^)|MR(A}+lP22QY{ z_(fM+Cf9-DjkhHWpVwX5Xl<$JsMG7+`d5Ji#LHqs>^RY@CreqiZYfn6K2l8rDktLg zYVGa@lO2H~lv#6he!g9$=wiIUPu7J=0~~t{7k6b#IUN{CcJ#RP_)d0AD3abWtbxeB zCDW{>ivzf=B7=6%L~u@wV5os!)xt!qFJNBJ#2n{VPx3|%oKUuWk3du>_=qW7$#Xf2 z!8973)d25PAtPjWq&@tPFyHW?Lg`0VhV%OX(hXjgUo-#~8-+|Oh3CPcjP!L`svb3( z{*n9UM;GXf8RS$fy*5S-f!p(Dd=3ZUVj8}qzp9m2iHQG0tz_cVe~t!VUXj3A~AXPsDF|2^Nnx0 zV_#xev`=0OaGL>`=cklC#S>4IJG)WWcPcr?x?KlTO%+vKt-mF%QrHAcPi|lLwDZiDpX@WZss&H9kk@E$Q- z+=2LHy?nHJsIJPGK#`knNJn#4_^RVCNwl5I1KSWssijo@tgrf#cR1wA!_1{2Vftx3S3w4$;P6Oh z$M7^(7HXEVut8V0xvRp`%|YyJsDT;HleBc@3WS(?TG^Z)lrA7vcaf4W4t+I=$ld;8 z&Vz*}h^w-(!7IUF2lG~;Gepu~)zIH(Aq)3Cz{-eQr1};BjR1hdfQ8IGbWa1RE$&>X zBwJFVERDX68qS%HEHlSuL<}-i7=^@9dOfE7cEd!p%EU+D5zekLck-Gaek(sR*k&ag zAdC@gjA`KR^z$eG%sJhbm|N<3`=IaV21T=lm7`jN(eI4pu4rHPX%#Ryrd#x%fIZz< z%+*9&>9^PGEozMqw{O(QkgL6s3`}g@_8@C=RM&SCRj(Oob57jtd{eosQ=;l0#FYbg zCQ}(i>?k@p+-Jibjzaa`V|lwJykoH5@`<7i?tipT$s!a4Q=Pum6Jp+w@A=?Yd%xsW zHHlgethJCGy@vZ_vK!S2{P@A-!7!Crhzd|w=Pr7jRmy1iabh!){ zA>Q#SLY;2IDI%Oj$!t^&296@6vtk^i3ieMPT{Ut~x_!_%D>%7(S}mil&>^K5;(WV* zD#@+VDq12tgg^T7(X$yVF){5PlU**w;2dOsdagT;DqHX* z#p$xu9b$I8%o;XBF8^HoF^`hhhhRL7)qMP-eG!bdB6r^FbOWN>O0Q|tMC=Oe4v_ik zNCSs^%Hq1UopiW<-Ya_?&vgpzg}PUSu^`qdl20@dpOs$J-V44Dr3#-`9qQx^&6thI z4$4?5RxQ)k{j8slr(e#|KKLtFGWD3F)^v#Da-}FPD~c*lvYfl6e>^Vqx7|5EflHo5 zZVY#PD7$HH%mTL2egV4u-8%h|*C>kNe{tO@@!w|sUx$qR7uS=Tx_jb%B}!U{MJMR#RN=L_)Hc71V8eY@dQ}Y(WBw5pbIF;H&HN6B zVVkiCOT*~KBF{57Z|3&3jOVZNTO>m2trfV#ZQwItohElpSBXb0j_^E?IV-PHhtXB} zg|`COZ3PrJsiGT){%Pk@Pd64LDE4~|CEuDkRoJviKh(j28|PlFa#<_`#(@TD$$axI z?QN22*^Gj!Z}C8Wy9ptdeP?qB%sdCB;?UAq4qG$WVj`H0U(@Aa4L}SBu964429o#? zK2%Sz_MmJ0mXZ*5{w8_tHTxnoebpzb+zI1muOdU-u9;fnR_IUF2e<2)?py18ER)~S zJw0Zk{&54sIo(uk1ToU4keKW~Ynr)*094Ua&?(6WI!Zm_h2uxe>L?!=aF`>W(|E|! z`Yo$HK9KaswUw1uv_vnys_ozO#g=0ZVd+PEes_qMBH@g z|7mvwZ3a)G3|KA_HE1Pb=6n!| zu|wB3z}MJd2vU4Wwnm-?&5OO^zsd8zOV;^?aS9-Q+u@{pLp>XUo(-Z=g6*Vxby#XZON z!7|ElP0+ChZ^Io^(qar-DDDy}#c}aHZYOXANa2-GS5Wx&6tm%X*p*sjn=r2pWUMsJzmd`p`C!# zn8lUMCO7yC3^y2wZF70ZCi~sM-YI&%;}jY8Ct>#M5vaWbT@2YP3@Xzsno9%|SDd`%A9sC4WkzYc zHF3?yW}d%J$B0$9yK2k7g{+Y5_fgU+qAp*hzTvL6IwAXApgx0}g6o`3nu(=sppwlW7wztjMRjh5^Nwd3M`B6vG)!kCMIDN>a4(OuJs1l}m63IEjXFrDz| zJp~u7d17pXdZ#hy%p;UH*<{$DleX;mu);z2{;7{&=kR2uP8pGDi{s~-6Jt4wo1`g0 zi?_#qId0EO_oaZ}<0#NGoix#tm(HQ!>0TOG2mQ>k%^oP6(R*t_kCL#_Ud{VKx+5p^ z01ve*sYw*;Th6r2GtLqR*_?P+T~)_goMQvu06J&STj)yp?ru+T{`!vr3f^%7c(prd zHx?#m5r!dHv&$pYA$qYA7%O}$M`NgMox%a^`$5rx0@Kibb5uW@b&vHHkfC6j$I3MY zM4s$(-M6XC+`_!uAP#gR$m-T7GVnX0%6|L`$6oXol8OTa+6=qB_Qw8QU4sV_?^jIS*sY8Z#reWl$tPJz9!m`#iMoOe0q-A6P=W{*9It0Q_- zGXsrN_K!Hy26W@v`4lqhfTsLFpF`-&Y*FN`-s3 zjqwj(%(f3+??TFT>NcXX@hLSX&iHZ-Ap}==)Ea5ozct{eugi+~Y|+aH0EF?0G^$U% z{P?@qGKR?blQ1RW_oGGDnGYk_dG!zBt%CY;&+Z%d1@Oh;UC9CHSMKx2wFjI%h4F_L zcbUyb?XK@miOSZAXTfJ8L9C?W3gjJ#=E@hg?({>;e#ERuJtsX+?$-W-q#vsS`6QBm zX~>yb`DwiEXYN?dak3trCyLu#pq;)@)O*0x`wzyE;otrj<0yYIE}nVe1~GB4l$RIe z;(`(r5dlZ?6UquOW>>hp*PAI+`?A;yP_`9qw4mn_ji9HCx7&_p>%xbW-z3ln2`1@1 zArDt4Vbdrpt<#v((_nKcw&m+tgKFFziz-O#i0CwtOD+}>TSG=sFuFSd#Pt%R20&~J zCrOkS+oMO`@F#7s?CcoJ1hs(A)&nseMdN658;{$oQfmqv-iR_8er#tZMrL>nBtl%K z!@qwY*)YYASSdJP8c~Nw;d4jfCi)3+q=b<|A*opP~YeP?q({mG)l`^QSd8yq=Lr z=k2rP@gLoq{_sM1^vZV&KpG5T(2bjrKp$dg=*U6>f!UnW-+e4NkP{_Z(K;=hm==LG z&Tok@_GS1`eL5wGSh90NiU^9wnTC)p1~FD;TO*kONO&%9+^m_-C^%lRE04}MUb18% zJS^>Qo-UtY6DC}m=bJLQNQ1Tgq9R0;p?1V=#BO~{z_SC)f-xO@7b9s?iwJRK#Ag9za+ogrNM<6L;a4rj#-#^_e5gQ)>{C4!OF7@6?;3hvbj?|z_|Ajk$n_O5zXgD zFYGuL-^z|*yr3A8%7}0>KFu)sk9u=4IQgnyOwrdPk-Cm4Q#%b#bn-k6*OsA9DV)y; zS&!4=hqtIS#78FTL;qO`>^>g`fX|JbwSB)Hw0`{%6m6be^us$vishfzMJRz9R0QnNMm;n<{aCLJ?Wnp9i0XPAGJ^%m! z002*CXHx(G0000000000Ch{o70RR91%plrr0X|P~b#qiE;2VR zF)%Oz0000T0001GZewp`WpX`CVRmCRIW99dE-^4LAZ%%3Z*X;UPiJRS002P000000 z001WPD8&K*000snvVIXfNN#pTMyW*ZbVpu<2UY;F1hSDFB_aHl3xyQKdSm2jZ zO=W!waFr&gSl|`H;`N@W!ELO-#0x!yc37naGoJs+QH6yQk|nnAPD<9 z)jRMeMu=1A(%tIvvaCtadl&R=*h zcI@Aa4#z$MzPjW86VqN@OVW_En-(7FD%5? z2CtPZ1H%j!e_Zw;3^p6Ox+h#tt&^Mu_cM%Ut+Qt}Z*4VVOkkLTnFj&N!wfA3;N^oQDi^DVTCzY_a|9!c@ zZ2L*2nYkaRSngs-Q_uirI}mHwQH2evgtoZYquTK&)1Yun_aVhK5p7LZaYGEulNFEx zwINOt+X;Fx1!Zo=@Q?OoWnhG9Uaa0dUH*z0fVT-no5>#P++>~ZA8(F=qoC>pX9NbA z-zh@(DEoJ-G^l7~SnXVBccgF_i+{EzX#zbp!3ZIF|GwRvRZFXeE20?f0%-TBjCILGIDGi+A_Iv434~nklNAT(_F*jT=SnX>9hU~G74t~LIWYapy z)#+~8U+AEO@m53(*~4~(SW{2<3Ia&$+Q;s~$A^>hG@__8K;OS01tI>oJsJIRd`EZn z=Gj@q*oIiRYZ0e)C5pb*n6I~{IHGeoh8aUTJ2x!3+#u#50ayWP27A6(=;y-L35O-} z1Hlr#uUCB(U@M`Bteb%&9E^w7=bBNlG}{duzk^PvJ*QHi(3uZ_vYkQ_s}%$VS|Z=5 z4wS|rRvos%$gb%E9IC!N6UGW-2!(jlUOgA>$=oyx3YmBnp|{E`j9-l?%&>-t4kY0@ z>z;AP;QRQgIn0v~v?>xLaV(%~fLQO&6RbmJEpesNfTARzolmpjFP45gu5SCRSl0U! zNQw17SQ`!1d0f|_TTDKAU3)s#I0V%?dHJ$4{XBzOc-hi|v;R5=o*KHJa|Na=eoG_6 zwGB6ue!pg~bCjoZk73mBc%;-l&C0c!lnwn7gtn%onP-P8b{)cYwOH$TUX`=^hX zaSl`0W@Gvo2pI2ZqzLJ~|90}U?wT!lxw2EZI-k}fFDAr5#2dZAtxAcx$a#IRGg#G3 zn=Qxyd!W7-1e4cjPyIn3EBwe4=zO8=k9-O5$-mqw=;O-cPO-fZ{VDo(q2bhy-YDEy z>$}iN5#Q4_-OsHb$G=751L%I9g26*KoYM&}dtU7#ov>~Cdn_PFuJJnHB|FWGlPM9{ z(MOxYy);<*gA!H6{;`l*^59ja9N^#+&@2G!Blf*~i~hcv!k<1?G%aAoyWb_HymhFC zylDKGZ%0FI@TBNo1I+e#8Yo!dEXzUJj_X7Z_iO=4gc~12EeYTg=*$X=Y(@JHyaFqZyY)z)p(Dep@ur7L0yn2g@ZSH@<2?O&Sy0J zaH4DKH#Q7Vn}j*uqbEk-!SGo*hV`O?SnRF7f=!?)vZJRP@Q zk;k;gxHY;|nrU~8HX86@tW}Nn+l%Hgi@(O1q#Cf*zHrl_{zO&%(G=FA+DJUcG|a?r zT+i|d9ehQgO-90Uxc_(tuQ{vne_(MOd`u`9s}{=2Xd7gXWiz%%d{1X*Qvd`wJOKaz z0000c@+idv0002(&SsemZF_lDOgAzf92plCSgZYk<`7l%+9ypBF}0`l3e$nsPfK4I zbP~~uK4yHg$z}rC@0MIjufh+qbF_;C4;0l&8XN4%Dl88^Sd2x{?xju4Jx~3ekc6Y>7O)R-l5(vVtpY?a z)&>&2`h%gpBOT+i!@|uo;A66)f6BCO?Jy}M^?Zzl;OjQnQ>3neB2yU88YdYNk?Qx% z+vg5zW2XzedH0$qr2?!TfLMS`49pPnd`-;u$l&szs#^38txKNY{nQDA3yt+D^U-po z>eG__*SdFem`!_Rl`qYlFsiz>aT54FGFk#QrRHs?X;$XAO+)lCMJpTrLv9Y9!eCeg zQ+h?DS#u+#RMOVZPgwV(^r_gNj%MEcv0tlXIwIt{r#T|EJbOnUpknz+}<185BQ# zWG%HmFWKZ_3Q1H5`e&;W9yhF_xbu@8W>^Bw(B3gAtY1Wx6lJiqoJOA0hyjN52y`BT{4iR)fi0$hK>D!$U4H7_4?MrVt@%6UrxqzoxiAMlj5N>~B%UUD{)9|ihHjcF{8APW2YDJWx#qqks`L`_EbCs9Z5J!`3`Qq-<$caN=gYa)y4PK<-`?x~bZvyQvoR5v=zqk`$L#y}xNS#n0lJRx3G~-? zv~vJ~k1j+y+@yV*q%R#I4PCN_jvHQo}FBQbFy>_e1EiQ-Bk@g zhDveCiwx3-_VE)~UJp4=8qoQ6bKAoK63>4;w5J84bexk=ad28}JXeUN&l@)MxF#E5 z7FVOgnmFcE6X=Jv+!=|z;Q)<5XN4n}{9BpaAHf9WLtB~I*7bRS1sV|}ghp4mC2#Fi z=;aJ&N5;5Jhg#_VaAmoAsp(An$eRewNEQC=-VOIJxz#|H@z8zkOi2|{NpVkuy>t;a zeU2_tm%h}^;PJku#fpi$eIrleOp%-q8}vX6{nG&}4}O|uyD`1}8hFxa=vQc%=Vi-E>EfM_;mArKR(IPZ)_-Fj37924k7XMqARNAZJ(dM@6;3CXK%8Xii z=Q<>cZo}h=JZ{&FPt00LX|J=Rokuus`4vb+)saU%9g+}bo9H7-i>7EEHZmIac&&M1 z!-v{A4)bYSTw|X$DHsIs7f8RAlUziSrvOn4MV`|)X1o4B#aS;(GJl*^P91R3pFe{Q zQV8+E6PCrjnjONfoysLKnm=-h+rFXVU>{b!MiUf2H@nsgbMxejxs@;B z*Q-*vICl|uh+Xf1I8G(RjC5zY^Cia^5tsBQ@)EvJx4isPqcA1T>X}P*6JZoILTqpV z51k%}E+})XKV?g$*g2ZONNar{&jr~E-jJqG6J-Z6y{}}#mMOZ7EzI9*_N@Cbo&l*{63f|zoX>Ju8W{^?%^SMkI894-)Y`dA}YoD)?YU|9UVA@H^ zfGw@d6drEIfwdgrG_jpPmx9p52;zkR!PeF38W`VN*rD-g6tMM?&1u%VAbaMW z9<#2hXWZC!$x;-KH#v7;#kVuqrb6aY%|kQ!6VVr?c9s54masqF5^BiSo08Or4r3lf zXsH~@y#wWU;RN-3l)+GFpZ++AcqthxBg)W>E%W6n=RA6LE$xVwPEna@>gHhufOnl- z-j}KJ0SPIYXaCvomrOvzU7tzJ+_(_rSFl*!S(UU>F+8YEX!@t>CW*{i^lz=8;LA;k z59i^Gt&~m$%3ZpbyC!X?W@?3r{@HLcj?9PKlUaZ6N7%DzlWS~K0C*E!%c2(E1kAct zQaKnyVSDm|ls|S5N~vJ)*TR-@M7*RKu8Qe+?-!I7ht?Z7*u{p}xyEER=@K#Iy!1pL zO1VJh1T4~=#Gy)~MzP#oQ{Y(mTR5<_jcL?&gDA845wkG8YUMGfouGqHTWQhU`}(_B zK4H=@*uYSlm~M*bzw*A&m~uhJBX`_Y^sP%O5Y?&(h;x5QO-PjYRdZK zSEy(vA7`s?4gGlRgM8L`d#bZ(wc;7D^`46mzS9E_lkZmfJj# zb#WGa^V?{2bpyXzdOF>mi7xG@PF_EX_rHZ!SHJ&rbSLPxob2_yO;6m&gJXrpiHM|2 zB4oR;B;k|#s?n>K@A>Ta?+Nq}Irk8RSWZ5Ii!5rH0i1hjqgRJ3L(;0@s{P>+u4;Ce zZOuGIlF#&cPGX@FO;qV_}*DsGdwvp>-w<5PhWN}2Cbiz zpv7#@pO*&?pD0=1tMyq}>gWw}cpAM`L!s62cgdGemqG?gQ<&65!JYTw_0y#+yN(u5 zXc`G7{(XHN9?9LJ`p+fLB@zAapRgH>#c6q@zwqo5#bBmy^JKTl+?=1p5<)D#7}^Yilo&oU?cwF;U*s8v0H3SNM$XtzB?T%w1k-+}Oz+Wno= z{y33`+1>frhvqM$nNN0pp2z?+q z^9|_~i(urZeuG}I(Yu(OYR6oOyA4b=^3bMei%DBAx&R?@|tDB;LEnCFEDd5QLb=Onc)($(8e7eNtXq3MK z)0{mKm+g7{v|-(e2Q7g|U8HP(Pg%-OUjFUZJvh8ICJI#fSW7Hy+6X{^UZzg)K(0J94_^_DNH%wrnju@ApBK07b{tQ-3eqsRFb?| zaBJjevlg1@>^XfBeeRkROlmCN=?oYgMRb?(3tz|E$P@O!a>GKhg^7nL>k08&4?hlr zLmLS22f&0q|96vCc`*Px{K*}eV!@ceoIjRzf(%Q;>}wmeL?7#wURP07s;_QVkF1Ut zz3s0eG&LbAaOVP9>uth$U7Bk56&igVLj825G4@vqN7PY}f}t-S@k4h*I0Pe(eUP!( z{OTl?)`xzEAfsebh3Qh6^IH*(@c?kI`c!_ayBQA-D-XA(T02PO@n;@Aiun#U2t^Be z4789`^1%C3-AQOvvm#|mt<&70Q0rBO^cNg*%r)-Rj{d?C}X zDabd~jUP6CgeFtdcy8HYQ#6V&xlRGL`f@P}kLo#I4|Rk4%993qZD<+JHKH`=XL}cS zLetq{~_*^h(+VXINnr&MZ=0*ztOkl8-KtE9e_J1 zBns@%?@d#PK?zebam(|*H|yb1i93WY$X9eV8lBI7@w+1v?Gf{S%#vDdoW@)4c0VF7 zGykU2FY6V3X3>D>dQ{Ii{kBu#qg*LUgI^6|BVe$x{W6wOx%ijTq}?oi(6o1f>i}+~ zCz5r!_PFbNMa+%V9mSZ8@$)VL@v-!YmAu+F>ds{dt|1INN02u87NMZI~B8+-NvB z8}0-yXS5%cDwnL|nQ)STVB;?!gJufuN0gYcZ+v<+o$1SWko*hRevhK4M^7-zI}Ft} z34%EQu|nzQ2noX?jaovGcEuEj4{v`-gy5xnlT6E~pO-D!MKevqh7mWV{YQ1u%?DO9 z#B=~SN2;t}9CM0dmZ?31tb2UYl9>Cr=)*X-^{udR12$tg06Ms94Vl~&`CiMbx>uyrfz2Cv zzRh4l=5h&u2-beGS=^+jT4}B#89Y>HXTm)H4Na29=>H2%lB>{EAA~f3nEu~_{{ZU} Bd_n*K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/zh-TW/wificonfig.ogg deleted file mode 100644 index 7ef88e2521bb6dac3f5813d952e4bda0685cdf40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3155 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 Codec(AudioCodec) - - subgraph AudioInputTask - Codec -->|Raw PCM| Read(ReadAudioData) - Read -->|16kHz PCM| Processor(AudioProcessor) - end - - subgraph OpusCodecTask - Processor -->|Clean PCM| EncodeQueue(audio_encode_queue_) - EncodeQueue --> Encoder(OpusEncoder) - Encoder -->|Opus Packet| SendQueue(audio_send_queue_) - end - - SendQueue --> |"PopPacketFromSendQueue()"| App(Application Layer) - end - - App -->|Network| Server((Cloud Server)) -``` - -- The `AudioInputTask` continuously reads raw PCM data from the `AudioCodec`. -- This data is fed into an `AudioProcessor` for cleaning (AEC, VAD). -- The processed PCM data is pushed into the `audio_encode_queue_`. -- The `OpusCodecTask` picks up the PCM data, encodes it into Opus format, and pushes the resulting packet to the `audio_send_queue_`. -- The application can then retrieve these Opus packets and send them over the network. - -### 2. Audio Output (Downlink) Flow - -This flow receives encoded audio data, decodes it, and plays it on the speaker. - -```mermaid -graph TD - Server((Cloud Server)) -->|Network| App(Application Layer) - - subgraph Device - App -->|"PushPacketToDecodeQueue()"| DecodeQueue(audio_decode_queue_) - - subgraph OpusCodecTask - DecodeQueue -->|Opus Packet| Decoder(OpusDecoder) - Decoder -->|PCM| PlaybackQueue(audio_playback_queue_) - end - - subgraph AudioOutputTask - PlaybackQueue -->|PCM| Codec(AudioCodec) - end - - Codec -->|I2S| Speaker[("Speaker")] - end -``` - -- The application receives Opus packets from the network and pushes them into the `audio_decode_queue_`. -- The `OpusCodecTask` retrieves these packets, decodes them back into PCM data, and pushes the data to the `audio_playback_queue_`. -- The `AudioOutputTask` takes the PCM data from the queue and sends it to the `AudioCodec` for playback. - -## Power Management - -To conserve energy, the audio codec's input (ADC) and output (DAC) channels are automatically disabled after a period of inactivity (`AUDIO_POWER_TIMEOUT_MS`). A timer (`audio_power_timer_`) periodically checks for activity and manages the power state. The channels are automatically re-enabled when new audio needs to be captured or played. \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.cc deleted file mode 100644 index 055cd82a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.cc +++ /dev/null @@ -1,77 +0,0 @@ -#include "audio_codec.h" -#include "board.h" -#include "settings.h" - -#include -#include -#include - -#define TAG "AudioCodec" - -AudioCodec::AudioCodec() { -} - -AudioCodec::~AudioCodec() { -} - -void AudioCodec::OutputData(std::vector& data) { - Write(data.data(), data.size()); -} - -bool AudioCodec::InputData(std::vector& data) { - int samples = Read(data.data(), data.size()); - if (samples > 0) { - return true; - } - return false; -} - -void AudioCodec::Start() { - Settings settings("audio", false); - output_volume_ = settings.GetInt("output_volume", output_volume_); - if (output_volume_ <= 0) { - ESP_LOGW(TAG, "Output volume value (%d) is too small, setting to default (10)", output_volume_); - output_volume_ = 10; - } - - if (tx_handle_ != nullptr) { - ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); - } - - if (rx_handle_ != nullptr) { - ESP_ERROR_CHECK(i2s_channel_enable(rx_handle_)); - } - - EnableInput(true); - EnableOutput(true); - ESP_LOGI(TAG, "Audio codec started"); -} - -void AudioCodec::SetOutputVolume(int volume) { - output_volume_ = volume; - ESP_LOGI(TAG, "Set output volume to %d", output_volume_); - - Settings settings("audio", true); - settings.SetInt("output_volume", output_volume_); -} - -void AudioCodec::SetInputGain(float gain) { - input_gain_ = gain; - ESP_LOGI(TAG, "Set input gain to %.1f", input_gain_); -} - -void AudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - input_enabled_ = enable; - ESP_LOGI(TAG, "Set input enable to %s", enable ? "true" : "false"); -} - -void AudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - output_enabled_ = enable; - ESP_LOGI(TAG, "Set output enable to %s", enable ? "true" : "false"); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.h deleted file mode 100644 index 819e6462..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_codec.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef _AUDIO_CODEC_H -#define _AUDIO_CODEC_H - -#include -#include -#include - -#include -#include -#include - -#include "board.h" - -#define AUDIO_CODEC_DMA_DESC_NUM 6 -#define AUDIO_CODEC_DMA_FRAME_NUM 240 - -class AudioCodec { -public: - AudioCodec(); - virtual ~AudioCodec(); - - virtual void SetOutputVolume(int volume); - virtual void SetInputGain(float gain); - virtual void EnableInput(bool enable); - virtual void EnableOutput(bool enable); - - virtual void OutputData(std::vector& data); - virtual bool InputData(std::vector& data); - virtual void Start(); - - inline bool duplex() const { return duplex_; } - inline bool input_reference() const { return input_reference_; } - inline int input_sample_rate() const { return input_sample_rate_; } - inline int output_sample_rate() const { return output_sample_rate_; } - inline int input_channels() const { return input_channels_; } - inline int output_channels() const { return output_channels_; } - inline int output_volume() const { return output_volume_; } - inline float input_gain() const { return input_gain_; } - inline bool input_enabled() const { return input_enabled_; } - inline bool output_enabled() const { return output_enabled_; } - -protected: - i2s_chan_handle_t tx_handle_ = nullptr; - i2s_chan_handle_t rx_handle_ = nullptr; - - bool duplex_ = false; - bool input_reference_ = false; - bool input_enabled_ = false; - bool output_enabled_ = false; - int input_sample_rate_ = 0; - int output_sample_rate_ = 0; - int input_channels_ = 1; - int output_channels_ = 1; - int output_volume_ = 70; - float input_gain_ = 0.0; - - virtual int Read(int16_t* dest, int samples) = 0; - virtual int Write(const int16_t* data, int samples) = 0; -}; - -#endif // _AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_processor.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_processor.h deleted file mode 100644 index 543c7ae0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_processor.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef AUDIO_PROCESSOR_H -#define AUDIO_PROCESSOR_H - -#include -#include -#include - -#include -#include "audio_codec.h" - -class AudioProcessor { -public: - virtual ~AudioProcessor() = default; - - virtual void Initialize(AudioCodec* codec, int frame_duration_ms, srmodel_list_t* models_list) = 0; - virtual void Feed(std::vector&& data) = 0; - virtual void Start() = 0; - virtual void Stop() = 0; - virtual bool IsRunning() = 0; - virtual void OnOutput(std::function&& data)> callback) = 0; - virtual void OnVadStateChange(std::function callback) = 0; - virtual size_t GetFeedSize() = 0; - virtual void EnableDeviceAec(bool enable) = 0; -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.cc deleted file mode 100644 index c5d3ed77..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.cc +++ /dev/null @@ -1,686 +0,0 @@ -#include "audio_service.h" -#include -#include - -#if CONFIG_USE_AUDIO_PROCESSOR -#include "processors/afe_audio_processor.h" -#else -#include "processors/no_audio_processor.h" -#endif - -#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 -#include "wake_words/afe_wake_word.h" -#include "wake_words/custom_wake_word.h" -#else -#include "wake_words/esp_wake_word.h" -#endif - -#define TAG "AudioService" - - -AudioService::AudioService() { - event_group_ = xEventGroupCreate(); -} - -AudioService::~AudioService() { - if (event_group_ != nullptr) { - vEventGroupDelete(event_group_); - } -} - - -void AudioService::Initialize(AudioCodec* codec) { - codec_ = codec; - codec_->Start(); - - /* Setup the audio codec */ - opus_decoder_ = std::make_unique(codec->output_sample_rate(), 1, OPUS_FRAME_DURATION_MS); - opus_encoder_ = std::make_unique(16000, 1, OPUS_FRAME_DURATION_MS); - opus_encoder_->SetComplexity(0); - - if (codec->input_sample_rate() != 16000) { - input_resampler_.Configure(codec->input_sample_rate(), 16000); - reference_resampler_.Configure(codec->input_sample_rate(), 16000); - } - -#if CONFIG_USE_AUDIO_PROCESSOR - audio_processor_ = std::make_unique(); -#else - audio_processor_ = std::make_unique(); -#endif - - audio_processor_->OnOutput([this](std::vector&& data) { - PushTaskToEncodeQueue(kAudioTaskTypeEncodeToSendQueue, std::move(data)); - }); - - audio_processor_->OnVadStateChange([this](bool speaking) { - voice_detected_ = speaking; - if (callbacks_.on_vad_change) { - callbacks_.on_vad_change(speaking); - } - }); - - esp_timer_create_args_t audio_power_timer_args = { - .callback = [](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->CheckAndUpdateAudioPowerState(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "audio_power_timer", - .skip_unhandled_events = true, - }; - esp_timer_create(&audio_power_timer_args, &audio_power_timer_); -} - -void AudioService::Start() { - service_stopped_ = false; - xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING | AS_EVENT_WAKE_WORD_RUNNING | AS_EVENT_AUDIO_PROCESSOR_RUNNING); - - esp_timer_start_periodic(audio_power_timer_, 1000000); - -#if CONFIG_USE_AUDIO_PROCESSOR - /* Start the audio input task */ - xTaskCreatePinnedToCore([](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->AudioInputTask(); - vTaskDelete(NULL); - }, "audio_input", 2048 * 3, this, 8, &audio_input_task_handle_, 0); - - /* Start the audio output task */ - xTaskCreate([](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->AudioOutputTask(); - vTaskDelete(NULL); - }, "audio_output", 2048 * 2, this, 4, &audio_output_task_handle_); -#else - /* Start the audio input task */ - xTaskCreate([](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->AudioInputTask(); - vTaskDelete(NULL); - }, "audio_input", 2048 * 2, this, 8, &audio_input_task_handle_); - - /* Start the audio output task */ - xTaskCreate([](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->AudioOutputTask(); - vTaskDelete(NULL); - }, "audio_output", 2048, this, 4, &audio_output_task_handle_); -#endif - - /* Start the opus codec task */ - xTaskCreate([](void* arg) { - AudioService* audio_service = (AudioService*)arg; - audio_service->OpusCodecTask(); - vTaskDelete(NULL); - }, "opus_codec", 2048 * 13, this, 2, &opus_codec_task_handle_); -} - -void AudioService::Stop() { - esp_timer_stop(audio_power_timer_); - service_stopped_ = true; - xEventGroupSetBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING | - AS_EVENT_WAKE_WORD_RUNNING | - AS_EVENT_AUDIO_PROCESSOR_RUNNING); - - std::lock_guard lock(audio_queue_mutex_); - audio_encode_queue_.clear(); - audio_decode_queue_.clear(); - audio_playback_queue_.clear(); - audio_testing_queue_.clear(); - audio_queue_cv_.notify_all(); -} - -bool AudioService::ReadAudioData(std::vector& data, int sample_rate, int samples) { - if (!codec_->input_enabled()) { - esp_timer_stop(audio_power_timer_); - esp_timer_start_periodic(audio_power_timer_, AUDIO_POWER_CHECK_INTERVAL_MS * 1000); - codec_->EnableInput(true); - } - - if (codec_->input_sample_rate() != sample_rate) { - data.resize(samples * codec_->input_sample_rate() / sample_rate * codec_->input_channels()); - if (!codec_->InputData(data)) { - return false; - } - if (codec_->input_channels() == 2) { - auto mic_channel = std::vector(data.size() / 2); - auto reference_channel = std::vector(data.size() / 2); - for (size_t i = 0, j = 0; i < mic_channel.size(); ++i, j += 2) { - mic_channel[i] = data[j]; - reference_channel[i] = data[j + 1]; - } - auto resampled_mic = std::vector(input_resampler_.GetOutputSamples(mic_channel.size())); - auto resampled_reference = std::vector(reference_resampler_.GetOutputSamples(reference_channel.size())); - input_resampler_.Process(mic_channel.data(), mic_channel.size(), resampled_mic.data()); - reference_resampler_.Process(reference_channel.data(), reference_channel.size(), resampled_reference.data()); - data.resize(resampled_mic.size() + resampled_reference.size()); - for (size_t i = 0, j = 0; i < resampled_mic.size(); ++i, j += 2) { - data[j] = resampled_mic[i]; - data[j + 1] = resampled_reference[i]; - } - } else { - auto resampled = std::vector(input_resampler_.GetOutputSamples(data.size())); - input_resampler_.Process(data.data(), data.size(), resampled.data()); - data = std::move(resampled); - } - } else { - data.resize(samples * codec_->input_channels()); - if (!codec_->InputData(data)) { - return false; - } - } - - /* Update the last input time */ - last_input_time_ = std::chrono::steady_clock::now(); - debug_statistics_.input_count++; - -#if CONFIG_USE_AUDIO_DEBUGGER - // 音频调试:发送原始音频数据 - if (audio_debugger_ == nullptr) { - audio_debugger_ = std::make_unique(); - } - audio_debugger_->Feed(data); -#endif - - return true; -} - -void AudioService::AudioInputTask() { - while (true) { - EventBits_t bits = xEventGroupWaitBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING | - AS_EVENT_WAKE_WORD_RUNNING | AS_EVENT_AUDIO_PROCESSOR_RUNNING, - pdFALSE, pdFALSE, portMAX_DELAY); - - if (service_stopped_) { - break; - } - if (audio_input_need_warmup_) { - audio_input_need_warmup_ = false; - vTaskDelay(pdMS_TO_TICKS(120)); - continue; - } - - /* Used for audio testing in NetworkConfiguring mode by clicking the BOOT button */ - if (bits & AS_EVENT_AUDIO_TESTING_RUNNING) { - if (audio_testing_queue_.size() >= AUDIO_TESTING_MAX_DURATION_MS / OPUS_FRAME_DURATION_MS) { - ESP_LOGW(TAG, "Audio testing queue is full, stopping audio testing"); - EnableAudioTesting(false); - continue; - } - std::vector data; - int samples = OPUS_FRAME_DURATION_MS * 16000 / 1000; - if (ReadAudioData(data, 16000, samples)) { - // If input channels is 2, we need to fetch the left channel data - if (codec_->input_channels() == 2) { - auto mono_data = std::vector(data.size() / 2); - for (size_t i = 0, j = 0; i < mono_data.size(); ++i, j += 2) { - mono_data[i] = data[j]; - } - data = std::move(mono_data); - } - PushTaskToEncodeQueue(kAudioTaskTypeEncodeToTestingQueue, std::move(data)); - continue; - } - } - - /* Feed the wake word */ - if (bits & AS_EVENT_WAKE_WORD_RUNNING) { - std::vector data; - int samples = wake_word_->GetFeedSize(); - if (samples > 0) { - if (ReadAudioData(data, 16000, samples)) { - wake_word_->Feed(data); - continue; - } - } - } - - /* Feed the audio processor */ - if (bits & AS_EVENT_AUDIO_PROCESSOR_RUNNING) { - std::vector data; - int samples = audio_processor_->GetFeedSize(); - if (samples > 0) { - if (ReadAudioData(data, 16000, samples)) { - audio_processor_->Feed(std::move(data)); - continue; - } - } - } - - ESP_LOGE(TAG, "Should not be here, bits: %lx", bits); - break; - } - - ESP_LOGW(TAG, "Audio input task stopped"); -} - -void AudioService::AudioOutputTask() { - while (true) { - std::unique_lock lock(audio_queue_mutex_); - audio_queue_cv_.wait(lock, [this]() { return !audio_playback_queue_.empty() || service_stopped_; }); - if (service_stopped_) { - break; - } - - auto task = std::move(audio_playback_queue_.front()); - audio_playback_queue_.pop_front(); - audio_queue_cv_.notify_all(); - lock.unlock(); - - if (!codec_->output_enabled()) { - esp_timer_stop(audio_power_timer_); - esp_timer_start_periodic(audio_power_timer_, AUDIO_POWER_CHECK_INTERVAL_MS * 1000); - codec_->EnableOutput(true); - } - codec_->OutputData(task->pcm); - - /* Update the last output time */ - last_output_time_ = std::chrono::steady_clock::now(); - debug_statistics_.playback_count++; - -#if CONFIG_USE_SERVER_AEC - /* Record the timestamp for server AEC */ - if (task->timestamp > 0) { - lock.lock(); - timestamp_queue_.push_back(task->timestamp); - } -#endif - } - - ESP_LOGW(TAG, "Audio output task stopped"); -} - -void AudioService::OpusCodecTask() { - while (true) { - std::unique_lock lock(audio_queue_mutex_); - audio_queue_cv_.wait(lock, [this]() { - return service_stopped_ || - (!audio_encode_queue_.empty() && audio_send_queue_.size() < MAX_SEND_PACKETS_IN_QUEUE) || - (!audio_decode_queue_.empty() && audio_playback_queue_.size() < MAX_PLAYBACK_TASKS_IN_QUEUE); - }); - if (service_stopped_) { - break; - } - - /* Decode the audio from decode queue */ - if (!audio_decode_queue_.empty() && audio_playback_queue_.size() < MAX_PLAYBACK_TASKS_IN_QUEUE) { - auto packet = std::move(audio_decode_queue_.front()); - audio_decode_queue_.pop_front(); - audio_queue_cv_.notify_all(); - lock.unlock(); - - auto task = std::make_unique(); - task->type = kAudioTaskTypeDecodeToPlaybackQueue; - task->timestamp = packet->timestamp; - - SetDecodeSampleRate(packet->sample_rate, packet->frame_duration); - if (opus_decoder_->Decode(std::move(packet->payload), task->pcm)) { - // Resample if the sample rate is different - if (opus_decoder_->sample_rate() != codec_->output_sample_rate()) { - int target_size = output_resampler_.GetOutputSamples(task->pcm.size()); - std::vector resampled(target_size); - output_resampler_.Process(task->pcm.data(), task->pcm.size(), resampled.data()); - task->pcm = std::move(resampled); - } - - lock.lock(); - audio_playback_queue_.push_back(std::move(task)); - audio_queue_cv_.notify_all(); - } else { - ESP_LOGE(TAG, "Failed to decode audio"); - lock.lock(); - } - debug_statistics_.decode_count++; - } - - /* Encode the audio to send queue */ - if (!audio_encode_queue_.empty() && audio_send_queue_.size() < MAX_SEND_PACKETS_IN_QUEUE) { - auto task = std::move(audio_encode_queue_.front()); - audio_encode_queue_.pop_front(); - audio_queue_cv_.notify_all(); - lock.unlock(); - - auto packet = std::make_unique(); - packet->frame_duration = OPUS_FRAME_DURATION_MS; - packet->sample_rate = 16000; - packet->timestamp = task->timestamp; - if (!opus_encoder_->Encode(std::move(task->pcm), packet->payload)) { - ESP_LOGE(TAG, "Failed to encode audio"); - continue; - } - - if (task->type == kAudioTaskTypeEncodeToSendQueue) { - { - std::lock_guard lock(audio_queue_mutex_); - audio_send_queue_.push_back(std::move(packet)); - } - if (callbacks_.on_send_queue_available) { - callbacks_.on_send_queue_available(); - } - } else if (task->type == kAudioTaskTypeEncodeToTestingQueue) { - std::lock_guard lock(audio_queue_mutex_); - audio_testing_queue_.push_back(std::move(packet)); - } - debug_statistics_.encode_count++; - lock.lock(); - } - } - - ESP_LOGW(TAG, "Opus codec task stopped"); -} - -void AudioService::SetDecodeSampleRate(int sample_rate, int frame_duration) { - if (opus_decoder_->sample_rate() == sample_rate && opus_decoder_->duration_ms() == frame_duration) { - return; - } - - opus_decoder_.reset(); - opus_decoder_ = std::make_unique(sample_rate, 1, frame_duration); - - auto codec = Board::GetInstance().GetAudioCodec(); - if (opus_decoder_->sample_rate() != codec->output_sample_rate()) { - ESP_LOGI(TAG, "Resampling audio from %d to %d", opus_decoder_->sample_rate(), codec->output_sample_rate()); - output_resampler_.Configure(opus_decoder_->sample_rate(), codec->output_sample_rate()); - } -} - -void AudioService::PushTaskToEncodeQueue(AudioTaskType type, std::vector&& pcm) { - auto task = std::make_unique(); - task->type = type; - task->pcm = std::move(pcm); - - /* Push the task to the encode queue */ - std::unique_lock lock(audio_queue_mutex_); - - /* If the task is to send queue, we need to set the timestamp */ - if (type == kAudioTaskTypeEncodeToSendQueue && !timestamp_queue_.empty()) { - if (timestamp_queue_.size() <= MAX_TIMESTAMPS_IN_QUEUE) { - task->timestamp = timestamp_queue_.front(); - } else { - ESP_LOGW(TAG, "Timestamp queue (%u) is full, dropping timestamp", timestamp_queue_.size()); - } - timestamp_queue_.pop_front(); - } - - audio_queue_cv_.wait(lock, [this]() { return audio_encode_queue_.size() < MAX_ENCODE_TASKS_IN_QUEUE; }); - audio_encode_queue_.push_back(std::move(task)); - audio_queue_cv_.notify_all(); -} - -bool AudioService::PushPacketToDecodeQueue(std::unique_ptr packet, bool wait) { - std::unique_lock lock(audio_queue_mutex_); - if (audio_decode_queue_.size() >= MAX_DECODE_PACKETS_IN_QUEUE) { - if (wait) { - audio_queue_cv_.wait(lock, [this]() { return audio_decode_queue_.size() < MAX_DECODE_PACKETS_IN_QUEUE; }); - } else { - return false; - } - } - audio_decode_queue_.push_back(std::move(packet)); - audio_queue_cv_.notify_all(); - return true; -} - -std::unique_ptr AudioService::PopPacketFromSendQueue() { - std::lock_guard lock(audio_queue_mutex_); - if (audio_send_queue_.empty()) { - return nullptr; - } - auto packet = std::move(audio_send_queue_.front()); - audio_send_queue_.pop_front(); - audio_queue_cv_.notify_all(); - return packet; -} - -void AudioService::EncodeWakeWord() { - if (wake_word_) { - wake_word_->EncodeWakeWordData(); - } -} - -const std::string& AudioService::GetLastWakeWord() const { - return wake_word_->GetLastDetectedWakeWord(); -} - -std::unique_ptr AudioService::PopWakeWordPacket() { - auto packet = std::make_unique(); - if (wake_word_->GetWakeWordOpus(packet->payload)) { - return packet; - } - return nullptr; -} - -void AudioService::EnableWakeWordDetection(bool enable) { - if (!wake_word_) { - return; - } - - ESP_LOGD(TAG, "%s wake word detection", enable ? "Enabling" : "Disabling"); - if (enable) { - if (!wake_word_initialized_) { - if (!wake_word_->Initialize(codec_, models_list_)) { - ESP_LOGE(TAG, "Failed to initialize wake word"); - return; - } - wake_word_initialized_ = true; - } - wake_word_->Start(); - xEventGroupSetBits(event_group_, AS_EVENT_WAKE_WORD_RUNNING); - } else { - wake_word_->Stop(); - xEventGroupClearBits(event_group_, AS_EVENT_WAKE_WORD_RUNNING); - } -} - -void AudioService::EnableVoiceProcessing(bool enable) { - ESP_LOGD(TAG, "%s voice processing", enable ? "Enabling" : "Disabling"); - if (enable) { - if (!audio_processor_initialized_) { - audio_processor_->Initialize(codec_, OPUS_FRAME_DURATION_MS, models_list_); - audio_processor_initialized_ = true; - } - - /* We should make sure no audio is playing */ - ResetDecoder(); - audio_input_need_warmup_ = true; - audio_processor_->Start(); - xEventGroupSetBits(event_group_, AS_EVENT_AUDIO_PROCESSOR_RUNNING); - } else { - audio_processor_->Stop(); - xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_PROCESSOR_RUNNING); - } -} - -void AudioService::EnableAudioTesting(bool enable) { - ESP_LOGI(TAG, "%s audio testing", enable ? "Enabling" : "Disabling"); - if (enable) { - xEventGroupSetBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING); - } else { - xEventGroupClearBits(event_group_, AS_EVENT_AUDIO_TESTING_RUNNING); - /* Copy audio_testing_queue_ to audio_decode_queue_ */ - std::lock_guard lock(audio_queue_mutex_); - audio_decode_queue_ = std::move(audio_testing_queue_); - audio_queue_cv_.notify_all(); - } -} - -void AudioService::EnableDeviceAec(bool enable) { - ESP_LOGI(TAG, "%s device AEC", enable ? "Enabling" : "Disabling"); - if (!audio_processor_initialized_) { - audio_processor_->Initialize(codec_, OPUS_FRAME_DURATION_MS, models_list_); - audio_processor_initialized_ = true; - } - - audio_processor_->EnableDeviceAec(enable); -} - -void AudioService::SetCallbacks(AudioServiceCallbacks& callbacks) { - callbacks_ = callbacks; -} - -void AudioService::PlaySound(const std::string_view& ogg) { - if (!codec_->output_enabled()) { - esp_timer_stop(audio_power_timer_); - esp_timer_start_periodic(audio_power_timer_, AUDIO_POWER_CHECK_INTERVAL_MS * 1000); - codec_->EnableOutput(true); - } - - const uint8_t* buf = reinterpret_cast(ogg.data()); - size_t size = ogg.size(); - size_t offset = 0; - - auto find_page = [&](size_t start)->size_t { - for (size_t i = start; i + 4 <= size; ++i) { - if (buf[i] == 'O' && buf[i+1] == 'g' && buf[i+2] == 'g' && buf[i+3] == 'S') return i; - } - return static_cast(-1); - }; - - bool seen_head = false; - bool seen_tags = false; - int sample_rate = 16000; // 默认值 - - while (true) { - size_t pos = find_page(offset); - if (pos == static_cast(-1)) break; - offset = pos; - if (offset + 27 > size) break; - - const uint8_t* page = buf + offset; - uint8_t page_segments = page[26]; - size_t seg_table_off = offset + 27; - if (seg_table_off + page_segments > size) break; - - size_t body_size = 0; - for (size_t i = 0; i < page_segments; ++i) body_size += page[27 + i]; - - size_t body_off = seg_table_off + page_segments; - if (body_off + body_size > size) break; - - // Parse packets using lacing - size_t cur = body_off; - size_t seg_idx = 0; - while (seg_idx < page_segments) { - size_t pkt_len = 0; - size_t pkt_start = cur; - bool continued = false; - do { - uint8_t l = page[27 + seg_idx++]; - pkt_len += l; - cur += l; - continued = (l == 255); - } while (continued && seg_idx < page_segments); - - if (pkt_len == 0) continue; - const uint8_t* pkt_ptr = buf + pkt_start; - - if (!seen_head) { - // 解析OpusHead包 - if (pkt_len >= 19 && std::memcmp(pkt_ptr, "OpusHead", 8) == 0) { - seen_head = true; - - // OpusHead结构:[0-7] "OpusHead", [8] version, [9] channel_count, [10-11] pre_skip - // [12-15] input_sample_rate, [16-17] output_gain, [18] mapping_family - if (pkt_len >= 12) { - uint8_t version = pkt_ptr[8]; - uint8_t channel_count = pkt_ptr[9]; - - if (pkt_len >= 16) { - // 读取输入采样率 (little-endian) - sample_rate = pkt_ptr[12] | (pkt_ptr[13] << 8) | - (pkt_ptr[14] << 16) | (pkt_ptr[15] << 24); - ESP_LOGI(TAG, "OpusHead: version=%d, channels=%d, sample_rate=%d", - version, channel_count, sample_rate); - } - } - } - continue; - } - if (!seen_tags) { - // Expect OpusTags in second packet - if (pkt_len >= 8 && std::memcmp(pkt_ptr, "OpusTags", 8) == 0) { - seen_tags = true; - } - continue; - } - - // Audio packet (Opus) - auto packet = std::make_unique(); - packet->sample_rate = sample_rate; - packet->frame_duration = 60; - packet->payload.resize(pkt_len); - std::memcpy(packet->payload.data(), pkt_ptr, pkt_len); - PushPacketToDecodeQueue(std::move(packet), true); - } - - offset = body_off + body_size; - } -} - -bool AudioService::IsIdle() { - std::lock_guard lock(audio_queue_mutex_); - return audio_encode_queue_.empty() && audio_decode_queue_.empty() && audio_playback_queue_.empty() && audio_testing_queue_.empty(); -} - -void AudioService::ResetDecoder() { - std::lock_guard lock(audio_queue_mutex_); - opus_decoder_->ResetState(); - timestamp_queue_.clear(); - audio_decode_queue_.clear(); - audio_playback_queue_.clear(); - audio_testing_queue_.clear(); - audio_queue_cv_.notify_all(); -} - -void AudioService::CheckAndUpdateAudioPowerState() { - auto now = std::chrono::steady_clock::now(); - auto input_elapsed = std::chrono::duration_cast(now - last_input_time_).count(); - auto output_elapsed = std::chrono::duration_cast(now - last_output_time_).count(); - if (input_elapsed > AUDIO_POWER_TIMEOUT_MS && codec_->input_enabled()) { - codec_->EnableInput(false); - } - if (output_elapsed > AUDIO_POWER_TIMEOUT_MS && codec_->output_enabled()) { - codec_->EnableOutput(false); - } - if (!codec_->input_enabled() && !codec_->output_enabled()) { - esp_timer_stop(audio_power_timer_); - } -} - -void AudioService::SetModelsList(srmodel_list_t* models_list) { - models_list_ = models_list; - -#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 - if (esp_srmodel_filter(models_list_, ESP_MN_PREFIX, NULL) != nullptr) { - wake_word_ = std::make_unique(); - } else if (esp_srmodel_filter(models_list_, ESP_WN_PREFIX, NULL) != nullptr) { - wake_word_ = std::make_unique(); - } else { - wake_word_ = nullptr; - } -#else - if (esp_srmodel_filter(models_list_, ESP_WN_PREFIX, NULL) != nullptr) { - wake_word_ = std::make_unique(); - } else { - wake_word_ = nullptr; - } -#endif - - if (wake_word_) { - wake_word_->OnWakeWordDetected([this](const std::string& wake_word) { - if (callbacks_.on_wake_word_detected) { - callbacks_.on_wake_word_detected(wake_word); - } - }); - } -} - -bool AudioService::IsAfeWakeWord() { -#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 - return wake_word_ != nullptr && dynamic_cast(wake_word_.get()) != nullptr; -#else - return false; -#endif -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.h deleted file mode 100644 index c7808068..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/audio_service.h +++ /dev/null @@ -1,161 +0,0 @@ -#ifndef AUDIO_SERVICE_H -#define AUDIO_SERVICE_H - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "audio_codec.h" -#include "audio_processor.h" -#include "processors/audio_debugger.h" -#include "wake_word.h" -#include "protocol.h" - - -/* - * There are two types of audio data flow: - * 1. (MIC) -> [Processors] -> {Encode Queue} -> [Opus Encoder] -> {Send Queue} -> (Server) - * 2. (Server) -> {Decode Queue} -> [Opus Decoder] -> {Playback Queue} -> (Speaker) - * - * We use one task for MIC / Speaker / Processors, and one task for Opus Encoder / Opus Decoder. - * - * Decode Queue and Send Queue are the main queues, because Opus packets are quite smaller than PCM packets. - * - */ - -#define OPUS_FRAME_DURATION_MS 60 -#define MAX_ENCODE_TASKS_IN_QUEUE 2 -#define MAX_PLAYBACK_TASKS_IN_QUEUE 2 -#define MAX_DECODE_PACKETS_IN_QUEUE (2400 / OPUS_FRAME_DURATION_MS) -#define MAX_SEND_PACKETS_IN_QUEUE (2400 / OPUS_FRAME_DURATION_MS) -#define AUDIO_TESTING_MAX_DURATION_MS 10000 -#define MAX_TIMESTAMPS_IN_QUEUE 3 - -#define AUDIO_POWER_TIMEOUT_MS 15000 -#define AUDIO_POWER_CHECK_INTERVAL_MS 1000 - - -#define AS_EVENT_AUDIO_TESTING_RUNNING (1 << 0) -#define AS_EVENT_WAKE_WORD_RUNNING (1 << 1) -#define AS_EVENT_AUDIO_PROCESSOR_RUNNING (1 << 2) -#define AS_EVENT_PLAYBACK_NOT_EMPTY (1 << 3) - -struct AudioServiceCallbacks { - std::function on_send_queue_available; - std::function on_wake_word_detected; - std::function on_vad_change; - std::function on_audio_testing_queue_full; -}; - - -enum AudioTaskType { - kAudioTaskTypeEncodeToSendQueue, - kAudioTaskTypeEncodeToTestingQueue, - kAudioTaskTypeDecodeToPlaybackQueue, -}; - -struct AudioTask { - AudioTaskType type; - std::vector pcm; - uint32_t timestamp; -}; - -struct DebugStatistics { - uint32_t input_count = 0; - uint32_t decode_count = 0; - uint32_t encode_count = 0; - uint32_t playback_count = 0; -}; - -class AudioService { -public: - AudioService(); - ~AudioService(); - - void Initialize(AudioCodec* codec); - void Start(); - void Stop(); - void EncodeWakeWord(); - std::unique_ptr PopWakeWordPacket(); - const std::string& GetLastWakeWord() const; - bool IsVoiceDetected() const { return voice_detected_; } - bool IsIdle(); - bool IsWakeWordRunning() const { return xEventGroupGetBits(event_group_) & AS_EVENT_WAKE_WORD_RUNNING; } - bool IsAudioProcessorRunning() const { return xEventGroupGetBits(event_group_) & AS_EVENT_AUDIO_PROCESSOR_RUNNING; } - bool IsAfeWakeWord(); - - void EnableWakeWordDetection(bool enable); - void EnableVoiceProcessing(bool enable); - void EnableAudioTesting(bool enable); - void EnableDeviceAec(bool enable); - - void SetCallbacks(AudioServiceCallbacks& callbacks); - - bool PushPacketToDecodeQueue(std::unique_ptr packet, bool wait = false); - std::unique_ptr PopPacketFromSendQueue(); - void PlaySound(const std::string_view& sound); - bool ReadAudioData(std::vector& data, int sample_rate, int samples); - void ResetDecoder(); - void SetModelsList(srmodel_list_t* models_list); - -private: - AudioCodec* codec_ = nullptr; - AudioServiceCallbacks callbacks_; - std::unique_ptr audio_processor_; - std::unique_ptr wake_word_; - std::unique_ptr audio_debugger_; - std::unique_ptr opus_encoder_; - std::unique_ptr opus_decoder_; - OpusResampler input_resampler_; - OpusResampler reference_resampler_; - OpusResampler output_resampler_; - DebugStatistics debug_statistics_; - srmodel_list_t* models_list_ = nullptr; - - EventGroupHandle_t event_group_; - - // Audio encode / decode - TaskHandle_t audio_input_task_handle_ = nullptr; - TaskHandle_t audio_output_task_handle_ = nullptr; - TaskHandle_t opus_codec_task_handle_ = nullptr; - std::mutex audio_queue_mutex_; - std::condition_variable audio_queue_cv_; - std::deque> audio_decode_queue_; - std::deque> audio_send_queue_; - std::deque> audio_testing_queue_; - std::deque> audio_encode_queue_; - std::deque> audio_playback_queue_; - // For server AEC - std::deque timestamp_queue_; - - bool wake_word_initialized_ = false; - bool audio_processor_initialized_ = false; - bool voice_detected_ = false; - bool service_stopped_ = true; - bool audio_input_need_warmup_ = false; - - esp_timer_handle_t audio_power_timer_ = nullptr; - std::chrono::steady_clock::time_point last_input_time_; - std::chrono::steady_clock::time_point last_output_time_; - - void AudioInputTask(); - void AudioOutputTask(); - void OpusCodecTask(); - void PushTaskToEncodeQueue(AudioTaskType type, std::vector&& pcm); - void SetDecodeSampleRate(int sample_rate, int frame_duration); - void CheckAndUpdateAudioPowerState(); -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.cc deleted file mode 100644 index a3db34fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.cc +++ /dev/null @@ -1,245 +0,0 @@ -#include "box_audio_codec.h" - -#include -#include -#include - -#define TAG "BoxAudioCodec" - -BoxAudioCodec::BoxAudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7210_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 30; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = (i2c_port_t)1, - .addr = es8311_addr, - .bus_handle = i2c_master_handle, - }; - out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(out_ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8311_codec_cfg_t es8311_cfg = {}; - es8311_cfg.ctrl_if = out_ctrl_if_; - es8311_cfg.gpio_if = gpio_if_; - es8311_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_DAC; - es8311_cfg.pa_pin = pa_pin; - es8311_cfg.use_mclk = true; - es8311_cfg.hw_gain.pa_voltage = 5.0; - es8311_cfg.hw_gain.codec_dac_voltage = 3.3; - out_codec_if_ = es8311_codec_new(&es8311_cfg); - assert(out_codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = out_codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - - // Input - i2c_cfg.addr = es7210_addr; - in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7210_codec_cfg_t es7210_cfg = {}; - es7210_cfg.ctrl_if = in_ctrl_if_; - es7210_cfg.mic_selected = ES7210_SEL_MIC1 | ES7210_SEL_MIC2 | ES7210_SEL_MIC3 | ES7210_SEL_MIC4; - in_codec_if_ = es7210_codec_new(&es7210_cfg); - assert(in_codec_if_ != NULL); - - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - dev_cfg.codec_if = in_codec_if_; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - - ESP_LOGI(TAG, "BoxAudioDevice initialized"); -} - -BoxAudioCodec::~BoxAudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void BoxAudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bclk_div = 8, - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), - .ws_width = I2S_TDM_AUTO_WS_WIDTH, - .ws_pol = false, - .bit_shift = true, - .left_align = false, - .big_endian = false, - .bit_order_lsb = false, - .skip_mask = false, - .total_slot = I2S_TDM_AUTO_SLOT_NUM - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = I2S_GPIO_UNUSED, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void BoxAudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void BoxAudioCodec::EnableInput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 4, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - if (input_reference_) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void BoxAudioCodec::EnableOutput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int BoxAudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int BoxAudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.h deleted file mode 100644 index cb7d3898..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/box_audio_codec.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_H -#define _BOX_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include - - -class BoxAudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - std::mutex data_if_mutex_; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - BoxAudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7210_addr, bool input_reference); - virtual ~BoxAudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.cc deleted file mode 100644 index 5f646b3e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.cc +++ /dev/null @@ -1,20 +0,0 @@ -#include "dummy_audio_codec.h" - -DummyAudioCodec::DummyAudioCodec(int input_sample_rate, int output_sample_rate) { - duplex_ = true; - input_reference_ = false; - input_channels_ = 1; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; -} - -DummyAudioCodec::~DummyAudioCodec() { -} - -int DummyAudioCodec::Read(int16_t* dest, int samples) { - return 0; -} - -int DummyAudioCodec::Write(const int16_t* data, int samples) { - return 0; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.h deleted file mode 100644 index 158f1404..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/dummy_audio_codec.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef _DUMMY_AUDIO_CODEC_H -#define _DUMMY_AUDIO_CODEC_H - -#include "audio_codec.h" - -class DummyAudioCodec : public AudioCodec { -private: - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - DummyAudioCodec(int input_sample_rate, int output_sample_rate); - virtual ~DummyAudioCodec(); -}; - -#endif // _DUMMY_AUDIO_CODEC_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.cc deleted file mode 100644 index 0a03e87b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.cc +++ /dev/null @@ -1,197 +0,0 @@ -#include "es8311_audio_codec.h" - -#include - -#define TAG "Es8311AudioCodec" - -Es8311AudioCodec::Es8311AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, bool use_mclk, bool pa_inverted) { - duplex_ = true; // 是否双工 - input_reference_ = false; // 是否使用参考输入,实现回声消除 - input_channels_ = 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - pa_pin_ = pa_pin; - pa_inverted_ = pa_inverted; - input_gain_ = 30; - - assert(input_sample_rate_ == output_sample_rate_); - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = i2c_port, - .addr = es8311_addr, - .bus_handle = i2c_master_handle, - }; - ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8311_codec_cfg_t es8311_cfg = {}; - es8311_cfg.ctrl_if = ctrl_if_; - es8311_cfg.gpio_if = gpio_if_; - es8311_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH; - es8311_cfg.pa_pin = pa_pin; - es8311_cfg.use_mclk = use_mclk; - es8311_cfg.hw_gain.pa_voltage = 5.0; - es8311_cfg.hw_gain.codec_dac_voltage = 3.3; - es8311_cfg.pa_reverted = pa_inverted_; - codec_if_ = es8311_codec_new(&es8311_cfg); - - if (codec_if_ == nullptr) { - ESP_LOGE(TAG, "Failed to create Es8311AudioCodec"); - } else { - ESP_LOGI(TAG, "Es8311AudioCodec initialized"); - } -} - -Es8311AudioCodec::~Es8311AudioCodec() { - esp_codec_dev_delete(dev_); - - audio_codec_delete_codec_if(codec_if_); - audio_codec_delete_ctrl_if(ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Es8311AudioCodec::UpdateDeviceState() { - if ((input_enabled_ || output_enabled_) && dev_ == nullptr) { - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT, - .codec_if = codec_if_, - .data_if = data_if_, - }; - dev_ = esp_codec_dev_new(&dev_cfg); - assert(dev_ != NULL); - - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(dev_, input_gain_)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(dev_, output_volume_)); - } else if (!input_enabled_ && !output_enabled_ && dev_ != nullptr) { - esp_codec_dev_close(dev_); - dev_ = nullptr; - } - if (pa_pin_ != GPIO_NUM_NC) { - int level = output_enabled_ ? 1 : 0; - gpio_set_level(pa_pin_, pa_inverted_ ? !level : level); - } -} - -void Es8311AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void Es8311AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void Es8311AudioCodec::EnableInput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (codec_if_ == nullptr) { - return; - } - if (enable == input_enabled_) { - return; - } - AudioCodec::EnableInput(enable); - UpdateDeviceState(); -} - -void Es8311AudioCodec::EnableOutput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (codec_if_ == nullptr) { - return; - } - if (enable == output_enabled_) { - return; - } - AudioCodec::EnableOutput(enable); - UpdateDeviceState(); -} - -int Es8311AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int Es8311AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.h deleted file mode 100644 index dd0e6398..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8311_audio_codec.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _ES8311_AUDIO_CODEC_H -#define _ES8311_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include -#include -#include - - -class Es8311AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* ctrl_if_ = nullptr; - const audio_codec_if_t* codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t dev_ = nullptr; - gpio_num_t pa_pin_ = GPIO_NUM_NC; - bool pa_inverted_ = false; - std::mutex data_if_mutex_; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - void UpdateDeviceState(); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - Es8311AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, bool use_mclk = true, bool pa_inverted = false); - virtual ~Es8311AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _ES8311_AUDIO_CODEC_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.cc deleted file mode 100644 index 30b1ba36..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.cc +++ /dev/null @@ -1,198 +0,0 @@ -#include "es8374_audio_codec.h" - -#include - -#define TAG "Es8374AudioCodec" - -Es8374AudioCodec::Es8374AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8374_addr, bool use_mclk) { - duplex_ = true; // 是否双工 - input_reference_ = false; // 是否使用参考输入,实现回声消除 - input_channels_ = 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 30; - - pa_pin_ = pa_pin; - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = i2c_port, - .addr = es8374_addr, - .bus_handle = i2c_master_handle, - }; - ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8374_codec_cfg_t es8374_cfg = {}; - es8374_cfg.ctrl_if = ctrl_if_; - es8374_cfg.gpio_if = gpio_if_; - es8374_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH; - es8374_cfg.pa_pin = pa_pin; - codec_if_ = es8374_codec_new(&es8374_cfg); - assert(codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - esp_codec_set_disable_when_closed(output_dev_, false); - esp_codec_set_disable_when_closed(input_dev_, false); - ESP_LOGI(TAG, "Es8374AudioCodec initialized"); -} - -Es8374AudioCodec::~Es8374AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(codec_if_); - audio_codec_delete_ctrl_if(ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Es8374AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = 6, - .dma_frame_num = 240, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void Es8374AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void Es8374AudioCodec::EnableInput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void Es8374AudioCodec::EnableOutput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 1); - } - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 0); - } - } - AudioCodec::EnableOutput(enable); -} - -int Es8374AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int Es8374AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.h deleted file mode 100644 index 7533c222..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8374_audio_codec.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _ES8374_AUDIO_CODEC_H -#define _ES8374_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include -#include -#include - - -class Es8374AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* ctrl_if_ = nullptr; - const audio_codec_if_t* codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_pin_ = GPIO_NUM_NC; - std::mutex data_if_mutex_; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - Es8374AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8374_addr, bool use_mclk = true); - virtual ~Es8374AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _ES8374_AUDIO_CODEC_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.cc deleted file mode 100644 index aa26ae77..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.cc +++ /dev/null @@ -1,221 +0,0 @@ -#include "es8388_audio_codec.h" - -#include - -#define TAG "Es8388AudioCodec" - -Es8388AudioCodec::Es8388AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8388_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 24; - - pa_pin_ = pa_pin; - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = i2c_port, - .addr = es8388_addr, - .bus_handle = i2c_master_handle, - }; - ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8388_codec_cfg_t es8388_cfg = {}; - es8388_cfg.ctrl_if = ctrl_if_; - es8388_cfg.gpio_if = gpio_if_; - es8388_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH; - es8388_cfg.master_mode = true; - es8388_cfg.pa_pin = pa_pin; - es8388_cfg.pa_reverted = false; - es8388_cfg.hw_gain.pa_voltage = 5.0; - es8388_cfg.hw_gain.codec_dac_voltage = 3.3; - codec_if_ = es8388_codec_new(&es8388_cfg); - assert(codec_if_ != NULL); - - esp_codec_dev_cfg_t outdev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&outdev_cfg); - assert(output_dev_ != NULL); - - esp_codec_dev_cfg_t indev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN, - .codec_if = codec_if_, - .data_if = data_if_, - }; - input_dev_ = esp_codec_dev_new(&indev_cfg); - assert(input_dev_ != NULL); - esp_codec_set_disable_when_closed(output_dev_, false); - esp_codec_set_disable_when_closed(input_dev_, false); - ESP_LOGI(TAG, "Es8388AudioCodec initialized"); -} - -Es8388AudioCodec::~Es8388AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(codec_if_); - audio_codec_delete_ctrl_if(ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Es8388AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din){ - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void Es8388AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void Es8388AudioCodec::EnableInput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = (uint8_t) input_channels_, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - if (input_reference_) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - if (input_reference_) { - uint8_t gain = (11 << 4) + 0; - ctrl_if_->write_reg(ctrl_if_, 0x09, 1, &gain, 1); - }else{ - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_)); - } - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void Es8388AudioCodec::EnableOutput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == output_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - - // Set analog output volume to 0dB, default is -45dB - uint8_t reg_val = 30; // 0dB - if(input_reference_){ - reg_val = 27; - } - uint8_t regs[] = { 46, 47, 48, 49 }; // HP_LVOL, HP_RVOL, SPK_LVOL, SPK_RVOL - for (uint8_t reg : regs) { - ctrl_if_->write_reg(ctrl_if_, reg, 1, ®_val, 1); - } - - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 1); - } - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 0); - } - } - AudioCodec::EnableOutput(enable); -} - -int Es8388AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int Es8388AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_ && output_dev_ && data != nullptr) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.h deleted file mode 100644 index 316dfce5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8388_audio_codec.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _ES8388_AUDIO_CODEC_H -#define _ES8388_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include -#include - - -class Es8388AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* ctrl_if_ = nullptr; - const audio_codec_if_t* codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_pin_ = GPIO_NUM_NC; - std::mutex data_if_mutex_; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - Es8388AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8388_addr, bool input_reference = false); - virtual ~Es8388AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _ES8388_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.cc deleted file mode 100644 index 351ad454..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.cc +++ /dev/null @@ -1,204 +0,0 @@ -#include "es8389_audio_codec.h" - -#include - -static const char TAG[] = "Es8389AudioCodec"; - -Es8389AudioCodec::Es8389AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8389_addr, bool use_mclk) { - duplex_ = true; // 是否双工 - input_reference_ = false; // 是否使用参考输入,实现回声消除 - input_channels_ = 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 40; - pa_pin_ = pa_pin; - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = i2c_port, - .addr = es8389_addr, - .bus_handle = i2c_master_handle, - }; - ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8389_codec_cfg_t es8389_cfg = {}; - es8389_cfg.ctrl_if = ctrl_if_; - es8389_cfg.gpio_if = gpio_if_; - es8389_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH; - es8389_cfg.pa_pin = pa_pin; - es8389_cfg.use_mclk = use_mclk; - es8389_cfg.hw_gain.pa_voltage = 5.0; - es8389_cfg.hw_gain.codec_dac_voltage = 3.3; - codec_if_ = es8389_codec_new(&es8389_cfg); - - assert(codec_if_ != NULL); - - esp_codec_dev_cfg_t outdev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&outdev_cfg); - assert(output_dev_ != NULL); - - esp_codec_dev_cfg_t indev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN, - .codec_if = codec_if_, - .data_if = data_if_, - }; - input_dev_ = esp_codec_dev_new(&indev_cfg); - assert(input_dev_ != NULL); - esp_codec_set_disable_when_closed(output_dev_, false); - esp_codec_set_disable_when_closed(input_dev_, false); - ESP_LOGI(TAG, "Es8389AudioCodec initialized"); -} - -Es8389AudioCodec::~Es8389AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(codec_if_); - audio_codec_delete_ctrl_if(ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Es8389AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = 6, - .dma_frame_num = 240, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, -#ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, -#endif - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void Es8389AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void Es8389AudioCodec::EnableInput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, input_gain_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void Es8389AudioCodec::EnableOutput(bool enable) { - std::lock_guard lock(data_if_mutex_); - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 1); - } - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 0); - } - } - AudioCodec::EnableOutput(enable); -} - -int Es8389AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int Es8389AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.h deleted file mode 100644 index b55b4273..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/es8389_audio_codec.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _ES8389_AUDIO_CODEC_H -#define _ES8389_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include -#include -#include - -class Es8389AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* ctrl_if_ = nullptr; - const audio_codec_if_t* codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_pin_ = GPIO_NUM_NC; - std::mutex data_if_mutex_; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - Es8389AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8389_addr, bool use_mclk = true); - virtual ~Es8389AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _ES8389_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.cc deleted file mode 100644 index 4c839c87..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.cc +++ /dev/null @@ -1,359 +0,0 @@ -#include "no_audio_codec.h" - -#include -#include -#include - -#define TAG "NoAudioCodec" - -NoAudioCodec::~NoAudioCodec() { - if (rx_handle_ != nullptr) { - ESP_ERROR_CHECK(i2s_channel_disable(rx_handle_)); - } - if (tx_handle_ != nullptr) { - ESP_ERROR_CHECK(i2s_channel_disable(tx_handle_)); - } -} - -NoAudioCodecDuplex::NoAudioCodecDuplex(int input_sample_rate, int output_sample_rate, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - duplex_ = true; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = I2S_STD_SLOT_LEFT, - .ws_width = I2S_DATA_BIT_WIDTH_32BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - - }, - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - - -NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_ws, gpio_num_t mic_din) { - duplex_ = false; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - // Create a new channel for speaker - i2s_chan_config_t chan_cfg = { - .id = (i2s_port_t)0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, nullptr)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = I2S_STD_SLOT_LEFT, - .ws_width = I2S_DATA_BIT_WIDTH_32BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - - }, - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = spk_bclk, - .ws = spk_ws, - .dout = spk_dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - - // Create a new channel for MIC - chan_cfg.id = (i2s_port_t)1; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, nullptr, &rx_handle_)); - std_cfg.clk_cfg.sample_rate_hz = (uint32_t)input_sample_rate_; - std_cfg.gpio_cfg.bclk = mic_sck; - std_cfg.gpio_cfg.ws = mic_ws; - std_cfg.gpio_cfg.dout = I2S_GPIO_UNUSED; - std_cfg.gpio_cfg.din = mic_din; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Simplex channels created"); -} - -NoAudioCodecSimplex::NoAudioCodecSimplex(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask, gpio_num_t mic_sck, gpio_num_t mic_ws, gpio_num_t mic_din, i2s_std_slot_mask_t mic_slot_mask){ - duplex_ = false; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - // Create a new channel for speaker - i2s_chan_config_t chan_cfg = { - .id = (i2s_port_t)0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, nullptr)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = spk_slot_mask, - .ws_width = I2S_DATA_BIT_WIDTH_32BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - - }, - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = spk_bclk, - .ws = spk_ws, - .dout = spk_dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - - // Create a new channel for MIC - chan_cfg.id = (i2s_port_t)1; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, nullptr, &rx_handle_)); - std_cfg.clk_cfg.sample_rate_hz = (uint32_t)input_sample_rate_; - std_cfg.slot_cfg.slot_mask = mic_slot_mask; - std_cfg.gpio_cfg.bclk = mic_sck; - std_cfg.gpio_cfg.ws = mic_ws; - std_cfg.gpio_cfg.dout = I2S_GPIO_UNUSED; - std_cfg.gpio_cfg.din = mic_din; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Simplex channels created"); -} - -int NoAudioCodec::Write(const int16_t* data, int samples) { - std::lock_guard lock(data_if_mutex_); - std::vector buffer(samples); - - // output_volume_: 0-100 - // volume_factor_: 0-65536 - int32_t volume_factor = pow(double(output_volume_) / 100.0, 2) * 65536; - for (int i = 0; i < samples; i++) { - int64_t temp = int64_t(data[i]) * volume_factor; // 使用 int64_t 进行乘法运算 - if (temp > INT32_MAX) { - buffer[i] = INT32_MAX; - } else if (temp < INT32_MIN) { - buffer[i] = INT32_MIN; - } else { - buffer[i] = static_cast(temp); - } - } - - size_t bytes_written; - ESP_ERROR_CHECK(i2s_channel_write(tx_handle_, buffer.data(), samples * sizeof(int32_t), &bytes_written, portMAX_DELAY)); - return bytes_written / sizeof(int32_t); -} - -int NoAudioCodec::Read(int16_t* dest, int samples) { - size_t bytes_read; - - std::vector bit32_buffer(samples); - if (i2s_channel_read(rx_handle_, bit32_buffer.data(), samples * sizeof(int32_t), &bytes_read, portMAX_DELAY) != ESP_OK) { - ESP_LOGE(TAG, "Read Failed!"); - return 0; - } - - samples = bytes_read / sizeof(int32_t); - for (int i = 0; i < samples; i++) { - int32_t value = bit32_buffer[i] >> 12; - dest[i] = (value > INT16_MAX) ? INT16_MAX : (value < -INT16_MAX) ? -INT16_MAX : (int16_t)value; - } - return samples; -} - -// Delegating constructor: calls the main constructor with default slot mask -NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_din) - : NoAudioCodecSimplexPdm(input_sample_rate, output_sample_rate, spk_bclk, spk_ws, spk_dout, I2S_STD_SLOT_LEFT, mic_sck, mic_din) { - // All initialization is handled by the delegated constructor -} - -NoAudioCodecSimplexPdm::NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask, gpio_num_t mic_sck, gpio_num_t mic_din) { - duplex_ = false; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - // Create a new channel for speaker - i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)1, I2S_ROLE_MASTER); - tx_chan_cfg.dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM; - tx_chan_cfg.dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM; - tx_chan_cfg.auto_clear_after_cb = true; - tx_chan_cfg.auto_clear_before_cb = false; - tx_chan_cfg.intr_priority = 0; - ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_handle_, NULL)); - - - i2s_std_config_t tx_std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_32BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = spk_slot_mask, - .ws_width = I2S_DATA_BIT_WIDTH_32BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - - }, - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = spk_bclk, - .ws = spk_ws, - .dout = spk_dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - }, - }, - }; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &tx_std_cfg)); -#if SOC_I2S_SUPPORTS_PDM_RX - // Create a new channel for MIC in PDM mode - i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG((i2s_port_t)0, I2S_ROLE_MASTER); - ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_handle_)); - i2s_pdm_rx_config_t pdm_rx_cfg = { - .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG((uint32_t)input_sample_rate_), - /* The data bit-width of PDM mode is fixed to 16 */ - .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), - .gpio_cfg = { - .clk = mic_sck, - .din = mic_din, - - .invert_flags = { - .clk_inv = false, - }, - }, - }; - ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_handle_, &pdm_rx_cfg)); -#else - ESP_LOGE(TAG, "PDM is not supported"); -#endif - ESP_LOGI(TAG, "Simplex channels created"); -} - -int NoAudioCodecSimplexPdm::Read(int16_t* dest, int samples) { - size_t bytes_read; - - // PDM 解调后的数据位宽为 16 位,直接读取到目标缓冲区 - if (i2s_channel_read(rx_handle_, dest, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY) != ESP_OK) { - ESP_LOGE(TAG, "Read Failed!"); - return 0; - } - - samples = bytes_read / sizeof(int16_t); - if (input_gain_ > 0) { - int gain_factor = (int)input_gain_; - for (int i = 0; i < samples; i++) { - int32_t amplified = dest[i] * gain_factor; - dest[i] = (amplified > INT16_MAX) ? INT16_MAX : (amplified < -INT16_MAX) ? -INT16_MAX : (int16_t)amplified; - } - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.h deleted file mode 100644 index 098ee001..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/codecs/no_audio_codec.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _NO_AUDIO_CODEC_H -#define _NO_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include - -class NoAudioCodec : public AudioCodec { -protected: - std::mutex data_if_mutex_; - - virtual int Write(const int16_t* data, int samples) override; - virtual int Read(int16_t* dest, int samples) override; - -public: - virtual ~NoAudioCodec(); -}; - -class NoAudioCodecDuplex : public NoAudioCodec { -public: - NoAudioCodecDuplex(int input_sample_rate, int output_sample_rate, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); -}; - -class NoAudioCodecSimplex : public NoAudioCodec { -public: - NoAudioCodecSimplex(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_ws, gpio_num_t mic_din); - NoAudioCodecSimplex(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask, gpio_num_t mic_sck, gpio_num_t mic_ws, gpio_num_t mic_din, i2s_std_slot_mask_t mic_slot_mask); -}; - -class NoAudioCodecSimplexPdm : public NoAudioCodec { -public: - NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, gpio_num_t mic_sck, gpio_num_t mic_din); - NoAudioCodecSimplexPdm(int input_sample_rate, int output_sample_rate, gpio_num_t spk_bclk, gpio_num_t spk_ws, gpio_num_t spk_dout, i2s_std_slot_mask_t spk_slot_mask, gpio_num_t mic_sck, gpio_num_t mic_din); - int Read(int16_t* dest, int samples); -}; - -#endif // _NO_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.cc deleted file mode 100644 index 0281b135..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.cc +++ /dev/null @@ -1,187 +0,0 @@ -#include "afe_audio_processor.h" -#include - -#define PROCESSOR_RUNNING 0x01 - -#define TAG "AfeAudioProcessor" - -AfeAudioProcessor::AfeAudioProcessor() - : afe_data_(nullptr) { - event_group_ = xEventGroupCreate(); -} - -void AfeAudioProcessor::Initialize(AudioCodec* codec, int frame_duration_ms, srmodel_list_t* models_list) { - codec_ = codec; - frame_samples_ = frame_duration_ms * 16000 / 1000; - - // Pre-allocate output buffer capacity - output_buffer_.reserve(frame_samples_); - - int ref_num = codec_->input_reference() ? 1 : 0; - - std::string input_format; - for (int i = 0; i < codec_->input_channels() - ref_num; i++) { - input_format.push_back('M'); - } - for (int i = 0; i < ref_num; i++) { - input_format.push_back('R'); - } - - srmodel_list_t *models; - if (models_list == nullptr) { - models = esp_srmodel_init("model"); - } else { - models = models_list; - } - - char* ns_model_name = esp_srmodel_filter(models, ESP_NSNET_PREFIX, NULL); - char* vad_model_name = esp_srmodel_filter(models, ESP_VADN_PREFIX, NULL); - - afe_config_t* afe_config = afe_config_init(input_format.c_str(), NULL, AFE_TYPE_VC, AFE_MODE_HIGH_PERF); - afe_config->aec_mode = AEC_MODE_VOIP_HIGH_PERF; - afe_config->vad_mode = VAD_MODE_0; - afe_config->vad_min_noise_ms = 100; - if (vad_model_name != nullptr) { - afe_config->vad_model_name = vad_model_name; - } - - if (ns_model_name != nullptr) { - afe_config->ns_init = true; - afe_config->ns_model_name = ns_model_name; - afe_config->afe_ns_mode = AFE_NS_MODE_NET; - } else { - afe_config->ns_init = false; - } - - afe_config->agc_init = false; - afe_config->memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM; - -#ifdef CONFIG_USE_DEVICE_AEC - afe_config->aec_init = true; - afe_config->vad_init = false; -#else - afe_config->aec_init = false; - afe_config->vad_init = true; -#endif - - afe_iface_ = esp_afe_handle_from_config(afe_config); - afe_data_ = afe_iface_->create_from_config(afe_config); - - xTaskCreate([](void* arg) { - auto this_ = (AfeAudioProcessor*)arg; - this_->AudioProcessorTask(); - vTaskDelete(NULL); - }, "audio_communication", 4096, this, 3, NULL); -} - -AfeAudioProcessor::~AfeAudioProcessor() { - if (afe_data_ != nullptr) { - afe_iface_->destroy(afe_data_); - } - vEventGroupDelete(event_group_); -} - -size_t AfeAudioProcessor::GetFeedSize() { - if (afe_data_ == nullptr) { - return 0; - } - return afe_iface_->get_feed_chunksize(afe_data_); -} - -void AfeAudioProcessor::Feed(std::vector&& data) { - if (afe_data_ == nullptr) { - return; - } - afe_iface_->feed(afe_data_, data.data()); -} - -void AfeAudioProcessor::Start() { - xEventGroupSetBits(event_group_, PROCESSOR_RUNNING); -} - -void AfeAudioProcessor::Stop() { - xEventGroupClearBits(event_group_, PROCESSOR_RUNNING); - if (afe_data_ != nullptr) { - afe_iface_->reset_buffer(afe_data_); - } -} - -bool AfeAudioProcessor::IsRunning() { - return xEventGroupGetBits(event_group_) & PROCESSOR_RUNNING; -} - -void AfeAudioProcessor::OnOutput(std::function&& data)> callback) { - output_callback_ = callback; -} - -void AfeAudioProcessor::OnVadStateChange(std::function callback) { - vad_state_change_callback_ = callback; -} - -void AfeAudioProcessor::AudioProcessorTask() { - auto fetch_size = afe_iface_->get_fetch_chunksize(afe_data_); - auto feed_size = afe_iface_->get_feed_chunksize(afe_data_); - ESP_LOGI(TAG, "Audio communication task started, feed size: %d fetch size: %d", - feed_size, fetch_size); - - while (true) { - xEventGroupWaitBits(event_group_, PROCESSOR_RUNNING, pdFALSE, pdTRUE, portMAX_DELAY); - - auto res = afe_iface_->fetch_with_delay(afe_data_, portMAX_DELAY); - if ((xEventGroupGetBits(event_group_) & PROCESSOR_RUNNING) == 0) { - continue; - } - if (res == nullptr || res->ret_value == ESP_FAIL) { - if (res != nullptr) { - ESP_LOGI(TAG, "Error code: %d", res->ret_value); - } - continue; - } - - // VAD state change - if (vad_state_change_callback_) { - if (res->vad_state == VAD_SPEECH && !is_speaking_) { - is_speaking_ = true; - vad_state_change_callback_(true); - } else if (res->vad_state == VAD_SILENCE && is_speaking_) { - is_speaking_ = false; - vad_state_change_callback_(false); - } - } - - if (output_callback_) { - size_t samples = res->data_size / sizeof(int16_t); - - // Add data to buffer - output_buffer_.insert(output_buffer_.end(), res->data, res->data + samples); - - // Output complete frames when buffer has enough data - while (output_buffer_.size() >= frame_samples_) { - if (output_buffer_.size() == frame_samples_) { - // If buffer size equals frame size, move the entire buffer - output_callback_(std::move(output_buffer_)); - output_buffer_.clear(); - output_buffer_.reserve(frame_samples_); - } else { - // If buffer size exceeds frame size, copy one frame and remove it - output_callback_(std::vector(output_buffer_.begin(), output_buffer_.begin() + frame_samples_)); - output_buffer_.erase(output_buffer_.begin(), output_buffer_.begin() + frame_samples_); - } - } - } - } -} - -void AfeAudioProcessor::EnableDeviceAec(bool enable) { - if (enable) { -#if CONFIG_USE_DEVICE_AEC - afe_iface_->disable_vad(afe_data_); - afe_iface_->enable_aec(afe_data_); -#else - ESP_LOGE(TAG, "Device AEC is not supported"); -#endif - } else { - afe_iface_->disable_aec(afe_data_); - afe_iface_->enable_vad(afe_data_); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.h deleted file mode 100644 index 74d7fa40..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/afe_audio_processor.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef AFE_AUDIO_PROCESSOR_H -#define AFE_AUDIO_PROCESSOR_H - -#include -#include -#include -#include - -#include -#include -#include - -#include "audio_processor.h" -#include "audio_codec.h" - -class AfeAudioProcessor : public AudioProcessor { -public: - AfeAudioProcessor(); - ~AfeAudioProcessor(); - - void Initialize(AudioCodec* codec, int frame_duration_ms, srmodel_list_t* models_list) override; - void Feed(std::vector&& data) override; - void Start() override; - void Stop() override; - bool IsRunning() override; - void OnOutput(std::function&& data)> callback) override; - void OnVadStateChange(std::function callback) override; - size_t GetFeedSize() override; - void EnableDeviceAec(bool enable) override; - -private: - EventGroupHandle_t event_group_ = nullptr; - const esp_afe_sr_iface_t* afe_iface_ = nullptr; - esp_afe_sr_data_t* afe_data_ = nullptr; - std::function&& data)> output_callback_; - std::function vad_state_change_callback_; - AudioCodec* codec_ = nullptr; - int frame_samples_ = 0; - bool is_speaking_ = false; - std::vector output_buffer_; - - void AudioProcessorTask(); -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.cc deleted file mode 100644 index 630057cf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.cc +++ /dev/null @@ -1,68 +0,0 @@ -#include "audio_debugger.h" -#include "sdkconfig.h" - -#if CONFIG_USE_AUDIO_DEBUGGER -#include -#include -#include -#include -#include -#include -#endif - -#define TAG "AudioDebugger" - - -AudioDebugger::AudioDebugger() { -#if CONFIG_USE_AUDIO_DEBUGGER - udp_sockfd_ = socket(AF_INET, SOCK_DGRAM, 0); - if (udp_sockfd_ >= 0) { - // 解析配置的服务器地址 "IP:PORT" - std::string server_addr = CONFIG_AUDIO_DEBUG_UDP_SERVER; - size_t colon_pos = server_addr.find(':'); - - if (colon_pos != std::string::npos) { - std::string ip = server_addr.substr(0, colon_pos); - int port = std::stoi(server_addr.substr(colon_pos + 1)); - - memset(&udp_server_addr_, 0, sizeof(udp_server_addr_)); - udp_server_addr_.sin_family = AF_INET; - udp_server_addr_.sin_port = htons(port); - inet_pton(AF_INET, ip.c_str(), &udp_server_addr_.sin_addr); - - ESP_LOGI(TAG, "Initialized server address: %s", CONFIG_AUDIO_DEBUG_UDP_SERVER); - } else { - ESP_LOGW(TAG, "Invalid server address: %s, should be IP:PORT", CONFIG_AUDIO_DEBUG_UDP_SERVER); - close(udp_sockfd_); - udp_sockfd_ = -1; - } - } else { - ESP_LOGW(TAG, "Failed to create UDP socket: %d", errno); - } -#endif -} - -AudioDebugger::~AudioDebugger() { -#if CONFIG_USE_AUDIO_DEBUGGER - if (udp_sockfd_ >= 0) { - close(udp_sockfd_); - ESP_LOGI(TAG, "Closed UDP socket"); - } -#endif -} - -void AudioDebugger::Feed(const std::vector& data) { -#if CONFIG_USE_AUDIO_DEBUGGER - if (udp_sockfd_ >= 0) { - ssize_t sent = sendto(udp_sockfd_, data.data(), data.size() * sizeof(int16_t), 0, - (struct sockaddr*)&udp_server_addr_, sizeof(udp_server_addr_)); - if (sent < 0) { - ESP_LOGW(TAG, "Failed to send audio data to %s: %d", CONFIG_AUDIO_DEBUG_UDP_SERVER, errno); - } else { - ESP_LOGD(TAG, "Sent %d bytes audio data to %s", sent, CONFIG_AUDIO_DEBUG_UDP_SERVER); - } - } -#endif -} - - \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.h deleted file mode 100644 index a81336cb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/audio_debugger.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef AUDIO_DEBUGGER_H -#define AUDIO_DEBUGGER_H - -#include -#include - -#include -#include - -class AudioDebugger { -public: - AudioDebugger(); - ~AudioDebugger(); - - void Feed(const std::vector& data); - -private: - int udp_sockfd_ = -1; - struct sockaddr_in udp_server_addr_; -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.cc deleted file mode 100644 index bac5bad6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.cc +++ /dev/null @@ -1,59 +0,0 @@ -#include "no_audio_processor.h" -#include - -#define TAG "NoAudioProcessor" - -void NoAudioProcessor::Initialize(AudioCodec* codec, int frame_duration_ms, srmodel_list_t* models_list) { - codec_ = codec; - frame_samples_ = frame_duration_ms * 16000 / 1000; -} - -void NoAudioProcessor::Feed(std::vector&& data) { - if (!is_running_ || !output_callback_) { - return; - } - - if (codec_->input_channels() == 2) { - // If input channels is 2, we need to fetch the left channel data - auto mono_data = std::vector(data.size() / 2); - for (size_t i = 0, j = 0; i < mono_data.size(); ++i, j += 2) { - mono_data[i] = data[j]; - } - output_callback_(std::move(mono_data)); - } else { - output_callback_(std::move(data)); - } -} - -void NoAudioProcessor::Start() { - is_running_ = true; -} - -void NoAudioProcessor::Stop() { - is_running_ = false; -} - -bool NoAudioProcessor::IsRunning() { - return is_running_; -} - -void NoAudioProcessor::OnOutput(std::function&& data)> callback) { - output_callback_ = callback; -} - -void NoAudioProcessor::OnVadStateChange(std::function callback) { - vad_state_change_callback_ = callback; -} - -size_t NoAudioProcessor::GetFeedSize() { - if (!codec_) { - return 0; - } - return frame_samples_; -} - -void NoAudioProcessor::EnableDeviceAec(bool enable) { - if (enable) { - ESP_LOGE(TAG, "Device AEC is not supported"); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.h deleted file mode 100644 index d326d505..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/processors/no_audio_processor.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef DUMMY_AUDIO_PROCESSOR_H -#define DUMMY_AUDIO_PROCESSOR_H - -#include -#include - -#include "audio_processor.h" -#include "audio_codec.h" - -class NoAudioProcessor : public AudioProcessor { -public: - NoAudioProcessor() = default; - ~NoAudioProcessor() = default; - - void Initialize(AudioCodec* codec, int frame_duration_ms, srmodel_list_t* models_list) override; - void Feed(std::vector&& data) override; - void Start() override; - void Stop() override; - bool IsRunning() override; - void OnOutput(std::function&& data)> callback) override; - void OnVadStateChange(std::function callback) override; - size_t GetFeedSize() override; - void EnableDeviceAec(bool enable) override; - -private: - AudioCodec* codec_ = nullptr; - int frame_samples_ = 0; - std::function&& data)> output_callback_; - std::function vad_state_change_callback_; - bool is_running_ = false; -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_word.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_word.h deleted file mode 100644 index 9b8986ac..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_word.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef WAKE_WORD_H -#define WAKE_WORD_H - -#include -#include -#include - -#include -#include "audio_codec.h" - -class WakeWord { -public: - virtual ~WakeWord() = default; - - virtual bool Initialize(AudioCodec* codec, srmodel_list_t* models_list) = 0; - virtual void Feed(const std::vector& data) = 0; - virtual void OnWakeWordDetected(std::function callback) = 0; - virtual void Start() = 0; - virtual void Stop() = 0; - virtual size_t GetFeedSize() = 0; - virtual void EncodeWakeWordData() = 0; - virtual bool GetWakeWordOpus(std::vector& opus) = 0; - virtual const std::string& GetLastDetectedWakeWord() const = 0; -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.cc deleted file mode 100644 index bcdc697c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.cc +++ /dev/null @@ -1,208 +0,0 @@ -#include "afe_wake_word.h" -#include "audio_service.h" - -#include -#include - -#define DETECTION_RUNNING_EVENT 1 - -#define TAG "AfeWakeWord" - -AfeWakeWord::AfeWakeWord() - : afe_data_(nullptr), - wake_word_pcm_(), - wake_word_opus_() { - - event_group_ = xEventGroupCreate(); -} - -AfeWakeWord::~AfeWakeWord() { - if (afe_data_ != nullptr) { - afe_iface_->destroy(afe_data_); - } - - if (wake_word_encode_task_stack_ != nullptr) { - heap_caps_free(wake_word_encode_task_stack_); - } - - if (wake_word_encode_task_buffer_ != nullptr) { - heap_caps_free(wake_word_encode_task_buffer_); - } - - if (models_ != nullptr) { - esp_srmodel_deinit(models_); - } - - vEventGroupDelete(event_group_); -} - -bool AfeWakeWord::Initialize(AudioCodec* codec, srmodel_list_t* models_list) { - codec_ = codec; - int ref_num = codec_->input_reference() ? 1 : 0; - - if (models_list == nullptr) { - models_ = esp_srmodel_init("model"); - } else { - models_ = models_list; - } - - if (models_ == nullptr || models_->num == -1) { - ESP_LOGE(TAG, "Failed to initialize wakenet model"); - return false; - } - for (int i = 0; i < models_->num; i++) { - ESP_LOGI(TAG, "Model %d: %s", i, models_->model_name[i]); - if (strstr(models_->model_name[i], ESP_WN_PREFIX) != NULL) { - wakenet_model_ = models_->model_name[i]; - auto words = esp_srmodel_get_wake_words(models_, wakenet_model_); - // split by ";" to get all wake words - std::stringstream ss(words); - std::string word; - while (std::getline(ss, word, ';')) { - wake_words_.push_back(word); - } - } - } - - std::string input_format; - for (int i = 0; i < codec_->input_channels() - ref_num; i++) { - input_format.push_back('M'); - } - for (int i = 0; i < ref_num; i++) { - input_format.push_back('R'); - } - afe_config_t* afe_config = afe_config_init(input_format.c_str(), models_, AFE_TYPE_SR, AFE_MODE_HIGH_PERF); - afe_config->aec_init = codec_->input_reference(); - afe_config->aec_mode = AEC_MODE_SR_HIGH_PERF; - afe_config->afe_perferred_core = 1; - afe_config->afe_perferred_priority = 1; - afe_config->memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM; - - afe_iface_ = esp_afe_handle_from_config(afe_config); - afe_data_ = afe_iface_->create_from_config(afe_config); - - xTaskCreate([](void* arg) { - auto this_ = (AfeWakeWord*)arg; - this_->AudioDetectionTask(); - vTaskDelete(NULL); - }, "audio_detection", 4096, this, 3, nullptr); - - return true; -} - -void AfeWakeWord::OnWakeWordDetected(std::function callback) { - wake_word_detected_callback_ = callback; -} - -void AfeWakeWord::Start() { - xEventGroupSetBits(event_group_, DETECTION_RUNNING_EVENT); -} - -void AfeWakeWord::Stop() { - xEventGroupClearBits(event_group_, DETECTION_RUNNING_EVENT); - if (afe_data_ != nullptr) { - afe_iface_->reset_buffer(afe_data_); - } -} - -void AfeWakeWord::Feed(const std::vector& data) { - if (afe_data_ == nullptr) { - return; - } - afe_iface_->feed(afe_data_, data.data()); -} - -size_t AfeWakeWord::GetFeedSize() { - if (afe_data_ == nullptr) { - return 0; - } - return afe_iface_->get_feed_chunksize(afe_data_); -} - -void AfeWakeWord::AudioDetectionTask() { - auto fetch_size = afe_iface_->get_fetch_chunksize(afe_data_); - auto feed_size = afe_iface_->get_feed_chunksize(afe_data_); - ESP_LOGI(TAG, "Audio detection task started, feed size: %d fetch size: %d", - feed_size, fetch_size); - - while (true) { - xEventGroupWaitBits(event_group_, DETECTION_RUNNING_EVENT, pdFALSE, pdTRUE, portMAX_DELAY); - - auto res = afe_iface_->fetch_with_delay(afe_data_, portMAX_DELAY); - if (res == nullptr || res->ret_value == ESP_FAIL) { - continue;; - } - - // Store the wake word data for voice recognition, like who is speaking - StoreWakeWordData(res->data, res->data_size / sizeof(int16_t)); - - if (res->wakeup_state == WAKENET_DETECTED) { - Stop(); - last_detected_wake_word_ = wake_words_[res->wakenet_model_index - 1]; - - if (wake_word_detected_callback_) { - wake_word_detected_callback_(last_detected_wake_word_); - } - } - } -} - -void AfeWakeWord::StoreWakeWordData(const int16_t* data, size_t samples) { - // store audio data to wake_word_pcm_ - wake_word_pcm_.emplace_back(std::vector(data, data + samples)); - // keep about 2 seconds of data, detect duration is 30ms (sample_rate == 16000, chunksize == 512) - while (wake_word_pcm_.size() > 2000 / 30) { - wake_word_pcm_.pop_front(); - } -} - -void AfeWakeWord::EncodeWakeWordData() { - const size_t stack_size = 4096 * 7; - wake_word_opus_.clear(); - if (wake_word_encode_task_stack_ == nullptr) { - wake_word_encode_task_stack_ = (StackType_t*)heap_caps_malloc(stack_size, MALLOC_CAP_SPIRAM); - assert(wake_word_encode_task_stack_ != nullptr); - } - if (wake_word_encode_task_buffer_ == nullptr) { - wake_word_encode_task_buffer_ = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL); - assert(wake_word_encode_task_buffer_ != nullptr); - } - - wake_word_encode_task_ = xTaskCreateStatic([](void* arg) { - auto this_ = (AfeWakeWord*)arg; - { - auto start_time = esp_timer_get_time(); - auto encoder = std::make_unique(16000, 1, OPUS_FRAME_DURATION_MS); - encoder->SetComplexity(0); // 0 is the fastest - - int packets = 0; - for (auto& pcm: this_->wake_word_pcm_) { - encoder->Encode(std::move(pcm), [this_](std::vector&& opus) { - std::lock_guard lock(this_->wake_word_mutex_); - this_->wake_word_opus_.emplace_back(std::move(opus)); - this_->wake_word_cv_.notify_all(); - }); - packets++; - } - this_->wake_word_pcm_.clear(); - - auto end_time = esp_timer_get_time(); - ESP_LOGI(TAG, "Encode wake word opus %d packets in %ld ms", packets, (long)((end_time - start_time) / 1000)); - - std::lock_guard lock(this_->wake_word_mutex_); - this_->wake_word_opus_.push_back(std::vector()); - this_->wake_word_cv_.notify_all(); - } - vTaskDelete(NULL); - }, "encode_wake_word", stack_size, this, 2, wake_word_encode_task_stack_, wake_word_encode_task_buffer_); -} - -bool AfeWakeWord::GetWakeWordOpus(std::vector& opus) { - std::unique_lock lock(wake_word_mutex_); - wake_word_cv_.wait(lock, [this]() { - return !wake_word_opus_.empty(); - }); - opus.swap(wake_word_opus_.front()); - wake_word_opus_.pop_front(); - return !opus.empty(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.h deleted file mode 100644 index 8f5a2807..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/afe_wake_word.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef AFE_WAKE_WORD_H -#define AFE_WAKE_WORD_H - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "audio_codec.h" -#include "wake_word.h" - -class AfeWakeWord : public WakeWord { -public: - AfeWakeWord(); - ~AfeWakeWord(); - - bool Initialize(AudioCodec* codec, srmodel_list_t* models_list); - void Feed(const std::vector& data); - void OnWakeWordDetected(std::function callback); - void Start(); - void Stop(); - size_t GetFeedSize(); - void EncodeWakeWordData(); - bool GetWakeWordOpus(std::vector& opus); - const std::string& GetLastDetectedWakeWord() const { return last_detected_wake_word_; } - -private: - srmodel_list_t *models_ = nullptr; - const esp_afe_sr_iface_t* afe_iface_ = nullptr; - esp_afe_sr_data_t* afe_data_ = nullptr; - char* wakenet_model_ = NULL; - std::vector wake_words_; - EventGroupHandle_t event_group_; - std::function wake_word_detected_callback_; - AudioCodec* codec_ = nullptr; - std::string last_detected_wake_word_; - - TaskHandle_t wake_word_encode_task_ = nullptr; - StaticTask_t* wake_word_encode_task_buffer_ = nullptr; - StackType_t* wake_word_encode_task_stack_ = nullptr; - std::deque> wake_word_pcm_; - std::deque> wake_word_opus_; - std::mutex wake_word_mutex_; - std::condition_variable wake_word_cv_; - - void StoreWakeWordData(const int16_t* data, size_t size); - void AudioDetectionTask(); -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.cc deleted file mode 100644 index 2a1fb7ae..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.cc +++ /dev/null @@ -1,254 +0,0 @@ -#include "custom_wake_word.h" -#include "audio_service.h" -#include "system_info.h" -#include "assets.h" - -#include -#include -#include -#include -#include - - -#define TAG "CustomWakeWord" - - -CustomWakeWord::CustomWakeWord() - : wake_word_pcm_(), wake_word_opus_() { -} - -CustomWakeWord::~CustomWakeWord() { - if (multinet_model_data_ != nullptr && multinet_ != nullptr) { - multinet_->destroy(multinet_model_data_); - multinet_model_data_ = nullptr; - } - - if (wake_word_encode_task_stack_ != nullptr) { - heap_caps_free(wake_word_encode_task_stack_); - } - - if (wake_word_encode_task_buffer_ != nullptr) { - heap_caps_free(wake_word_encode_task_buffer_); - } - - if (models_ != nullptr) { - esp_srmodel_deinit(models_); - } -} - -void CustomWakeWord::ParseWakenetModelConfig() { - // Read index.json - auto& assets = Assets::GetInstance(); - void* ptr = nullptr; - size_t size = 0; - if (!assets.GetAssetData("index.json", ptr, size)) { - ESP_LOGE(TAG, "Failed to read index.json"); - return; - } - cJSON* root = cJSON_ParseWithLength(static_cast(ptr), size); - if (root == nullptr) { - ESP_LOGE(TAG, "Failed to parse index.json"); - return; - } - cJSON* multinet_model = cJSON_GetObjectItem(root, "multinet_model"); - if (cJSON_IsObject(multinet_model)) { - cJSON* language = cJSON_GetObjectItem(multinet_model, "language"); - cJSON* duration = cJSON_GetObjectItem(multinet_model, "duration"); - cJSON* threshold = cJSON_GetObjectItem(multinet_model, "threshold"); - cJSON* commands = cJSON_GetObjectItem(multinet_model, "commands"); - if (cJSON_IsString(language)) { - language_ = language->valuestring; - } - if (cJSON_IsNumber(duration)) { - duration_ = duration->valueint; - } - if (cJSON_IsNumber(threshold)) { - threshold_ = threshold->valuedouble; - } - if (cJSON_IsArray(commands)) { - for (int i = 0; i < cJSON_GetArraySize(commands); i++) { - cJSON* command = cJSON_GetArrayItem(commands, i); - if (cJSON_IsObject(command)) { - cJSON* command_name = cJSON_GetObjectItem(command, "command"); - cJSON* text = cJSON_GetObjectItem(command, "text"); - cJSON* action = cJSON_GetObjectItem(command, "action"); - if (cJSON_IsString(command_name) && cJSON_IsString(text) && cJSON_IsString(action)) { - commands_.push_back({command_name->valuestring, text->valuestring, action->valuestring}); - ESP_LOGI(TAG, "Command: %s, Text: %s, Action: %s", command_name->valuestring, text->valuestring, action->valuestring); - } - } - } - } - } - cJSON_Delete(root); -} - - -bool CustomWakeWord::Initialize(AudioCodec* codec, srmodel_list_t* models_list) { - codec_ = codec; - commands_.clear(); - - if (models_list == nullptr) { - language_ = "cn"; - models_ = esp_srmodel_init("model"); -#ifdef CONFIG_CUSTOM_WAKE_WORD - threshold_ = CONFIG_CUSTOM_WAKE_WORD_THRESHOLD / 100.0f; - commands_.push_back({CONFIG_CUSTOM_WAKE_WORD, CONFIG_CUSTOM_WAKE_WORD_DISPLAY, "wake"}); -#endif - } else { - models_ = models_list; - ParseWakenetModelConfig(); - } - - if (models_ == nullptr || models_->num == -1) { - ESP_LOGE(TAG, "Failed to initialize wakenet model"); - return false; - } - - // 初始化 multinet (命令词识别) - mn_name_ = esp_srmodel_filter(models_, ESP_MN_PREFIX, language_.c_str()); - if (mn_name_ == nullptr) { - ESP_LOGW(TAG, "Language '%s' multinet not found, falling back to any multinet model", language_.c_str()); - mn_name_ = esp_srmodel_filter(models_, ESP_MN_PREFIX, NULL); - } - if (mn_name_ == nullptr) { - ESP_LOGE(TAG, "Failed to initialize multinet, mn_name is nullptr"); - ESP_LOGI(TAG, "Please refer to https://pcn7cs20v8cr.feishu.cn/wiki/CpQjwQsCJiQSWSkYEvrcxcbVnwh to add custom wake word"); - return false; - } - - multinet_ = esp_mn_handle_from_name(mn_name_); - multinet_model_data_ = multinet_->create(mn_name_, duration_); - multinet_->set_det_threshold(multinet_model_data_, threshold_); - esp_mn_commands_clear(); - for (int i = 0; i < commands_.size(); i++) { - esp_mn_commands_add(i + 1, commands_[i].command.c_str()); - } - esp_mn_commands_update(); - - multinet_->print_active_speech_commands(multinet_model_data_); - return true; -} - -void CustomWakeWord::OnWakeWordDetected(std::function callback) { - wake_word_detected_callback_ = callback; -} - -void CustomWakeWord::Start() { - running_ = true; -} - -void CustomWakeWord::Stop() { - running_ = false; -} - -void CustomWakeWord::Feed(const std::vector& data) { - if (multinet_model_data_ == nullptr || !running_) { - return; - } - - esp_mn_state_t mn_state; - // If input channels is 2, we need to fetch the left channel data - if (codec_->input_channels() == 2) { - auto mono_data = std::vector(data.size() / 2); - for (size_t i = 0, j = 0; i < mono_data.size(); ++i, j += 2) { - mono_data[i] = data[j]; - } - - StoreWakeWordData(mono_data); - mn_state = multinet_->detect(multinet_model_data_, const_cast(mono_data.data())); - } else { - StoreWakeWordData(data); - mn_state = multinet_->detect(multinet_model_data_, const_cast(data.data())); - } - - if (mn_state == ESP_MN_STATE_DETECTING) { - return; - } else if (mn_state == ESP_MN_STATE_DETECTED) { - esp_mn_results_t *mn_result = multinet_->get_results(multinet_model_data_); - for (int i = 0; i < mn_result->num && running_; i++) { - ESP_LOGI(TAG, "Custom wake word detected: command_id=%d, string=%s, prob=%f", - mn_result->command_id[i], mn_result->string, mn_result->prob[i]); - auto& command = commands_[mn_result->command_id[i] - 1]; - if (command.action == "wake") { - last_detected_wake_word_ = command.text; - running_ = false; - - if (wake_word_detected_callback_) { - wake_word_detected_callback_(last_detected_wake_word_); - } - } - } - multinet_->clean(multinet_model_data_); - } else if (mn_state == ESP_MN_STATE_TIMEOUT) { - ESP_LOGD(TAG, "Command word detection timeout, cleaning state"); - multinet_->clean(multinet_model_data_); - } -} - -size_t CustomWakeWord::GetFeedSize() { - if (multinet_model_data_ == nullptr) { - return 0; - } - return multinet_->get_samp_chunksize(multinet_model_data_); -} - -void CustomWakeWord::StoreWakeWordData(const std::vector& data) { - // store audio data to wake_word_pcm_ - wake_word_pcm_.push_back(data); - // keep about 2 seconds of data, detect duration is 30ms (sample_rate == 16000, chunksize == 512) - while (wake_word_pcm_.size() > 2000 / 30) { - wake_word_pcm_.pop_front(); - } -} - -void CustomWakeWord::EncodeWakeWordData() { - const size_t stack_size = 4096 * 7; - wake_word_opus_.clear(); - if (wake_word_encode_task_stack_ == nullptr) { - wake_word_encode_task_stack_ = (StackType_t*)heap_caps_malloc(stack_size, MALLOC_CAP_SPIRAM); - assert(wake_word_encode_task_stack_ != nullptr); - } - if (wake_word_encode_task_buffer_ == nullptr) { - wake_word_encode_task_buffer_ = (StaticTask_t*)heap_caps_malloc(sizeof(StaticTask_t), MALLOC_CAP_INTERNAL); - assert(wake_word_encode_task_buffer_ != nullptr); - } - - wake_word_encode_task_ = xTaskCreateStatic([](void* arg) { - auto this_ = (CustomWakeWord*)arg; - { - auto start_time = esp_timer_get_time(); - auto encoder = std::make_unique(16000, 1, OPUS_FRAME_DURATION_MS); - encoder->SetComplexity(0); // 0 is the fastest - - int packets = 0; - for (auto& pcm: this_->wake_word_pcm_) { - encoder->Encode(std::move(pcm), [this_](std::vector&& opus) { - std::lock_guard lock(this_->wake_word_mutex_); - this_->wake_word_opus_.emplace_back(std::move(opus)); - this_->wake_word_cv_.notify_all(); - }); - packets++; - } - this_->wake_word_pcm_.clear(); - - auto end_time = esp_timer_get_time(); - ESP_LOGI(TAG, "Encode wake word opus %d packets in %ld ms", packets, (long)((end_time - start_time) / 1000)); - - std::lock_guard lock(this_->wake_word_mutex_); - this_->wake_word_opus_.push_back(std::vector()); - this_->wake_word_cv_.notify_all(); - } - vTaskDelete(NULL); - }, "encode_wake_word", stack_size, this, 2, wake_word_encode_task_stack_, wake_word_encode_task_buffer_); -} - -bool CustomWakeWord::GetWakeWordOpus(std::vector& opus) { - std::unique_lock lock(wake_word_mutex_); - wake_word_cv_.wait(lock, [this]() { - return !wake_word_opus_.empty(); - }); - opus.swap(wake_word_opus_.front()); - wake_word_opus_.pop_front(); - return !opus.empty(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.h deleted file mode 100644 index d4e6d8c3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/custom_wake_word.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef CUSTOM_WAKE_WORD_H -#define CUSTOM_WAKE_WORD_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "audio_codec.h" -#include "wake_word.h" - -class CustomWakeWord : public WakeWord { -public: - CustomWakeWord(); - ~CustomWakeWord(); - - bool Initialize(AudioCodec* codec, srmodel_list_t* models_list); - void Feed(const std::vector& data); - void OnWakeWordDetected(std::function callback); - void Start(); - void Stop(); - size_t GetFeedSize(); - void EncodeWakeWordData(); - bool GetWakeWordOpus(std::vector& opus); - const std::string& GetLastDetectedWakeWord() const { return last_detected_wake_word_; } - -private: - struct Command { - std::string command; - std::string text; - std::string action; - }; - - // multinet 相关成员变量 - esp_mn_iface_t* multinet_ = nullptr; - model_iface_data_t* multinet_model_data_ = nullptr; - srmodel_list_t *models_ = nullptr; - char* mn_name_ = nullptr; - std::string language_ = "cn"; - int duration_ = 3000; - float threshold_ = 0.2; - std::deque commands_; - - std::function wake_word_detected_callback_; - AudioCodec* codec_ = nullptr; - std::string last_detected_wake_word_; - std::atomic running_ = false; - - TaskHandle_t wake_word_encode_task_ = nullptr; - StaticTask_t* wake_word_encode_task_buffer_ = nullptr; - StackType_t* wake_word_encode_task_stack_ = nullptr; - std::deque> wake_word_pcm_; - std::deque> wake_word_opus_; - std::mutex wake_word_mutex_; - std::condition_variable wake_word_cv_; - - void StoreWakeWordData(const std::vector& data); - void ParseWakenetModelConfig(); -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.cc deleted file mode 100644 index d4aaf9d0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.cc +++ /dev/null @@ -1,87 +0,0 @@ -#include "esp_wake_word.h" -#include - - -#define TAG "EspWakeWord" - -EspWakeWord::EspWakeWord() { -} - -EspWakeWord::~EspWakeWord() { - if (wakenet_data_ != nullptr) { - wakenet_iface_->destroy(wakenet_data_); - esp_srmodel_deinit(wakenet_model_); - } -} - -bool EspWakeWord::Initialize(AudioCodec* codec, srmodel_list_t* models_list) { - codec_ = codec; - - if (models_list == nullptr) { - wakenet_model_ = esp_srmodel_init("model"); - } else { - wakenet_model_ = models_list; - } - - if (wakenet_model_ == nullptr || wakenet_model_->num == -1) { - ESP_LOGE(TAG, "Failed to initialize wakenet model"); - return false; - } - if(wakenet_model_->num > 1) { - ESP_LOGW(TAG, "More than one model found, using the first one"); - } else if (wakenet_model_->num == 0) { - ESP_LOGE(TAG, "No model found"); - return false; - } - char *model_name = wakenet_model_->model_name[0]; - wakenet_iface_ = (esp_wn_iface_t*)esp_wn_handle_from_name(model_name); - wakenet_data_ = wakenet_iface_->create(model_name, DET_MODE_95); - - int frequency = wakenet_iface_->get_samp_rate(wakenet_data_); - int audio_chunksize = wakenet_iface_->get_samp_chunksize(wakenet_data_); - ESP_LOGI(TAG, "Wake word(%s),freq: %d, chunksize: %d", model_name, frequency, audio_chunksize); - - return true; -} - -void EspWakeWord::OnWakeWordDetected(std::function callback) { - wake_word_detected_callback_ = callback; -} - -void EspWakeWord::Start() { - running_ = true; -} - -void EspWakeWord::Stop() { - running_ = false; -} - -void EspWakeWord::Feed(const std::vector& data) { - if (wakenet_data_ == nullptr || !running_) { - return; - } - - int res = wakenet_iface_->detect(wakenet_data_, (int16_t *)data.data()); - if (res > 0) { - last_detected_wake_word_ = wakenet_iface_->get_word_name(wakenet_data_, res); - running_ = false; - - if (wake_word_detected_callback_) { - wake_word_detected_callback_(last_detected_wake_word_); - } - } -} - -size_t EspWakeWord::GetFeedSize() { - if (wakenet_data_ == nullptr) { - return 0; - } - return wakenet_iface_->get_samp_chunksize(wakenet_data_); -} - -void EspWakeWord::EncodeWakeWordData() { -} - -bool EspWakeWord::GetWakeWordOpus(std::vector& opus) { - return false; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.h deleted file mode 100644 index 9a1d73aa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/audio/wake_words/esp_wake_word.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef ESP_WAKE_WORD_H -#define ESP_WAKE_WORD_H - -#include -#include -#include - -#include -#include -#include -#include - -#include "audio_codec.h" -#include "wake_word.h" - -class EspWakeWord : public WakeWord { -public: - EspWakeWord(); - ~EspWakeWord(); - - bool Initialize(AudioCodec* codec, srmodel_list_t* models_list); - void Feed(const std::vector& data); - void OnWakeWordDetected(std::function callback); - void Start(); - void Stop(); - size_t GetFeedSize(); - void EncodeWakeWordData(); - bool GetWakeWordOpus(std::vector& opus); - const std::string& GetLastDetectedWakeWord() const { return last_detected_wake_word_; } - -private: - esp_wn_iface_t *wakenet_iface_ = nullptr; - model_iface_data_t *wakenet_data_ = nullptr; - srmodel_list_t *wakenet_model_ = nullptr; - AudioCodec* codec_ = nullptr; - std::atomic running_ = false; - - std::function wake_word_detected_callback_; - std::string last_detected_wake_word_; -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README.md deleted file mode 100644 index 28f56660..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# 编译命令 - -## 一键编译 - -```bash -python scripts/release.py aipi-lite -``` - -## 手动配置编译 - -```bash -idf.py set-target esp32s3 -``` - -**配置** - -```bash -idf.py menuconfig -``` - -选择板子 - -``` -Xiaozhi Assistant -> Board Type -> AIPI-Lite -``` - -## 编译烧入 - -```bash -idf.py -DBOARD_NAME=aipi-lite build flash -``` - -注意: 如果当前设备出货之前是AiPi-Lite 固件(非小智版本),请特别小心处理闪存固件分区地址,以避免错误擦除 AiPi-Lite 的自身设备信息(EUI 等),否则设备即使恢复成Xorigin固件也无法正确连接到 服务器!所以在刷写固件之前,请务必记录设备的相关必要信息,以确保有恢复的方法! - -您可以使用以下命令备份生产信息 - -```bash -# firstly backup the factory information partition which contains the credentials for connecting the SenseCraft server -esptool.py --chip esp32s3 --baud 2000000 --before default_reset --after hard_reset --no-stub read_flash 0x9000 16384 nvsfactory.bin - -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README_en.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README_en.md deleted file mode 100644 index df9deb5d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/README_en.md +++ /dev/null @@ -1,40 +0,0 @@ -# Build Instructions - -## One-click Build - -```bash -python scripts/release.py aipi-lite -c config_en.json -``` - -## Manual Configuration and Build - -```bash -idf.py set-target esp32s3 -``` - -**Configuration** - -```bash -idf.py menuconfig -``` - -Select the board: - -``` -Xiaozhi Assistant -> Board Type -> AiPi-Lite -``` - -## Build and Flash - -```bash -idf.py -DBOARD_NAME=aipi-lite build flash -``` - -Note: If your device was previously shipped with the AiPi-Lite firmware (not the Xiaozhi version), please be very careful with the flash partition addresses to avoid accidentally erasing the device information (such as EUI) of the AiPi-Lite. Otherwise, even if you restore the AiPi-Lite firmware, the device may not be able to connect to the Xorigin server correctly! Therefore, before flashing the firmware, be sure to record the necessary device information to ensure you have a way to recover it! - -You can use the following command to back up the factory information: - -```bash -# Firstly backup the factory information partition which contains the credentials for connecting the SenseCraft server -esptool.py --chip esp32s3 --baud 2000000 --before default_reset --after hard_reset --no-stub read_flash 0x9000 16384 nvsfactory.bin -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/aipi-lite.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/aipi-lite.cc deleted file mode 100644 index a257dfe3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/aipi-lite.cc +++ /dev/null @@ -1,246 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "application.h" -#include "button.h" -#include "codecs/es8311_audio_codec.h" -#include "config.h" -#include "display/lcd_display.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "power_manager.h" -#include "power_save_timer.h" -#include "system_reset.h" -#include "wifi_board.h" - -#define TAG "AIPI-Lite" - -class AIPILite : public WifiBoard { - private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button power_button_; - LcdDisplay* display_; - PowerManager* power_manager_; - PowerSaveTimer* power_save_timer_; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(POWER_CHARGE_DETECT_PIN); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - esp_lcd_panel_disp_on_off(panel_, false); // 关闭显示 - rtc_gpio_set_level(POWER_CONTROL_PIN, 0); - rtc_gpio_hold_dis(POWER_CONTROL_PIN); - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = - { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SPI_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK( - spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN; - io_config.dc_gpio_num = DISPLAY_SPI_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK( - esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK( - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel_)); - - esp_lcd_panel_reset(panel_); - - esp_lcd_panel_init(panel_); - esp_lcd_panel_invert_color(panel_, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel_, DISPLAY_WIDTH, - DISPLAY_HEIGHT, DISPLAY_OFFSET_X, - DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - // 设置开机按钮的长按事件(直接进入配网模式) - boot_button_.OnLongPress([this]() { - // 唤醒电源保存定时器 - power_save_timer_->WakeUp(); - // 获取应用程序实例 - auto& app = Application::GetInstance(); - - // 进入配网模式 - app.SetDeviceState(kDeviceStateWifiConfiguring); - - // 重置WiFi配置以确保进入配网模式 - EnterWifiConfigMode(); - }); - - power_button_.OnClick([this]() { power_save_timer_->WakeUp(); }); - power_button_.OnLongPress([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() != kDeviceStateStarting && - !(power_manager_->IsCharging() && - power_manager_->GetBatteryLevel() < 100)) { - ESP_LOGI(TAG, "Power button long pressed, shutting down"); - esp_lcd_panel_disp_on_off(panel_, false); // 关闭显示 - rtc_gpio_set_level(POWER_CONTROL_PIN, 0); - rtc_gpio_hold_dis(POWER_CONTROL_PIN); - esp_deep_sleep_start(); - } - }); - } - - void InitializePowerCtl() { - ESP_LOGI(TAG, "Initialize Power Control GPIO"); - rtc_gpio_init(POWER_CONTROL_PIN); - rtc_gpio_set_direction(POWER_CONTROL_PIN, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(POWER_CONTROL_PIN, 1); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() {} - - public: - AIPILite() - : boot_button_(BOOT_BUTTON_GPIO), power_button_(POWER_BUTTON_GPIO) { - InitializePowerCtl(); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR, false); - return &audio_codec; - } - - virtual Display* GetDisplay() override { return display_; } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, - DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, - bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(AIPILite); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.h deleted file mode 100644 index 22aef8ec..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// aipi-lite configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_6 // MCLK -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 // LRCK -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_14 // SCLK -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_13 // DIN -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11 // DOUT - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_9 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_5 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_4 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_46 -#define BOOT_BUTTON_GPIO GPIO_NUM_42 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_3 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_16 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_17 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_15 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_7 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_18 -#define DISPLAY_SPI_MODE 0 -#define DISPLAY_SPI_SCLK_HZ (20 * 1000 * 1000) - -#define POWER_BUTTON_GPIO GPIO_NUM_1 -#define POWER_CONTROL_PIN GPIO_NUM_10 -#define POWER_CHARGE_DETECT_PIN GPIO_NUM_8 -#define POWER_ADC_UNIT ADC_UNIT_1 -#define POWER_ADC_CHANNEL ADC_CHANNEL_1 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.json deleted file mode 100644 index 9ea01683..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "aipi-lite", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/16m.csv\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config_en.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config_en.json deleted file mode 100644 index 6f71bafd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/config_en.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "aipi-lite_en", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/16m.csv\"", - "CONFIG_LANGUAGE_EN_US=y", - "CONFIG_SR_WN_WN9_NIHAOXIAOZHI_TTS=n", - "CONFIG_SR_WN_WN9_JARVIS_TTS=y", - "CONFIG_SR_WN_WN9_SOPHIA_TTS=y" - ] - } - ] -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/power_manager.h deleted file mode 100644 index e93b9445..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/aipi-lite/power_manager.h +++ /dev/null @@ -1,187 +0,0 @@ -#pragma once -#include -#include -#include - -#include -#include - -class PowerManager { - private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = POWER_CHARGE_DETECT_PIN; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick - // 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK( - adc_oneshot_read(adc_handle_, POWER_ADC_CHANNEL, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = {{1480, 0}, {1581, 20}, {1663, 40}, - {1750, 60}, {1840, 80}, {1980, 100}}; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && - average_adc < levels[i + 1].adc) { - float ratio = - static_cast(average_adc - levels[i].adc) / - (levels[i + 1].adc - levels[i].adc); - battery_level_ = - levels[i].level + - ratio * (levels[i + 1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", - adc_value, average_adc, battery_level_); - } - - public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = - [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 100000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel( - adc_handle_, POWER_ADC_CHANNEL, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { return battery_level_; } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/atk_dnesp32s3_box.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/atk_dnesp32s3_box.cc deleted file mode 100644 index c025389f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/atk_dnesp32s3_box.cc +++ /dev/null @@ -1,299 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "atk_dnesp32s3_box" - -class ATK_NoAudioCodecDuplex : public NoAudioCodec { -public: - ATK_NoAudioCodecDuplex(int input_sample_rate, int output_sample_rate, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - duplex_ = true; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - #ifdef I2S_HW_VERSION_2 - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - #endif - }, - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); - } -}; - -class XL9555_IN : public I2cDevice { -public: - XL9555_IN(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(0x06, 0x3B); - WriteReg(0x07, 0xFE); - } - - void xl9555_cfg(void) { - WriteReg(0x06, 0x1B); - WriteReg(0x07, 0xFE); - } - - void SetOutputState(uint8_t bit, uint8_t level) { - uint16_t data; - int index = bit; - - if (bit < 8) { - data = ReadReg(0x02); - } else { - data = ReadReg(0x03); - index -= 8; - } - - data = (data & ~(1 << index)) | (level << index); - - if (bit < 8) { - WriteReg(0x02, data); - } else { - WriteReg(0x03, data); - } - } - - int GetPingState(uint16_t pin) { - uint8_t data; - if (pin <= 0x0080) { - data = ReadReg(0x00); - return (data & (uint8_t)(pin & 0xFF)) ? 1 : 0; - } else { - data = ReadReg(0x01); - return (data & (uint8_t)((pin >> 8) & 0xFF )) ? 1 : 0; - } - - return 0; - } -}; - -class atk_dnesp32s3_box : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - i2c_master_dev_handle_t xl9555_handle_; - Button boot_button_; - LcdDisplay* display_; - XL9555_IN* xl9555_in_; - bool es8311_detected_ = false; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = GPIO_NUM_48, - .scl_io_num = GPIO_NUM_45, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - // Initialize XL9555 - xl9555_in_ = new XL9555_IN(i2c_bus_, 0x20); - - if (xl9555_in_->GetPingState(0x0020) == 1) { - es8311_detected_ = true; /* 音频设备标志位,SPK_CTRL_IO为高电平时,该标志位置1,且判定为ES8311 */ - } else { - es8311_detected_ = false; /* 音频设备标志位,SPK_CTRL_IO为低电平时,该标志位置0,且判定为NS4168 */ - } - - xl9555_in_->xl9555_cfg(); - } - - void InitializeATK_ST7789_80_Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - /* 配置RD引脚 */ - gpio_config_t gpio_init_struct; - gpio_init_struct.intr_type = GPIO_INTR_DISABLE; - gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT; - gpio_init_struct.pin_bit_mask = 1ull << LCD_NUM_RD; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&gpio_init_struct); - gpio_set_level(LCD_NUM_RD, 1); - - esp_lcd_i80_bus_handle_t i80_bus = NULL; - esp_lcd_i80_bus_config_t bus_config = { - .dc_gpio_num = LCD_NUM_DC, - .wr_gpio_num = LCD_NUM_WR, - .clk_src = LCD_CLK_SRC_DEFAULT, - .data_gpio_nums = { - GPIO_LCD_D0, - GPIO_LCD_D1, - GPIO_LCD_D2, - GPIO_LCD_D3, - GPIO_LCD_D4, - GPIO_LCD_D5, - GPIO_LCD_D6, - GPIO_LCD_D7, - }, - .bus_width = 8, - .max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t), - .psram_trans_align = 64, - .sram_trans_align = 4, - }; - ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); - - esp_lcd_panel_io_i80_config_t io_config = { - .cs_gpio_num = LCD_NUM_CS, - .pclk_hz = (10 * 1000 * 1000), - .trans_queue_depth = 10, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .dc_levels = { - .dc_idle_level = 0, - .dc_cmd_level = 0, - .dc_dummy_level = 0, - .dc_data_level = 1, - }, - .flags = { - .swap_color_bytes = 0, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io)); - - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = LCD_NUM_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_set_gap(panel, 0, 0); - uint8_t data0[] = {0x00}; - uint8_t data1[] = {0x65}; - esp_lcd_panel_io_tx_param(panel_io, 0x36, data0, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x3A, data1, 1); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - atk_dnesp32s3_box() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeATK_ST7789_80_Display(); - xl9555_in_->SetOutputState(5, 1); - xl9555_in_->SetOutputState(7, 1); - InitializeButtons(); - } - - virtual AudioCodec* GetAudioCodec() override { - /* 根据探测结果初始化编解码器 */ - if (es8311_detected_) { - /* 使用ES8311 驱动 */ - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - GPIO_NUM_NC, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } else { - static ATK_NoAudioCodecDuplex audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN); - return &audio_codec; - } - return NULL; - } - - virtual Display* GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(atk_dnesp32s3_box); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.h deleted file mode 100644 index 4b8e0022..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_13 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_21 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_47 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_4 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY true -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - -// Pin Definitions -#define LCD_NUM_CS GPIO_NUM_1 -#define LCD_NUM_DC GPIO_NUM_2 -#define LCD_NUM_RD GPIO_NUM_41 -#define LCD_NUM_WR GPIO_NUM_42 -#define LCD_NUM_RST GPIO_NUM_NC - -#define GPIO_LCD_D0 GPIO_NUM_40 -#define GPIO_LCD_D1 GPIO_NUM_39 -#define GPIO_LCD_D2 GPIO_NUM_38 -#define GPIO_LCD_D3 GPIO_NUM_12 -#define GPIO_LCD_D4 GPIO_NUM_11 -#define GPIO_LCD_D5 GPIO_NUM_10 -#define GPIO_LCD_D6 GPIO_NUM_9 -#define GPIO_LCD_D7 GPIO_NUM_46 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.json deleted file mode 100644 index 21e97d3f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atk-dnesp32s3-box", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/atk_dnesp32s3_box0.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/atk_dnesp32s3_box0.cc deleted file mode 100644 index 21c6e9d5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/atk_dnesp32s3_box0.cc +++ /dev/null @@ -1,388 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include "i2c_device.h" -#include -#include - -#include -#include - -#define TAG "atk_dnesp32s3_box0" - -class atk_dnesp32s3_box0 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button right_button_; - Button left_button_; - Button middle_button_; - LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - PowerSupply power_status_; - LcdStatus LcdStatus_ = kDevicelcdbacklightOn; - PowerSleep power_sleep_ = kDeviceNoSleep; - WakeStatus wake_status_ = kDeviceAwakened; - XiaozhiStatus XiaozhiStatus_ = kDevice_Exit_Distributionnetwork; - esp_timer_handle_t wake_timer_handle_; - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - int ticks_ = 0; - const int kChgCtrlInterval = 5; - - void InitializeBoardPowerManager() { - gpio_config_t gpio_init_struct = {0}; - gpio_init_struct.intr_type = GPIO_INTR_DISABLE; - gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pin_bit_mask = (1ull << CODEC_PWR_PIN) | (1ull << SYS_POW_PIN); - gpio_config(&gpio_init_struct); - - gpio_set_level(CODEC_PWR_PIN, 1); - gpio_set_level(SYS_POW_PIN, 1); - - gpio_config_t chg_init_struct = {0}; - - chg_init_struct.intr_type = GPIO_INTR_DISABLE; - chg_init_struct.mode = GPIO_MODE_INPUT; - chg_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - chg_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - chg_init_struct.pin_bit_mask = 1ull << CHRG_PIN; - ESP_ERROR_CHECK(gpio_config(&chg_init_struct)); - - chg_init_struct.mode = GPIO_MODE_OUTPUT; - chg_init_struct.pull_up_en = GPIO_PULLUP_DISABLE; - chg_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - chg_init_struct.pin_bit_mask = 1ull << CHG_CTRL_PIN; - ESP_ERROR_CHECK(gpio_config(&chg_init_struct)); - gpio_set_level(CHG_CTRL_PIN, 1); - - if (gpio_get_level(CHRG_PIN) == 0) { - power_status_ = kDeviceTypecSupply; - } else { - power_status_ = kDeviceBatterySupply; - } - - esp_timer_create_args_t wake_display_timer_args = { - .callback = [](void *arg) { - atk_dnesp32s3_box0* self = static_cast(arg); - if (self->LcdStatus_ == kDevicelcdbacklightOff && Application::GetInstance().GetDeviceState() == kDeviceStateListening - && self->wake_status_ == kDeviceWaitWake) { - - if (self->power_sleep_ == kDeviceNeutralSleep) { - self->power_save_timer_->WakeUp(); - } - - self->GetBacklight()->RestoreBrightness(); - self->wake_status_ = kDeviceAwakened; - self->LcdStatus_ = kDevicelcdbacklightOn; - } else if (self->power_sleep_ == kDeviceNeutralSleep && Application::GetInstance().GetDeviceState() == kDeviceStateListening - && self->LcdStatus_ != kDevicelcdbacklightOff && self->wake_status_ == kDeviceAwakened) { - self->power_save_timer_->WakeUp(); - self->power_sleep_ = kDeviceNoSleep; - } else { - self->ticks_ ++; - if (self->ticks_ % self->kChgCtrlInterval == 0) { - if (gpio_get_level(CHRG_PIN) == 0) { - self->power_status_ = kDeviceTypecSupply; - } else { - self->power_status_ = kDeviceBatterySupply; - } - - if (self->power_manager_->low_voltage_ < 2877 && self->power_status_ != kDeviceTypecSupply) { - esp_timer_stop(self->power_manager_->timer_handle_); - gpio_set_level(CHG_CTRL_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - gpio_set_level(SYS_POW_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - } - } - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "wake_update_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&wake_display_timer_args, &wake_timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(wake_timer_handle_, 300000)); - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(CHRG_PIN); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - power_sleep_ = kDeviceNeutralSleep; - XiaozhiStatus_ = kDevice_join_Sleep; - GetDisplay()->SetPowerSaveMode(true); - - if (LcdStatus_ != kDevicelcdbacklightOff) { - GetBacklight()->SetBrightness(1); - } - }); - power_save_timer_->OnExitSleepMode([this]() { - power_sleep_ = kDeviceNoSleep; - GetDisplay()->SetPowerSaveMode(false); - - if (XiaozhiStatus_ != kDevice_Exit_Sleep) { - GetBacklight()->RestoreBrightness(); - } - }); - power_save_timer_->OnShutdownRequest([this]() { - if (power_status_ == kDeviceBatterySupply) { - esp_timer_stop(power_manager_->timer_handle_); - gpio_set_level(CHG_CTRL_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - gpio_set_level(SYS_POW_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - }); - - power_save_timer_->SetEnabled(true); - } - - // Initialize I2C peripheral - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - middle_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - - if (LcdStatus_ != kDevicelcdbacklightOff) { - if (power_sleep_ == kDeviceNeutralSleep) { - power_save_timer_->WakeUp(); - power_sleep_ = kDeviceNoSleep; - } - - app.ToggleChatState(); - } - }); - - middle_button_.OnPressUp([this]() { - if (LcdStatus_ == kDevicelcdbacklightOff) { - Application::GetInstance().StopListening(); - Application::GetInstance().SetDeviceState(kDeviceStateIdle); - wake_status_ = kDeviceWaitWake; - } - - if (XiaozhiStatus_ == kDevice_Distributionnetwork || XiaozhiStatus_ == kDevice_Exit_Sleep) { - esp_timer_stop(power_manager_->timer_handle_); - gpio_set_level(CHG_CTRL_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - gpio_set_level(SYS_POW_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } else if (XiaozhiStatus_ == kDevice_join_Sleep) { - GetBacklight()->RestoreBrightness(); - XiaozhiStatus_ = kDevice_null; - } - }); - - middle_button_.OnLongPress([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - - if (app.GetDeviceState() != kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - if (app.GetDeviceState() == kDeviceStateWifiConfiguring && power_status_ != kDeviceTypecSupply) { - GetBacklight()->SetBrightness(0); - XiaozhiStatus_ = kDevice_Distributionnetwork; - } else if (power_status_ == kDeviceBatterySupply && LcdStatus_ != kDevicelcdbacklightOff) { - Application::GetInstance().StartListening(); - GetBacklight()->SetBrightness(0); - XiaozhiStatus_ = kDevice_Exit_Sleep; - } else if (power_status_ == kDeviceTypecSupply && LcdStatus_ == kDevicelcdbacklightOn && Application::GetInstance().GetDeviceState() != kDeviceStateStarting) { - Application::GetInstance().StartListening(); - GetBacklight()->SetBrightness(0); - LcdStatus_ = kDevicelcdbacklightOff; - } else if (LcdStatus_ == kDevicelcdbacklightOff && (power_status_ == kDeviceTypecSupply || power_status_ == kDeviceBatterySupply)) { - GetDisplay()->SetChatMessage("system", ""); - GetBacklight()->RestoreBrightness(); - wake_status_ = kDeviceAwakened; - LcdStatus_ = kDevicelcdbacklightOn; - } - } - }); - - left_button_.OnClick([this]() { - if (power_sleep_ == kDeviceNeutralSleep && LcdStatus_ != kDevicelcdbacklightOff) { - power_save_timer_->WakeUp(); - power_sleep_ = kDeviceNoSleep; - } - - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - left_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - right_button_.OnClick([this]() { - if (power_sleep_ == kDeviceNeutralSleep && LcdStatus_ != kDevicelcdbacklightOff) { - power_save_timer_->WakeUp(); - power_sleep_ = kDeviceNoSleep; - } - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - right_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - } - - void InitializeSt7789Display() { - ESP_LOGI(TAG, "Install panel IO"); - - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); - - ESP_LOGI(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_init(panel); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - atk_dnesp32s3_box0() : - right_button_(R_BUTTON_GPIO, false), - left_button_(L_BUTTON_GPIO, false), - middle_button_(M_BUTTON_GPIO, true) { - InitializeBoardPowerManager(); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - GPIO_NUM_NC, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(atk_dnesp32s3_box0); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.h deleted file mode 100644 index f2c940e1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.h +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -enum XiaozhiStatus { - kDevice_null, - kDevice_join_Sleep, - kDevice_Exit_Sleep, - kDevice_Distributionnetwork, - kDevice_Exit_Distributionnetwork, -}; - -enum LcdStatus { - kDevicelcdbacklightOn, - kDevicelcdbacklightOff, -}; - -enum WakeStatus { - kDeviceAwakened, - kDeviceWaitWake, - kDeviceSleeped, -}; - -enum PowerSupply { - kDeviceTypecSupply, - kDeviceBatterySupply, -}; - -enum PowerSleep { - kDeviceNoSleep, - kDeviceDeepSleep, - kDeviceNeutralSleep, -}; - -#define SYS_POW_PIN GPIO_NUM_2 -#define CHG_CTRL_PIN GPIO_NUM_47 -#define CODEC_PWR_PIN GPIO_NUM_14 -#define CHRG_PIN GPIO_NUM_48 - -#define BAT_VSEN_PIN GPIO_NUM_1 - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_11 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_12 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define AUDIO_SPK_GPIO_PIN GPIO_NUM_21 - -#define R_BUTTON_GPIO GPIO_NUM_0 -#define M_BUTTON_GPIO GPIO_NUM_4 -#define L_BUTTON_GPIO GPIO_NUM_3 - -#define BUILTIN_LED_GPIO GPIO_NUM_13 - -#define LCD_SCLK_PIN GPIO_NUM_39 -#define LCD_MOSI_PIN GPIO_NUM_40 -#define LCD_MISO_PIN GPIO_NUM_NC -#define LCD_DC_PIN GPIO_NUM_38 -#define LCD_CS_PIN GPIO_NUM_41 -#define LCD_RST_PIN GPIO_NUM_NC - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.json deleted file mode 100644 index 20849d4f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atk-dnesp32s3-box0", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/power_manager.h deleted file mode 100644 index e9a206c4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box0/power_manager.h +++ /dev/null @@ -1,193 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 0; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - uint32_t temp_val = 0; - - gpio_set_level(CHG_CTRL_PIN, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - - for(int t = 0; t < 10; t ++) { - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); - temp_val += adc_value; - } - - gpio_set_level(CHG_CTRL_PIN, 1); - vTaskDelay(pdMS_TO_TICKS(100)); - - adc_value = temp_val / 10; - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {2951, 0}, /* 3.80V */ - {3019, 20}, - {3037, 40}, - {3091, 60}, /* 3.88 */ - {3124, 80}, - {3231, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - low_voltage_ = adc_value; - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - esp_timer_handle_t timer_handle_; - uint16_t low_voltage_ = 2877; - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/atk_dnesp32s3_box2.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/atk_dnesp32s3_box2.cc deleted file mode 100644 index 7e888a77..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/atk_dnesp32s3_box2.cc +++ /dev/null @@ -1,477 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/es8389_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include "i2c_device.h" -#include -#include - -#include -#include -#include "esp_io_expander_tca95xx_16bit.h" - -#define TAG "atk_dnesp32s3_box2_4g" - -class atk_dnesp32s3_box2_4g : public DualNetworkBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - LcdDisplay* display_; - esp_io_expander_handle_t io_exp_handle; - button_handle_t btns; - button_driver_t* btn_driver_ = nullptr; - static atk_dnesp32s3_box2_4g* instance_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - PowerSupply power_status_; - esp_timer_handle_t wake_timer_handle_; - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - int ticks_ = 0; - const int kChgCtrlInterval = 5; - - void InitializeBoardPowerManager() { - instance_ = this; - - if (IoExpanderGetLevel(XIO_CHRG) == 0) { - power_status_ = kDeviceTypecSupply; - } else { - power_status_ = kDeviceBatterySupply; - } - - esp_timer_create_args_t wake_display_timer_args = { - .callback = [](void *arg) { - atk_dnesp32s3_box2_4g* self = static_cast(arg); - - self->ticks_ ++; - if (self->ticks_ % self->kChgCtrlInterval == 0) { - if (self->IoExpanderGetLevel(XIO_CHRG) == 0) { - self->power_status_ = kDeviceTypecSupply; - } else { - self->power_status_ = kDeviceBatterySupply; - } - - /* 低于某个电量,会自动关机 */ - if (self->power_manager_->low_voltage_ < 2630 && self->power_status_ == kDeviceBatterySupply) { - esp_timer_stop(self->power_manager_->timer_handle_); - - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_INPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - } - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "wake_update_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&wake_display_timer_args, &wake_timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(wake_timer_handle_, 100000)); - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(io_exp_handle); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - if (power_status_ == kDeviceBatterySupply) { - GetBacklight()->SetBrightness(0); - esp_timer_stop(power_manager_->timer_handle_); - esp_io_expander_set_dir( io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 0); - } - }); - - power_save_timer_->SetEnabled(true); - } - - void audio_volume_change(bool direction) { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume(); - - if (direction) { - volume += 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - } else { - volume -= 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - } - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - } - - void audio_volume_minimum(){ - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - } - - void audio_volume_maxmum(){ - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - } - - esp_err_t IoExpanderSetLevel(uint16_t pin_mask, uint8_t level) { - return esp_io_expander_set_level(io_exp_handle, pin_mask, level); - } - - uint8_t IoExpanderGetLevel(uint16_t pin_mask) { - uint32_t pin_val = 0; - esp_io_expander_get_level(io_exp_handle, DRV_IO_EXP_INPUT_MASK, &pin_val); - pin_mask &= DRV_IO_EXP_INPUT_MASK; - return (uint8_t)((pin_val & pin_mask) ? 1 : 0); - } - - void InitializeIoExpander() { - esp_err_t ret = ESP_OK; - esp_io_expander_new_i2c_tca95xx_16bit(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000, &io_exp_handle); - - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_OUTPUT_MASK, IO_EXPANDER_OUTPUT); - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_INPUT_MASK, IO_EXPANDER_INPUT); - - ret |= esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_3V3A, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_4G, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_SPK_EN, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_USB_SEL, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_VBUS_EN, 0); - - assert(ret == ESP_OK); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeButtons() { - instance_ = this; - - button_config_t l_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_config_t m_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_config_t r_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_driver_t* xio_l_btn_driver_ = nullptr; - button_driver_t* xio_m_btn_driver_ = nullptr; - - button_handle_t l_btn_handle = NULL; - button_handle_t m_btn_handle = NULL; - button_handle_t r_btn_handle = NULL; - - xio_l_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - xio_l_btn_driver_->enable_power_save = false; - xio_l_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !instance_->IoExpanderGetLevel(XIO_KEY_L); - }; - ESP_ERROR_CHECK(iot_button_create(&l_btn_cfg, xio_l_btn_driver_, &l_btn_handle)); - - xio_m_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - xio_m_btn_driver_->enable_power_save = false; - xio_m_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return instance_->IoExpanderGetLevel(XIO_KEY_M); - }; - ESP_ERROR_CHECK(iot_button_create(&m_btn_cfg, xio_m_btn_driver_, &m_btn_handle)); - - button_gpio_config_t r_cfg = { - .gpio_num = R_BUTTON_GPIO, - .active_level = BUTTON_INACTIVE, - .enable_power_save = false, - .disable_pull = false - }; - ESP_ERROR_CHECK(iot_button_new_gpio_device(&r_btn_cfg, &r_cfg, &r_btn_handle)); - - iot_button_register_cb(l_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_change(false); - }, this); - - iot_button_register_cb(l_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_minimum(); - }, this); - - iot_button_register_cb(m_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (self->GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - } - else { - app.ToggleChatState(); - } - } else { - app.ToggleChatState(); - } - }, this); - - iot_button_register_cb(m_btn_handle, BUTTON_DOUBLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - self->SwitchNetworkType(); - } - }, this); - - iot_button_register_cb(m_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - - auto& app = Application::GetInstance(); - if (self->GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - auto& wifi_board = static_cast(self->GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - - if (self->power_status_ == kDeviceBatterySupply) { - auto backlight = Board::GetInstance().GetBacklight(); - backlight->SetBrightness(0); - esp_timer_stop(self->power_manager_->timer_handle_); - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_io_expander_set_level(self->io_exp_handle, XIO_SYS_POW, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - }, this); - - iot_button_register_cb(r_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_change(true); - }, this); - - iot_button_register_cb(r_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_maxmum(); - }, this); - } - - void InitializeSt7789Display() { - ESP_LOGI(TAG, "Install panel IO"); - - /*RD PIN */ - gpio_config_t gpio_init_struct; - gpio_init_struct.intr_type = GPIO_INTR_DISABLE; - gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT; - gpio_init_struct.pin_bit_mask = 1ull << LCD_PIN_RD; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&gpio_init_struct); - gpio_set_level(LCD_PIN_RD, 1); - - /* BL PIN */ - gpio_init_struct.pin_bit_mask = 1ull << DISPLAY_BACKLIGHT_PIN; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&gpio_init_struct); - - esp_lcd_i80_bus_handle_t i80_bus = NULL; - esp_lcd_i80_bus_config_t bus_config = { - .dc_gpio_num = LCD_PIN_DC, - .wr_gpio_num = LCD_PIN_WR, - .clk_src = LCD_CLK_SRC_DEFAULT, - .data_gpio_nums = { - LCD_PIN_D0, - LCD_PIN_D1, - LCD_PIN_D2, - LCD_PIN_D3, - LCD_PIN_D4, - LCD_PIN_D5, - LCD_PIN_D6, - LCD_PIN_D7, - }, - .bus_width = 8, - .max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t), - .psram_trans_align = 64, - .sram_trans_align = 4, - }; - ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); - - esp_lcd_panel_io_i80_config_t io_config = { - .cs_gpio_num = LCD_PIN_CS, - .pclk_hz = (20 * 1000 * 1000), - .trans_queue_depth = 7, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .dc_levels = { - .dc_idle_level = 1, - .dc_cmd_level = 0, - .dc_dummy_level = 0, - .dc_data_level = 1, - }, - .flags = { - .cs_active_high = 0, - .pclk_active_neg = 0, - .pclk_idle_low = 0, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io)); - - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = LCD_PIN_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_set_gap(panel, 0, 0); - esp_lcd_panel_io_tx_param(panel_io, 0xCF, (uint8_t[]) {0x00,0x83,0x30}, 3); - esp_lcd_panel_io_tx_param(panel_io, 0xED, (uint8_t[]) {0x64,0x03,0x12,0x81}, 4); - esp_lcd_panel_io_tx_param(panel_io, 0xE8, (uint8_t[]) {0x85,0x01,0x79}, 3); - esp_lcd_panel_io_tx_param(panel_io, 0xCB, (uint8_t[]) {0x39,0x2C,0x00,0x34,0x02}, 5); - esp_lcd_panel_io_tx_param(panel_io, 0xF7, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xEA, (uint8_t[]) {0x00,0x00}, 2); - esp_lcd_panel_io_tx_param(panel_io, 0xbb, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xc3, (uint8_t[]) {0x00}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC4, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC5, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC6, (uint8_t[]) {0x10}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC7, (uint8_t[]) {0xB0}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x36, (uint8_t[]) {0x60}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x3A, (uint8_t[]) {0x55}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xB1, (uint8_t[]) {0x00,0x1B}, 2); - esp_lcd_panel_io_tx_param(panel_io, 0xF2, (uint8_t[]) {0x08}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x26, (uint8_t[]) {0x01}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xE0, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x32,0x44,0x42,0x06,0x0E,0x12,0x14,0x17}, 14); - esp_lcd_panel_io_tx_param(panel_io, 0xE1, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x31,0x54,0x47,0x0E,0x1C,0x17,0x1B,0x1E}, 14); - esp_lcd_panel_io_tx_param(panel_io, 0xB7, (uint8_t[]) {0x07}, 1); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - atk_dnesp32s3_box2_4g() : - DualNetworkBoard(Module_4G_TX_PIN, Module_4G_RX_PIN) { - InitializeI2c(); - InitializeIoExpander(); - InitializePowerSaveTimer(); - InitializePowerManager(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - InitializeBoardPowerManager(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8389AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8389_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(atk_dnesp32s3_box2_4g); - -// 定义静态成员变量 -atk_dnesp32s3_box2_4g* atk_dnesp32s3_box2_4g::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.h deleted file mode 100644 index 70e9d4d8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -enum PowerSupply { - kDeviceTypecSupply, - kDeviceBatterySupply, -}; - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_41 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_48 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_47 -#define AUDIO_CODEC_ES8389_ADDR ES8389_CODEC_DEFAULT_ADDR - -#define SPISD_PIN_MOSI GPIO_NUM_16 -#define SPISD_PIN_MISO GPIO_NUM_18 -#define SPISD_PIN_CLK GPIO_NUM_17 -#define SPISD_PIN_TS GPIO_NUM_15 - -#define R_BUTTON_GPIO GPIO_NUM_0 - -#define XL9555_INT_GPIO GPIO_NUM_2 -#define XIO_IO_SBU2 (IO_EXPANDER_PIN_NUM_3) -#define XIO_IO_SBU1 (IO_EXPANDER_PIN_NUM_4) -#define XIO_KEY_L (IO_EXPANDER_PIN_NUM_5) -#define XIO_KEY_Q (IO_EXPANDER_PIN_NUM_6) -#define XIO_KEY_M (IO_EXPANDER_PIN_NUM_7) -#define XIO_USB_SEL (IO_EXPANDER_PIN_NUM_8) -#define XIO_SPK_EN (IO_EXPANDER_PIN_NUM_9) -#define XIO_SYS_POW (IO_EXPANDER_PIN_NUM_10) -#define XIO_VBUS_EN (IO_EXPANDER_PIN_NUM_11) -#define XIO_EN_4G (IO_EXPANDER_PIN_NUM_12) -#define XIO_EN_3V3A (IO_EXPANDER_PIN_NUM_13) -#define XIO_CHG_CTRL (IO_EXPANDER_PIN_NUM_14) -#define XIO_CHRG (IO_EXPANDER_PIN_NUM_15) - -#define DRV_IO_EXP_OUTPUT_MASK 0x3F18 -#define DRV_IO_EXP_INPUT_MASK 0xC0E7 - -#define LCD_PIN_CS GPIO_NUM_14 -#define LCD_PIN_DC GPIO_NUM_12 -#define LCD_PIN_RD GPIO_NUM_10 -#define LCD_PIN_WR GPIO_NUM_11 -#define LCD_PIN_RST GPIO_NUM_NC -#define LCD_PIN_D0 GPIO_NUM_13 -#define LCD_PIN_D1 GPIO_NUM_9 -#define LCD_PIN_D2 GPIO_NUM_8 -#define LCD_PIN_D3 GPIO_NUM_7 -#define LCD_PIN_D4 GPIO_NUM_6 -#define LCD_PIN_D5 GPIO_NUM_5 -#define LCD_PIN_D6 GPIO_NUM_4 -#define LCD_PIN_D7 GPIO_NUM_3 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_21 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define Module_4G_RX_PIN GPIO_NUM_44 -#define Module_4G_TX_PIN GPIO_NUM_43 - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.json deleted file mode 100644 index 076253a3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atk-dnesp32s3-box2-4g", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/power_manager.h deleted file mode 100644 index 103ce888..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-4g/power_manager.h +++ /dev/null @@ -1,195 +0,0 @@ -#pragma once -#include -#include -#include "esp_io_expander_tca95xx_16bit.h" -#include -#include -#include - - -class PowerManager { -private: - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - esp_io_expander_handle_t xl9555_; - uint32_t pin_val = 0; - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - esp_io_expander_get_level(xl9555_, DRV_IO_EXP_INPUT_MASK, &pin_val); - bool new_charging_status = ((uint8_t)((pin_val & XIO_CHRG) ? 1 : 0)) == 0; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - uint32_t temp_val = 0; - - esp_io_expander_set_dir(xl9555_, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(xl9555_, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(500)); - - for(int t = 0; t < 10; t ++) { - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); - temp_val += adc_value; - } - - esp_io_expander_set_dir(xl9555_, XIO_CHG_CTRL, IO_EXPANDER_INPUT); - - adc_value = temp_val / 10; - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {2696, 0}, /* 3.48V -屏幕闪屏 */ - {2724, 20}, /* 3.53V */ - {2861, 40}, /* 3.7V */ - {3038, 60}, /* 3.90V */ - {3150, 80}, /* 4.02V */ - {3280, 100} /* 4.14V */ - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - low_voltage_ = adc_value; - - // ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - esp_timer_handle_t timer_handle_; - uint16_t low_voltage_ = 2630; - PowerManager(esp_io_expander_handle_t xl9555) : xl9555_(xl9555) { - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/atk_dnesp32s3_box2.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/atk_dnesp32s3_box2.cc deleted file mode 100644 index 55e297f1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/atk_dnesp32s3_box2.cc +++ /dev/null @@ -1,456 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8389_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include "i2c_device.h" -#include -#include - -#include -#include -#include "esp_io_expander_tca95xx_16bit.h" - -#define TAG "atk_dnesp32s3_box2_wifi" - -class atk_dnesp32s3_box2_wifi : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - LcdDisplay* display_; - esp_io_expander_handle_t io_exp_handle; - button_handle_t btns; - button_driver_t* btn_driver_ = nullptr; - static atk_dnesp32s3_box2_wifi* instance_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - PowerSupply power_status_; - esp_timer_handle_t wake_timer_handle_; - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - int ticks_ = 0; - const int kChgCtrlInterval = 5; - - void InitializeBoardPowerManager() { - instance_ = this; - - if (IoExpanderGetLevel(XIO_CHRG) == 0) { - power_status_ = kDeviceTypecSupply; - } else { - power_status_ = kDeviceBatterySupply; - } - - esp_timer_create_args_t wake_display_timer_args = { - .callback = [](void *arg) { - atk_dnesp32s3_box2_wifi* self = static_cast(arg); - - self->ticks_ ++; - if (self->ticks_ % self->kChgCtrlInterval == 0) { - if (self->IoExpanderGetLevel(XIO_CHRG) == 0) { - self->power_status_ = kDeviceTypecSupply; - } else { - self->power_status_ = kDeviceBatterySupply; - } - - /* 低于某个电量,会自动关机 */ - if (self->power_manager_->low_voltage_ < 2630 && self->power_status_ == kDeviceBatterySupply) { - esp_timer_stop(self->power_manager_->timer_handle_); - - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_INPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - } - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "wake_update_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&wake_display_timer_args, &wake_timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(wake_timer_handle_, 100000)); - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(io_exp_handle); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - if (power_status_ == kDeviceBatterySupply) { - GetBacklight()->SetBrightness(0); - esp_timer_stop(power_manager_->timer_handle_); - esp_io_expander_set_dir( io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 0); - } - }); - - power_save_timer_->SetEnabled(true); - } - - void audio_volume_change(bool direction) { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume(); - - if (direction) { - volume += 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - } else { - volume -= 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - } - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - } - - void audio_volume_minimum(){ - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - } - - void audio_volume_maxmum(){ - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - } - - esp_err_t IoExpanderSetLevel(uint16_t pin_mask, uint8_t level) { - return esp_io_expander_set_level(io_exp_handle, pin_mask, level); - } - - uint8_t IoExpanderGetLevel(uint16_t pin_mask) { - uint32_t pin_val = 0; - esp_io_expander_get_level(io_exp_handle, DRV_IO_EXP_INPUT_MASK, &pin_val); - pin_mask &= DRV_IO_EXP_INPUT_MASK; - return (uint8_t)((pin_val & pin_mask) ? 1 : 0); - } - - void InitializeIoExpander() { - esp_err_t ret = ESP_OK; - esp_io_expander_new_i2c_tca95xx_16bit(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000, &io_exp_handle); - - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_OUTPUT_MASK, IO_EXPANDER_OUTPUT); - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_INPUT_MASK, IO_EXPANDER_INPUT); - - ret |= esp_io_expander_set_level(io_exp_handle, XIO_SYS_POW, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_3V3A, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_EN_4G, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_SPK_EN, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_USB_SEL, 1); - ret |= esp_io_expander_set_level(io_exp_handle, XIO_VBUS_EN, 0); - - assert(ret == ESP_OK); - } - - // Initialize I2C peripheral - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeButtons() { - instance_ = this; - - button_config_t l_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_config_t m_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_config_t r_btn_cfg = { - .long_press_time = 800, - .short_press_time = 500 - }; - - button_driver_t* xio_l_btn_driver_ = nullptr; - button_driver_t* xio_m_btn_driver_ = nullptr; - - button_handle_t l_btn_handle = NULL; - button_handle_t m_btn_handle = NULL; - button_handle_t r_btn_handle = NULL; - - xio_l_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - xio_l_btn_driver_->enable_power_save = false; - xio_l_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !instance_->IoExpanderGetLevel(XIO_KEY_L); - }; - ESP_ERROR_CHECK(iot_button_create(&l_btn_cfg, xio_l_btn_driver_, &l_btn_handle)); - - xio_m_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - xio_m_btn_driver_->enable_power_save = false; - xio_m_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return instance_->IoExpanderGetLevel(XIO_KEY_M); - }; - ESP_ERROR_CHECK(iot_button_create(&m_btn_cfg, xio_m_btn_driver_, &m_btn_handle)); - - button_gpio_config_t r_cfg = { - .gpio_num = R_BUTTON_GPIO, - .active_level = BUTTON_INACTIVE, - .enable_power_save = false, - .disable_pull = false - }; - ESP_ERROR_CHECK(iot_button_new_gpio_device(&r_btn_cfg, &r_cfg, &r_btn_handle)); - - iot_button_register_cb(l_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_change(false); - }, this); - - iot_button_register_cb(l_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_minimum(); - }, this); - - iot_button_register_cb(m_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - app.ToggleChatState(); - }, this); - - iot_button_register_cb(m_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - - if (self->power_status_ == kDeviceBatterySupply) { - auto backlight = Board::GetInstance().GetBacklight(); - backlight->SetBrightness(0); - esp_timer_stop(self->power_manager_->timer_handle_); - esp_io_expander_set_dir(self->io_exp_handle, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(self->io_exp_handle, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_io_expander_set_level(self->io_exp_handle, XIO_SYS_POW, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - } - }, this); - - iot_button_register_cb(r_btn_handle, BUTTON_PRESS_DOWN, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_change(true); - }, this); - - iot_button_register_cb(r_btn_handle, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - self->audio_volume_maxmum(); - }, this); - } - - void InitializeSt7789Display() { - ESP_LOGI(TAG, "Install panel IO"); - - /* RD PIN */ - gpio_config_t gpio_init_struct; - gpio_init_struct.intr_type = GPIO_INTR_DISABLE; - gpio_init_struct.mode = GPIO_MODE_INPUT_OUTPUT; - gpio_init_struct.pin_bit_mask = 1ull << LCD_PIN_RD; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&gpio_init_struct); - gpio_set_level(LCD_PIN_RD, 1); - - /* BL PIN */ - gpio_init_struct.pin_bit_mask = 1ull << DISPLAY_BACKLIGHT_PIN; - gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&gpio_init_struct); - - esp_lcd_i80_bus_handle_t i80_bus = NULL; - esp_lcd_i80_bus_config_t bus_config = { - .dc_gpio_num = LCD_PIN_DC, - .wr_gpio_num = LCD_PIN_WR, - .clk_src = LCD_CLK_SRC_DEFAULT, - .data_gpio_nums = { - LCD_PIN_D0, - LCD_PIN_D1, - LCD_PIN_D2, - LCD_PIN_D3, - LCD_PIN_D4, - LCD_PIN_D5, - LCD_PIN_D6, - LCD_PIN_D7, - }, - .bus_width = 8, - .max_transfer_bytes = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t), - .psram_trans_align = 64, - .sram_trans_align = 4, - }; - ESP_ERROR_CHECK(esp_lcd_new_i80_bus(&bus_config, &i80_bus)); - - esp_lcd_panel_io_i80_config_t io_config = { - .cs_gpio_num = LCD_PIN_CS, - .pclk_hz = (20 * 1000 * 1000), - .trans_queue_depth = 7, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .dc_levels = { - .dc_idle_level = 1, - .dc_cmd_level = 0, - .dc_dummy_level = 0, - .dc_data_level = 1, - }, - .flags = { - .cs_active_high = 0, - .pclk_active_neg = 0, - .pclk_idle_low = 0, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &panel_io)); - - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = LCD_PIN_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_set_gap(panel, 0, 0); - esp_lcd_panel_io_tx_param(panel_io, 0xCF, (uint8_t[]) {0x00,0x83,0x30}, 3); - esp_lcd_panel_io_tx_param(panel_io, 0xED, (uint8_t[]) {0x64,0x03,0x12,0x81}, 4); - esp_lcd_panel_io_tx_param(panel_io, 0xE8, (uint8_t[]) {0x85,0x01,0x79}, 3); - esp_lcd_panel_io_tx_param(panel_io, 0xCB, (uint8_t[]) {0x39,0x2C,0x00,0x34,0x02}, 5); - esp_lcd_panel_io_tx_param(panel_io, 0xF7, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xEA, (uint8_t[]) {0x00,0x00}, 2); - esp_lcd_panel_io_tx_param(panel_io, 0xbb, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xc3, (uint8_t[]) {0x00}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC4, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC5, (uint8_t[]) {0x20}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC6, (uint8_t[]) {0x10}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xC7, (uint8_t[]) {0xB0}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x36, (uint8_t[]) {0x60}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x3A, (uint8_t[]) {0x55}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xB1, (uint8_t[]) {0x00,0x1B}, 2); - esp_lcd_panel_io_tx_param(panel_io, 0xF2, (uint8_t[]) {0x08}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0x26, (uint8_t[]) {0x01}, 1); - esp_lcd_panel_io_tx_param(panel_io, 0xE0, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x32,0x44,0x42,0x06,0x0E,0x12,0x14,0x17}, 14); - esp_lcd_panel_io_tx_param(panel_io, 0xE1, (uint8_t[]) {0xD0,0x00,0x02,0x07,0x0A,0x28,0x31,0x54,0x47,0x0E,0x1C,0x17,0x1B,0x1E}, 14); - esp_lcd_panel_io_tx_param(panel_io, 0xB7, (uint8_t[]) {0x07}, 1); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - atk_dnesp32s3_box2_wifi() { - InitializeI2c(); - InitializeIoExpander(); - InitializePowerSaveTimer(); - InitializePowerManager(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - InitializeBoardPowerManager(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8389AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8389_ADDR, - false); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(atk_dnesp32s3_box2_wifi); - -// 定义静态成员变量 -atk_dnesp32s3_box2_wifi* atk_dnesp32s3_box2_wifi::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.h deleted file mode 100644 index a12384c1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -enum PowerSupply { - kDeviceTypecSupply, - kDeviceBatterySupply, -}; - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_41 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_48 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_47 -#define AUDIO_CODEC_ES8389_ADDR ES8389_CODEC_DEFAULT_ADDR - -#define R_BUTTON_GPIO GPIO_NUM_0 - -#define XL9555_INT_GPIO GPIO_NUM_2 -#define XIO_IO_SBU2 (IO_EXPANDER_PIN_NUM_3) -#define XIO_IO_SBU1 (IO_EXPANDER_PIN_NUM_4) -#define XIO_KEY_L (IO_EXPANDER_PIN_NUM_5) -#define XIO_KEY_Q (IO_EXPANDER_PIN_NUM_6) -#define XIO_KEY_M (IO_EXPANDER_PIN_NUM_7) -#define XIO_USB_SEL (IO_EXPANDER_PIN_NUM_8) -#define XIO_SPK_EN (IO_EXPANDER_PIN_NUM_9) -#define XIO_SYS_POW (IO_EXPANDER_PIN_NUM_10) -#define XIO_VBUS_EN (IO_EXPANDER_PIN_NUM_11) -#define XIO_EN_4G (IO_EXPANDER_PIN_NUM_12) -#define XIO_EN_3V3A (IO_EXPANDER_PIN_NUM_13) -#define XIO_CHG_CTRL (IO_EXPANDER_PIN_NUM_14) -#define XIO_CHRG (IO_EXPANDER_PIN_NUM_15) - -#define DRV_IO_EXP_OUTPUT_MASK 0x3F18 -#define DRV_IO_EXP_INPUT_MASK 0xC0E7 - -#define LCD_PIN_CS GPIO_NUM_14 -#define LCD_PIN_DC GPIO_NUM_12 -#define LCD_PIN_RD GPIO_NUM_10 -#define LCD_PIN_WR GPIO_NUM_11 -#define LCD_PIN_RST GPIO_NUM_NC -#define LCD_PIN_D0 GPIO_NUM_13 -#define LCD_PIN_D1 GPIO_NUM_9 -#define LCD_PIN_D2 GPIO_NUM_8 -#define LCD_PIN_D3 GPIO_NUM_7 -#define LCD_PIN_D4 GPIO_NUM_6 -#define LCD_PIN_D5 GPIO_NUM_5 -#define LCD_PIN_D6 GPIO_NUM_4 -#define LCD_PIN_D7 GPIO_NUM_3 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_21 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.json deleted file mode 100644 index 2add4715..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atk-dnesp32s3-box2-wifi", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/power_manager.h deleted file mode 100644 index 103ce888..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3-box2-wifi/power_manager.h +++ /dev/null @@ -1,195 +0,0 @@ -#pragma once -#include -#include -#include "esp_io_expander_tca95xx_16bit.h" -#include -#include -#include - - -class PowerManager { -private: - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - esp_io_expander_handle_t xl9555_; - uint32_t pin_val = 0; - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - esp_io_expander_get_level(xl9555_, DRV_IO_EXP_INPUT_MASK, &pin_val); - bool new_charging_status = ((uint8_t)((pin_val & XIO_CHRG) ? 1 : 0)) == 0; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - uint32_t temp_val = 0; - - esp_io_expander_set_dir(xl9555_, XIO_CHG_CTRL, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(xl9555_, XIO_CHG_CTRL, 0); - vTaskDelay(pdMS_TO_TICKS(500)); - - for(int t = 0; t < 10; t ++) { - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); - temp_val += adc_value; - } - - esp_io_expander_set_dir(xl9555_, XIO_CHG_CTRL, IO_EXPANDER_INPUT); - - adc_value = temp_val / 10; - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {2696, 0}, /* 3.48V -屏幕闪屏 */ - {2724, 20}, /* 3.53V */ - {2861, 40}, /* 3.7V */ - {3038, 60}, /* 3.90V */ - {3150, 80}, /* 4.02V */ - {3280, 100} /* 4.14V */ - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - low_voltage_ = adc_value; - - // ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - esp_timer_handle_t timer_handle_; - uint16_t low_voltage_ = 2630; - PowerManager(esp_io_expander_handle_t xl9555) : xl9555_(xl9555) { - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/atk_dnesp32s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/atk_dnesp32s3.cc deleted file mode 100644 index cd9b7598..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/atk_dnesp32s3.cc +++ /dev/null @@ -1,225 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8388_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/single_led.h" -#include "esp32_camera.h" - -#include -#include -#include -#include - -#define TAG "atk_dnesp32s3" - -class XL9555 : public I2cDevice { -public: - XL9555(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(0x06, 0x03); - WriteReg(0x07, 0xF0); - } - - void SetOutputState(uint8_t bit, uint8_t level) { - uint16_t data; - int index = bit; - - if (bit < 8) { - data = ReadReg(0x02); - } else { - data = ReadReg(0x03); - index -= 8; - } - - data = (data & ~(1 << index)) | (level << index); - - if (bit < 8) { - WriteReg(0x02, data); - } else { - WriteReg(0x03, data); - } - } -}; - -class atk_dnesp32s3 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - XL9555* xl9555_; - Esp32Camera* camera_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - // Initialize XL9555 - xl9555_ = new XL9555(i2c_bus_, 0x20); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - ESP_LOGD(TAG, "Install panel IO"); - // 液晶屏控制IO初始化 - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 20 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - xl9555_->SetOutputState(8, 1); - xl9555_->SetOutputState(2, 0); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - // 初始化摄像头:ov2640; - // 根据正点原子官方示例参数 - void InitializeCamera() { - xl9555_->SetOutputState(OV_PWDN_IO, 0); // PWDN=低 (上电) - xl9555_->SetOutputState(OV_RESET_IO, 0); // 确保复位 - vTaskDelay(pdMS_TO_TICKS(50)); // 延长复位保持时间 - xl9555_->SetOutputState(OV_RESET_IO, 1); // 释放复位 - vTaskDelay(pdMS_TO_TICKS(50)); // 延长 50ms - - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAM_PIN_D0, - [1] = CAM_PIN_D1, - [2] = CAM_PIN_D2, - [3] = CAM_PIN_D3, - [4] = CAM_PIN_D4, - [5] = CAM_PIN_D5, - [6] = CAM_PIN_D6, - [7] = CAM_PIN_D7, - }, - .vsync_io = CAM_PIN_VSYNC, - .de_io = CAM_PIN_HREF, - .pclk_io = CAM_PIN_PCLK, - .xclk_io = CAM_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = true, - .i2c_config = { - .port = 1, - .scl_pin = CAM_PIN_SIOC, - .sda_pin = CAM_PIN_SIOD, - }, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAM_PIN_RESET, // 实际由 XL9555 控制 - .pwdn_pin = CAM_PIN_PWDN, // 实际由 XL9555 控制 - .dvp_pin = dvp_pin_config, - .xclk_freq = 20000000, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - -public: - atk_dnesp32s3() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - InitializeCamera(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8388_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(atk_dnesp32s3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.h deleted file mode 100644 index c0b72da9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.h +++ /dev/null @@ -1,64 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_3 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_9 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_46 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_10 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_41 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_42 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BUILTIN_LED_GPIO GPIO_NUM_1 - -#define LCD_SCLK_PIN GPIO_NUM_12 -#define LCD_MOSI_PIN GPIO_NUM_11 -#define LCD_MISO_PIN GPIO_NUM_13 -#define LCD_DC_PIN GPIO_NUM_40 -#define LCD_CS_PIN GPIO_NUM_21 - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -/* 相机引脚配置 */ -#define CAM_PIN_PWDN GPIO_NUM_NC -#define CAM_PIN_RESET GPIO_NUM_NC -#define CAM_PIN_VSYNC GPIO_NUM_47 -#define CAM_PIN_HREF GPIO_NUM_48 -#define CAM_PIN_PCLK GPIO_NUM_45 -#define CAM_PIN_XCLK GPIO_NUM_NC -#define CAM_PIN_SIOD GPIO_NUM_39 -#define CAM_PIN_SIOC GPIO_NUM_38 -#define CAM_PIN_D0 GPIO_NUM_4 -#define CAM_PIN_D1 GPIO_NUM_5 -#define CAM_PIN_D2 GPIO_NUM_6 -#define CAM_PIN_D3 GPIO_NUM_7 -#define CAM_PIN_D4 GPIO_NUM_15 -#define CAM_PIN_D5 GPIO_NUM_16 -#define CAM_PIN_D6 GPIO_NUM_17 -#define CAM_PIN_D7 GPIO_NUM_18 -#define OV_PWDN_IO 4 -#define OV_RESET_IO 5 - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.json deleted file mode 100644 index edbfeed0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atk-dnesp32s3", - "sdkconfig_append": [ - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_240X240_25FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/atk_dnesp32s3m.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/atk_dnesp32s3m.cc deleted file mode 100644 index 9f2f7014..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/atk_dnesp32s3m.cc +++ /dev/null @@ -1,220 +0,0 @@ -#include "ml307_board.h" -#include "codecs/es8388_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/single_led.h" -#include "driver/gpio.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include - -#define TAG "atk_dnesp32s3m_4g" - -class atk_dnesp32s3m_4g : public Ml307Board { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - Button phone_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - Application::GetInstance().ToggleChatState(); - }); - - volume_up_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - //不插耳机 - phone_button_.OnPressDown([this]() { - gpio_set_level(SPK_EN_PIN, 1); - }); - - //插入耳机 - phone_button_.OnPressUp([this]() { - gpio_set_level(SPK_EN_PIN, 0); - }); - } - - void InitializeSt7735Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 60 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); - - // 初始化液晶屏驱动芯片ST7735 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); - - //使能功放引脚 - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << SPK_EN_PIN); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - gpio_set_level(SPK_EN_PIN, 0); - - //检测耳机是否插入,插入时为高电平 - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << PHONE_CK_PIN); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - //耳机插入 - if (gpio_get_level(PHONE_CK_PIN)) { - gpio_set_level(SPK_EN_PIN, 1); - } - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - - uint8_t data0[] = {0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10}; - uint8_t data1[] = {0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10}; - esp_lcd_panel_io_tx_param(panel_io, 0xe0, data0, 16); - esp_lcd_panel_io_tx_param(panel_io, 0xe1, data1, 16); - - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - atk_dnesp32s3m_4g() : Ml307Board(Module_4G_TX_PIN, Module_4G_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO), - phone_button_(PHONE_CK_PIN, true) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7735Display(); - InitializeButtons(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8388_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } -}; - -DECLARE_BOARD(atk_dnesp32s3m_4g); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/config.h deleted file mode 100644 index 92505c5c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-4g/config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_48 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_47 - -#define Module_4G_RX_PIN GPIO_NUM_21 -#define Module_4G_TX_PIN GPIO_NUM_45 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_16 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_4 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_5 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BUILTIN_LED_GPIO GPIO_NUM_1 - -#define LCD_SCLK_PIN GPIO_NUM_12 -#define LCD_MOSI_PIN GPIO_NUM_11 -#define LCD_MISO_PIN GPIO_NUM_13 -#define LCD_DC_PIN GPIO_NUM_40 -#define LCD_CS_PIN GPIO_NUM_39 -#define LCD_RST_PIN GPIO_NUM_38 - -#define SPK_EN_PIN GPIO_NUM_42 -#define PHONE_CK_PIN GPIO_NUM_3 - -#define DISPLAY_WIDTH 160 -#define DISPLAY_HEIGHT 80 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 1 -#define DISPLAY_OFFSET_Y 26 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_41 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/atk_dnesp32s3m.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/atk_dnesp32s3m.cc deleted file mode 100644 index 76f5b399..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/atk_dnesp32s3m.cc +++ /dev/null @@ -1,230 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8388_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/single_led.h" -#include "driver/gpio.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "atk_dnesp32s3m_wifi" - -class atk_dnesp32s3m_wifi : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - Button phone_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - volume_up_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - //不插耳机 - phone_button_.OnPressDown([this]() { - gpio_set_level(SPK_EN_PIN, 1); - }); - - //插入耳机 - phone_button_.OnPressUp([this]() { - gpio_set_level(SPK_EN_PIN, 0); - }); - - } - - void InitializeSt7735Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 60 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - //使能功放引脚 - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << SPK_EN_PIN); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - gpio_set_level(SPK_EN_PIN, 0); - - //检测耳机是否插入,插入时为高电平 - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << PHONE_CK_PIN); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - //耳机插入 - if (gpio_get_level(PHONE_CK_PIN)) { - gpio_set_level(SPK_EN_PIN, 1); - } - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - - uint8_t data0[] = {0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10}; - uint8_t data1[] = {0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10}; - esp_lcd_panel_io_tx_param(panel_io, 0xe0, data0, 16); - esp_lcd_panel_io_tx_param(panel_io, 0xe1, data1, 16); - - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - atk_dnesp32s3m_wifi() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO), - phone_button_(PHONE_CK_PIN, true) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7735Display(); - InitializeButtons(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8388_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } -}; - -DECLARE_BOARD(atk_dnesp32s3m_wifi); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/config.h deleted file mode 100644 index df221818..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atk-dnesp32s3m-wifi/config.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_48 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_47 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_16 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_4 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_5 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BUILTIN_LED_GPIO GPIO_NUM_1 - -#define LCD_SCLK_PIN GPIO_NUM_12 -#define LCD_MOSI_PIN GPIO_NUM_11 -#define LCD_MISO_PIN GPIO_NUM_13 -#define LCD_DC_PIN GPIO_NUM_40 -#define LCD_CS_PIN GPIO_NUM_39 -#define LCD_RST_PIN GPIO_NUM_38 - -#define SPK_EN_PIN GPIO_NUM_42 -#define PHONE_CK_PIN GPIO_NUM_3 - -#define DISPLAY_WIDTH 160 -#define DISPLAY_HEIGHT 80 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 1 -#define DISPLAY_OFFSET_Y 26 -// #define DISPLAY_OFFSET_X 0 -// #define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_41 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/README.md deleted file mode 100644 index ccb452f4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# AtomEchoS3R -## 简介 - -AtomEchoS3R 是 M5Stack 推出的基于 ESP32-S3-PICO-1-N8R8 的物联网可编程控制器,采用了 ES8311 单声道音频解码器、MEMS 麦克风和 NS4150B 功率放大器的集成方案。 - -开发版**不带屏幕、不带额外按键**,需要使用语音唤醒。必要时,需要使用 `idf.py monitor` 查看 log 以确定运行状态。 - -## 配置、编译命令 - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig 并配置** - -```bash -idf.py menuconfig -``` - -分别配置如下选项: - -- `Xiaozhi Assistant` → `Board Type` → 选择 `AtomEchoS3R` -- `Partition Table` → `Custom partition CSV file` → 删除原有内容,输入 `partitions/v2/8m.csv` -- `Serial flasher config` → `Flash size` → 选择 `8 MB` -- `Component config` → `ESP PSRAM` → `Support for external, SPI-connected RAM` → `SPI RAM config` → 选择 `Octal Mode PSRAM` - -按 `S` 保存,按 `Q` 退出。 - -**编译** - -```bash -idf.py build -``` - -**烧录** - -将 AtomEchoS3R 连接到电脑,按住侧面 RESET 按键,直到 RESET 按键下方绿灯闪烁。 - -```bash -idf.py flash -``` - -烧录完毕后,按一下 RESET 按钮重启设备。 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/atom_echos3r.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/atom_echos3r.cc deleted file mode 100644 index ec5b61bb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/atom_echos3r.cc +++ /dev/null @@ -1,91 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "assets/lang_config.h" - -#include -#include - -#define TAG "AtomEchoS3R" - -class AtomEchoS3rBaseBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } -public: - AtomEchoS3rBaseBoard() : boot_button_(USER_BUTTON_GPIO) { - InitializeI2c(); - I2cDetect(); - InitializeButtons(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_GPIO_PA, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } -}; - -DECLARE_BOARD(AtomEchoS3rBaseBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.h deleted file mode 100644 index 4803c426..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// AtomEchoS3R Board configuration - -#include - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_11 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_3 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_4 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_45 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_0 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_GPIO_PA GPIO_NUM_18 - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define USER_BUTTON_GPIO GPIO_NUM_41 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.json deleted file mode 100644 index 7e7328d5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atom-echos3r/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atom-echos3r", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" - ] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/README.md deleted file mode 100644 index 67ab32fd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32:** - -```bash -idf.py set-target esp32 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> AtomMatrix + Echo Base -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/atommatrix_echo_base.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/atommatrix_echo_base.cc deleted file mode 100644 index 97ae7e3f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/atommatrix_echo_base.cc +++ /dev/null @@ -1,133 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" - -#include -#include -#include "led/circular_strip.h" - -#define TAG "XX+EchoBase" - -#define PI4IOE_ADDR 0x43 -#define PI4IOE_REG_CTRL 0x00 -#define PI4IOE_REG_IO_PP 0x07 -#define PI4IOE_REG_IO_DIR 0x03 -#define PI4IOE_REG_IO_OUT 0x05 -#define PI4IOE_REG_IO_PULLUP 0x0D - -class Pi4ioe : public I2cDevice { -public: - Pi4ioe(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(PI4IOE_REG_IO_PP, 0x00); // Set to high-impedance - WriteReg(PI4IOE_REG_IO_PULLUP, 0xFF); // Enable pull-up - WriteReg(PI4IOE_REG_IO_DIR, 0x6E); // Set input=0, output=1 - WriteReg(PI4IOE_REG_IO_OUT, 0xFF); // Set outputs to 1 - } - - void SetSpeakerMute(bool mute) { - WriteReg(PI4IOE_REG_IO_OUT, mute ? 0x00 : 0xFF); - } -}; - -class AtomMatrixEchoBaseBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - - Pi4ioe* pi4ioe_; - - Button face_button_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - void InitializePi4ioe() { - ESP_LOGI(TAG, "Init PI4IOE"); - pi4ioe_ = new Pi4ioe(i2c_bus_, PI4IOE_ADDR); - pi4ioe_->SetSpeakerMute(false); - } - - void InitializeButtons() { - face_button_.OnClick([this]() { - - ESP_LOGI(TAG, " ===>>> face_button_.OnClick "); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - AtomMatrixEchoBaseBoard() : face_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - I2cDetect(); - InitializePi4ioe(); - InitializeButtons(); - } - - virtual Led* GetLed() override { - static CircularStrip led(BUILTIN_LED_GPIO, 25); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_1, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_GPIO_PA, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } - -}; - -DECLARE_BOARD(AtomMatrixEchoBaseBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.h deleted file mode 100644 index d1684cbd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// AtomMatrix+EchoBase Board configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_19 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_33 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_23 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_22 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_25 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_21 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_GPIO_PA GPIO_NUM_NC - -#define BUILTIN_LED_GPIO GPIO_NUM_27 -#define BOOT_BUTTON_GPIO GPIO_NUM_39 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.json deleted file mode 100644 index 794d5741..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atommatrix-echo-base/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "target": "esp32", - "builds": [ - { - "name": "atommatrix-echo-base", - "sdkconfig_append": [ - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/README.md deleted file mode 100644 index ef2ad28b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> AtomS3 + Echo Base -``` - -**关闭语音唤醒:** - -``` -Xiaozhi Assistant -> [ ] 启用语音唤醒与音频处理 -> Unselect -``` - -**修改 flash 大小:** - -``` -Serial flasher config -> Flash size -> 8 MB -``` - -**修改分区表:** - -``` -Partition Table -> Custom partition CSV file -> partitions/v2/8m.csv -``` - -**关闭片外 PSRAM:** - -``` -Component config -> ESP PSRAM -> [ ] Support for external, SPI-connected RAM -> Unselect -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/atoms3_echo_base.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/atoms3_echo_base.cc deleted file mode 100644 index 22060763..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/atoms3_echo_base.cc +++ /dev/null @@ -1,228 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#define TAG "AtomS3+EchoBase" - -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb2, (uint8_t[]){0x2f}, 1, 0}, - {0xb3, (uint8_t[]){0x03}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x01}, 1, 0}, - {0xac, (uint8_t[]){0xcb}, 1, 0}, - {0xab, (uint8_t[]){0x0e}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x19}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xe8, (uint8_t[]){0x24}, 1, 0}, - {0xe9, (uint8_t[]){0x48}, 1, 0}, - {0xea, (uint8_t[]){0x22}, 1, 0}, - {0xc6, (uint8_t[]){0x30}, 1, 0}, - {0xc7, (uint8_t[]){0x18}, 1, 0}, - {0xf0, - (uint8_t[]){0x1f, 0x28, 0x04, 0x3e, 0x2a, 0x2e, 0x20, 0x00, 0x0c, 0x06, - 0x00, 0x1c, 0x1f, 0x0f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x00, 0x2d, 0x2f, 0x3c, 0x6f, 0x1c, 0x0b, 0x00, 0x00, 0x00, - 0x07, 0x0d, 0x11, 0x0f}, - 14, 0}, -}; - -class AtomS3EchoBaseBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Display* display_; - Button boot_button_; - bool is_echo_base_connected_ = false; - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - is_echo_base_connected_ = false; - uint8_t echo_base_connected_flag = 0x00; - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - if (address == 0x18) { - echo_base_connected_flag |= 0xF0; - } else if (address == 0x43) { - echo_base_connected_flag |= 0x0F; - } - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - is_echo_base_connected_ = (echo_base_connected_flag == 0xFF); - } - - void CheckEchoBaseConnection() { - if (is_echo_base_connected_) { - return; - } - - // Pop error page - InitializeSpi(); - InitializeGc9107Display(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - display_->SetStatus(Lang::Strings::ERROR); - display_->SetEmotion("triangle_exclamation"); - display_->SetChatMessage("system", "Echo Base\nnot connected"); - - while (1) { - ESP_LOGE(TAG, "Atomic Echo Base is disconnected"); - vTaskDelay(pdMS_TO_TICKS(1000)); - - // Rerun detection - I2cDetect(); - if (is_echo_base_connected_) { - vTaskDelay(pdMS_TO_TICKS(500)); - I2cDetect(); - if (is_echo_base_connected_) { - ESP_LOGI(TAG, "Atomic Echo Base is reconnected"); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_restart(); - } - } - } - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_21; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_17; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeGc9107Display() { - ESP_LOGI(TAG, "Init GC9107 display"); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_15; - io_config.dc_gpio_num = GPIO_NUM_33; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_34; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; - panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18) - panel_config.vendor_config = &gc9107_vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - display_ = new SpiLcdDisplay(io_handle, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - AtomS3EchoBaseBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - I2cDetect(); - CheckEchoBaseConnection(); - InitializeSpi(); - InitializeGc9107Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_1, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_GPIO_PA, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT, 256); - return &backlight; - } -}; - -DECLARE_BOARD(AtomS3EchoBaseBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.h deleted file mode 100644 index 6b2fdada..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// AtomS3+EchoBase Board configuration - -#include - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_6 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_5 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_38 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_39 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_GPIO_PA GPIO_NUM_NC - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_41 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 32 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_16 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.json deleted file mode 100644 index cd2fd6e5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3-echo-base/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atoms3-echo-base", - "sdkconfig_append": [ - "CONFIG_SPIRAM=n", - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/README.md deleted file mode 100644 index 83738ec4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# AtomS3R CAM/M12 + Echo Base - -## 简介 - -

    - -AtomS3R CAM、AtomS3R M12 是 M5Stack 推出的基于 ESP32-S3-PICO-1-N8R8 的物联网可编程控制器,搭载了摄像头。Atomic Echo Base 是一款专为 M5 Atom 系列主机设计的语音识别底座,采用了 ES8311 单声道音频解码器、MEMS 麦克风和 NS4150B 功率放大器的集成方案。 - -两款开发版均**不带屏幕、不带额外按键**,需要使用语音唤醒。必要时,需要使用 `idf.py monitor` 查看 log 以确定运行状态。 - -> ![NOTE] -> -> 自版本 [待定] 起,由于依赖库不支持 OV3660 传感器,AtomS3R M12 无法使用摄像头识别功能。 -> -> AtomS3R CAM 不受影响;使用旧版本小智固件的 AtomS3R M12 不受影响。 - -## 配置、编译命令 - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig 并配置** - -```bash -idf.py menuconfig -``` - -分别配置如下选项: - -- `Xiaozhi Assistant` → `Board Type` → 选择 `AtomS3R CAM/M12 + Echo Base` -- `Xiaozhi Assistant` → `IoT Protocol` → 选择 `MCP协议` 可开启摄像头识别功能 -- `Partition Table` → `Custom partition CSV file` → 删除原有内容,输入 `partitions/v2/8m.csv` -- `Serial flasher config` → `Flash size` → 选择 `8 MB` - -按 `S` 保存,按 `Q` 退出。 - -**编译** - -```bash -idf.py build -``` - -**烧录** - -将 AtomS3R CAM/M12 连接到电脑,按住侧面 RESET 按键,直到 RESET 按键下方绿灯闪烁。 - -```bash -idf.py flash -``` - -烧录完毕后,按一下 RESET 按钮重启。 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/atoms3r_cam_m12_echo_base.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/atoms3r_cam_m12_echo_base.cc deleted file mode 100644 index b9f6233f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/atoms3r_cam_m12_echo_base.cc +++ /dev/null @@ -1,204 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "assets/lang_config.h" - -#include -#include -#include "esp32_camera.h" - -#define TAG "AtomS3R CAM/M12 + EchoBase" - -#define PI4IOE_ADDR 0x43 -#define PI4IOE_REG_CTRL 0x00 -#define PI4IOE_REG_IO_PP 0x07 -#define PI4IOE_REG_IO_DIR 0x03 -#define PI4IOE_REG_IO_OUT 0x05 -#define PI4IOE_REG_IO_PULLUP 0x0D - -class Pi4ioe : public I2cDevice { -public: - Pi4ioe(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(PI4IOE_REG_IO_PP, 0x00); // Set to high-impedance - WriteReg(PI4IOE_REG_IO_PULLUP, 0xFF); // Enable pull-up - WriteReg(PI4IOE_REG_IO_DIR, 0x6E); // Set input=0, output=1 - WriteReg(PI4IOE_REG_IO_OUT, 0xFF); // Set outputs to 1 - } - - void SetSpeakerMute(bool mute) { - WriteReg(PI4IOE_REG_IO_OUT, mute ? 0x00 : 0xFF); - } -}; - -class AtomS3rCamM12EchoBaseBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pi4ioe* pi4ioe_ = nullptr; - bool is_echo_base_connected_ = false; - Esp32Camera* camera_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - is_echo_base_connected_ = false; - uint8_t echo_base_connected_flag = 0x00; - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - if (address == 0x18) { - echo_base_connected_flag |= 0xF0; - } else if (address == 0x43) { - echo_base_connected_flag |= 0x0F; - } - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - is_echo_base_connected_ = (echo_base_connected_flag == 0xFF); - } - - void CheckEchoBaseConnection() { - if (is_echo_base_connected_) { - return; - } - - while (1) { - ESP_LOGE(TAG, "Atomic Echo Base is disconnected"); - vTaskDelay(pdMS_TO_TICKS(1000)); - - // Rerun detection - I2cDetect(); - if (is_echo_base_connected_) { - vTaskDelay(pdMS_TO_TICKS(500)); - I2cDetect(); - if (is_echo_base_connected_) { - ESP_LOGI(TAG, "Atomic Echo Base is reconnected"); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_restart(); - } - } - } - } - - void InitializePi4ioe() { - ESP_LOGI(TAG, "Init PI4IOE"); - pi4ioe_ = new Pi4ioe(i2c_bus_, PI4IOE_ADDR); - pi4ioe_->SetSpeakerMute(false); - } - - void EnableCameraPower() { - gpio_reset_pin((gpio_num_t)18); - gpio_set_direction((gpio_num_t)18, GPIO_MODE_OUTPUT); - gpio_set_pull_mode((gpio_num_t)18, GPIO_PULLDOWN_ONLY); - - ESP_LOGI(TAG, "Camera Power Enabled"); - - vTaskDelay(pdMS_TO_TICKS(1000)); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = true, - .i2c_config = { - .port = 1, - .scl_pin = CAMERA_PIN_SIOC, - .sda_pin = CAMERA_PIN_SIOD, - }, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetHMirror(false); - } - - virtual Camera* GetCamera() override { - return camera_; - } -public: - AtomS3rCamM12EchoBaseBoard() { - EnableCameraPower(); // IO18 还会控制指示灯 - InitializeCamera(); - InitializeI2c(); - I2cDetect(); - CheckEchoBaseConnection(); - InitializePi4ioe(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_GPIO_PA, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } -}; - -DECLARE_BOARD(AtomS3rCamM12EchoBaseBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.h deleted file mode 100644 index 61fef498..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// AtomS3R M12+EchoBase Board configuration - -#include - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_6 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_5 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_38 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_39 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_GPIO_PA GPIO_NUM_NC - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_41 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - - -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_VSYNC GPIO_NUM_10 -#define CAMERA_PIN_HREF GPIO_NUM_14 -#define CAMERA_PIN_PCLK GPIO_NUM_40 -#define CAMERA_PIN_XCLK GPIO_NUM_21 -#define CAMERA_PIN_SIOD GPIO_NUM_12 -#define CAMERA_PIN_SIOC GPIO_NUM_9 -#define CAMERA_PIN_D0 GPIO_NUM_3 -#define CAMERA_PIN_D1 GPIO_NUM_42 -#define CAMERA_PIN_D2 GPIO_NUM_46 -#define CAMERA_PIN_D3 GPIO_NUM_48 -#define CAMERA_PIN_D4 GPIO_NUM_4 -#define CAMERA_PIN_D5 GPIO_NUM_17 -#define CAMERA_PIN_D6 GPIO_NUM_11 -#define CAMERA_PIN_D7 GPIO_NUM_13 -#define CAMERA_XCLK_FREQ (20000000) -#define XCLK_FREQ_HZ CAMERA_XCLK_FREQ - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.json deleted file mode 100644 index 1c798134..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-cam-m12-echo-base/config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atoms3r-cam-m12-echo-base", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_CAMERA_GC0308=y", - "CONFIG_CAMERA_GC0308_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_GC0308_DVP_YUV422_320X240_20FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/README.md deleted file mode 100644 index 4252e38a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> AtomS3R + Echo Base -``` - -**修改 flash 大小:** - -``` -Serial flasher config -> Flash size -> 8 MB -``` - -**修改分区表:** - -``` -Partition Table -> Custom partition CSV file -> partitions/v2/8m.csv -``` - -**修改 psram 配置:** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> Octal Mode PSRAM -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/atoms3r_echo_base.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/atoms3r_echo_base.cc deleted file mode 100644 index b2ca5652..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/atoms3r_echo_base.cc +++ /dev/null @@ -1,308 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#define TAG "AtomS3R+EchoBase" - -#define PI4IOE_ADDR 0x43 -#define PI4IOE_REG_CTRL 0x00 -#define PI4IOE_REG_IO_PP 0x07 -#define PI4IOE_REG_IO_DIR 0x03 -#define PI4IOE_REG_IO_OUT 0x05 -#define PI4IOE_REG_IO_PULLUP 0x0D - -class Pi4ioe : public I2cDevice { -public: - Pi4ioe(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(PI4IOE_REG_IO_PP, 0x00); // Set to high-impedance - WriteReg(PI4IOE_REG_IO_PULLUP, 0xFF); // Enable pull-up - WriteReg(PI4IOE_REG_IO_DIR, 0x6E); // Set input=0, output=1 - WriteReg(PI4IOE_REG_IO_OUT, 0xFF); // Set outputs to 1 - } - - void SetSpeakerMute(bool mute) { - WriteReg(PI4IOE_REG_IO_OUT, mute ? 0x00 : 0xFF); - } -}; - -class Lp5562 : public I2cDevice { -public: - Lp5562(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(0x00, 0B01000000); // Set chip_en to 1 - WriteReg(0x08, 0B00000001); // Enable internal clock - WriteReg(0x70, 0B00000000); // Configure all LED outputs to be controlled from I2C registers - - // PWM clock frequency 558 Hz - auto data = ReadReg(0x08); - data = data | 0B01000000; - WriteReg(0x08, data); - } - - void SetBrightness(uint8_t brightness) { - // Map 0~100 to 0~255 - brightness = brightness * 255 / 100; - WriteReg(0x0E, brightness); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(Lp5562* lp5562) : lp5562_(lp5562) {} - - void SetBrightnessImpl(uint8_t brightness) override { - if (lp5562_) { - lp5562_->SetBrightness(brightness); - } else { - ESP_LOGE(TAG, "LP5562 not available"); - } - } - -private: - Lp5562* lp5562_ = nullptr; -}; - -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb2, (uint8_t[]){0x2f}, 1, 0}, - {0xb3, (uint8_t[]){0x03}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x01}, 1, 0}, - {0xac, (uint8_t[]){0xcb}, 1, 0}, - {0xab, (uint8_t[]){0x0e}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x19}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xe8, (uint8_t[]){0x24}, 1, 0}, - {0xe9, (uint8_t[]){0x48}, 1, 0}, - {0xea, (uint8_t[]){0x22}, 1, 0}, - {0xc6, (uint8_t[]){0x30}, 1, 0}, - {0xc7, (uint8_t[]){0x18}, 1, 0}, - {0xf0, - (uint8_t[]){0x1f, 0x28, 0x04, 0x3e, 0x2a, 0x2e, 0x20, 0x00, 0x0c, 0x06, - 0x00, 0x1c, 0x1f, 0x0f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x00, 0x2d, 0x2f, 0x3c, 0x6f, 0x1c, 0x0b, 0x00, 0x00, 0x00, - 0x07, 0x0d, 0x11, 0x0f}, - 14, 0}, -}; - -class AtomS3rEchoBaseBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - i2c_master_bus_handle_t i2c_bus_internal_; - Pi4ioe* pi4ioe_ = nullptr; - Lp5562* lp5562_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - bool is_echo_base_connected_ = false; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - i2c_bus_cfg.i2c_port = I2C_NUM_0; - i2c_bus_cfg.sda_io_num = GPIO_NUM_45; - i2c_bus_cfg.scl_io_num = GPIO_NUM_0; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_internal_)); - } - - void I2cDetect() { - is_echo_base_connected_ = false; - uint8_t echo_base_connected_flag = 0x00; - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - if (address == 0x18) { - echo_base_connected_flag |= 0xF0; - } else if (address == 0x43) { - echo_base_connected_flag |= 0x0F; - } - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - is_echo_base_connected_ = (echo_base_connected_flag == 0xFF); - } - - void CheckEchoBaseConnection() { - if (is_echo_base_connected_) { - return; - } - - // Pop error page - InitializeLp5562(); - InitializeSpi(); - InitializeGc9107Display(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - display_->SetStatus(Lang::Strings::ERROR); - display_->SetEmotion("triangle_exclamation"); - display_->SetChatMessage("system", "Echo Base\nnot connected"); - - while (1) { - ESP_LOGE(TAG, "Atomic Echo Base is disconnected"); - vTaskDelay(pdMS_TO_TICKS(1000)); - - // Rerun detection - I2cDetect(); - if (is_echo_base_connected_) { - vTaskDelay(pdMS_TO_TICKS(500)); - I2cDetect(); - if (is_echo_base_connected_) { - ESP_LOGI(TAG, "Atomic Echo Base is reconnected"); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_restart(); - } - } - } - } - - void InitializePi4ioe() { - ESP_LOGI(TAG, "Init PI4IOE"); - pi4ioe_ = new Pi4ioe(i2c_bus_, PI4IOE_ADDR); - pi4ioe_->SetSpeakerMute(false); - } - - void InitializeLp5562() { - ESP_LOGI(TAG, "Init LP5562"); - lp5562_ = new Lp5562(i2c_bus_internal_, 0x30); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_21; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_15; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeGc9107Display() { - ESP_LOGI(TAG, "Init GC9107 display"); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_14; - io_config.dc_gpio_num = GPIO_NUM_42; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_48; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; - panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18) - panel_config.vendor_config = &gc9107_vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - display_ = new SpiLcdDisplay(io_handle, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - AtomS3rEchoBaseBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - I2cDetect(); - CheckEchoBaseConnection(); - InitializePi4ioe(); - InitializeLp5562(); - InitializeSpi(); - InitializeGc9107Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_1, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_GPIO_PA, - AUDIO_CODEC_ES8311_ADDR, - false); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight *GetBacklight() override { - static CustomBacklight backlight(lp5562_); - return &backlight; - } -}; - -DECLARE_BOARD(AtomS3rEchoBaseBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.h deleted file mode 100644 index d519c2ee..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// AtomS3R+EchoBase Board configuration - -#include - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_6 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_5 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_38 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_39 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_GPIO_PA GPIO_NUM_NC - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_41 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 32 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.json deleted file mode 100644 index d3b1549f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/atoms3r-echo-base/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "atoms3r-echo-base", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.h deleted file mode 100644 index d9a21486..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.h +++ /dev/null @@ -1,278 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_25 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_26 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_32 - -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_33 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_27 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_5 -#define ASR_BUTTON_GPIO GPIO_NUM_19 -#define BUILTIN_LED_GPIO GPIO_NUM_2 - -#define ML307_RX_PIN GPIO_NUM_16 -#define ML307_TX_PIN GPIO_NUM_17 - -#ifdef CONFIG_LCD_ST7789_240X240_7PIN -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_22 -#define DISPLAY_CS_PIN GPIO_NUM_NC -#else -#define DISPLAY_CS_PIN GPIO_NUM_22 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_23 -#endif - -#define DISPLAY_MOSI_PIN GPIO_NUM_4 -#define DISPLAY_CLK_PIN GPIO_NUM_15 -#define DISPLAY_DC_PIN GPIO_NUM_21 -#define DISPLAY_RST_PIN GPIO_NUM_18 - - -#ifdef CONFIG_LCD_ST7789_240X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X320_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_170X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 170 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 35 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_172X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 172 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 34 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X280 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240_7PIN -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 2 -#endif - -#ifdef CONFIG_LCD_ST7789_240X135 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 135 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 40 -#define DISPLAY_OFFSET_Y 53 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X160 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X128 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 32 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320 -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320_NO_IPS -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_GC9A01_240X240 -#define LCD_TYPE_GC9A01_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_CUSTOM -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.json deleted file mode 100644 index 07a853af..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32", - "builds": [ - { - "name": "bread-compact-esp32-lcd", - "sdkconfig_append": [ - "LCD_ST7789_240X240_7PIN=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/esp32_bread_board_lcd.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/esp32_bread_board_lcd.cc deleted file mode 100644 index 8cf457e0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32-lcd/esp32_bread_board_lcd.cc +++ /dev/null @@ -1,213 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include -#include -#include -#include - -#if defined(LCD_TYPE_ILI9341_SERIAL) -#include "esp_lcd_ili9341.h" -#endif - -#if defined(LCD_TYPE_GC9A01_SERIAL) -#include "esp_lcd_gc9a01.h" -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; -#endif - -#define TAG "ESP32-LCD-MarsbearSupport" - -class CompactWifiBoardLCD : public DualNetworkBoard { -private: - Button boot_button_; - Button touch_button_; - Button asr_button_; - - LcdDisplay* display_; - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; -#if defined(LCD_TYPE_ILI9341_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); -#elif defined(LCD_TYPE_GC9A01_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel)); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; -#else - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); -#endif - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); -#ifdef LCD_TYPE_GC9A01_SERIAL - panel_config.vendor_config = &gc9107_vendor_config; -#endif - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - - // 配置 GPIO - gpio_config_t io_conf = { - .pin_bit_mask = 1ULL << BUILTIN_LED_GPIO, // 设置需要配置的 GPIO 引脚 - .mode = GPIO_MODE_OUTPUT, // 设置为输出模式 - .pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉 - .pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉 - .intr_type = GPIO_INTR_DISABLE // 禁用中断 - }; - gpio_config(&io_conf); // 应用配置 - - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - gpio_set_level(BUILTIN_LED_GPIO, 1); - app.ToggleChatState(); - }); - - - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - asr_button_.OnClick([this]() { - std::string wake_word="你好小智"; - Application::GetInstance().WakeWordInvoke(wake_word); - }); - - touch_button_.OnPressDown([this]() { - gpio_set_level(BUILTIN_LED_GPIO, 1); - Application::GetInstance().StartListening(); - }); - - touch_button_.OnPressUp([this]() { - gpio_set_level(BUILTIN_LED_GPIO, 0); - Application::GetInstance().StopListening(); - }); - - } - -public: - CompactWifiBoardLCD() : - DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), touch_button_(TOUCH_BUTTON_GPIO), asr_button_(ASR_BUTTON_GPIO) { - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } -}; - -DECLARE_BOARD(CompactWifiBoardLCD); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/README.md deleted file mode 100644 index 617e83b3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32:** - -```bash -idf.py set-target esp32 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> 面包板 ESP32 DevKit -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.h deleted file mode 100644 index 0d5ab75d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_25 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_26 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_32 - -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_33 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_27 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_5 -#define ASR_BUTTON_GPIO GPIO_NUM_19 -#define BUILTIN_LED_GPIO GPIO_NUM_2 - -#define ML307_RX_PIN GPIO_NUM_16 -#define ML307_TX_PIN GPIO_NUM_17 - -#define DISPLAY_SDA_PIN GPIO_NUM_4 -#define DISPLAY_SCL_PIN GPIO_NUM_15 -#define DISPLAY_WIDTH 128 - -#if CONFIG_OLED_SSD1306_128X32 -#define DISPLAY_HEIGHT 32 -#elif CONFIG_OLED_SSD1306_128X64 -#define DISPLAY_HEIGHT 64 -#else -#error "未选择 OLED 屏幕类型" -#endif - -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_18 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.json deleted file mode 100644 index 9a7dd551..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32", - "builds": [ - { - "name": "bread-compact-esp32", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X64=y" - ] - }, - { - "name": "bread-compact-esp32-128x32", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X32=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/esp32_bread_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/esp32_bread_board.cc deleted file mode 100644 index 31b6e7d1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-esp32/esp32_bread_board.cc +++ /dev/null @@ -1,174 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "display/oled_display.h" - -#include -#include -#include -#include - -#define TAG "ESP32-MarsbearSupport" - -class CompactWifiBoard : public DualNetworkBoard { -private: - Button boot_button_; - Button touch_button_; - Button asr_button_; - - i2c_master_bus_handle_t display_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - - // 配置 GPIO - gpio_config_t io_conf = { - .pin_bit_mask = 1ULL << BUILTIN_LED_GPIO, // 设置需要配置的 GPIO 引脚 - .mode = GPIO_MODE_OUTPUT, // 设置为输出模式 - .pull_up_en = GPIO_PULLUP_DISABLE, // 禁用上拉 - .pull_down_en = GPIO_PULLDOWN_DISABLE, // 禁用下拉 - .intr_type = GPIO_INTR_DISABLE // 禁用中断 - }; - gpio_config(&io_conf); // 应用配置 - - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - gpio_set_level(BUILTIN_LED_GPIO, 1); - app.ToggleChatState(); - }); - - - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - asr_button_.OnClick([this]() { - std::string wake_word="你好小智"; - Application::GetInstance().WakeWordInvoke(wake_word); - }); - - touch_button_.OnPressDown([this]() { - gpio_set_level(BUILTIN_LED_GPIO, 1); - Application::GetInstance().StartListening(); - }); - touch_button_.OnPressUp([this]() { - gpio_set_level(BUILTIN_LED_GPIO, 0); - Application::GetInstance().StopListening(); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - CompactWifiBoard() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), boot_button_(BOOT_BUTTON_GPIO), touch_button_(TOUCH_BUTTON_GPIO), asr_button_(ASR_BUTTON_GPIO) - { - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override - { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - -}; - -DECLARE_BOARD(CompactWifiBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/compact_ml307_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/compact_ml307_board.cc deleted file mode 100644 index 15b25f4e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/compact_ml307_board.cc +++ /dev/null @@ -1,191 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "display/oled_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include - -#define TAG "CompactMl307Board" - -class CompactMl307Board : public DualNetworkBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - Button touch_button_; - Button volume_up_button_; - Button volume_down_button_; - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - touch_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - touch_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - volume_up_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - CompactMl307Board() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN, GPIO_NUM_NC), - boot_button_(BOOT_BUTTON_GPIO), - touch_button_(TOUCH_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(CompactMl307Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.h deleted file mode 100644 index de9ef7f2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_47 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA_PIN GPIO_NUM_41 -#define DISPLAY_SCL_PIN GPIO_NUM_42 -#define DISPLAY_WIDTH 128 - -#if CONFIG_OLED_SSD1306_128X32 -#define DISPLAY_HEIGHT 32 -#elif CONFIG_OLED_SSD1306_128X64 -#define DISPLAY_HEIGHT 64 -#else -#error "未选择 OLED 屏幕类型" -#endif - -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_18 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.json deleted file mode 100644 index 9da8cabd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-ml307/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "bread-compact-ml307", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X32=y" - ] - }, - { - "name": "bread-compact-ml307-128x64", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X64=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/compact_wifi_board_lcd.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/compact_wifi_board_lcd.cc deleted file mode 100644 index 431cc43c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/compact_wifi_board_lcd.cc +++ /dev/null @@ -1,183 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" - -#include -#include -#include -#include -#include -#include - -#if defined(LCD_TYPE_ILI9341_SERIAL) -#include "esp_lcd_ili9341.h" -#endif - -#if defined(LCD_TYPE_GC9A01_SERIAL) -#include "esp_lcd_gc9a01.h" -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; -#endif - -#define TAG "CompactWifiBoardLCD" - -class CompactWifiBoardLCD : public WifiBoard { -private: - - Button boot_button_; - LcdDisplay* display_; - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; -#if defined(LCD_TYPE_ILI9341_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); -#elif defined(LCD_TYPE_GC9A01_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel)); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; -#else - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); -#endif - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); -#ifdef LCD_TYPE_GC9A01_SERIAL - panel_config.vendor_config = &gc9107_vendor_config; -#endif - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - CompactWifiBoardLCD() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } -}; - -DECLARE_BOARD(CompactWifiBoardLCD); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/config.h deleted file mode 100644 index 12d3802a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-lcd/config.h +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42 -#define DISPLAY_MOSI_PIN GPIO_NUM_47 -#define DISPLAY_CLK_PIN GPIO_NUM_21 -#define DISPLAY_DC_PIN GPIO_NUM_40 -#define DISPLAY_RST_PIN GPIO_NUM_45 -#define DISPLAY_CS_PIN GPIO_NUM_41 - - -#ifdef CONFIG_LCD_ST7789_240X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X320_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_170X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 170 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 35 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_172X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 172 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 34 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X280 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240_7PIN -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 3 -#endif - -#ifdef CONFIG_LCD_ST7789_240X135 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 135 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 40 -#define DISPLAY_OFFSET_Y 53 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X160 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X128 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 32 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320 -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320_NO_IPS -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_GC9A01_240X240 -#define LCD_TYPE_GC9A01_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_CUSTOM -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_18 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/README.md deleted file mode 100644 index 51e7fdc5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/README.md +++ /dev/null @@ -1,51 +0,0 @@ -硬件基于基于ESP32S3CAM开发板,代码基于bread-compact-wifi-lcd修改 -使用的摄像头是OV2640 -注意因为摄像头占用IO较多,所以占用了ESP32S3的USB 19 20两个引脚 -连线方式参考config.h文件中对引脚的定义 - - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -```bash -Xiaozhi Assistant -> Board Type ->面包板新版接线(WiFi)+ LCD + Camera -``` - -**配置摄像头传感器:** - -> **注意:** 确认摄像头传感器型号,确定型号在 esp_cam_sensor 支持的范围内。当前板子用的是 OV2640,是符合支持范围。 - -在 menuconfig 中按以下步骤启用对应型号的支持: - -1. **导航到传感器配置:** - ``` - (Top) → Component config → Espressif Camera Sensors Configurations → Camera Sensor Configuration → Select and Set Camera Sensor - ``` - -2. **选择传感器型号:** - - 选中所需的传感器型号(OV2640) - -3. **配置传感器参数:** - - 按 → 进入传感器详细设置 - - 启用 **Auto detect** - - 推荐将 **default output format** 调整为 **YUV422** 及合适的分辨率大小 - - (目前支持 YUV422、RGB565,YUV422 更节省内存空间) - -**编译烧入:** - -```bash -idf.py build flash -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/compact_wifi_board_s3cam.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/compact_wifi_board_s3cam.cc deleted file mode 100644 index 98b76f47..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/compact_wifi_board_s3cam.cc +++ /dev/null @@ -1,229 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "esp32_camera.h" - -#include -#include -#include -#include -#include -#include - -#if defined(LCD_TYPE_ILI9341_SERIAL) -#include "esp_lcd_ili9341.h" -#endif - -#if defined(LCD_TYPE_GC9A01_SERIAL) -#include "esp_lcd_gc9a01.h" -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; -#endif - -#define TAG "CompactWifiBoardS3Cam" - -class CompactWifiBoardS3Cam : public WifiBoard { -private: - - Button boot_button_; - LcdDisplay* display_; - Esp32Camera* camera_; - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; -#if defined(LCD_TYPE_ILI9341_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); -#elif defined(LCD_TYPE_GC9A01_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel)); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; -#else - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); -#endif - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); -#ifdef LCD_TYPE_GC9A01_SERIAL - panel_config.vendor_config = &gc9107_vendor_config; -#endif - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = true, - .i2c_config = { - .port = 0, - .scl_pin = CAMERA_PIN_SIOC, - .sda_pin = CAMERA_PIN_SIOD, - }, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetHMirror(false); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - CompactWifiBoardS3Cam() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeCamera(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(CompactWifiBoardS3Cam); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/config.h deleted file mode 100644 index 857d8c08..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi-s3cam/config.h +++ /dev/null @@ -1,308 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_1 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_2 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_42 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_39 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_40 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_41 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -//Camera Config -#define CAMERA_PIN_D0 GPIO_NUM_11 -#define CAMERA_PIN_D1 GPIO_NUM_9 -#define CAMERA_PIN_D2 GPIO_NUM_8 -#define CAMERA_PIN_D3 GPIO_NUM_10 -#define CAMERA_PIN_D4 GPIO_NUM_12 -#define CAMERA_PIN_D5 GPIO_NUM_18 -#define CAMERA_PIN_D6 GPIO_NUM_17 -#define CAMERA_PIN_D7 GPIO_NUM_16 -#define CAMERA_PIN_XCLK GPIO_NUM_15 -#define CAMERA_PIN_PCLK GPIO_NUM_13 -#define CAMERA_PIN_VSYNC GPIO_NUM_6 -#define CAMERA_PIN_HREF GPIO_NUM_7 -#define CAMERA_PIN_SIOC GPIO_NUM_5 -#define CAMERA_PIN_SIOD GPIO_NUM_4 -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define XCLK_FREQ_HZ 20000000 - - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_38 -#define DISPLAY_MOSI_PIN GPIO_NUM_20 -#define DISPLAY_CLK_PIN GPIO_NUM_19 -#define DISPLAY_DC_PIN GPIO_NUM_47 -#define DISPLAY_RST_PIN GPIO_NUM_21 -#define DISPLAY_CS_PIN GPIO_NUM_45 - - -#ifdef CONFIG_LCD_ST7789_240X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X320_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_170X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 170 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 35 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_172X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 172 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 34 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X280 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240_7PIN -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 3 -#endif - -#ifdef CONFIG_LCD_ST7789_240X135 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 135 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 40 -#define DISPLAY_OFFSET_Y 53 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X160 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X128 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 32 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320 -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320_NO_IPS -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_GC9A01_240X240 -#define LCD_TYPE_GC9A01_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_CUSTOM -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_14 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/compact_wifi_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/compact_wifi_board.cc deleted file mode 100644 index 04d71910..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/compact_wifi_board.cc +++ /dev/null @@ -1,188 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/oled_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include - -#ifdef SH1106 -#include -#endif - -#define TAG "CompactWifiBoard" - -class CompactWifiBoard : public WifiBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - Button touch_button_; - Button volume_up_button_; - Button volume_down_button_; - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - -#ifdef SH1106 - ESP_ERROR_CHECK(esp_lcd_new_panel_sh1106(panel_io_, &panel_config, &panel_)); -#else - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); -#endif - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, false)); - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - touch_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - touch_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - volume_up_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - // 物联网初始化,逐步迁移到 MCP 协议 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - CompactWifiBoard() : - boot_button_(BOOT_BUTTON_GPIO), - touch_button_(TOUCH_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(CompactWifiBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.h deleted file mode 100644 index 7bb0982b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_47 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA_PIN GPIO_NUM_41 -#define DISPLAY_SCL_PIN GPIO_NUM_42 -#define DISPLAY_WIDTH 128 - -#if CONFIG_OLED_SSD1306_128X32 -#define DISPLAY_HEIGHT 32 -#elif CONFIG_OLED_SSD1306_128X64 -#define DISPLAY_HEIGHT 64 -#elif CONFIG_OLED_SH1106_128X64 -#define DISPLAY_HEIGHT 64 -#define SH1106 -#else -#error "未选择 OLED 屏幕类型" -#endif - -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_18 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.json deleted file mode 100644 index ea296f9a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/bread-compact-wifi/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "bread-compact-wifi", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X32=y" - ] - }, - { - "name": "bread-compact-wifi-128x64", - "sdkconfig_append": [ - "CONFIG_OLED_SSD1306_128X64=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.cc deleted file mode 100644 index c34da68c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.cc +++ /dev/null @@ -1,116 +0,0 @@ -#include "adc_battery_monitor.h" - -AdcBatteryMonitor::AdcBatteryMonitor(adc_unit_t adc_unit, adc_channel_t adc_channel, float upper_resistor, float lower_resistor, gpio_num_t charging_pin) - : charging_pin_(charging_pin) { - - // Initialize charging pin (only if it's not NC) - if (charging_pin_ != GPIO_NUM_NC) { - gpio_config_t gpio_cfg = { - .pin_bit_mask = 1ULL << charging_pin, - .mode = GPIO_MODE_INPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&gpio_cfg)); - } - - // Initialize ADC battery estimation - adc_battery_estimation_t adc_cfg = { - .internal = { - .adc_unit = adc_unit, - .adc_bitwidth = ADC_BITWIDTH_DEFAULT, - .adc_atten = ADC_ATTEN_DB_12, - }, - .adc_channel = adc_channel, - .upper_resistor = upper_resistor, - .lower_resistor = lower_resistor - }; - - // 在ADC配置部分进行条件设置 - if (charging_pin_ != GPIO_NUM_NC) { - adc_cfg.charging_detect_cb = [](void *user_data) -> bool { - AdcBatteryMonitor *self = (AdcBatteryMonitor *)user_data; - return gpio_get_level(self->charging_pin_) == 1; - }; - adc_cfg.charging_detect_user_data = this; - } else { - // 不设置回调,让adc_battery_estimation库使用软件估算 - adc_cfg.charging_detect_cb = nullptr; - adc_cfg.charging_detect_user_data = nullptr; - } - adc_battery_estimation_handle_ = adc_battery_estimation_create(&adc_cfg); - - // Initialize timer - esp_timer_create_args_t timer_cfg = { - .callback = [](void *arg) { - AdcBatteryMonitor *self = (AdcBatteryMonitor *)arg; - self->CheckBatteryStatus(); - }, - .arg = this, - .name = "adc_battery_monitor", - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_cfg, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); -} - -AdcBatteryMonitor::~AdcBatteryMonitor() { - if (adc_battery_estimation_handle_) { - ESP_ERROR_CHECK(adc_battery_estimation_destroy(adc_battery_estimation_handle_)); - } - - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } -} - -bool AdcBatteryMonitor::IsCharging() { - // 优先使用adc_battery_estimation库的功能 - if (adc_battery_estimation_handle_ != nullptr) { - bool is_charging = false; - esp_err_t err = adc_battery_estimation_get_charging_state(adc_battery_estimation_handle_, &is_charging); - if (err == ESP_OK) { - return is_charging; - } - } - - // 回退到GPIO读取或返回默认值 - if (charging_pin_ != GPIO_NUM_NC) { - return gpio_get_level(charging_pin_) == 1; - } - - return false; -} - -bool AdcBatteryMonitor::IsDischarging() { - return !IsCharging(); -} - -uint8_t AdcBatteryMonitor::GetBatteryLevel() { - // 如果句柄无效,返回默认值 - if (adc_battery_estimation_handle_ == nullptr) { - return 100; - } - - float capacity = 0; - esp_err_t err = adc_battery_estimation_get_capacity(adc_battery_estimation_handle_, &capacity); - if (err != ESP_OK) { - return 100; // 出错时返回默认值 - } - return (uint8_t)capacity; -} - -void AdcBatteryMonitor::OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; -} - -void AdcBatteryMonitor::CheckBatteryStatus() { - bool new_charging_status = IsCharging(); - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.h deleted file mode 100644 index 6a123a7d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/adc_battery_monitor.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ADC_BATTERY_MONITOR_H -#define ADC_BATTERY_MONITOR_H - -#include -#include -#include -#include - -class AdcBatteryMonitor { -public: - AdcBatteryMonitor(adc_unit_t adc_unit, adc_channel_t adc_channel, float upper_resistor, float lower_resistor, gpio_num_t charging_pin = GPIO_NUM_NC); - ~AdcBatteryMonitor(); - - bool IsCharging(); - bool IsDischarging(); - uint8_t GetBatteryLevel(); - - void OnChargingStatusChanged(std::function callback); - -private: - gpio_num_t charging_pin_; - adc_battery_estimation_handle_t adc_battery_estimation_handle_ = nullptr; - esp_timer_handle_t timer_handle_ = nullptr; - bool is_charging_ = false; - std::function on_charging_status_changed_; - - void CheckBatteryStatus(); -}; - -#endif // ADC_BATTERY_MONITOR_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.cc deleted file mode 100644 index 0fe41ea7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.cc +++ /dev/null @@ -1,375 +0,0 @@ -#include "afsk_demod.h" -#include -#include -#include "esp_log.h" -#include "display.h" -#include "ssid_manager.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -namespace audio_wifi_config -{ - static const char *kLogTag = "AUDIO_WIFI_CONFIG"; - - void ReceiveWifiCredentialsFromAudio(Application *app, - WifiManager *wifi_manager, - Display *display, - size_t input_channels - ) - { - const int kInputSampleRate = 16000; // Input sampling rate - const float kDownsampleStep = static_cast(kInputSampleRate) / static_cast(kAudioSampleRate); // Downsampling step - std::vector audio_data; - AudioSignalProcessor signal_processor(kAudioSampleRate, kMarkFrequency, kSpaceFrequency, kBitRate, kWindowSize); - AudioDataBuffer data_buffer; - - while (true) - { - // 检查Application状态,只有在WiFi配置模式下才处理音频 - if (app->GetDeviceState() != kDeviceStateWifiConfiguring) { - // 不在WiFi配置状态,休眠100ms后再检查 - vTaskDelay(pdMS_TO_TICKS(100)); - continue; - } - - if (!app->GetAudioService().ReadAudioData(audio_data, 16000, 480)) { // 16kHz, 480 samples corresponds to 30ms data - // 读取音频失败,短暂延迟后重试 - ESP_LOGI(kLogTag, "Failed to read audio data, retrying."); - vTaskDelay(pdMS_TO_TICKS(10)); - continue; - } - - if (input_channels == 2) { // 如果是双声道输入,转换为单声道 - auto mono_data = std::vector(audio_data.size() / 2); - for (size_t i = 0, j = 0; i < mono_data.size(); ++i, j += 2) { - mono_data[i] = audio_data[j]; - } - audio_data = std::move(mono_data); - } - - // Downsample the audio data - std::vector downsampled_data; - size_t last_index = 0; - - if (kDownsampleStep > 1.0f) { - downsampled_data.reserve(audio_data.size() / static_cast(kDownsampleStep)); - for (size_t i = 0; i < audio_data.size(); ++i) { - size_t sample_index = static_cast(i / kDownsampleStep); - if ((sample_index + 1) > last_index) { - downsampled_data.push_back(static_cast(audio_data[i])); - last_index = sample_index + 1; - } - } - } else { - downsampled_data.reserve(audio_data.size()); - for (int16_t sample : audio_data) { - downsampled_data.push_back(static_cast(sample)); - } - } - - // Process audio samples to get probability data - auto probabilities = signal_processor.ProcessAudioSamples(downsampled_data); - - // Feed probability data to the data buffer - if (data_buffer.ProcessProbabilityData(probabilities, 0.5f)) { - // If complete data was received, extract WiFi credentials - if (data_buffer.decoded_text.has_value()) { - ESP_LOGI(kLogTag, "Received text data: %s", data_buffer.decoded_text->c_str()); - display->SetChatMessage("system", data_buffer.decoded_text->c_str()); - - // Split SSID and password by newline character - std::string wifi_ssid, wifi_password; - size_t newline_position = data_buffer.decoded_text->find('\n'); - if (newline_position != std::string::npos) { - wifi_ssid = data_buffer.decoded_text->substr(0, newline_position); - wifi_password = data_buffer.decoded_text->substr(newline_position + 1); - ESP_LOGI(kLogTag, "WiFi SSID: %s, Password: %s", wifi_ssid.c_str(), wifi_password.c_str()); - } else { - ESP_LOGE(kLogTag, "Invalid data format, no newline character found"); - continue; - } - - // Save WiFi credentials using SsidManager - auto& ssid_manager = SsidManager::GetInstance(); - ssid_manager.AddSsid(wifi_ssid, wifi_password); - ESP_LOGI(kLogTag, "WiFi credentials saved successfully"); - - // Exit config mode (triggers ConfigModeExit event) - wifi_manager->StopConfigAp(); - - data_buffer.decoded_text.reset(); // Clear processed data - return; // Exit the function - } - } - vTaskDelay(pdMS_TO_TICKS(1)); // 1ms delay - } - } - - // Default start and end transmission identifiers - // \x01\x02 = 00000001 00000010 - const std::vector kDefaultStartTransmissionPattern = { - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0}; - - // \x03\x04 = 00000011 00000100 - const std::vector kDefaultEndTransmissionPattern = { - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0}; - - // FrequencyDetector implementation - FrequencyDetector::FrequencyDetector(float frequency, size_t window_size) - : frequency_(frequency), window_size_(window_size) { - frequency_bin_ = std::floor(frequency_ * static_cast(window_size_)); - angular_frequency_ = 2.0f * M_PI * frequency_; - cos_coefficient_ = std::cos(angular_frequency_); - sin_coefficient_ = std::sin(angular_frequency_); - filter_coefficient_ = 2.0f * cos_coefficient_; - - // Initialize state buffer - state_buffer_.push_back(0.0f); - state_buffer_.push_back(0.0f); - } - - void FrequencyDetector::Reset() { - state_buffer_.clear(); - state_buffer_.push_back(0.0f); - state_buffer_.push_back(0.0f); - } - - void FrequencyDetector::ProcessSample(float sample) { - if (state_buffer_.size() < 2) { - return; - } - - float s_minus_2 = state_buffer_.front(); // S[-2] - state_buffer_.pop_front(); - float s_minus_1 = state_buffer_.front(); // S[-1] - state_buffer_.pop_front(); - - float s_current = sample + filter_coefficient_ * s_minus_1 - s_minus_2; - - state_buffer_.push_back(s_minus_1); // Put S[-1] back - state_buffer_.push_back(s_current); // Add new S[0] - } - - float FrequencyDetector::GetAmplitude() const { - if (state_buffer_.size() < 2) { - return 0.0f; - } - - float s_minus_1 = state_buffer_[1]; // S[-1] - float s_minus_2 = state_buffer_[0]; // S[-2] - float real_part = cos_coefficient_ * s_minus_1 - s_minus_2; // Real part - float imaginary_part = sin_coefficient_ * s_minus_1; // Imaginary part - - return std::sqrt(real_part * real_part + imaginary_part * imaginary_part) / - (static_cast(window_size_) / 2.0f); - } - - // AudioSignalProcessor implementation - AudioSignalProcessor::AudioSignalProcessor(size_t sample_rate, size_t mark_frequency, size_t space_frequency, - size_t bit_rate, size_t window_size) - : input_buffer_size_(window_size), output_sample_count_(0) { - if (sample_rate % bit_rate != 0) { - // On ESP32 we can continue execution, but log the error - ESP_LOGW(kLogTag, "Sample rate %zu is not divisible by bit rate %zu", sample_rate, bit_rate); - } - - float normalized_mark_freq = static_cast(mark_frequency) / static_cast(sample_rate); - float normalized_space_freq = static_cast(space_frequency) / static_cast(sample_rate); - - mark_detector_ = std::make_unique(normalized_mark_freq, window_size); - space_detector_ = std::make_unique(normalized_space_freq, window_size); - - samples_per_bit_ = sample_rate / bit_rate; // Number of samples per bit - } - - std::vector AudioSignalProcessor::ProcessAudioSamples(const std::vector &samples) { - std::vector result; - - for (float sample : samples) { - if (input_buffer_.size() < input_buffer_size_) { - input_buffer_.push_back(sample); // Just add, don't process yet - } else { - // Input buffer is full, process the data - input_buffer_.pop_front(); // Remove oldest sample - input_buffer_.push_back(sample); // Add new sample - output_sample_count_++; - - if (output_sample_count_ >= samples_per_bit_) { - // Process all samples in the window using Goertzel algorithm - for (float window_sample : input_buffer_) { - mark_detector_->ProcessSample(window_sample); - space_detector_->ProcessSample(window_sample); - } - - float mark_amplitude = mark_detector_->GetAmplitude(); // Mark amplitude - float space_amplitude = space_detector_->GetAmplitude(); // Space amplitude - - // Avoid division by zero - float mark_probability = mark_amplitude / - (space_amplitude + mark_amplitude + std::numeric_limits::epsilon()); - result.push_back(mark_probability); - - // Reset detector windows - mark_detector_->Reset(); - space_detector_->Reset(); - output_sample_count_ = 0; // Reset output counter - } - } - } - - return result; - } - - // AudioDataBuffer implementation - AudioDataBuffer::AudioDataBuffer() - : current_state_(DataReceptionState::kInactive), - start_of_transmission_(kDefaultStartTransmissionPattern), - end_of_transmission_(kDefaultEndTransmissionPattern), - enable_checksum_validation_(true) { - identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size()); - max_bit_buffer_size_ = 776; // Preset bit buffer size, 776 bits = (32 + 1 + 63 + 1) * 8 = 776 - - bit_buffer_.reserve(max_bit_buffer_size_); - } - - AudioDataBuffer::AudioDataBuffer(size_t max_byte_size, const std::vector &start_identifier, - const std::vector &end_identifier, bool enable_checksum) - : current_state_(DataReceptionState::kInactive), - start_of_transmission_(start_identifier), - end_of_transmission_(end_identifier), - enable_checksum_validation_(enable_checksum) { - identifier_buffer_size_ = std::max(start_of_transmission_.size(), end_of_transmission_.size()); - max_bit_buffer_size_ = max_byte_size * 8; // Bit buffer size in bytes - - bit_buffer_.reserve(max_bit_buffer_size_); - } - - uint8_t AudioDataBuffer::CalculateChecksum(const std::string &text) { - uint8_t checksum = 0; - for (char character : text) { - checksum += static_cast(character); - } - return checksum; - } - - void AudioDataBuffer::ClearBuffers() { - identifier_buffer_.clear(); - bit_buffer_.clear(); - } - - bool AudioDataBuffer::ProcessProbabilityData(const std::vector &probabilities, float threshold) { - for (float probability : probabilities) { - uint8_t bit = (probability > threshold) ? 1 : 0; - - if (identifier_buffer_.size() >= identifier_buffer_size_) { - identifier_buffer_.pop_front(); // Maintain buffer size - } - identifier_buffer_.push_back(bit); - - // Process received bit based on state machine - switch (current_state_) { - case DataReceptionState::kInactive: - if (identifier_buffer_.size() >= start_of_transmission_.size()) { - current_state_ = DataReceptionState::kWaiting; // Enter waiting state - ESP_LOGI(kLogTag, "Entering Waiting state"); - } - break; - - case DataReceptionState::kWaiting: - // Waiting state, possibly waiting for transmission end - if (identifier_buffer_.size() >= start_of_transmission_.size()) { - std::vector identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end()); - if (identifier_snapshot == start_of_transmission_) - { - ClearBuffers(); // Clear buffers - current_state_ = DataReceptionState::kReceiving; // Enter receiving state - ESP_LOGI(kLogTag, "Entering Receiving state"); - } - } - break; - - case DataReceptionState::kReceiving: - bit_buffer_.push_back(bit); - if (identifier_buffer_.size() >= end_of_transmission_.size()) { - std::vector identifier_snapshot(identifier_buffer_.begin(), identifier_buffer_.end()); - if (identifier_snapshot == end_of_transmission_) { - current_state_ = DataReceptionState::kInactive; // Enter inactive state - - // Convert bits to bytes - std::vector bytes = ConvertBitsToBytes(bit_buffer_); - - uint8_t received_checksum = 0; - size_t minimum_length = 0; - - if (enable_checksum_validation_) { - // If checksum is required, last byte is checksum - minimum_length = 1 + start_of_transmission_.size() / 8; - if (bytes.size() >= minimum_length) - { - received_checksum = bytes[bytes.size() - start_of_transmission_.size() / 8 - 1]; - } - } else { - minimum_length = start_of_transmission_.size() / 8; - } - - if (bytes.size() < minimum_length) { - ClearBuffers(); - ESP_LOGW(kLogTag, "Data too short, clearing buffer"); - return false; // Data too short, return failure - } - - // Extract text data (remove trailing identifier part) - std::vector text_bytes( - bytes.begin(), bytes.begin() + bytes.size() - minimum_length); - - std::string result(text_bytes.begin(), text_bytes.end()); - - // Validate checksum if required - if (enable_checksum_validation_) { - uint8_t calculated_checksum = CalculateChecksum(result); - if (calculated_checksum != received_checksum) { - // Checksum mismatch - ESP_LOGW(kLogTag, "Checksum mismatch: expected %d, got %d", - received_checksum, calculated_checksum); - ClearBuffers(); - return false; - } - } - - ClearBuffers(); - decoded_text = result; - return true; // Return success - } else if (bit_buffer_.size() >= max_bit_buffer_size_) { - // If not end identifier and bit buffer is full, reset - ClearBuffers(); - ESP_LOGW(kLogTag, "Buffer overflow, clearing buffer"); - current_state_ = DataReceptionState::kInactive; // Reset state machine - } - } - break; - } - } - - return false; - } - - std::vector AudioDataBuffer::ConvertBitsToBytes(const std::vector &bits) const { - std::vector bytes; - - // Ensure number of bits is a multiple of 8 - size_t complete_bytes_count = bits.size() / 8; - bytes.reserve(complete_bytes_count); - - for (size_t i = 0; i < complete_bytes_count; ++i) { - uint8_t byte_value = 0; - for (size_t j = 0; j < 8; ++j) { - byte_value |= bits[i * 8 + j] << (7 - j); - } - bytes.push_back(byte_value); - } - - return bytes; - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.h deleted file mode 100644 index 4ac0ab6d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/afsk_demod.h +++ /dev/null @@ -1,177 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "wifi_manager.h" -#include "application.h" - -// Audio signal processing constants for WiFi configuration via audio -const size_t kAudioSampleRate = 6400; -const size_t kMarkFrequency = 1800; -const size_t kSpaceFrequency = 1500; -const size_t kBitRate = 100; -const size_t kWindowSize = 64; - -namespace audio_wifi_config -{ - // Main function to receive WiFi credentials through audio signal - void ReceiveWifiCredentialsFromAudio(Application *app, WifiManager *wifi_manager, Display *display, - size_t input_channels = 1); - - /** - * Goertzel algorithm implementation for single frequency detection - * Used to detect specific audio frequencies in the AFSK demodulation process - */ - class FrequencyDetector - { - private: - float frequency_; // Target frequency (normalized, i.e., f / fs) - size_t window_size_; // Window size for analysis - float frequency_bin_; // Frequency bin - float angular_frequency_; // Angular frequency - float cos_coefficient_; // cos(w) - float sin_coefficient_; // sin(w) - float filter_coefficient_; // 2 * cos(w) - std::deque state_buffer_; // Circular buffer for storing S[-1] and S[-2] - - public: - /** - * Constructor - * @param frequency Normalized frequency (f / fs) - * @param window_size Window size for analysis - */ - FrequencyDetector(float frequency, size_t window_size); - - /** - * Reset the detector state - */ - void Reset(); - - /** - * Process one audio sample - * @param sample Input audio sample - */ - void ProcessSample(float sample); - - /** - * Calculate current amplitude - * @return Amplitude value - */ - float GetAmplitude() const; - }; - - /** - * Audio signal processor for Mark/Space frequency pair detection - * Processes audio signals to extract digital data using AFSK demodulation - */ - class AudioSignalProcessor - { - private: - std::deque input_buffer_; // Input sample buffer - size_t input_buffer_size_; // Input buffer size = window size - size_t output_sample_count_; // Output sample counter - size_t samples_per_bit_; // Samples per bit threshold - std::unique_ptr mark_detector_; // Mark frequency detector - std::unique_ptr space_detector_; // Space frequency detector - - public: - /** - * Constructor - * @param sample_rate Audio sampling rate - * @param mark_frequency Mark frequency for digital '1' - * @param space_frequency Space frequency for digital '0' - * @param bit_rate Data transmission bit rate - * @param window_size Analysis window size - */ - AudioSignalProcessor(size_t sample_rate, size_t mark_frequency, size_t space_frequency, - size_t bit_rate, size_t window_size); - - /** - * Process input audio samples - * @param samples Input audio sample vector - * @return Vector of Mark probability values (0.0 to 1.0) - */ - std::vector ProcessAudioSamples(const std::vector &samples); - }; - - /** - * Data reception state machine states - */ - enum class DataReceptionState - { - kInactive, // Waiting for start signal - kWaiting, // Detected potential start, waiting for confirmation - kReceiving // Actively receiving data - }; - - /** - * Data buffer for managing audio-to-digital data conversion - * Handles the complete process from audio signal to decoded text data - */ - class AudioDataBuffer - { - private: - DataReceptionState current_state_; // Current reception state - std::deque identifier_buffer_; // Buffer for start/end identifier detection - size_t identifier_buffer_size_; // Identifier buffer size - std::vector bit_buffer_; // Buffer for storing bit stream - size_t max_bit_buffer_size_; // Maximum bit buffer size - const std::vector start_of_transmission_; // Start-of-transmission identifier - const std::vector end_of_transmission_; // End-of-transmission identifier - bool enable_checksum_validation_; // Whether to validate checksum - - public: - std::optional decoded_text; // Successfully decoded text data - - /** - * Default constructor using predefined start and end identifiers - */ - AudioDataBuffer(); - - /** - * Constructor with custom parameters - * @param max_byte_size Expected maximum data size in bytes - * @param start_identifier Start-of-transmission identifier - * @param end_identifier End-of-transmission identifier - * @param enable_checksum Whether to enable checksum validation - */ - AudioDataBuffer(size_t max_byte_size, const std::vector &start_identifier, - const std::vector &end_identifier, bool enable_checksum = false); - - /** - * Process probability data and attempt to decode - * @param probabilities Vector of Mark probabilities - * @param threshold Decision threshold for bit detection - * @return true if complete data was successfully received and decoded - */ - bool ProcessProbabilityData(const std::vector &probabilities, float threshold = 0.5f); - - /** - * Calculate checksum for ASCII text - * @param text Input text string - * @return Checksum value (0-255) - */ - static uint8_t CalculateChecksum(const std::string &text); - - private: - /** - * Convert bit vector to byte vector - * @param bits Input bit vector - * @return Converted byte vector - */ - std::vector ConvertBitsToBytes(const std::vector &bits) const; - - /** - * Clear all buffers and reset state - */ - void ClearBuffers(); - }; - - // Default start and end transmission identifiers - extern const std::vector kDefaultStartTransmissionPattern; - extern const std::vector kDefaultEndTransmissionPattern; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.cc deleted file mode 100644 index 854f0b83..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.cc +++ /dev/null @@ -1,41 +0,0 @@ -#include "axp2101.h" -#include "board.h" -#include "display.h" - -#include - -#define TAG "Axp2101" - -Axp2101::Axp2101(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { -} - -int Axp2101::GetBatteryCurrentDirection() { - return (ReadReg(0x01) & 0b01100000) >> 5; -} - -bool Axp2101::IsCharging() { - return GetBatteryCurrentDirection() == 1; -} - -bool Axp2101::IsDischarging() { - return GetBatteryCurrentDirection() == 2; -} - -bool Axp2101::IsChargingDone() { - uint8_t value = ReadReg(0x01); - return (value & 0b00000111) == 0b00000100; -} - -int Axp2101::GetBatteryLevel() { - return ReadReg(0xA4); -} - -float Axp2101::GetTemperature() { - return ReadReg(0xA5); -} - -void Axp2101::PowerOff() { - uint8_t value = ReadReg(0x10); - value = value | 0x01; - WriteReg(0x10, value); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.h deleted file mode 100644 index 473cd3e1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/axp2101.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __AXP2101_H__ -#define __AXP2101_H__ - -#include "i2c_device.h" - -class Axp2101 : public I2cDevice { -public: - Axp2101(i2c_master_bus_handle_t i2c_bus, uint8_t addr); - bool IsCharging(); - bool IsDischarging(); - bool IsChargingDone(); - int GetBatteryLevel(); - float GetTemperature(); - void PowerOff(); - -private: - int GetBatteryCurrentDirection(); -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.cc deleted file mode 100644 index c62fd7ac..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.cc +++ /dev/null @@ -1,121 +0,0 @@ -#include "backlight.h" -#include "settings.h" - -#include -#include - -#define TAG "Backlight" - - -Backlight::Backlight() { - // 创建背光渐变定时器 - const esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - auto self = static_cast(arg); - self->OnTransitionTimer(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "backlight_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &transition_timer_)); -} - -Backlight::~Backlight() { - if (transition_timer_ != nullptr) { - esp_timer_stop(transition_timer_); - esp_timer_delete(transition_timer_); - } -} - -void Backlight::RestoreBrightness() { - // Load brightness from settings - Settings settings("display"); - int saved_brightness = settings.GetInt("brightness", 75); - - // 检查亮度值是否为0或过小,设置默认值 - if (saved_brightness <= 0) { - ESP_LOGW(TAG, "Brightness value (%d) is too small, setting to default (10)", saved_brightness); - saved_brightness = 10; // 设置一个较低的默认值 - } - - SetBrightness(saved_brightness); -} - -void Backlight::SetBrightness(uint8_t brightness, bool permanent) { - if (brightness > 100) { - brightness = 100; - } - - if (brightness_ == brightness) { - return; - } - - if (permanent) { - Settings settings("display", true); - settings.SetInt("brightness", brightness); - } - - target_brightness_ = brightness; - step_ = (target_brightness_ > brightness_) ? 1 : -1; - - if (transition_timer_ != nullptr) { - // 启动定时器,每 5ms 更新一次 - esp_timer_start_periodic(transition_timer_, 5 * 1000); - } - ESP_LOGI(TAG, "Set brightness to %d", brightness); -} - -void Backlight::OnTransitionTimer() { - if (brightness_ == target_brightness_) { - esp_timer_stop(transition_timer_); - return; - } - - brightness_ += step_; - SetBrightnessImpl(brightness_); - - if (brightness_ == target_brightness_) { - esp_timer_stop(transition_timer_); - } -} - -PwmBacklight::PwmBacklight(gpio_num_t pin, bool output_invert, uint32_t freq_hz) : Backlight() { - const ledc_timer_config_t backlight_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_10_BIT, - .timer_num = LEDC_TIMER_0, - .freq_hz = freq_hz, //背光pwm频率需要高一点,防止电感啸叫 - .clk_cfg = LEDC_AUTO_CLK, - .deconfigure = false - }; - ESP_ERROR_CHECK(ledc_timer_config(&backlight_timer)); - - // Setup LEDC peripheral for PWM backlight control - const ledc_channel_config_t backlight_channel = { - .gpio_num = pin, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = LEDC_CHANNEL_0, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_0, - .duty = 0, - .hpoint = 0, - .flags = { - .output_invert = output_invert, - } - }; - ESP_ERROR_CHECK(ledc_channel_config(&backlight_channel)); -} - -PwmBacklight::~PwmBacklight() { - ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 0); -} - -void PwmBacklight::SetBrightnessImpl(uint8_t brightness) { - // LEDC resolution set to 10bits, thus: 100% = 1023 - uint32_t duty_cycle = (1023 * brightness) / 100; - ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty_cycle); - ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.h deleted file mode 100644 index 5c09b3d2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/backlight.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include - -#include -#include - - -class Backlight { -public: - Backlight(); - ~Backlight(); - - void RestoreBrightness(); - void SetBrightness(uint8_t brightness, bool permanent = false); - inline uint8_t brightness() const { return brightness_; } - -protected: - void OnTransitionTimer(); - virtual void SetBrightnessImpl(uint8_t brightness) = 0; - - esp_timer_handle_t transition_timer_ = nullptr; - uint8_t brightness_ = 0; - uint8_t target_brightness_ = 0; - uint8_t step_ = 1; -}; - - -class PwmBacklight : public Backlight { -public: - PwmBacklight(gpio_num_t pin, bool output_invert = false, uint32_t freq_hz = 25000); - ~PwmBacklight(); - - void SetBrightnessImpl(uint8_t brightness) override; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.cpp b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.cpp deleted file mode 100644 index ccfce118..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.cpp +++ /dev/null @@ -1,777 +0,0 @@ -#include "blufi.h" -#include -#include -#include -#include - -#include "application.h" -#include "esp_bt.h" -#include "esp_log.h" -#include "esp_mac.h" -#include "esp_system.h" -#include "esp_wifi.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "wifi_manager.h" - -// Bluedroid specific -#ifdef CONFIG_BT_BLUEDROID_ENABLED -#include "esp_bt_device.h" -#include "esp_bt_main.h" -#include "esp_gap_ble_api.h" -#endif - -// NimBLE specific -#ifdef CONFIG_BT_NIMBLE_ENABLED -#include "console/console.h" -#include "host/ble_hs.h" -#include "nimble/nimble_port.h" -#include "nimble/nimble_port_freertos.h" -#include "services/gap/ble_svc_gap.h" -extern void esp_blufi_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); -extern int esp_blufi_gatt_svr_init(void); -extern void esp_blufi_gatt_svr_deinit(void); -extern void esp_blufi_btc_init(void); -extern void esp_blufi_btc_deinit(void); -#endif - -extern "C" { -// Blufi Advertising & Connection -void esp_blufi_adv_start(void); - -void esp_blufi_adv_stop(void); - -void esp_blufi_disconnect(void); - -// Internal BTC layer functions needed for error reporting -void btc_blufi_report_error(esp_blufi_error_state_t state); - -// Bluedroid specific GAP event handler -#ifdef CONFIG_BT_BLUEDROID_ENABLED -void esp_blufi_gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param); -#endif - -// NimBLE specific internal functions -#ifdef CONFIG_BT_NIMBLE_ENABLED -void esp_blufi_gatt_svr_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg); -int esp_blufi_gatt_svr_init(void); -void esp_blufi_gatt_svr_deinit(void); -void esp_blufi_btc_init(void); -void esp_blufi_btc_deinit(void); -#endif -} - -// mbedTLS for security -#include -#include "esp_crc.h" -#include "esp_random.h" -#include "mbedtls/md5.h" -#include "ssid_manager.h" - -// Logging Tag -static const char *BLUFI_TAG = "BLUFI_CLASS"; - -static wifi_mode_t GetWifiModeWithFallback(const WifiManager &wifi) { - if (wifi.IsConfigMode()) { - return WIFI_MODE_AP; - } - if (wifi.IsInitialized() && wifi.IsConnected()) { - return WIFI_MODE_STA; - } - - wifi_mode_t mode = WIFI_MODE_STA; - esp_wifi_get_mode(&mode); - return mode; -} - -Blufi &Blufi::GetInstance() { - static Blufi instance; - return instance; -} - -Blufi::Blufi() - : m_sec(nullptr), - m_ble_is_connected(false), - m_sta_connected(false), - m_sta_got_ip(false), - m_provisioned(false), - m_deinited(false), - m_sta_ssid_len(0), - m_sta_is_connecting(false) { - // Initialize member variables - memset(&m_sta_config, 0, sizeof(m_sta_config)); - memset(&m_ap_config, 0, sizeof(m_ap_config)); - memset(m_sta_bssid, 0, sizeof(m_sta_bssid)); - memset(m_sta_ssid, 0, sizeof(m_sta_ssid)); - memset(&m_sta_conn_info, 0, sizeof(m_sta_conn_info)); -} - -Blufi::~Blufi() { - if (m_sec) { - _security_deinit(); - } -} - -esp_err_t Blufi::init() { - esp_err_t ret; - inited_ = true; - m_provisioned = false; - m_deinited = false; - -#if CONFIG_BT_CONTROLLER_ENABLED || !CONFIG_BT_NIMBLE_ENABLED - ret = _controller_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "BLUFI controller init failed: %s", esp_err_to_name(ret)); - return ret; - } -#endif - - ret = _host_and_cb_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "BLUFI host and cb init failed: %s", esp_err_to_name(ret)); - return ret; - } - - ESP_LOGI(BLUFI_TAG, "BLUFI VERSION %04x", esp_blufi_get_version()); - return ESP_OK; -} - -esp_err_t Blufi::deinit() { - esp_err_t ret = ESP_OK; - - if (inited_) { - if (m_deinited) { - return ESP_OK; - } - m_deinited = true; - ret = _host_deinit(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "Host deinit failed: %s", esp_err_to_name(ret)); - } -#if CONFIG_BT_CONTROLLER_ENABLED || !CONFIG_BT_NIMBLE_ENABLED - ret = _controller_deinit(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "Controller deinit failed: %s", esp_err_to_name(ret)); - } -#endif - } - return ret; -} - -#ifdef CONFIG_BT_BLUEDROID_ENABLED -esp_err_t Blufi::_host_init() { - esp_err_t ret = esp_bluedroid_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s init bluedroid failed: %s", __func__, esp_err_to_name(ret)); - return ESP_FAIL; - } - ret = esp_bluedroid_enable(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(ret)); - return ESP_FAIL; - } - ESP_LOGI(BLUFI_TAG, "BD ADDR: " ESP_BD_ADDR_STR, ESP_BD_ADDR_HEX(esp_bt_dev_get_address())); - return ESP_OK; -} - -esp_err_t Blufi::_host_deinit() { - esp_err_t ret = esp_blufi_profile_deinit(); - if (ret != ESP_OK) - return ret; - - ret = esp_bluedroid_disable(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s disable bluedroid failed: %s", __func__, esp_err_to_name(ret)); - return ESP_FAIL; - } - ret = esp_bluedroid_deinit(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s deinit bluedroid failed: %s", __func__, esp_err_to_name(ret)); - return ESP_FAIL; - } - return ESP_OK; -} - -esp_err_t Blufi::_gap_register_callback() { - esp_err_t rc = esp_ble_gap_register_callback(esp_blufi_gap_event_handler); - if (rc) { - return rc; - } - return esp_blufi_profile_init(); -} - -esp_err_t Blufi::_host_and_cb_init() { - static esp_blufi_callbacks_t blufi_callbacks = { - .event_cb = &_event_callback_trampoline, - .negotiate_data_handler = &_negotiate_data_handler_trampoline, - .encrypt_func = &_encrypt_func_trampoline, - .decrypt_func = &_decrypt_func_trampoline, - .checksum_func = &_checksum_func_trampoline, - }; - - esp_err_t ret = _host_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s initialise host failed: %s", __func__, esp_err_to_name(ret)); - return ret; - } - ret = esp_blufi_register_callbacks(&blufi_callbacks); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s blufi register failed, error code = %x", __func__, ret); - return ret; - } - ret = _gap_register_callback(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s gap register failed, error code = %x", __func__, ret); - return ret; - } - return ESP_OK; -} -#endif /* CONFIG_BT_BLUEDROID_ENABLED */ - -#ifdef CONFIG_BT_NIMBLE_ENABLED -// Stubs for NimBLE specific store functionality -void ble_store_config_init(); - -void Blufi::_nimble_on_reset(int reason) { - ESP_LOGE(BLUFI_TAG, "NimBLE Resetting state; reason=%d", reason); -} - -void Blufi::_nimble_on_sync() { - // This is called when the host and controller are synced. - // It's a good place to initialize the Blufi profile. - esp_blufi_profile_init(); -} - -void Blufi::_nimble_host_task(void *param) { - ESP_LOGI(BLUFI_TAG, "BLE Host Task Started"); - nimble_port_run(); // This function will return only when nimble_port_stop() is executed - nimble_port_freertos_deinit(); -} - -esp_err_t Blufi::_host_init() { - // esp_nimble_init() is called by controller_init for NimBLE - ble_hs_cfg.reset_cb = _nimble_on_reset; - ble_hs_cfg.sync_cb = _nimble_on_sync; - ble_hs_cfg.gatts_register_cb = esp_blufi_gatt_svr_register_cb; - - // Security Manager settings (can be customized) - ble_hs_cfg.sm_io_cap = 4; // IO capability: No Input, No Output -#ifdef CONFIG_EXAMPLE_BONDING - ble_hs_cfg.sm_bonding = 1; -#endif - - int rc = esp_blufi_gatt_svr_init(); - assert(rc == 0); - - ble_store_config_init(); // Configure the BLE storage - esp_blufi_btc_init(); - - esp_err_t err = esp_nimble_enable(_nimble_host_task); - if (err) { - ESP_LOGE(BLUFI_TAG, "%s failed: %s", __func__, esp_err_to_name(err)); - return ESP_FAIL; - } - return ESP_OK; -} - -esp_err_t Blufi::_host_deinit(void) { - esp_err_t ret = nimble_port_stop(); - if (ret == ESP_OK) { - esp_nimble_deinit(); - } - esp_blufi_gatt_svr_deinit(); - ret = esp_blufi_profile_deinit(); - esp_blufi_btc_deinit(); - return ret; -} - -esp_err_t Blufi::_gap_register_callback(void) { - return ESP_OK; // For NimBLE, GAP callbacks are handled differently -} - -esp_err_t Blufi::_host_and_cb_init() { - static esp_blufi_callbacks_t blufi_callbacks = { - .event_cb = &_event_callback_trampoline, - .negotiate_data_handler = &_negotiate_data_handler_trampoline, - .encrypt_func = &_encrypt_func_trampoline, - .decrypt_func = &_decrypt_func_trampoline, - .checksum_func = &_checksum_func_trampoline, - }; - - esp_err_t ret = esp_blufi_register_callbacks(&blufi_callbacks); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s blufi register failed, error code = %x", __func__, ret); - return ret; - } - - // Host init must be called after registering callbacks for NimBLE - ret = _host_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s initialise host failed: %s", __func__, esp_err_to_name(ret)); - return ret; - } - return ESP_OK; -} -#endif /* CONFIG_BT_NIMBLE_ENABLED */ - -#if CONFIG_BT_CONTROLLER_ENABLED || !CONFIG_BT_NIMBLE_ENABLED -esp_err_t Blufi::_controller_init() { - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - esp_err_t ret = esp_bt_controller_init(&bt_cfg); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret)); - return ret; - } - ret = esp_bt_controller_enable(ESP_BT_MODE_BLE); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret)); - return ret; - } - -#ifdef CONFIG_BT_NIMBLE_ENABLED - // For NimBLE, host init needs to be done after controller init - ret = esp_nimble_init(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "esp_nimble_init() failed: %s", esp_err_to_name(ret)); - return ret; - } -#endif - return ESP_OK; -} - -esp_err_t Blufi::_controller_deinit() { - esp_err_t ret = esp_bt_controller_disable(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s disable controller failed: %s", __func__, esp_err_to_name(ret)); - } - ret = esp_bt_controller_deinit(); - if (ret) { - ESP_LOGE(BLUFI_TAG, "%s deinit controller failed: %s", __func__, esp_err_to_name(ret)); - } - return ret; -} -#endif // Generic controller init - -static int myrand(void *rng_state, unsigned char *output, size_t len) { - esp_fill_random(output, len); - return 0; -} - -void Blufi::_security_init() { - m_sec = new BlufiSecurity(); - if (m_sec == nullptr) { - ESP_LOGE(BLUFI_TAG, "Failed to allocate security context"); - return; - } - memset(m_sec, 0, sizeof(BlufiSecurity)); - m_sec->dhm = new mbedtls_dhm_context(); - m_sec->aes = new mbedtls_aes_context(); - - mbedtls_dhm_init(m_sec->dhm); - mbedtls_aes_init(m_sec->aes); - - memset(m_sec->iv, 0x0, sizeof(m_sec->iv)); -} - -void Blufi::_security_deinit() { - if (m_sec == nullptr) - return; - - if (m_sec->dh_param) { - free(m_sec->dh_param); - } - mbedtls_dhm_free(m_sec->dhm); - mbedtls_aes_free(m_sec->aes); - delete m_sec->dhm; - delete m_sec->aes; - delete m_sec; - m_sec = nullptr; -} - -void Blufi::_dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, - int *output_len, bool *need_free) { - if (m_sec == nullptr) { - ESP_LOGE(BLUFI_TAG, "Security not initialized in DH handler"); - btc_blufi_report_error(ESP_BLUFI_INIT_SECURITY_ERROR); - return; - } - - if (len < 1) { - ESP_LOGE(BLUFI_TAG, "DH handler: data too short"); - btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR); - return; - } - - uint8_t type = data[0]; - switch (type) { - case 0x00: /* DH_PARAM_LEN */ - if (len < 3) { - ESP_LOGE(BLUFI_TAG, "DH_PARAM_LEN packet too short"); - btc_blufi_report_error(ESP_BLUFI_DATA_FORMAT_ERROR); - return; - } - - m_sec->dh_param_len = (data[1] << 8) | data[2]; - if (m_sec->dh_param) { - free(m_sec->dh_param); - m_sec->dh_param = nullptr; - } - m_sec->dh_param = (uint8_t *)malloc(m_sec->dh_param_len); - if (m_sec->dh_param == nullptr) { - ESP_LOGE(BLUFI_TAG, "DH malloc failed"); - btc_blufi_report_error(ESP_BLUFI_DH_MALLOC_ERROR); - } - break; - case 0x01: /* DH_PARAM_DATA */ { - if (m_sec->dh_param == nullptr) { - ESP_LOGE(BLUFI_TAG, "DH param not allocated"); - btc_blufi_report_error(ESP_BLUFI_DH_PARAM_ERROR); - return; - } - uint8_t *param = m_sec->dh_param; - memcpy(m_sec->dh_param, &data[1], m_sec->dh_param_len); - int ret = mbedtls_dhm_read_params(m_sec->dhm, ¶m, ¶m[m_sec->dh_param_len]); - if (ret) { - ESP_LOGE(BLUFI_TAG, "mbedtls_dhm_read_params failed %d", ret); - btc_blufi_report_error(ESP_BLUFI_READ_PARAM_ERROR); - return; - } - - const int dhm_len = mbedtls_dhm_get_len(m_sec->dhm); - - ret = mbedtls_dhm_make_public(m_sec->dhm, dhm_len, m_sec->self_public_key, dhm_len, - myrand, NULL); - if (ret != 0) { - ESP_LOGE(BLUFI_TAG, "mbedtls_dhm_make_public failed: %d", ret); - btc_blufi_report_error(ESP_BLUFI_MAKE_PUBLIC_ERROR); - return; - } - ret = mbedtls_dhm_calc_secret(m_sec->dhm, m_sec->share_key, SHARE_KEY_LEN, - &m_sec->share_len, myrand, NULL); - if (ret != 0) { - ESP_LOGE(BLUFI_TAG, "mbedtls_dhm_calc_secret failed: %d", ret); - btc_blufi_report_error(ESP_BLUFI_ENCRYPT_ERROR); - return; - } - - ret = mbedtls_md5(m_sec->share_key, m_sec->share_len, m_sec->psk); - if (ret != 0) { - ESP_LOGE(BLUFI_TAG, "mbedtls_md5 failed: %d", ret); - btc_blufi_report_error(ESP_BLUFI_CALC_MD5_ERROR); - return; - } - ret = mbedtls_aes_setkey_enc(m_sec->aes, m_sec->psk, PSK_LEN * 8); - if (ret != 0) { - ESP_LOGE(BLUFI_TAG, "mbedtls_aes_setkey_enc failed: -0x%04X", -ret); - btc_blufi_report_error(ESP_BLUFI_ENCRYPT_ERROR); - return; - } - *output_data = m_sec->self_public_key; - *output_len = dhm_len; - *need_free = false; - ESP_LOGI(BLUFI_TAG, "DH negotiation completed successfully"); - - free(m_sec->dh_param); - m_sec->dh_param = nullptr; - m_sec->dh_param_len = 0; - break; - } - default: - ESP_LOGE(BLUFI_TAG, "DH handler unknown type: %d", type); - } -} - -int Blufi::_aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) { - if (!m_sec || !m_sec->aes || !crypt_data || crypt_len <= 0) { - ESP_LOGE(BLUFI_TAG, "Invalid parameters for AES encryption"); - return -ESP_ERR_INVALID_ARG; - } - - size_t iv_offset = 0; - uint8_t iv0[16]; - memcpy(iv0, m_sec->iv, 16); - iv0[0] = iv8; - int ret = mbedtls_aes_crypt_cfb128(m_sec->aes, MBEDTLS_AES_ENCRYPT, crypt_len, &iv_offset, iv0, - crypt_data, crypt_data); - - if (ret == 0) { - return crypt_len; - } else { - ESP_LOGE(BLUFI_TAG, "AES encrypt failed: %d", ret); - return ret; - } -} - -int Blufi::_aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len) { - if (!m_sec || !m_sec->aes || !crypt_data || crypt_len < 0) { - ESP_LOGE(BLUFI_TAG, "Invalid parameters for AES decryption %p %p %d", m_sec->aes, - crypt_data, crypt_len); - return -ESP_ERR_INVALID_ARG; - } - - size_t iv_offset = 0; - uint8_t iv0[16]; - memcpy(iv0, m_sec->iv, 16); - iv0[0] = iv8; - int ret = mbedtls_aes_crypt_cfb128(m_sec->aes, MBEDTLS_AES_DECRYPT, crypt_len, &iv_offset, iv0, - crypt_data, crypt_data); - if (ret != 0) { - ESP_LOGE(BLUFI_TAG, "AES decrypt failed: %d", ret); - return ret; - } else { - return crypt_len; - } -} - -uint16_t Blufi::_crc_checksum(uint8_t iv8, uint8_t *data, int len) { - return esp_crc16_be(0, data, len); -} - -int Blufi::_get_softap_conn_num() { - auto &wifi = WifiManager::GetInstance(); - if (!wifi.IsInitialized() || !wifi.IsConfigMode()) { - return 0; - } - - wifi_sta_list_t sta_list{}; - if (esp_wifi_ap_get_sta_list(&sta_list) == ESP_OK) { - return sta_list.num; - } - return 0; -} - -void Blufi::_handle_event(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param) { - switch (event) { - case ESP_BLUFI_EVENT_INIT_FINISH: - ESP_LOGI(BLUFI_TAG, "BLUFI init finish"); - esp_blufi_adv_start(); - break; - case ESP_BLUFI_EVENT_DEINIT_FINISH: - ESP_LOGI(BLUFI_TAG, "BLUFI deinit finish"); - break; - case ESP_BLUFI_EVENT_BLE_CONNECT: - ESP_LOGI(BLUFI_TAG, "BLUFI ble connect"); - m_ble_is_connected = true; - esp_blufi_adv_stop(); - _security_init(); - break; - case ESP_BLUFI_EVENT_BLE_DISCONNECT: - ESP_LOGI(BLUFI_TAG, "BLUFI ble disconnect"); - m_ble_is_connected = false; - _security_deinit(); - if (!m_provisioned) { - esp_blufi_adv_start(); - } else { - esp_blufi_adv_stop(); - if (!m_deinited) { - // Deinit BLE stack after provisioning completes to free resources. - xTaskCreate( - [](void *ctx) { - static_cast(ctx)->deinit(); - vTaskDelete(nullptr); - }, - "blufi_deinit", 4096, this, 5, nullptr); - } - } - break; - case ESP_BLUFI_EVENT_SET_WIFI_OPMODE: { - ESP_LOGI(BLUFI_TAG, "BLUFI Set WIFI opmode %d", param->wifi_mode.op_mode); - auto &wifi_manager = WifiManager::GetInstance(); - if (!wifi_manager.IsInitialized() && !wifi_manager.Initialize()) { - ESP_LOGE(BLUFI_TAG, "Failed to initialize WifiManager for opmode change"); - break; - } - switch (param->wifi_mode.op_mode) { - case WIFI_MODE_STA: - wifi_manager.StartStation(); - break; - case WIFI_MODE_AP: - wifi_manager.StartConfigAp(); - break; - case WIFI_MODE_APSTA: - ESP_LOGW(BLUFI_TAG, "APSTA mode not supported, starting station only"); - wifi_manager.StartStation(); - break; - default: - wifi_manager.StopStation(); - wifi_manager.StopConfigAp(); - break; - } - break; - } - case ESP_BLUFI_EVENT_REQ_CONNECT_TO_AP: { - ESP_LOGI(BLUFI_TAG, "BLUFI request wifi connect to AP via esp-wifi-connect"); - std::string ssid(reinterpret_cast(m_sta_config.sta.ssid)); - std::string password(reinterpret_cast(m_sta_config.sta.password)); - - // Save credentials through SsidManager - SsidManager::GetInstance().AddSsid(ssid, password); - auto &wifi_manager = WifiManager::GetInstance(); - if (!wifi_manager.IsInitialized() && !wifi_manager.Initialize()) { - ESP_LOGE(BLUFI_TAG, "Failed to initialize WifiManager"); - break; - } - - // Track SSID for BLUFI status reporting. - m_sta_ssid_len = static_cast(std::min(ssid.size(), sizeof(m_sta_ssid))); - memcpy(m_sta_ssid, ssid.c_str(), m_sta_ssid_len); - memset(m_sta_bssid, 0, sizeof(m_sta_bssid)); - m_sta_connected = false; - m_sta_got_ip = false; - m_sta_is_connecting = true; - m_sta_conn_info = {}; // Reset connection info - m_sta_conn_info.sta_ssid = m_sta_ssid; - m_sta_conn_info.sta_ssid_len = m_sta_ssid_len; - - wifi_manager.StartStation(); - - // Wait for connection in a separate task to avoid blocking the BLUFI handler. - xTaskCreate( - [](void *ctx) { - auto *self = static_cast(ctx); - auto &wifi = WifiManager::GetInstance(); - constexpr int kConnectTimeoutMs = 10000; // 10s - constexpr TickType_t kDelayTick = pdMS_TO_TICKS(200); - int waited_ms = 0; - - while (waited_ms < kConnectTimeoutMs && !wifi.IsConnected()) { - vTaskDelay(kDelayTick); - waited_ms += 200; - } - - wifi_mode_t mode = GetWifiModeWithFallback(wifi); - const int softap_conn_num = _get_softap_conn_num(); - - if (wifi.IsConnected()) { - self->m_sta_is_connecting = false; - self->m_sta_connected = true; - self->m_sta_got_ip = true; - self->m_provisioned = true; - - auto current_ssid = wifi.GetSsid(); - if (!current_ssid.empty()) { - self->m_sta_ssid_len = static_cast( - std::min(current_ssid.size(), sizeof(self->m_sta_ssid))); - memcpy(self->m_sta_ssid, current_ssid.c_str(), self->m_sta_ssid_len); - } - - wifi_ap_record_t ap_info{}; - if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { - memcpy(self->m_sta_bssid, ap_info.bssid, sizeof(self->m_sta_bssid)); - } - - esp_blufi_extra_info_t info = {}; - memcpy(info.sta_bssid, self->m_sta_bssid, sizeof(self->m_sta_bssid)); - info.sta_bssid_set = true; - info.sta_ssid = self->m_sta_ssid; - info.sta_ssid_len = self->m_sta_ssid_len; - esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, - softap_conn_num, &info); - ESP_LOGI(BLUFI_TAG, "connected to WiFi"); - - // Close BluFi session after successful provisioning to free resources. - if (self->m_ble_is_connected) { - esp_blufi_disconnect(); - } - } else { - self->m_sta_is_connecting = false; - self->m_sta_connected = false; - self->m_sta_got_ip = false; - - esp_blufi_extra_info_t info = {}; - info.sta_ssid = self->m_sta_ssid; - info.sta_ssid_len = self->m_sta_ssid_len; - esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, - softap_conn_num, &info); - ESP_LOGE(BLUFI_TAG, "Failed to connect to WiFi via esp-wifi-connect"); - } - vTaskDelete(nullptr); - }, - "blufi_wifi_conn", 4096, this, 5, nullptr); - break; - } - case ESP_BLUFI_EVENT_REQ_DISCONNECT_FROM_AP: - ESP_LOGI(BLUFI_TAG, "BLUFI request wifi disconnect from AP"); - if (WifiManager::GetInstance().IsInitialized()) { - WifiManager::GetInstance().StopStation(); - } - m_sta_is_connecting = false; - m_sta_connected = false; - m_sta_got_ip = false; - break; - case ESP_BLUFI_EVENT_GET_WIFI_STATUS: { - auto &wifi = WifiManager::GetInstance(); - wifi_mode_t mode = GetWifiModeWithFallback(wifi); - const int softap_conn_num = _get_softap_conn_num(); - - if (wifi.IsInitialized() && wifi.IsConnected()) { - m_sta_connected = true; - m_sta_got_ip = true; - - auto current_ssid = wifi.GetSsid(); - if (!current_ssid.empty()) { - m_sta_ssid_len = - static_cast(std::min(current_ssid.size(), sizeof(m_sta_ssid))); - memcpy(m_sta_ssid, current_ssid.c_str(), m_sta_ssid_len); - } - - esp_blufi_extra_info_t info; - memset(&info, 0, sizeof(esp_blufi_extra_info_t)); - memcpy(info.sta_bssid, m_sta_bssid, 6); - info.sta_ssid = m_sta_ssid; - info.sta_ssid_len = m_sta_ssid_len; - esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_SUCCESS, softap_conn_num, - &info); - } else if (m_sta_is_connecting) { - esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONNECTING, softap_conn_num, - &m_sta_conn_info); - } else { - esp_blufi_send_wifi_conn_report(mode, ESP_BLUFI_STA_CONN_FAIL, softap_conn_num, - &m_sta_conn_info); - } - ESP_LOGI(BLUFI_TAG, "BLUFI get wifi status"); - break; - } - case ESP_BLUFI_EVENT_RECV_STA_BSSID: - memcpy(m_sta_config.sta.bssid, param->sta_bssid.bssid, 6); - m_sta_config.sta.bssid_set = true; - ESP_LOGI(BLUFI_TAG, "Recv STA BSSID"); - break; - case ESP_BLUFI_EVENT_RECV_STA_SSID: - strncpy((char *)m_sta_config.sta.ssid, (char *)param->sta_ssid.ssid, - param->sta_ssid.ssid_len); - m_sta_config.sta.ssid[param->sta_ssid.ssid_len] = '\0'; - ESP_LOGI(BLUFI_TAG, "Recv STA SSID: %s", m_sta_config.sta.ssid); - break; - case ESP_BLUFI_EVENT_RECV_STA_PASSWD: - strncpy((char *)m_sta_config.sta.password, (char *)param->sta_passwd.passwd, - param->sta_passwd.passwd_len); - m_sta_config.sta.password[param->sta_passwd.passwd_len] = '\0'; - ESP_LOGI(BLUFI_TAG, "Recv STA PASSWORD : %s", m_sta_config.sta.password); - break; - default: - ESP_LOGW(BLUFI_TAG, "Unhandled event: %d", event); - break; - } -} - -void Blufi::_event_callback_trampoline(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param) { - GetInstance()._handle_event(event, param); -} - -void Blufi::_negotiate_data_handler_trampoline(uint8_t *data, int len, uint8_t **output_data, - int *output_len, bool *need_free) { - GetInstance()._dh_negotiate_data_handler(data, len, output_data, output_len, need_free); -} - -int Blufi::_encrypt_func_trampoline(uint8_t iv8, uint8_t *crypt_data, int crypt_len) { - return GetInstance()._aes_encrypt(iv8, crypt_data, crypt_len); -} - -int Blufi::_decrypt_func_trampoline(uint8_t iv8, uint8_t *crypt_data, int crypt_len) { - return GetInstance()._aes_decrypt(iv8, crypt_data, crypt_len); -} - -uint16_t Blufi::_checksum_func_trampoline(uint8_t iv8, uint8_t *data, int len) { - return _crc_checksum(iv8, data, len); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.h deleted file mode 100644 index 39b84116..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/blufi.h +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include -#include "mbedtls/dhm.h" -#include "mbedtls/aes.h" -#include "esp_err.h" -#include "esp_blufi_api.h" -#include "esp_wifi_types.h" - - -class Blufi { -public: - /** - * @brief Get the singleton instance of the Blufi class. - */ - static Blufi &GetInstance(); - - /** - * @brief Initializes the Bluetooth controller, host, and Blufi profile. - * This is the main entry point to start the Blufi process. - * @return ESP_OK on success, otherwise an error code. - */ - esp_err_t init(); - - /** - * @brief Deinitializes Blufi and the Bluetooth stack. - * @return ESP_OK on success, otherwise an error code. - */ - esp_err_t deinit(); - - // Delete copy constructor and assignment operator for singleton - Blufi(const Blufi &) = delete; - - Blufi &operator=(const Blufi &) = delete; - -private: - bool inited_ = false; - - Blufi(); - - ~Blufi(); - - - // Initialization logic - static esp_err_t _controller_init(); - - static esp_err_t _controller_deinit(); - - static esp_err_t _host_init(); - - static esp_err_t _host_deinit(); - - static esp_err_t _gap_register_callback(); - - static esp_err_t _host_and_cb_init(); - - void _security_init(); - - void _security_deinit(); - - void _dh_negotiate_data_handler(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free); - - int _aes_encrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len); - - int _aes_decrypt(uint8_t iv8, uint8_t *crypt_data, int crypt_len); - - static uint16_t _crc_checksum(uint8_t iv8, uint8_t *data, int len); - - void _handle_event(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param); - - static int _get_softap_conn_num(); - - // These C-style functions are registered with ESP-IDF and call the corresponding instance methods. - - static void _event_callback_trampoline(esp_blufi_cb_event_t event, esp_blufi_cb_param_t *param); - - static void _negotiate_data_handler_trampoline(uint8_t *data, int len, uint8_t **output_data, int *output_len, - bool *need_free); - - static int _encrypt_func_trampoline(uint8_t iv8, uint8_t *crypt_data, int crypt_len); - - static int _decrypt_func_trampoline(uint8_t iv8, uint8_t *crypt_data, int crypt_len); - - static uint16_t _checksum_func_trampoline(uint8_t iv8, uint8_t *data, int len); - -#ifdef CONFIG_BT_NIMBLE_ENABLED - static void _nimble_on_reset(int reason); - static void _nimble_on_sync(); - static void _nimble_host_task(void *param); -#endif - - // Security context, formerly blufi_sec struct - struct BlufiSecurity { -#define DH_SELF_PUB_KEY_LEN 128 - uint8_t self_public_key[DH_SELF_PUB_KEY_LEN]; -#define SHARE_KEY_LEN 128 - uint8_t share_key[SHARE_KEY_LEN]; - size_t share_len; -#define PSK_LEN 16 - uint8_t psk[PSK_LEN]; - uint8_t *dh_param; - int dh_param_len; - uint8_t iv[16]; - mbedtls_dhm_context *dhm; - esp_aes_context *aes; - }; - - BlufiSecurity *m_sec; - - // State variables - wifi_config_t m_sta_config{}; - wifi_config_t m_ap_config{}; - bool m_ble_is_connected; - bool m_sta_connected; - bool m_sta_got_ip; - bool m_provisioned; - bool m_deinited; - uint8_t m_sta_bssid[6]{}; - uint8_t m_sta_ssid[32]{}; - int m_sta_ssid_len; - bool m_sta_is_connecting; - esp_blufi_extra_info_t m_sta_conn_info{}; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.cc deleted file mode 100644 index 8a2f85bc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.cc +++ /dev/null @@ -1,178 +0,0 @@ -#include "board.h" -#include "system_info.h" -#include "settings.h" -#include "display/display.h" -#include "display/oled_display.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include - -#define TAG "Board" - -Board::Board() { - Settings settings("board", true); - uuid_ = settings.GetString("uuid"); - if (uuid_.empty()) { - uuid_ = GenerateUuid(); - settings.SetString("uuid", uuid_); - } - ESP_LOGI(TAG, "UUID=%s SKU=%s", uuid_.c_str(), BOARD_NAME); -} - -std::string Board::GenerateUuid() { - // UUID v4 需要 16 字节的随机数据 - uint8_t uuid[16]; - - // 使用 ESP32 的硬件随机数生成器 - esp_fill_random(uuid, sizeof(uuid)); - - // 设置版本 (版本 4) 和变体位 - uuid[6] = (uuid[6] & 0x0F) | 0x40; // 版本 4 - uuid[8] = (uuid[8] & 0x3F) | 0x80; // 变体 1 - - // 将字节转换为标准的 UUID 字符串格式 - char uuid_str[37]; - snprintf(uuid_str, sizeof(uuid_str), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - uuid[0], uuid[1], uuid[2], uuid[3], - uuid[4], uuid[5], uuid[6], uuid[7], - uuid[8], uuid[9], uuid[10], uuid[11], - uuid[12], uuid[13], uuid[14], uuid[15]); - - return std::string(uuid_str); -} - -bool Board::GetBatteryLevel(int &level, bool& charging, bool& discharging) { - return false; -} - -bool Board::GetTemperature(float& esp32temp){ - return false; -} - -Display* Board::GetDisplay() { - static NoDisplay display; - return &display; -} - -Camera* Board::GetCamera() { - return nullptr; -} - -Led* Board::GetLed() { - static NoLed led; - return &led; -} - -std::string Board::GetSystemInfoJson() { - /* - { - "version": 2, - "flash_size": 4194304, - "psram_size": 0, - "minimum_free_heap_size": 123456, - "mac_address": "00:00:00:00:00:00", - "uuid": "00000000-0000-0000-0000-000000000000", - "chip_model_name": "esp32s3", - "chip_info": { - "model": 1, - "cores": 2, - "revision": 0, - "features": 0 - }, - "application": { - "name": "my-app", - "version": "1.0.0", - "compile_time": "2021-01-01T00:00:00Z" - "idf_version": "4.2-dev" - "elf_sha256": "" - }, - "partition_table": [ - "app": { - "label": "app", - "type": 1, - "subtype": 2, - "address": 0x10000, - "size": 0x100000 - } - ], - "ota": { - "label": "ota_0" - }, - "board": { - ... - } - } - */ - std::string json = R"({"version":2,"language":")" + std::string(Lang::CODE) + R"(",)"; - json += R"("flash_size":)" + std::to_string(SystemInfo::GetFlashSize()) + R"(,)"; - json += R"("minimum_free_heap_size":")" + std::to_string(SystemInfo::GetMinimumFreeHeapSize()) + R"(",)"; - json += R"("mac_address":")" + SystemInfo::GetMacAddress() + R"(",)"; - json += R"("uuid":")" + uuid_ + R"(",)"; - json += R"("chip_model_name":")" + SystemInfo::GetChipModelName() + R"(",)"; - - esp_chip_info_t chip_info; - esp_chip_info(&chip_info); - json += R"("chip_info":{)"; - json += R"("model":)" + std::to_string(chip_info.model) + R"(,)"; - json += R"("cores":)" + std::to_string(chip_info.cores) + R"(,)"; - json += R"("revision":)" + std::to_string(chip_info.revision) + R"(,)"; - json += R"("features":)" + std::to_string(chip_info.features) + R"(},)"; - - auto app_desc = esp_app_get_description(); - json += R"("application":{)"; - json += R"("name":")" + std::string(app_desc->project_name) + R"(",)"; - json += R"("version":")" + std::string(app_desc->version) + R"(",)"; - json += R"("compile_time":")" + std::string(app_desc->date) + R"(T)" + std::string(app_desc->time) + R"(Z",)"; - json += R"("idf_version":")" + std::string(app_desc->idf_ver) + R"(",)"; - char sha256_str[65]; - for (int i = 0; i < 32; i++) { - snprintf(sha256_str + i * 2, sizeof(sha256_str) - i * 2, "%02x", app_desc->app_elf_sha256[i]); - } - json += R"("elf_sha256":")" + std::string(sha256_str) + R"(")"; - json += R"(},)"; - - json += R"("partition_table": [)"; - esp_partition_iterator_t it = esp_partition_find(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, NULL); - while (it) { - const esp_partition_t *partition = esp_partition_get(it); - json += R"({)"; - json += R"("label":")" + std::string(partition->label) + R"(",)"; - json += R"("type":)" + std::to_string(partition->type) + R"(,)"; - json += R"("subtype":)" + std::to_string(partition->subtype) + R"(,)"; - json += R"("address":)" + std::to_string(partition->address) + R"(,)"; - json += R"("size":)" + std::to_string(partition->size) + R"(},)";; - it = esp_partition_next(it); - } - json.pop_back(); // Remove the last comma - json += R"(],)"; - - json += R"("ota":{)"; - auto ota_partition = esp_ota_get_running_partition(); - json += R"("label":")" + std::string(ota_partition->label) + R"(")"; - json += R"(},)"; - - // Append display info - auto display = GetDisplay(); - if (display) { - json += R"("display":{)"; - if (dynamic_cast(display)) { - json += R"("monochrome":)" + std::string("true") + R"(,)"; - } else { - json += R"("monochrome":)" + std::string("false") + R"(,)"; - } - json += R"("width":)" + std::to_string(display->width()) + R"(,)"; - json += R"("height":)" + std::to_string(display->height()) + R"(,)"; - json.pop_back(); // Remove the last comma - } - json += R"(},)"; - - json += R"("board":)" + GetBoardJson(); - - // Close the JSON object - json += R"(})"; - return json; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.h deleted file mode 100644 index 19d3f2f5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/board.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef BOARD_H -#define BOARD_H - -#include -#include -#include -#include -#include -#include -#include - -#include "led/led.h" -#include "backlight.h" -#include "camera.h" -#include "assets.h" - -/** - * Network events for unified callback - */ -enum class NetworkEvent { - Scanning, // Network is scanning (WiFi scanning, etc.) - Connecting, // Network is connecting (data: SSID/network name) - Connected, // Network connected successfully (data: SSID/network name) - Disconnected, // Network disconnected - WifiConfigModeEnter, // Entered WiFi configuration mode - WifiConfigModeExit, // Exited WiFi configuration mode - // Cellular modem specific events - ModemDetecting, // Detecting modem (baud rate, module type) - ModemErrorNoSim, // No SIM card detected - ModemErrorRegDenied, // Network registration denied - ModemErrorInitFailed, // Modem initialization failed - ModemErrorTimeout // Operation timeout -}; - -// Power save level enumeration -enum class PowerSaveLevel { - LOW_POWER, // Maximum power saving (lowest power consumption) - BALANCED, // Medium power saving (balanced) - PERFORMANCE, // No power saving (maximum power consumption / full performance) -}; - -// Network event callback type (event, data) -// data contains additional info like SSID for Connecting/Connected events -using NetworkEventCallback = std::function; - -void* create_board(); -class AudioCodec; -class Display; -class Board { -private: - Board(const Board&) = delete; // 禁用拷贝构造函数 - Board& operator=(const Board&) = delete; // 禁用赋值操作 - -protected: - Board(); - std::string GenerateUuid(); - - // 软件生成的设备唯一标识 - std::string uuid_; - -public: - static Board& GetInstance() { - static Board* instance = static_cast(create_board()); - return *instance; - } - - virtual ~Board() = default; - virtual std::string GetBoardType() = 0; - virtual std::string GetUuid() { return uuid_; } - virtual Backlight* GetBacklight() { return nullptr; } - virtual Led* GetLed(); - virtual AudioCodec* GetAudioCodec() = 0; - virtual bool GetTemperature(float& esp32temp); - virtual Display* GetDisplay(); - virtual Camera* GetCamera(); - virtual NetworkInterface* GetNetwork() = 0; - virtual void StartNetwork() = 0; - virtual void SetNetworkEventCallback(NetworkEventCallback callback) { (void)callback; } - virtual const char* GetNetworkStateIcon() = 0; - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging); - virtual std::string GetSystemInfoJson(); - virtual void SetPowerSaveLevel(PowerSaveLevel level) = 0; - virtual std::string GetBoardJson() = 0; - virtual std::string GetDeviceStatusJson() = 0; -}; - -#define DECLARE_BOARD(BOARD_CLASS_NAME) \ -void* create_board() { \ - return new BOARD_CLASS_NAME(); \ -} - -#endif // BOARD_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.cc deleted file mode 100644 index 9570a5fb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.cc +++ /dev/null @@ -1,125 +0,0 @@ -#include "button.h" - -#include -#include - -#define TAG "Button" - -#if CONFIG_SOC_ADC_SUPPORTED -AdcButton::AdcButton(const button_adc_config_t& adc_config) : Button(nullptr) { - button_config_t btn_config = { - .long_press_time = 2000, - .short_press_time = 0, - }; - ESP_ERROR_CHECK(iot_button_new_adc_device(&btn_config, &adc_config, &button_handle_)); -} -#endif - -Button::Button(button_handle_t button_handle) : button_handle_(button_handle) { -} - -Button::Button(gpio_num_t gpio_num, bool active_high, uint16_t long_press_time, uint16_t short_press_time, bool enable_power_save) : gpio_num_(gpio_num) { - if (gpio_num == GPIO_NUM_NC) { - return; - } - button_config_t button_config = { - .long_press_time = long_press_time, - .short_press_time = short_press_time - }; - button_gpio_config_t gpio_config = { - .gpio_num = gpio_num, - .active_level = static_cast(active_high ? 1 : 0), - .enable_power_save = enable_power_save, - .disable_pull = false - }; - ESP_ERROR_CHECK(iot_button_new_gpio_device(&button_config, &gpio_config, &button_handle_)); -} - -Button::~Button() { - if (button_handle_ != NULL) { - iot_button_delete(button_handle_); - } -} - -void Button::OnPressDown(std::function callback) { - if (button_handle_ == nullptr) { - return; - } - on_press_down_ = callback; - iot_button_register_cb(button_handle_, BUTTON_PRESS_DOWN, nullptr, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_press_down_) { - button->on_press_down_(); - } - }, this); -} - -void Button::OnPressUp(std::function callback) { - if (button_handle_ == nullptr) { - return; - } - on_press_up_ = callback; - iot_button_register_cb(button_handle_, BUTTON_PRESS_UP, nullptr, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_press_up_) { - button->on_press_up_(); - } - }, this); -} - -void Button::OnLongPress(std::function callback) { - if (button_handle_ == nullptr) { - return; - } - on_long_press_ = callback; - iot_button_register_cb(button_handle_, BUTTON_LONG_PRESS_START, nullptr, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_long_press_) { - button->on_long_press_(); - } - }, this); -} - -void Button::OnClick(std::function callback) { - if (button_handle_ == nullptr) { - return; - } - on_click_ = callback; - iot_button_register_cb(button_handle_, BUTTON_SINGLE_CLICK, nullptr, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_click_) { - button->on_click_(); - } - }, this); -} - -void Button::OnDoubleClick(std::function callback) { - if (button_handle_ == nullptr) { - return; - } - on_double_click_ = callback; - iot_button_register_cb(button_handle_, BUTTON_DOUBLE_CLICK, nullptr, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_double_click_) { - button->on_double_click_(); - } - }, this); -} - -void Button::OnMultipleClick(std::function callback, uint8_t click_count) { - if (button_handle_ == nullptr) { - return; - } - on_multiple_click_ = callback; - button_event_args_t event_args = { - .multiple_clicks = { - .clicks = click_count - } - }; - iot_button_register_cb(button_handle_, BUTTON_MULTIPLE_CLICK, &event_args, [](void* handle, void* usr_data) { - Button* button = static_cast(usr_data); - if (button->on_multiple_click_) { - button->on_multiple_click_(); - } - }, this); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.h deleted file mode 100644 index ceecbe51..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/button.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BUTTON_H_ -#define BUTTON_H_ - -#include -#include -#include -#include -#include -#include - -class Button { -public: - Button(button_handle_t button_handle); - Button(gpio_num_t gpio_num, bool active_high = false, uint16_t long_press_time = 0, uint16_t short_press_time = 0, bool enable_power_save = false); - ~Button(); - - void OnPressDown(std::function callback); - void OnPressUp(std::function callback); - void OnLongPress(std::function callback); - void OnClick(std::function callback); - void OnDoubleClick(std::function callback); - void OnMultipleClick(std::function callback, uint8_t click_count = 3); - -protected: - gpio_num_t gpio_num_; - button_handle_t button_handle_ = nullptr; - - std::function on_press_down_; - std::function on_press_up_; - std::function on_long_press_; - std::function on_click_; - std::function on_double_click_; - std::function on_multiple_click_; -}; - -#if CONFIG_SOC_ADC_SUPPORTED -class AdcButton : public Button { -public: - AdcButton(const button_adc_config_t& adc_config); -}; -#endif - -class PowerSaveButton : public Button { -public: - PowerSaveButton(gpio_num_t gpio_num) : Button(gpio_num, false, 0, 0, true) { - } -}; - -#endif // BUTTON_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/camera.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/camera.h deleted file mode 100644 index 75c780c1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/camera.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef CAMERA_H -#define CAMERA_H - -#include - -class Camera { -public: - virtual void SetExplainUrl(const std::string& url, const std::string& token) = 0; - virtual bool Capture() = 0; - virtual bool SetHMirror(bool enabled) = 0; - virtual bool SetVFlip(bool enabled) = 0; - virtual std::string Explain(const std::string& question) = 0; -}; - -#endif // CAMERA_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.cc deleted file mode 100644 index 7253e518..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.cc +++ /dev/null @@ -1,98 +0,0 @@ -#include "dual_network_board.h" -#include "application.h" -#include "display.h" -#include "assets/lang_config.h" -#include "settings.h" -#include - -static const char *TAG = "DualNetworkBoard"; - -DualNetworkBoard::DualNetworkBoard(gpio_num_t ml307_tx_pin, gpio_num_t ml307_rx_pin, gpio_num_t ml307_dtr_pin, int32_t default_net_type) - : Board(), - ml307_tx_pin_(ml307_tx_pin), - ml307_rx_pin_(ml307_rx_pin), - ml307_dtr_pin_(ml307_dtr_pin) { - - // 从Settings加载网络类型 - network_type_ = LoadNetworkTypeFromSettings(default_net_type); - - // 只初始化当前网络类型对应的板卡 - InitializeCurrentBoard(); -} - -NetworkType DualNetworkBoard::LoadNetworkTypeFromSettings(int32_t default_net_type) { - Settings settings("network", true); - int network_type = settings.GetInt("type", default_net_type); // 默认使用ML307 (1) - return network_type == 1 ? NetworkType::ML307 : NetworkType::WIFI; -} - -void DualNetworkBoard::SaveNetworkTypeToSettings(NetworkType type) { - Settings settings("network", true); - int network_type = (type == NetworkType::ML307) ? 1 : 0; - settings.SetInt("type", network_type); -} - -void DualNetworkBoard::InitializeCurrentBoard() { - if (network_type_ == NetworkType::ML307) { - ESP_LOGI(TAG, "Initialize ML307 board"); - current_board_ = std::make_unique(ml307_tx_pin_, ml307_rx_pin_, ml307_dtr_pin_); - } else { - ESP_LOGI(TAG, "Initialize WiFi board"); - current_board_ = std::make_unique(); - } -} - -void DualNetworkBoard::SwitchNetworkType() { - auto display = GetDisplay(); - if (network_type_ == NetworkType::WIFI) { - SaveNetworkTypeToSettings(NetworkType::ML307); - display->ShowNotification(Lang::Strings::SWITCH_TO_4G_NETWORK); - } else { - SaveNetworkTypeToSettings(NetworkType::WIFI); - display->ShowNotification(Lang::Strings::SWITCH_TO_WIFI_NETWORK); - } - vTaskDelay(pdMS_TO_TICKS(1000)); - auto& app = Application::GetInstance(); - app.Reboot(); -} - - -std::string DualNetworkBoard::GetBoardType() { - return current_board_->GetBoardType(); -} - -void DualNetworkBoard::StartNetwork() { - auto display = Board::GetInstance().GetDisplay(); - - if (network_type_ == NetworkType::WIFI) { - display->SetStatus(Lang::Strings::CONNECTING); - } else { - display->SetStatus(Lang::Strings::DETECTING_MODULE); - } - current_board_->StartNetwork(); -} - -void DualNetworkBoard::SetNetworkEventCallback(NetworkEventCallback callback) { - // Forward the callback to the current board - current_board_->SetNetworkEventCallback(std::move(callback)); -} - -NetworkInterface* DualNetworkBoard::GetNetwork() { - return current_board_->GetNetwork(); -} - -const char* DualNetworkBoard::GetNetworkStateIcon() { - return current_board_->GetNetworkStateIcon(); -} - -void DualNetworkBoard::SetPowerSaveLevel(PowerSaveLevel level) { - current_board_->SetPowerSaveLevel(level); -} - -std::string DualNetworkBoard::GetBoardJson() { - return current_board_->GetBoardJson(); -} - -std::string DualNetworkBoard::GetDeviceStatusJson() { - return current_board_->GetDeviceStatusJson(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.h deleted file mode 100644 index 8bc9ec8e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/dual_network_board.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef DUAL_NETWORK_BOARD_H -#define DUAL_NETWORK_BOARD_H - -#include "board.h" -#include "wifi_board.h" -#include "ml307_board.h" -#include - -//enum NetworkType -enum class NetworkType { - WIFI, - ML307 -}; - -// 双网络板卡类,可以在WiFi和ML307之间切换 -class DualNetworkBoard : public Board { -private: - // 使用基类指针存储当前活动的板卡 - std::unique_ptr current_board_; - NetworkType network_type_ = NetworkType::ML307; // Default to ML307 - - // ML307的引脚配置 - gpio_num_t ml307_tx_pin_; - gpio_num_t ml307_rx_pin_; - gpio_num_t ml307_dtr_pin_; - - // 从Settings加载网络类型 - NetworkType LoadNetworkTypeFromSettings(int32_t default_net_type); - - // 保存网络类型到Settings - void SaveNetworkTypeToSettings(NetworkType type); - - // 初始化当前网络类型对应的板卡 - void InitializeCurrentBoard(); - -public: - DualNetworkBoard(gpio_num_t ml307_tx_pin, gpio_num_t ml307_rx_pin, gpio_num_t ml307_dtr_pin = GPIO_NUM_NC, int32_t default_net_type = 1); - virtual ~DualNetworkBoard() = default; - - // 切换网络类型 - void SwitchNetworkType(); - - // 获取当前网络类型 - NetworkType GetNetworkType() const { return network_type_; } - - // 获取当前活动的板卡引用 - Board& GetCurrentBoard() const { return *current_board_; } - - // 重写Board接口 - virtual std::string GetBoardType() override; - virtual void StartNetwork() override; - virtual void SetNetworkEventCallback(NetworkEventCallback callback) override; - virtual NetworkInterface* GetNetwork() override; - virtual const char* GetNetworkStateIcon() override; - virtual void SetPowerSaveLevel(PowerSaveLevel level) override; - virtual std::string GetBoardJson() override; - virtual std::string GetDeviceStatusJson() override; -}; - -#endif // DUAL_NETWORK_BOARD_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.cc deleted file mode 100644 index ab51a793..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.cc +++ /dev/null @@ -1,1039 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_imgfx_color_convert.h" -#include "esp_video_device.h" -#include "esp_video_init.h" -#include "linux/videodev2.h" - -#include "board.h" -#include "display.h" -#include "esp32_camera.h" -#include "esp_jpeg_common.h" -#include "jpg/image_to_jpeg.h" -#include "jpg/jpeg_to_image.h" -#include "lvgl_display.h" -#include "mcp_server.h" -#include "system_info.h" - -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE -#undef LOG_LOCAL_LEVEL -#define LOG_LOCAL_LEVEL MAX(CONFIG_LOG_DEFAULT_LEVEL, ESP_LOG_DEBUG) -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE -#include // should be after LOCAL_LOG_LEVEL definition - -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE -#ifdef CONFIG_IDF_TARGET_ESP32P4 -#include "driver/ppa.h" -#if defined(CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90) -#define IMAGE_ROTATION_ANGLE (PPA_SRM_ROTATION_ANGLE_270) -#elif defined(CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_270) -#define IMAGE_ROTATION_ANGLE (PPA_SRM_ROTATION_ANGLE_90) -#else -#error "CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE is not set" -#endif // angle -#else // target -#include "esp_imgfx_rotate.h" -#if defined(CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_90) -#define IMAGE_ROTATION_ANGLE (90) -#elif defined(CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE_270) -#define IMAGE_ROTATION_ANGLE (270) -#else -#error "CONFIG_XIAOZHI_CAMERA_IMAGE_ROTATION_ANGLE is not set" -#endif // angle -#endif // target -#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - - -#define TAG "Esp32Camera" - -#if defined(CONFIG_CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER) || defined(CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP) -#warning \ - "CAMERA_SENSOR_SWAP_PIXEL_BYTE_ORDER or CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP is enabled, which may cause image corruption in YUV422 format!" -#endif - -#if CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE -#define CAM_PRINT_FOURCC(pixelformat) \ - char fourcc[5]; \ - fourcc[0] = pixelformat & 0xFF; \ - fourcc[1] = (pixelformat >> 8) & 0xFF; \ - fourcc[2] = (pixelformat >> 16) & 0xFF; \ - fourcc[3] = (pixelformat >> 24) & 0xFF; \ - fourcc[4] = '\0'; \ - ESP_LOGD(TAG, "FOURCC: '%c%c%c%c'", fourcc[0], fourcc[1], fourcc[2], fourcc[3]); - -// for compatibility with old esp_video version -#ifndef MAP_FAILED -#define MAP_FAILED nullptr -#endif - -__attribute__((weak)) esp_err_t esp_video_deinit(void) { - return ESP_ERR_NOT_SUPPORTED; -} -// end of for compatibility with old esp_video version - -static void log_available_video_devices() { - for (int i = 0; i < 50; i++) { - char path[16]; - snprintf(path, sizeof(path), "/dev/video%d", i); - int fd = open(path, O_RDONLY); - if (fd >= 0) { - ESP_LOGD(TAG, "found video device: %s", path); - close(fd); - } - } -} -#else -#define CAM_PRINT_FOURCC(pixelformat) (void)0; -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - -Esp32Camera::Esp32Camera(const esp_video_init_config_t& config) { - if (esp_video_init(&config) != ESP_OK) { - ESP_LOGE(TAG, "esp_video_init failed"); - return; - } - -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - - const char* video_device_name = nullptr; - - if (false) { /* 用于构建 else if */ - } -#if CONFIG_ESP_VIDEO_ENABLE_MIPI_CSI_VIDEO_DEVICE - else if (config.csi != nullptr) { - video_device_name = ESP_VIDEO_MIPI_CSI_DEVICE_NAME; - } -#endif -#if CONFIG_ESP_VIDEO_ENABLE_DVP_VIDEO_DEVICE - else if (config.dvp != nullptr) { - video_device_name = ESP_VIDEO_DVP_DEVICE_NAME; - } -#endif -#if CONFIG_ESP_VIDEO_ENABLE_HW_JPEG_VIDEO_DEVICE - else if (config.jpeg != nullptr) { - video_device_name = ESP_VIDEO_JPEG_DEVICE_NAME; - } -#endif -#if CONFIG_ESP_VIDEO_ENABLE_SPI_VIDEO_DEVICE - else if (config.spi != nullptr) { - video_device_name = ESP_VIDEO_SPI_DEVICE_NAME; - } -#endif -#if CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - else if (config.usb_uvc != nullptr) { - video_device_name = ESP_VIDEO_USB_UVC_DEVICE_NAME(0); - } -#endif - - if (video_device_name == nullptr) { - ESP_LOGE(TAG, "no video device is enabled"); - return; - } - - video_fd_ = open(video_device_name, O_RDWR); - - if (video_fd_ < 0) { - ESP_LOGE(TAG, "open %s failed, errno=%d(%s)", video_device_name, errno, strerror(errno)); -#if CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - log_available_video_devices(); -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - return; - } - - struct v4l2_capability cap = {}; - if (ioctl(video_fd_, VIDIOC_QUERYCAP, &cap) != 0) { - ESP_LOGE(TAG, "VIDIOC_QUERYCAP failed, errno=%d(%s)", errno, strerror(errno)); - close(video_fd_); - video_fd_ = -1; - return; - } - - ESP_LOGD( - TAG, - "VIDIOC_QUERYCAP: driver=%s, card=%s, bus_info=%s, version=0x%08lx, capabilities=0x%08lx, device_caps=0x%08lx", - cap.driver, cap.card, cap.bus_info, cap.version, cap.capabilities, cap.device_caps); - - struct v4l2_format format = {}; - format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(video_fd_, VIDIOC_G_FMT, &format) != 0) { - ESP_LOGE(TAG, "VIDIOC_G_FMT failed, errno=%d(%s)", errno, strerror(errno)); - close(video_fd_); - video_fd_ = -1; - return; - } - ESP_LOGD(TAG, "VIDIOC_G_FMT: pixelformat=0x%08lx, width=%ld, height=%ld", format.fmt.pix.pixelformat, - format.fmt.pix.width, format.fmt.pix.height); - CAM_PRINT_FOURCC(format.fmt.pix.pixelformat); - - struct v4l2_format setformat = {}; - setformat.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - sensor_width_ = format.fmt.pix.width; - sensor_height_ = format.fmt.pix.height; -#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - setformat.fmt.pix.width = format.fmt.pix.width; - setformat.fmt.pix.height = format.fmt.pix.height; - - struct v4l2_fmtdesc fmtdesc = {}; - fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - fmtdesc.index = 0; - uint32_t best_fmt = 0; - int best_rank = 1 << 30; // large number - - // 注: 当前版本 esp_video 中 YUV422P 实际输出为 YUYV。 -#if defined(CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE) && defined(CONFIG_SOC_PPA_SUPPORTED) - auto get_rank = [](uint32_t fmt) -> int { - switch (fmt) { - case V4L2_PIX_FMT_RGB24: - return 0; - case V4L2_PIX_FMT_RGB565: - return 1; -#ifdef CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - case V4L2_PIX_FMT_YUV420: // 软件 JPEG 编码器不支持 YUV420 格式 - return 2; -#endif // CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - case V4L2_PIX_FMT_GREY: - case V4L2_PIX_FMT_YUV422P: - default: - return 1 << 29; // unsupported - } - }; -#else - auto get_rank = [](uint32_t fmt) -> int { - switch (fmt) { - case V4L2_PIX_FMT_YUV422P: - return 10; - case V4L2_PIX_FMT_RGB565: - return 11; - case V4L2_PIX_FMT_RGB24: - return 12; -#ifdef CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - case V4L2_PIX_FMT_YUV420: - return 13; -#endif // CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER -#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - case V4L2_PIX_FMT_JPEG: - return 5; -#endif // CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - case V4L2_PIX_FMT_GREY: - return 20; - default: - return 1 << 29; // unsupported - } - }; -#endif - while (ioctl(video_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0) { - ESP_LOGD(TAG, "VIDIOC_ENUM_FMT: pixelformat=0x%08lx, description=%s", fmtdesc.pixelformat, fmtdesc.description); - CAM_PRINT_FOURCC(fmtdesc.pixelformat); - int rank = get_rank(fmtdesc.pixelformat); - if (rank < best_rank) { - best_rank = rank; - best_fmt = fmtdesc.pixelformat; - } - fmtdesc.index++; - } - if (best_rank < (1 << 29)) { - setformat.fmt.pix.pixelformat = best_fmt; - sensor_format_ = best_fmt; - } - - if (!setformat.fmt.pix.pixelformat) { - ESP_LOGE(TAG, "no supported pixel format found"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - - ESP_LOGD(TAG, "selected pixel format: 0x%08lx", setformat.fmt.pix.pixelformat); - - if (ioctl(video_fd_, VIDIOC_S_FMT, &setformat) != 0) { - ESP_LOGE(TAG, "VIDIOC_S_FMT failed, errno=%d(%s)", errno, strerror(errno)); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - frame_.width = setformat.fmt.pix.height; - frame_.height = setformat.fmt.pix.width; -#else - frame_.width = setformat.fmt.pix.width; - frame_.height = setformat.fmt.pix.height; -#endif - - // 申请缓冲并mmap - struct v4l2_requestbuffers req = {}; - req.count = strcmp(video_device_name, ESP_VIDEO_MIPI_CSI_DEVICE_NAME) == 0 ? 2 : 1; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if (ioctl(video_fd_, VIDIOC_REQBUFS, &req) != 0) { - ESP_LOGE(TAG, "VIDIOC_REQBUFS failed"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - mmap_buffers_.resize(req.count); - for (uint32_t i = 0; i < req.count; i++) { - struct v4l2_buffer buf = {}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - if (ioctl(video_fd_, VIDIOC_QUERYBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_QUERYBUF failed"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - void* start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, video_fd_, buf.m.offset); - if (start == MAP_FAILED) { - ESP_LOGE(TAG, "mmap failed"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - mmap_buffers_[i].start = start; - mmap_buffers_[i].length = buf.length; - - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_QBUF failed"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - } - - int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (ioctl(video_fd_, VIDIOC_STREAMON, &type) != 0) { - ESP_LOGE(TAG, "VIDIOC_STREAMON failed"); - close(video_fd_); - video_fd_ = -1; - sensor_format_ = 0; - return; - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_ISP_VIDEO_DEVICE - // 当启用 ISP 时,ISP 需要一些照片来初始化参数,因此开启后后台拍摄5s照片并丢弃 - xTaskCreate( - [](void* arg) { - Esp32Camera* self = static_cast(arg); - uint16_t capture_count = 0; - TickType_t start = xTaskGetTickCount(); - TickType_t duration = 5000 / portTICK_PERIOD_MS; // 5s - while ((xTaskGetTickCount() - start) < duration) { - struct v4l2_buffer buf = {}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if (ioctl(self->video_fd_, VIDIOC_DQBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_DQBUF failed during init"); - vTaskDelay(10 / portTICK_PERIOD_MS); - continue; - } - if (ioctl(self->video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_QBUF failed during init"); - } - capture_count++; - } - ESP_LOGI(TAG, "Camera init success, captured %d frames in %dms", capture_count, - (xTaskGetTickCount() - start) * portTICK_PERIOD_MS); - self->streaming_on_ = true; - vTaskDelete(NULL); - }, - "CameraInitTask", 4096, this, 5, nullptr); -#else - ESP_LOGI(TAG, "Camera init success"); - streaming_on_ = true; -#endif // CONFIG_ESP_VIDEO_ENABLE_ISP_VIDEO_DEVICE -} - -Esp32Camera::~Esp32Camera() { - if (streaming_on_ && video_fd_ >= 0) { - int type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - ioctl(video_fd_, VIDIOC_STREAMOFF, &type); - } - for (auto& b : mmap_buffers_) { - if (b.start && b.length) { - munmap(b.start, b.length); - } - } - if (video_fd_ >= 0) { - close(video_fd_); - video_fd_ = -1; - } - sensor_format_ = 0; - esp_video_deinit(); -} - -void Esp32Camera::SetExplainUrl(const std::string& url, const std::string& token) { - explain_url_ = url; - explain_token_ = token; -} - -bool Esp32Camera::Capture() { - if (encoder_thread_.joinable()) { - encoder_thread_.join(); - } - - if (!streaming_on_ || video_fd_ < 0) { - return false; - } - - for (int i = 0; i < 3; i++) { - struct v4l2_buffer buf = {}; - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - if (ioctl(video_fd_, VIDIOC_DQBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_DQBUF failed"); - return false; - } - if (i == 2) { - // 保存帧副本到PSRAM - if (frame_.data) { - heap_caps_free(frame_.data); - frame_.data = nullptr; - frame_.format = 0; - } - frame_.len = buf.bytesused; - frame_.data = (uint8_t*)heap_caps_malloc(frame_.len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!frame_.data) { - ESP_LOGE(TAG, "alloc frame copy failed: need allocate %lu bytes", buf.bytesused); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - ESP_LOGW(TAG, "mmap_buffers_[buf.index].length = %d, sensor_width = %d, sensor_height = %d", - mmap_buffers_[buf.index].length, sensor_width_, sensor_height_); -#else - ESP_LOGW(TAG, "mmap_buffers_[buf.index].length = %d, frame.width = %d, frame.height = %d", - mmap_buffers_[buf.index].length, frame_.width, frame_.height); -#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - ESP_LOG_BUFFER_HEXDUMP(TAG, mmap_buffers_[buf.index].start, MIN(mmap_buffers_[buf.index].length, 256), - ESP_LOG_DEBUG); - - switch (sensor_format_) { - case V4L2_PIX_FMT_RGB565: - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_GREY: -#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - case V4L2_PIX_FMT_JPEG: -#endif // CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP - { - auto src16 = (uint16_t*)mmap_buffers_[buf.index].start; - auto dst16 = (uint16_t*)frame_.data; - size_t count = (size_t)mmap_buffers_[buf.index].length / 2; - for (size_t i = 0; i < count; i++) { - dst16[i] = __builtin_bswap16(src16[i]); - } - } -#else - memcpy(frame_.data, mmap_buffers_[buf.index].start, - MIN(mmap_buffers_[buf.index].length, frame_.len)); -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP - frame_.format = sensor_format_; - break; - case V4L2_PIX_FMT_YUV422P: { - // 这个格式是 422 YUYV,不是 planer - frame_.format = V4L2_PIX_FMT_YUYV; -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP - { - auto src16 = (uint16_t*)mmap_buffers_[buf.index].start; - auto dst16 = (uint16_t*)frame_.data; - size_t count = (size_t)mmap_buffers_[buf.index].length / 2; - for (size_t i = 0; i < count; i++) { - dst16[i] = __builtin_bswap16(src16[i]); - } - } -#else - memcpy(frame_.data, mmap_buffers_[buf.index].start, - MIN(mmap_buffers_[buf.index].length, frame_.len)); -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP - break; - } - case V4L2_PIX_FMT_RGB565X: { - // 大端序的 RGB565 需要转换为小端序 - // 目前 esp_video 的大小端都会返回格式为 RGB565,不会返回格式为 RGB565X,此 case 用于未来版本兼容 - auto src16 = (uint16_t*)mmap_buffers_[buf.index].start; - auto dst16 = (uint16_t*)frame_.data; - size_t pixel_count = (size_t)frame_.width * (size_t)frame_.height; - for (size_t i = 0; i < pixel_count; i++) { - dst16[i] = __builtin_bswap16(src16[i]); - } - frame_.format = V4L2_PIX_FMT_RGB565; - break; - } - default: - ESP_LOGE(TAG, "unsupported sensor format: 0x%08lx", sensor_format_); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE -#ifndef CONFIG_SOC_PPA_SUPPORTED - uint8_t* rotate_dst = - (uint8_t*)heap_caps_aligned_alloc(64, frame_.len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rotate_dst == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for rotate image"); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - uint8_t* rotate_src = (uint8_t*)frame_.data; - - esp_imgfx_rotate_cfg_t rotate_cfg = { - .in_res = - { - .width = static_cast(sensor_width_), - .height = static_cast(sensor_height_), - }, - .degree = IMAGE_ROTATION_ANGLE, - }; - switch (frame_.format) { - case V4L2_PIX_FMT_RGB565: - rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE; - break; - case V4L2_PIX_FMT_YUYV: - rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE; - break; - case V4L2_PIX_FMT_GREY: - rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_Y; - break; - case V4L2_PIX_FMT_RGB24: - rotate_cfg.in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888; - break; - default: - ESP_LOGE(TAG, "unsupported sensor format: 0x%08lx", sensor_format_); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - esp_imgfx_rotate_handle_t rotate_handle = nullptr; - esp_imgfx_err_t imgfx_err = esp_imgfx_rotate_open(&rotate_cfg, &rotate_handle); - if (imgfx_err != ESP_IMGFX_ERR_OK || rotate_handle == nullptr) { - ESP_LOGE(TAG, "esp_imgfx_rotate_create failed"); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - - esp_imgfx_data_t rotate_input_data = { - .data = rotate_src, - .data_len = frame_.len, - }; - esp_imgfx_data_t rotate_output_data = { - .data = rotate_dst, - .data_len = frame_.len, - }; - - imgfx_err = esp_imgfx_rotate_process(rotate_handle, &rotate_input_data, &rotate_output_data); - if (imgfx_err != ESP_IMGFX_ERR_OK) { - ESP_LOGE(TAG, "esp_imgfx_rotate_process failed"); - heap_caps_free(rotate_dst); - rotate_dst = nullptr; - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - esp_imgfx_rotate_close(rotate_handle); - rotate_handle = nullptr; - return false; - } - - frame_.data = rotate_dst; - - heap_caps_free(rotate_src); - rotate_src = nullptr; - - esp_imgfx_rotate_close(rotate_handle); - rotate_handle = nullptr; -#else // CONFIG_SOC_PPA_SUPPORTED - uint8_t* rotate_src = nullptr; - - ppa_srm_color_mode_t ppa_color_mode; - switch (frame_.format) { - case V4L2_PIX_FMT_RGB565: - rotate_src = (uint8_t*)frame_.data; - ppa_color_mode = PPA_SRM_COLOR_MODE_RGB565; - break; - case V4L2_PIX_FMT_RGB24: - rotate_src = (uint8_t*)frame_.data; - ppa_color_mode = PPA_SRM_COLOR_MODE_RGB888; - break; - case V4L2_PIX_FMT_YUYV: { - ESP_LOGW(TAG, "YUYV format is not supported for PPA rotation, using software conversion to RGB888"); - rotate_src = (uint8_t*)heap_caps_malloc(frame_.width * frame_.height * 3, - MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rotate_src == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for rotate image"); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - esp_imgfx_color_convert_cfg_t convert_cfg = { - .in_res = {.width = static_cast(frame_.width), - .height = static_cast(frame_.height)}, - .in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_YUYV, - .out_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888, - }; - esp_imgfx_color_convert_handle_t convert_handle = nullptr; - esp_imgfx_err_t err = esp_imgfx_color_convert_open(&convert_cfg, &convert_handle); - if (err != ESP_IMGFX_ERR_OK || convert_handle == nullptr) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_open failed"); - heap_caps_free(rotate_src); - rotate_src = nullptr; - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - esp_imgfx_data_t convert_input_data = { - .data = frame_.data, - .data_len = frame_.len, - }; - esp_imgfx_data_t convert_output_data = { - .data = rotate_src, - .data_len = static_cast(frame_.width * frame_.height * 3), - }; - err = esp_imgfx_color_convert_process(convert_handle, &convert_input_data, &convert_output_data); - if (err != ESP_IMGFX_ERR_OK) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_process failed"); - heap_caps_free(rotate_src); - rotate_src = nullptr; - esp_imgfx_color_convert_close(convert_handle); - convert_handle = nullptr; - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - esp_imgfx_color_convert_close(convert_handle); - convert_handle = nullptr; - ppa_color_mode = PPA_SRM_COLOR_MODE_RGB888; - heap_caps_free(frame_.data); - frame_.data = rotate_src; - frame_.len = frame_.width * frame_.height * 3; - break; - } - default: - ESP_LOGE(TAG, "unsupported sensor format for PPA rotation: 0x%08lx", sensor_format_); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - - uint8_t* rotate_dst = (uint8_t*)heap_caps_malloc( - frame_.width * frame_.height * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT | MALLOC_CAP_CACHE_ALIGNED); - if (rotate_dst == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for rotate image"); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - - ppa_client_handle_t ppa_client = nullptr; - ppa_client_config_t client_cfg = { - .oper_type = PPA_OPERATION_SRM, - .max_pending_trans_num = 1, - }; - esp_err_t err = ppa_register_client(&client_cfg, &ppa_client); - if (err != ESP_OK || ppa_client == nullptr) { - ESP_LOGE(TAG, "ppa_register_client failed: %d", (int)err); - heap_caps_free(rotate_dst); - rotate_dst = nullptr; - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - - ppa_srm_rotation_angle_t ppa_angle = IMAGE_ROTATION_ANGLE; - - ppa_srm_oper_config_t srm_cfg = {}; - srm_cfg.in.buffer = (void*)rotate_src; - srm_cfg.in.pic_w = sensor_width_; - srm_cfg.in.pic_h = sensor_height_; - srm_cfg.in.block_w = sensor_width_; - srm_cfg.in.block_h = sensor_height_; - srm_cfg.in.block_offset_x = 0; - srm_cfg.in.block_offset_y = 0; - srm_cfg.in.srm_cm = ppa_color_mode; - - srm_cfg.out.buffer = (void*)rotate_dst; - srm_cfg.out.buffer_size = frame_.len; - srm_cfg.out.pic_w = frame_.width; - srm_cfg.out.pic_h = frame_.height; - srm_cfg.out.block_offset_x = 0; - srm_cfg.out.block_offset_y = 0; - srm_cfg.out.srm_cm = PPA_SRM_COLOR_MODE_RGB565; - - // 等比例缩放 1.0 - srm_cfg.scale_x = 1.0f; - srm_cfg.scale_y = 1.0f; - srm_cfg.rotation_angle = ppa_angle; - srm_cfg.mode = PPA_TRANS_MODE_BLOCKING; - srm_cfg.user_data = nullptr; - - err = ppa_do_scale_rotate_mirror(ppa_client, &srm_cfg); - if (err != ESP_OK) { - ESP_LOGE(TAG, "ppa_do_scale_rotate_mirror failed: %d", (int)err); - heap_caps_free(rotate_dst); - rotate_dst = nullptr; - (void)ppa_unregister_client(ppa_client); - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "Cleanup: VIDIOC_QBUF failed"); - } - return false; - } - - (void)ppa_unregister_client(ppa_client); - - frame_.data = rotate_dst; - frame_.len = frame_.width * frame_.height * 2; - frame_.format = V4L2_PIX_FMT_RGB565; - heap_caps_free(rotate_src); - rotate_src = nullptr; -#endif // CONFIG_SOC_PPA_SUPPORTED -#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - } - - if (ioctl(video_fd_, VIDIOC_QBUF, &buf) != 0) { - ESP_LOGE(TAG, "VIDIOC_QBUF failed"); - } - } - - // 显示预览图片 - auto display = dynamic_cast(Board::GetInstance().GetDisplay()); - if (display != nullptr) { - if (!frame_.data) { - ESP_LOGE(TAG, "frame.data is null"); - return false; - } - uint16_t w = frame_.width; - uint16_t h = frame_.height; - size_t lvgl_image_size = frame_.len; - size_t stride = ((w * 2) + 3) & ~3; // 4字节对齐 - lv_color_format_t color_format = LV_COLOR_FORMAT_RGB565; - uint8_t* data = nullptr; - - switch (frame_.format) { - // LVGL 显示 YUV 系的图像似乎都有问题,暂时转换为 RGB565 显示 - case V4L2_PIX_FMT_YUYV: - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_RGB24: { - color_format = LV_COLOR_FORMAT_RGB565; - data = (uint8_t*)heap_caps_malloc(w * h * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for preview image"); - return false; - } - esp_imgfx_color_convert_cfg_t convert_cfg = { - .in_res = {.width = static_cast(frame_.width), - .height = static_cast(frame_.height)}, - .in_pixel_fmt = static_cast(frame_.format), - .out_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE, - .color_space_std = ESP_IMGFX_COLOR_SPACE_STD_BT601, - }; - esp_imgfx_color_convert_handle_t convert_handle = nullptr; - esp_imgfx_err_t err = esp_imgfx_color_convert_open(&convert_cfg, &convert_handle); - if (err != ESP_IMGFX_ERR_OK || convert_handle == nullptr) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_open failed"); - heap_caps_free(data); - data = nullptr; - return false; - } - esp_imgfx_data_t convert_input_data = { - .data = frame_.data, - .data_len = frame_.len, - }; - esp_imgfx_data_t convert_output_data = { - .data = data, - .data_len = static_cast(w * h * 2), - }; - err = esp_imgfx_color_convert_process(convert_handle, &convert_input_data, &convert_output_data); - if (err != ESP_IMGFX_ERR_OK) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_process failed"); - heap_caps_free(data); - data = nullptr; - esp_imgfx_color_convert_close(convert_handle); - convert_handle = nullptr; - return false; - } - esp_imgfx_color_convert_close(convert_handle); - convert_handle = nullptr; - lvgl_image_size = w * h * 2; - break; - } - - case V4L2_PIX_FMT_RGB565: - data = (uint8_t*)heap_caps_malloc(w * h * 2, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for preview image"); - return false; - } - memcpy(data, frame_.data, frame_.len); - lvgl_image_size = frame_.len; // fallthrough 时兼顾 YUYV 与 RGB565 - break; - -#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - case V4L2_PIX_FMT_JPEG: { - uint8_t* out_data = nullptr; // out data is allocated by jpeg_to_image - size_t out_len = 0; - size_t out_width = 0; - size_t out_height = 0; - size_t out_stride = 0; - - esp_err_t ret = - jpeg_to_image(frame_.data, frame_.len, &out_data, &out_len, &out_width, &out_height, &out_stride); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to decode JPEG image: %d (%s)", (int)ret, esp_err_to_name(ret)); - if (out_data) { - heap_caps_free(out_data); - out_data = nullptr; - } - return false; - } - - data = out_data; - w = out_width; - h = out_height; - lvgl_image_size = out_len; - stride = out_stride; - break; - } -#endif - default: - ESP_LOGE(TAG, "unsupported frame format: 0x%08lx", frame_.format); - return false; - } - - auto image = std::make_unique(data, lvgl_image_size, w, h, stride, color_format); - display->SetPreviewImage(std::move(image)); - } - return true; -} - -bool Esp32Camera::SetHMirror(bool enabled) { - if (video_fd_ < 0) - return false; - struct v4l2_ext_controls ctrls = {}; - struct v4l2_ext_control ctrl = {}; - ctrl.id = V4L2_CID_HFLIP; - ctrl.value = enabled ? 1 : 0; - ctrls.ctrl_class = V4L2_CTRL_CLASS_USER; - ctrls.count = 1; - ctrls.controls = &ctrl; - if (ioctl(video_fd_, VIDIOC_S_EXT_CTRLS, &ctrls) != 0) { - ESP_LOGE(TAG, "set HFLIP failed"); - return false; - } - return true; -} - -bool Esp32Camera::SetVFlip(bool enabled) { - if (video_fd_ < 0) - return false; - struct v4l2_ext_controls ctrls = {}; - struct v4l2_ext_control ctrl = {}; - ctrl.id = V4L2_CID_VFLIP; - ctrl.value = enabled ? 1 : 0; - ctrls.ctrl_class = V4L2_CTRL_CLASS_USER; - ctrls.count = 1; - ctrls.controls = &ctrl; - if (ioctl(video_fd_, VIDIOC_S_EXT_CTRLS, &ctrls) != 0) { - ESP_LOGE(TAG, "set VFLIP failed"); - return false; - } - return true; -} - -/** - * @brief 将摄像头捕获的图像发送到远程服务器进行AI分析和解释 - * - * 该函数将当前摄像头缓冲区中的图像编码为JPEG格式,并通过HTTP POST请求 - * 以multipart/form-data的形式发送到指定的解释服务器。服务器将根据提供的 - * 问题对图像进行AI分析并返回结果。 - * - * 实现特点: - * - 使用独立线程编码JPEG,与主线程分离 - * - 采用分块传输编码(chunked transfer encoding)优化内存使用 - * - 通过队列机制实现编码线程和发送线程的数据同步 - * - 支持设备ID、客户端ID和认证令牌的HTTP头部配置 - * - * @param question 要向AI提出的关于图像的问题,将作为表单字段发送 - * @return std::string 服务器返回的JSON格式响应字符串 - * 成功时包含AI分析结果,失败时包含错误信息 - * 格式示例:{"success": true, "result": "分析结果"} - * {"success": false, "message": "错误信息"} - * - * @note 调用此函数前必须先调用SetExplainUrl()设置服务器URL - * @note 函数会等待之前的编码线程完成后再开始新的处理 - * @warning 如果摄像头缓冲区为空或网络连接失败,将返回错误信息 - */ -std::string Esp32Camera::Explain(const std::string& question) { - if (explain_url_.empty()) { - throw std::runtime_error("Image explain URL or token is not set"); - } - - // 创建局部的 JPEG 队列, 40 entries is about to store 512 * 40 = 20480 bytes of JPEG data - QueueHandle_t jpeg_queue = xQueueCreate(40, sizeof(JpegChunk)); - if (jpeg_queue == nullptr) { - ESP_LOGE(TAG, "Failed to create JPEG queue"); - throw std::runtime_error("Failed to create JPEG queue"); - } - - // We spawn a thread to encode the image to JPEG using optimized encoder (cost about 500ms and 8KB SRAM) - encoder_thread_ = std::thread([this, jpeg_queue]() { - uint16_t w = frame_.width ? frame_.width : 320; - uint16_t h = frame_.height ? frame_.height : 240; - v4l2_pix_fmt_t enc_fmt = frame_.format; - bool ok = image_to_jpeg_cb( - frame_.data, frame_.len, w, h, enc_fmt, 80, - [](void* arg, size_t index, const void* data, size_t len) -> size_t { - auto jpeg_queue = static_cast(arg); - JpegChunk chunk = {.data = nullptr, .len = len}; - if (index == 0 && data != nullptr && len > 0) { - chunk.data = (uint8_t*)heap_caps_aligned_alloc(16, len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (chunk.data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate %zu bytes for JPEG chunk", len); - chunk.len = 0; - } else { - memcpy(chunk.data, data, len); - } - } else { - chunk.len = 0; // Sentinel or error - } - xQueueSend(jpeg_queue, &chunk, portMAX_DELAY); - return len; - }, - jpeg_queue); - - if (!ok) { - JpegChunk chunk = {.data = nullptr, .len = 0}; - xQueueSend(jpeg_queue, &chunk, portMAX_DELAY); - } - }); - - auto network = Board::GetInstance().GetNetwork(); - auto http = network->CreateHttp(3); - // 构造multipart/form-data请求体 - std::string boundary = "----ESP32_CAMERA_BOUNDARY"; - - // 配置HTTP客户端,使用分块传输编码 - http->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); - http->SetHeader("Client-Id", Board::GetInstance().GetUuid().c_str()); - if (!explain_token_.empty()) { - http->SetHeader("Authorization", "Bearer " + explain_token_); - } - http->SetHeader("Content-Type", "multipart/form-data; boundary=" + boundary); - http->SetHeader("Transfer-Encoding", "chunked"); - if (!http->Open("POST", explain_url_)) { - ESP_LOGE(TAG, "Failed to connect to explain URL"); - // Clear the queue - encoder_thread_.join(); - JpegChunk chunk; - while (xQueueReceive(jpeg_queue, &chunk, portMAX_DELAY) == pdPASS) { - if (chunk.data != nullptr) { - heap_caps_free(chunk.data); - } else { - break; - } - } - vQueueDelete(jpeg_queue); - throw std::runtime_error("Failed to connect to explain URL"); - } - - { - // 第一块:question字段 - std::string question_field; - question_field += "--" + boundary + "\r\n"; - question_field += "Content-Disposition: form-data; name=\"question\"\r\n"; - question_field += "\r\n"; - question_field += question + "\r\n"; - http->Write(question_field.c_str(), question_field.size()); - } - { - // 第二块:文件字段头部 - std::string file_header; - file_header += "--" + boundary + "\r\n"; - file_header += "Content-Disposition: form-data; name=\"file\"; filename=\"camera.jpg\"\r\n"; - file_header += "Content-Type: image/jpeg\r\n"; - file_header += "\r\n"; - http->Write(file_header.c_str(), file_header.size()); - } - - // 第三块:JPEG数据 - size_t total_sent = 0; - bool saw_terminator = false; - while (true) { - JpegChunk chunk; - if (xQueueReceive(jpeg_queue, &chunk, portMAX_DELAY) != pdPASS) { - ESP_LOGE(TAG, "Failed to receive JPEG chunk"); - break; - } - if (chunk.data == nullptr) { - saw_terminator = true; - break; // The last chunk - } - http->Write((const char*)chunk.data, chunk.len); - total_sent += chunk.len; - heap_caps_free(chunk.data); - } - // Wait for the encoder thread to finish - encoder_thread_.join(); - // 清理队列 - vQueueDelete(jpeg_queue); - - if (!saw_terminator || total_sent == 0) { - ESP_LOGE(TAG, "JPEG encoder failed or produced empty output"); - throw std::runtime_error("Failed to encode image to JPEG"); - } - - { - // 第四块:multipart尾部 - std::string multipart_footer; - multipart_footer += "\r\n--" + boundary + "--\r\n"; - http->Write(multipart_footer.c_str(), multipart_footer.size()); - } - // 结束块 - http->Write("", 0); - - if (http->GetStatusCode() != 200) { - ESP_LOGE(TAG, "Failed to upload photo, status code: %d", http->GetStatusCode()); - throw std::runtime_error("Failed to upload photo"); - } - - std::string result = http->ReadAll(); - http->Close(); - - // Get remain task stack size - size_t remain_stack_size = uxTaskGetStackHighWaterMark(nullptr); - ESP_LOGI(TAG, "Explain image size=%d bytes, compressed size=%d, remain stack size=%d, question=%s\n%s", - (int)frame_.len, (int)total_sent, (int)remain_stack_size, question.c_str(), result.c_str()); - return result; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.h deleted file mode 100644 index 84366aca..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/esp32_camera.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once -#include "sdkconfig.h" - -#ifndef CONFIG_IDF_TARGET_ESP32 -#include -#include -#include -#include - -#include -#include - -#include "camera.h" -#include "jpg/image_to_jpeg.h" -#include "esp_video_init.h" - -struct JpegChunk { - uint8_t* data; - size_t len; -}; - -class Esp32Camera : public Camera { -private: - struct FrameBuffer { - uint8_t *data = nullptr; - size_t len = 0; - uint16_t width = 0; - uint16_t height = 0; - v4l2_pix_fmt_t format = 0; - } frame_; - v4l2_pix_fmt_t sensor_format_ = 0; -#ifdef CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - uint16_t sensor_width_ = 0; - uint16_t sensor_height_ = 0; -#endif // CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE - int video_fd_ = -1; - bool streaming_on_ = false; - struct MmapBuffer { void *start = nullptr; size_t length = 0; }; - std::vector mmap_buffers_; - std::string explain_url_; - std::string explain_token_; - std::thread encoder_thread_; - -public: - Esp32Camera(const esp_video_init_config_t& config); - ~Esp32Camera(); - - virtual void SetExplainUrl(const std::string& url, const std::string& token); - virtual bool Capture(); - // 翻转控制函数 - virtual bool SetHMirror(bool enabled) override; - virtual bool SetVFlip(bool enabled) override; - virtual std::string Explain(const std::string& question); -}; - -#endif // ndef CONFIG_IDF_TARGET_ESP32 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.cc deleted file mode 100644 index 835997d1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "i2c_device.h" - -#include - -#define TAG "I2cDevice" - - -I2cDevice::I2cDevice(i2c_master_bus_handle_t i2c_bus, uint8_t addr) { - i2c_device_config_t i2c_device_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = addr, - .scl_speed_hz = 400 * 1000, - .scl_wait_us = 0, - .flags = { - .disable_ack_check = 0, - }, - }; - ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus, &i2c_device_cfg, &i2c_device_)); - assert(i2c_device_ != NULL); -} - -void I2cDevice::WriteReg(uint8_t reg, uint8_t value) { - uint8_t buffer[2] = {reg, value}; - ESP_ERROR_CHECK(i2c_master_transmit(i2c_device_, buffer, 2, 100)); -} - -uint8_t I2cDevice::ReadReg(uint8_t reg) { - uint8_t buffer[1]; - ESP_ERROR_CHECK(i2c_master_transmit_receive(i2c_device_, ®, 1, buffer, 1, 100)); - return buffer[0]; -} - -void I2cDevice::ReadRegs(uint8_t reg, uint8_t* buffer, size_t length) { - ESP_ERROR_CHECK(i2c_master_transmit_receive(i2c_device_, ®, 1, buffer, length, 100)); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.h deleted file mode 100644 index 7bc917bf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/i2c_device.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef I2C_DEVICE_H -#define I2C_DEVICE_H - -#include - -class I2cDevice { -public: - I2cDevice(i2c_master_bus_handle_t i2c_bus, uint8_t addr); - -protected: - i2c_master_dev_handle_t i2c_device_; - - void WriteReg(uint8_t reg, uint8_t value); - uint8_t ReadReg(uint8_t reg); - void ReadRegs(uint8_t reg, uint8_t* buffer, size_t length); -}; - -#endif // I2C_DEVICE_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.cc deleted file mode 100644 index 350fda25..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.cc +++ /dev/null @@ -1,52 +0,0 @@ -#include "knob.h" - -static const char* TAG = "Knob"; - -Knob::Knob(gpio_num_t pin_a, gpio_num_t pin_b) { - knob_config_t config = { - .default_direction = 0, - .gpio_encoder_a = static_cast(pin_a), - .gpio_encoder_b = static_cast(pin_b), - }; - - esp_err_t err = ESP_OK; - knob_handle_ = iot_knob_create(&config); - if (knob_handle_ == NULL) { - ESP_LOGE(TAG, "Failed to create knob instance"); - return; - } - - err = iot_knob_register_cb(knob_handle_, KNOB_LEFT, knob_callback, this); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to register left callback: %s", esp_err_to_name(err)); - return; - } - - err = iot_knob_register_cb(knob_handle_, KNOB_RIGHT, knob_callback, this); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to register right callback: %s", esp_err_to_name(err)); - return; - } - - ESP_LOGI(TAG, "Knob initialized with pins A:%d B:%d", pin_a, pin_b); -} - -Knob::~Knob() { - if (knob_handle_ != NULL) { - iot_knob_delete(knob_handle_); - knob_handle_ = NULL; - } -} - -void Knob::OnRotate(std::function callback) { - on_rotate_ = callback; -} - -void Knob::knob_callback(void* arg, void* data) { - Knob* knob = static_cast(data); - knob_event_t event = iot_knob_get_event(arg); - - if (knob->on_rotate_) { - knob->on_rotate_(event == KNOB_RIGHT); - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.h deleted file mode 100644 index efea5f56..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/knob.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef KNOB_H_ -#define KNOB_H_ - -#include -#include -#include -#include - -class Knob { -public: - Knob(gpio_num_t pin_a, gpio_num_t pin_b); - ~Knob(); - - void OnRotate(std::function callback); - -private: - static void knob_callback(void* arg, void* data); - - knob_handle_t knob_handle_; - gpio_num_t pin_a_; - gpio_num_t pin_b_; - std::function on_rotate_; -}; - -#endif // KNOB_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/lamp_controller.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/lamp_controller.h deleted file mode 100644 index 1ed142c7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/lamp_controller.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __LAMP_CONTROLLER_H__ -#define __LAMP_CONTROLLER_H__ - -#include "mcp_server.h" - - -class LampController { -private: - bool power_ = false; - gpio_num_t gpio_num_; - -public: - LampController(gpio_num_t gpio_num) : gpio_num_(gpio_num) { - gpio_config_t config = { - .pin_bit_mask = (1ULL << gpio_num_), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&config)); - gpio_set_level(gpio_num_, 0); - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.lamp.get_state", "Get the power state of the lamp", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return power_ ? "{\"power\": true}" : "{\"power\": false}"; - }); - - mcp_server.AddTool("self.lamp.turn_on", "Turn on the lamp", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - power_ = true; - gpio_set_level(gpio_num_, 1); - return true; - }); - - mcp_server.AddTool("self.lamp.turn_off", "Turn off the lamp", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - power_ = false; - gpio_set_level(gpio_num_, 0); - return true; - }); - } -}; - - -#endif // __LAMP_CONTROLLER_H__ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.cc deleted file mode 100644 index fc551841..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.cc +++ /dev/null @@ -1,274 +0,0 @@ -#include "ml307_board.h" - -#include "application.h" -#include "display.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include - -static const char *TAG = "Ml307Board"; - -// Maximum retry count for modem detection -static constexpr int MODEM_DETECT_MAX_RETRIES = 30; -// Maximum retry count for network registration -static constexpr int NETWORK_REG_MAX_RETRIES = 6; - -Ml307Board::Ml307Board(gpio_num_t tx_pin, gpio_num_t rx_pin, gpio_num_t dtr_pin) : tx_pin_(tx_pin), rx_pin_(rx_pin), dtr_pin_(dtr_pin) { -} - -std::string Ml307Board::GetBoardType() { - return "ml307"; -} - -void Ml307Board::SetNetworkEventCallback(NetworkEventCallback callback) { - network_event_callback_ = std::move(callback); -} - -void Ml307Board::OnNetworkEvent(NetworkEvent event, const std::string& data) { - switch (event) { - case NetworkEvent::ModemDetecting: - ESP_LOGI(TAG, "Detecting modem..."); - break; - case NetworkEvent::Connecting: - ESP_LOGI(TAG, "Registering network..."); - break; - case NetworkEvent::Connected: - ESP_LOGI(TAG, "Network connected"); - break; - case NetworkEvent::Disconnected: - ESP_LOGW(TAG, "Network disconnected"); - break; - case NetworkEvent::ModemErrorNoSim: - ESP_LOGE(TAG, "No SIM card detected"); - break; - case NetworkEvent::ModemErrorRegDenied: - ESP_LOGE(TAG, "Network registration denied"); - break; - case NetworkEvent::ModemErrorInitFailed: - ESP_LOGE(TAG, "Modem initialization failed"); - break; - case NetworkEvent::ModemErrorTimeout: - ESP_LOGE(TAG, "Operation timeout"); - break; - default: - break; - } - - // Notify external callback if set - if (network_event_callback_) { - network_event_callback_(event, data); - } -} - -void Ml307Board::NetworkTask() { - auto& application = Application::GetInstance(); - - // Notify modem detection started - OnNetworkEvent(NetworkEvent::ModemDetecting); - - // Try to detect modem with retry limit - int detect_retries = 0; - while (detect_retries < MODEM_DETECT_MAX_RETRIES) { - modem_ = AtModem::Detect(tx_pin_, rx_pin_, dtr_pin_, 921600); - if (modem_ != nullptr) { - break; - } - detect_retries++; - vTaskDelay(pdMS_TO_TICKS(1000)); - } - - if (modem_ == nullptr) { - ESP_LOGE(TAG, "Failed to detect modem after %d retries", MODEM_DETECT_MAX_RETRIES); - OnNetworkEvent(NetworkEvent::ModemErrorInitFailed); - return; - } - - ESP_LOGI(TAG, "Modem detected successfully"); - - // Set up network state change callback - // Note: Don't call GetCarrierName() here as it sends AT command and will block ReceiveTask - modem_->OnNetworkStateChanged([this, &application](bool network_ready) { - if (network_ready) { - OnNetworkEvent(NetworkEvent::Connected); - } else { - OnNetworkEvent(NetworkEvent::Disconnected); - } - }); - - // Notify network registration started - OnNetworkEvent(NetworkEvent::Connecting); - - // Wait for network ready with retry limit - int reg_retries = 0; - while (reg_retries < NETWORK_REG_MAX_RETRIES) { - auto result = modem_->WaitForNetworkReady(); - if (result == NetworkStatus::Ready) { - break; - } else if (result == NetworkStatus::ErrorInsertPin) { - OnNetworkEvent(NetworkEvent::ModemErrorNoSim); - } else if (result == NetworkStatus::ErrorRegistrationDenied) { - OnNetworkEvent(NetworkEvent::ModemErrorRegDenied); - } else if (result == NetworkStatus::ErrorTimeout) { - OnNetworkEvent(NetworkEvent::ModemErrorTimeout); - } - reg_retries++; - vTaskDelay(pdMS_TO_TICKS(10000)); - } - - if (!modem_->network_ready()) { - ESP_LOGE(TAG, "Failed to register network after %d retries", NETWORK_REG_MAX_RETRIES); - return; - } - - // Print the ML307 modem information - std::string module_revision = modem_->GetModuleRevision(); - std::string imei = modem_->GetImei(); - std::string iccid = modem_->GetIccid(); - ESP_LOGI(TAG, "ML307 Revision: %s", module_revision.c_str()); - ESP_LOGI(TAG, "ML307 IMEI: %s", imei.c_str()); - ESP_LOGI(TAG, "ML307 ICCID: %s", iccid.c_str()); -} - -void Ml307Board::StartNetwork() { - // Create network initialization task and return immediately - xTaskCreate([](void* arg) { - Ml307Board* board = static_cast(arg); - board->NetworkTask(); - vTaskDelete(NULL); - }, "ml307_net", 4096, this, 5, NULL); -} - -NetworkInterface* Ml307Board::GetNetwork() { - return modem_.get(); -} - -const char* Ml307Board::GetNetworkStateIcon() { - if (modem_ == nullptr || !modem_->network_ready()) { - return FONT_AWESOME_SIGNAL_OFF; - } - int csq = modem_->GetCsq(); - if (csq == -1) { - return FONT_AWESOME_SIGNAL_OFF; - } else if (csq >= 0 && csq <= 9) { - return FONT_AWESOME_SIGNAL_WEAK; - } else if (csq >= 10 && csq <= 14) { - return FONT_AWESOME_SIGNAL_FAIR; - } else if (csq >= 15 && csq <= 19) { - return FONT_AWESOME_SIGNAL_GOOD; - } else if (csq >= 20 && csq <= 31) { - return FONT_AWESOME_SIGNAL_STRONG; - } - - ESP_LOGW(TAG, "Invalid CSQ: %d", csq); - return FONT_AWESOME_SIGNAL_OFF; -} - -std::string Ml307Board::GetBoardJson() { - // Set the board type for OTA - std::string board_json = std::string("{\"type\":\"" BOARD_TYPE "\","); - board_json += "\"name\":\"" BOARD_NAME "\","; - board_json += "\"revision\":\"" + modem_->GetModuleRevision() + "\","; - board_json += "\"carrier\":\"" + modem_->GetCarrierName() + "\","; - board_json += "\"csq\":\"" + std::to_string(modem_->GetCsq()) + "\","; - board_json += "\"imei\":\"" + modem_->GetImei() + "\","; - board_json += "\"iccid\":\"" + modem_->GetIccid() + "\","; - board_json += "\"cereg\":" + modem_->GetRegistrationState().ToString() + "}"; - return board_json; -} - -void Ml307Board::SetPowerSaveLevel(PowerSaveLevel level) { - // TODO: Implement power save level for ML307 - (void)level; -} - -std::string Ml307Board::GetDeviceStatusJson() { - /* - * 返回设备状态JSON - * - * 返回的JSON结构如下: - * { - * "audio_speaker": { - * "volume": 70 - * }, - * "screen": { - * "brightness": 100, - * "theme": "light" - * }, - * "battery": { - * "level": 50, - * "charging": true - * }, - * "network": { - * "type": "cellular", - * "carrier": "CHINA MOBILE", - * "csq": 10 - * } - * } - */ - auto& board = Board::GetInstance(); - auto root = cJSON_CreateObject(); - - // Audio speaker - auto audio_speaker = cJSON_CreateObject(); - auto audio_codec = board.GetAudioCodec(); - if (audio_codec) { - cJSON_AddNumberToObject(audio_speaker, "volume", audio_codec->output_volume()); - } - cJSON_AddItemToObject(root, "audio_speaker", audio_speaker); - - // Screen brightness - auto backlight = board.GetBacklight(); - auto screen = cJSON_CreateObject(); - if (backlight) { - cJSON_AddNumberToObject(screen, "brightness", backlight->brightness()); - } - auto display = board.GetDisplay(); - if (display && display->height() > 64) { // For LCD display only - auto theme = display->GetTheme(); - if (theme != nullptr) { - cJSON_AddStringToObject(screen, "theme", theme->name().c_str()); - } - } - cJSON_AddItemToObject(root, "screen", screen); - - // Battery - int battery_level = 0; - bool charging = false; - bool discharging = false; - if (board.GetBatteryLevel(battery_level, charging, discharging)) { - cJSON* battery = cJSON_CreateObject(); - cJSON_AddNumberToObject(battery, "level", battery_level); - cJSON_AddBoolToObject(battery, "charging", charging); - cJSON_AddItemToObject(root, "battery", battery); - } - - // Network - auto network = cJSON_CreateObject(); - cJSON_AddStringToObject(network, "type", "cellular"); - cJSON_AddStringToObject(network, "carrier", modem_->GetCarrierName().c_str()); - int csq = modem_->GetCsq(); - if (csq == -1) { - cJSON_AddStringToObject(network, "signal", "unknown"); - } else if (csq >= 0 && csq <= 14) { - cJSON_AddStringToObject(network, "signal", "very weak"); - } else if (csq >= 15 && csq <= 19) { - cJSON_AddStringToObject(network, "signal", "weak"); - } else if (csq >= 20 && csq <= 24) { - cJSON_AddStringToObject(network, "signal", "medium"); - } else if (csq >= 25 && csq <= 31) { - cJSON_AddStringToObject(network, "signal", "strong"); - } - cJSON_AddItemToObject(root, "network", network); - - auto json_str = cJSON_PrintUnformatted(root); - std::string json(json_str); - cJSON_free(json_str); - cJSON_Delete(root); - return json; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.h deleted file mode 100644 index 6e669918..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/ml307_board.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ML307_BOARD_H -#define ML307_BOARD_H - -#include -#include -#include "board.h" - - -class Ml307Board : public Board { -protected: - std::unique_ptr modem_; - gpio_num_t tx_pin_; - gpio_num_t rx_pin_; - gpio_num_t dtr_pin_; - NetworkEventCallback network_event_callback_; - - virtual std::string GetBoardJson() override; - - // Internal helper to trigger network event callback - void OnNetworkEvent(NetworkEvent event, const std::string& data = ""); - - // Network initialization task (runs in FreeRTOS task) - static void NetworkTaskEntry(void* arg); - void NetworkTask(); - -public: - Ml307Board(gpio_num_t tx_pin, gpio_num_t rx_pin, gpio_num_t dtr_pin = GPIO_NUM_NC); - virtual std::string GetBoardType() override; - virtual void StartNetwork() override; - virtual void SetNetworkEventCallback(NetworkEventCallback callback) override; - virtual NetworkInterface* GetNetwork() override; - virtual const char* GetNetworkStateIcon() override; - virtual void SetPowerSaveLevel(PowerSaveLevel level) override; - virtual AudioCodec* GetAudioCodec() override { return nullptr; } - virtual std::string GetDeviceStatusJson() override; -}; - -#endif // ML307_BOARD_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.cc deleted file mode 100644 index 522e64c5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.cc +++ /dev/null @@ -1,132 +0,0 @@ -#include "power_save_timer.h" -#include "application.h" -#include "settings.h" - -#include - -#define TAG "PowerSaveTimer" - - -PowerSaveTimer::PowerSaveTimer(int cpu_max_freq, int seconds_to_sleep, int seconds_to_shutdown) - : cpu_max_freq_(cpu_max_freq), seconds_to_sleep_(seconds_to_sleep), seconds_to_shutdown_(seconds_to_shutdown) { - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - auto self = static_cast(arg); - self->PowerSaveCheck(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "power_save_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &power_save_timer_)); -} - -PowerSaveTimer::~PowerSaveTimer() { - esp_timer_stop(power_save_timer_); - esp_timer_delete(power_save_timer_); -} - -void PowerSaveTimer::SetEnabled(bool enabled) { - if (enabled && !enabled_) { - Settings settings("wifi", false); - if (!settings.GetBool("sleep_mode", true)) { - ESP_LOGI(TAG, "Power save timer is disabled by settings"); - return; - } - - ticks_ = 0; - enabled_ = enabled; - ESP_ERROR_CHECK(esp_timer_start_periodic(power_save_timer_, 1000000)); - ESP_LOGI(TAG, "Power save timer enabled"); - } else if (!enabled && enabled_) { - ESP_ERROR_CHECK(esp_timer_stop(power_save_timer_)); - enabled_ = enabled; - WakeUp(); - ESP_LOGI(TAG, "Power save timer disabled"); - } -} - -void PowerSaveTimer::OnEnterSleepMode(std::function callback) { - on_enter_sleep_mode_ = callback; -} - -void PowerSaveTimer::OnExitSleepMode(std::function callback) { - on_exit_sleep_mode_ = callback; -} - -void PowerSaveTimer::OnShutdownRequest(std::function callback) { - on_shutdown_request_ = callback; -} - -void PowerSaveTimer::PowerSaveCheck() { - auto& app = Application::GetInstance(); - if (!in_sleep_mode_ && !app.CanEnterSleepMode()) { - ticks_ = 0; - return; - } - - ticks_++; - if (seconds_to_sleep_ != -1 && ticks_ >= seconds_to_sleep_) { - if (!in_sleep_mode_) { - ESP_LOGI(TAG, "Enabling power save mode"); - in_sleep_mode_ = true; - if (on_enter_sleep_mode_) { - on_enter_sleep_mode_(); - } - - if (cpu_max_freq_ != -1) { - // Disable wake word detection - auto& audio_service = app.GetAudioService(); - is_wake_word_running_ = audio_service.IsWakeWordRunning(); - if (is_wake_word_running_) { - audio_service.EnableWakeWordDetection(false); - vTaskDelay(pdMS_TO_TICKS(100)); - } - // Disable audio input - auto codec = Board::GetInstance().GetAudioCodec(); - if (codec) { - codec->EnableInput(false); - } - - esp_pm_config_t pm_config = { - .max_freq_mhz = cpu_max_freq_, - .min_freq_mhz = 40, - .light_sleep_enable = true, - }; - esp_pm_configure(&pm_config); - } - } - } - if (seconds_to_shutdown_ != -1 && ticks_ >= seconds_to_shutdown_ && on_shutdown_request_) { - on_shutdown_request_(); - } -} - -void PowerSaveTimer::WakeUp() { - ticks_ = 0; - if (in_sleep_mode_) { - ESP_LOGI(TAG, "Exiting power save mode"); - in_sleep_mode_ = false; - - if (cpu_max_freq_ != -1) { - esp_pm_config_t pm_config = { - .max_freq_mhz = cpu_max_freq_, - .min_freq_mhz = cpu_max_freq_, - .light_sleep_enable = false, - }; - esp_pm_configure(&pm_config); - - // Enable wake word detection - auto& app = Application::GetInstance(); - auto& audio_service = app.GetAudioService(); - if (is_wake_word_running_) { - audio_service.EnableWakeWordDetection(true); - } - } - - if (on_exit_sleep_mode_) { - on_exit_sleep_mode_(); - } - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.h deleted file mode 100644 index 4c95671d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/power_save_timer.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -#include -#include - -class PowerSaveTimer { -public: - PowerSaveTimer(int cpu_max_freq, int seconds_to_sleep = 20, int seconds_to_shutdown = -1); - ~PowerSaveTimer(); - - void SetEnabled(bool enabled); - void OnEnterSleepMode(std::function callback); - void OnExitSleepMode(std::function callback); - void OnShutdownRequest(std::function callback); - void WakeUp(); - -private: - void PowerSaveCheck(); - - esp_timer_handle_t power_save_timer_ = nullptr; - bool enabled_ = false; - bool in_sleep_mode_ = false; - bool is_wake_word_running_ = false; - int ticks_ = 0; - int cpu_max_freq_; - int seconds_to_sleep_; - int seconds_to_shutdown_; - - std::function on_enter_sleep_mode_; - std::function on_exit_sleep_mode_; - std::function on_shutdown_request_; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.cc deleted file mode 100644 index d6b0bc96..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.cc +++ /dev/null @@ -1,57 +0,0 @@ -#include "press_to_talk_mcp_tool.h" -#include - -static const char* TAG = "PressToTalkMcpTool"; - -PressToTalkMcpTool::PressToTalkMcpTool() - : press_to_talk_enabled_(false) { -} - -void PressToTalkMcpTool::Initialize() { - // 从设置中读取当前状态 - Settings settings("vendor"); - press_to_talk_enabled_ = settings.GetInt("press_to_talk", 0) != 0; - - // 注册MCP工具 - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.set_press_to_talk", - "Switch between press to talk mode (长按说话) and click to talk mode (单击说话).\n" - "The mode can be `press_to_talk` or `click_to_talk`.", - PropertyList({ - Property("mode", kPropertyTypeString) - }), - [this](const PropertyList& properties) -> ReturnValue { - return HandleSetPressToTalk(properties); - }); - - ESP_LOGI(TAG, "PressToTalkMcpTool initialized, current mode: %s", - press_to_talk_enabled_ ? "press_to_talk" : "click_to_talk"); -} - -bool PressToTalkMcpTool::IsPressToTalkEnabled() const { - return press_to_talk_enabled_; -} - -ReturnValue PressToTalkMcpTool::HandleSetPressToTalk(const PropertyList& properties) { - auto mode = properties["mode"].value(); - - if (mode == "press_to_talk") { - SetPressToTalkEnabled(true); - ESP_LOGI(TAG, "Switched to press to talk mode"); - return true; - } else if (mode == "click_to_talk") { - SetPressToTalkEnabled(false); - ESP_LOGI(TAG, "Switched to click to talk mode"); - return true; - } - - throw std::runtime_error("Invalid mode: " + mode); -} - -void PressToTalkMcpTool::SetPressToTalkEnabled(bool enabled) { - press_to_talk_enabled_ = enabled; - - Settings settings("vendor", true); - settings.SetInt("press_to_talk", enabled ? 1 : 0); - ESP_LOGI(TAG, "Press to talk enabled: %d", enabled); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.h deleted file mode 100644 index 3231a286..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/press_to_talk_mcp_tool.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef PRESS_TO_TALK_MCP_TOOL_H -#define PRESS_TO_TALK_MCP_TOOL_H - -#include "mcp_server.h" -#include "settings.h" - -// 可复用的按键说话模式MCP工具类 -class PressToTalkMcpTool { -private: - bool press_to_talk_enabled_; - -public: - PressToTalkMcpTool(); - - // 初始化工具,注册到MCP服务器 - void Initialize(); - - // 获取当前按键说话模式状态 - bool IsPressToTalkEnabled() const; - -private: - // MCP工具的回调函数 - ReturnValue HandleSetPressToTalk(const PropertyList& properties); - - // 内部方法:设置press to talk状态并保存到设置 - void SetPressToTalkEnabled(bool enabled); -}; - -#endif // PRESS_TO_TALK_MCP_TOOL_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.cc deleted file mode 100644 index 3490f6ce..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.cc +++ /dev/null @@ -1,133 +0,0 @@ -#include "sleep_timer.h" -#include "application.h" -#include "board.h" -#include "display.h" -#include "settings.h" - -#include -#include -#include - -#define TAG "SleepTimer" - - -SleepTimer::SleepTimer(int seconds_to_light_sleep, int seconds_to_deep_sleep) - : seconds_to_light_sleep_(seconds_to_light_sleep), seconds_to_deep_sleep_(seconds_to_deep_sleep) { - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - auto self = static_cast(arg); - self->CheckTimer(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "sleep_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &sleep_timer_)); -} - -SleepTimer::~SleepTimer() { - esp_timer_stop(sleep_timer_); - esp_timer_delete(sleep_timer_); -} - -void SleepTimer::SetEnabled(bool enabled) { - if (enabled && !enabled_) { - Settings settings("wifi", false); - if (!settings.GetBool("sleep_mode", true)) { - ESP_LOGI(TAG, "Power save timer is disabled by settings"); - return; - } - - ticks_ = 0; - enabled_ = enabled; - ESP_ERROR_CHECK(esp_timer_start_periodic(sleep_timer_, 1000000)); - ESP_LOGI(TAG, "Sleep timer enabled"); - } else if (!enabled && enabled_) { - ESP_ERROR_CHECK(esp_timer_stop(sleep_timer_)); - enabled_ = enabled; - WakeUp(); - ESP_LOGI(TAG, "Sleep timer disabled"); - } -} - -void SleepTimer::OnEnterLightSleepMode(std::function callback) { - on_enter_light_sleep_mode_ = callback; -} - -void SleepTimer::OnExitLightSleepMode(std::function callback) { - on_exit_light_sleep_mode_ = callback; -} - -void SleepTimer::OnEnterDeepSleepMode(std::function callback) { - on_enter_deep_sleep_mode_ = callback; -} - -void SleepTimer::CheckTimer() { - auto& app = Application::GetInstance(); - if (!app.CanEnterSleepMode()) { - ticks_ = 0; - return; - } - - ticks_++; - if (seconds_to_light_sleep_ != -1 && ticks_ >= seconds_to_light_sleep_) { - if (!in_light_sleep_mode_) { - in_light_sleep_mode_ = true; - if (on_enter_light_sleep_mode_) { - on_enter_light_sleep_mode_(); - } - - auto& audio_service = app.GetAudioService(); - bool is_wake_word_running = audio_service.IsWakeWordRunning(); - if (is_wake_word_running) { - audio_service.EnableWakeWordDetection(false); - vTaskDelay(pdMS_TO_TICKS(100)); - } - - app.Schedule([this, &app]() { - while (in_light_sleep_mode_) { - auto& board = Board::GetInstance(); - board.GetDisplay()->UpdateStatusBar(true); - lv_refr_now(nullptr); - lvgl_port_stop(); - - // 配置timer唤醒源(30秒后自动唤醒) - esp_sleep_enable_timer_wakeup(30 * 1000000); - - // 进入light sleep模式 - esp_light_sleep_start(); - lvgl_port_resume(); - - auto wakeup_reason = esp_sleep_get_wakeup_cause(); - ESP_LOGI(TAG, "Wake up from light sleep, wakeup_reason: %d", wakeup_reason); - if (wakeup_reason != ESP_SLEEP_WAKEUP_TIMER) { - break; - } - } - WakeUp(); - }); - - if (is_wake_word_running) { - audio_service.EnableWakeWordDetection(true); - } - } - } - if (seconds_to_deep_sleep_ != -1 && ticks_ >= seconds_to_deep_sleep_) { - if (on_enter_deep_sleep_mode_) { - on_enter_deep_sleep_mode_(); - } - - esp_deep_sleep_start(); - } -} - -void SleepTimer::WakeUp() { - ticks_ = 0; - if (in_light_sleep_mode_) { - in_light_sleep_mode_ = false; - if (on_exit_light_sleep_mode_) { - on_exit_light_sleep_mode_(); - } - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.h deleted file mode 100644 index 159e220a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sleep_timer.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include - -#include -#include - -class SleepTimer { -public: - SleepTimer(int seconds_to_light_sleep = 20, int seconds_to_deep_sleep = -1); - ~SleepTimer(); - - void SetEnabled(bool enabled); - void OnEnterLightSleepMode(std::function callback); - void OnExitLightSleepMode(std::function callback); - void OnEnterDeepSleepMode(std::function callback); - void WakeUp(); - -private: - void CheckTimer(); - - esp_timer_handle_t sleep_timer_ = nullptr; - bool enabled_ = false; - int ticks_ = 0; - int seconds_to_light_sleep_; - int seconds_to_deep_sleep_; - bool in_light_sleep_mode_ = false; - - std::function on_enter_light_sleep_mode_; - std::function on_exit_light_sleep_mode_; - std::function on_enter_deep_sleep_mode_; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.cc deleted file mode 100644 index 8a45d75a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.cc +++ /dev/null @@ -1,65 +0,0 @@ -#include "sy6970.h" -#include "board.h" -#include "display.h" - -#include - -#define TAG "Sy6970" - -Sy6970::Sy6970(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { -} - -int Sy6970::GetChangingStatus() { - return (ReadReg(0x0B) >> 3) & 0x03; -} - -bool Sy6970::IsCharging() { - return GetChangingStatus() != 0; -} - -bool Sy6970::IsPowerGood() { - return (ReadReg(0x0B) & 0x04) != 0; -} - -bool Sy6970::IsChargingDone() { - return GetChangingStatus() == 3; -} - -int Sy6970::GetBatteryVoltage() { - uint8_t value = ReadReg(0x0E); - value &= 0x7F; - if (value == 0) { - return 0; - } - return value * 20 + 2304; -} - -int Sy6970::GetChargeTargetVoltage() { - uint8_t value = ReadReg(0x06); - value = (value & 0xFC) >> 2; - if (value > 0x30) { - return 4608; - } - return value * 16 + 3840; -} - -int Sy6970::GetBatteryLevel() { - int level = 0; - // 电池所能掉电的最低电压 - int battery_minimum_voltage = 3200; - int battery_voltage = GetBatteryVoltage(); - int charge_voltage_limit = GetChargeTargetVoltage(); - // ESP_LOGI(TAG, "battery_voltage: %d, charge_voltage_limit: %d", battery_voltage, charge_voltage_limit); - if (battery_voltage > battery_minimum_voltage && charge_voltage_limit > battery_minimum_voltage) { - level = (((float) battery_voltage - (float) battery_minimum_voltage) / ((float) charge_voltage_limit - (float) battery_minimum_voltage)) * 100.0; - } - // 不连接电池时读取的充电状态不稳定且battery_voltage有时会超过charge_voltage_limit - if (level > 100) { - level = 100; - } - return level; -} - -void Sy6970::PowerOff() { - WriteReg(0x09, 0B01100100); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.h deleted file mode 100644 index a2eaaca4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/sy6970.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __SY6970_H__ -#define __SY6970_H__ - -#include "i2c_device.h" - -class Sy6970 : public I2cDevice { -public: - Sy6970(i2c_master_bus_handle_t i2c_bus, uint8_t addr); - bool IsCharging(); - bool IsPowerGood(); - bool IsChargingDone(); - int GetBatteryLevel(); - void PowerOff(); - -private: - int GetChangingStatus(); - int GetBatteryVoltage(); - int GetChargeTargetVoltage(); -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.cc deleted file mode 100644 index f51249bd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.cc +++ /dev/null @@ -1,72 +0,0 @@ -#include "system_reset.h" - -#include -#include -#include -#include -#include -#include - - -#define TAG "SystemReset" - - -SystemReset::SystemReset(gpio_num_t reset_nvs_pin, gpio_num_t reset_factory_pin) : reset_nvs_pin_(reset_nvs_pin), reset_factory_pin_(reset_factory_pin) { - // Configure GPIO1, GPIO2 as INPUT, reset NVS flash if the button is pressed - gpio_config_t io_conf; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << reset_nvs_pin_) | (1ULL << reset_factory_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); -} - - -void SystemReset::CheckButtons() { - if (gpio_get_level(reset_factory_pin_) == 0) { - ESP_LOGI(TAG, "Button is pressed, reset to factory"); - ResetNvsFlash(); - ResetToFactory(); - } - - if (gpio_get_level(reset_nvs_pin_) == 0) { - ESP_LOGI(TAG, "Button is pressed, reset NVS flash"); - ResetNvsFlash(); - } -} - -void SystemReset::ResetNvsFlash() { - ESP_LOGI(TAG, "Resetting NVS flash"); - esp_err_t ret = nvs_flash_erase(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to erase NVS flash"); - } - ret = nvs_flash_init(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize NVS flash"); - } -} - -void SystemReset::ResetToFactory() { - ESP_LOGI(TAG, "Resetting to factory"); - // Erase otadata partition - const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL); - if (partition == NULL) { - ESP_LOGE(TAG, "Failed to find otadata partition"); - return; - } - esp_partition_erase_range(partition, 0, partition->size); - ESP_LOGI(TAG, "Erased otadata partition"); - - // Reboot in 3 seconds - RestartInSeconds(3); -} - -void SystemReset::RestartInSeconds(int seconds) { - for (int i = seconds; i > 0; i--) { - ESP_LOGI(TAG, "Resetting in %d seconds", i); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - esp_restart(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.h deleted file mode 100644 index 7e78296c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/system_reset.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef _SYSTEM_RESET_H -#define _SYSTEM_RESET_H - -#include - -class SystemReset { -public: - SystemReset(gpio_num_t reset_nvs_pin, gpio_num_t reset_factory_pin); // 构造函数私有化 - void CheckButtons(); - -private: - gpio_num_t reset_nvs_pin_; - gpio_num_t reset_factory_pin_; - - void ResetNvsFlash(); - void ResetToFactory(); - void RestartInSeconds(int seconds); -}; - - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.cc deleted file mode 100644 index 77aff4fc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.cc +++ /dev/null @@ -1,359 +0,0 @@ -#include "wifi_board.h" - -#include "display.h" -#include "application.h" -#include "system_info.h" -#include "settings.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include "afsk_demod.h" -#ifdef CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING -#include "blufi.h" -#endif - -static const char *TAG = "WifiBoard"; - -// Connection timeout in seconds -static constexpr int CONNECT_TIMEOUT_SEC = 60; - -WifiBoard::WifiBoard() { - // Create connection timeout timer - esp_timer_create_args_t timer_args = { - .callback = OnWifiConnectTimeout, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "wifi_connect_timer", - .skip_unhandled_events = true - }; - esp_timer_create(&timer_args, &connect_timer_); -} - -WifiBoard::~WifiBoard() { - if (connect_timer_) { - esp_timer_stop(connect_timer_); - esp_timer_delete(connect_timer_); - } -} - -std::string WifiBoard::GetBoardType() { - return "wifi"; -} - -void WifiBoard::StartNetwork() { - auto& wifi_manager = WifiManager::GetInstance(); - - // Initialize WiFi manager - WifiManagerConfig config; - config.ssid_prefix = "Xiaozhi"; - config.language = Lang::CODE; - wifi_manager.Initialize(config); - - // Set unified event callback - forward to NetworkEvent with SSID data - wifi_manager.SetEventCallback([this, &wifi_manager](WifiEvent event) { - std::string ssid = wifi_manager.GetSsid(); - switch (event) { - case WifiEvent::Scanning: - OnNetworkEvent(NetworkEvent::Scanning); - break; - case WifiEvent::Connecting: - OnNetworkEvent(NetworkEvent::Connecting, ssid); - break; - case WifiEvent::Connected: - OnNetworkEvent(NetworkEvent::Connected, ssid); - break; - case WifiEvent::Disconnected: - OnNetworkEvent(NetworkEvent::Disconnected); - break; - case WifiEvent::ConfigModeEnter: - OnNetworkEvent(NetworkEvent::WifiConfigModeEnter); - break; - case WifiEvent::ConfigModeExit: - OnNetworkEvent(NetworkEvent::WifiConfigModeExit); - break; - } - }); - - // Try to connect or enter config mode - TryWifiConnect(); -} - -void WifiBoard::TryWifiConnect() { - auto& ssid_manager = SsidManager::GetInstance(); - bool have_ssid = !ssid_manager.GetSsidList().empty(); - - if (have_ssid) { - // Start connection attempt with timeout - ESP_LOGI(TAG, "Starting WiFi connection attempt"); - esp_timer_start_once(connect_timer_, CONNECT_TIMEOUT_SEC * 1000000ULL); - WifiManager::GetInstance().StartStation(); - } else { - // No SSID configured, enter config mode - // Wait for the board version to be shown - vTaskDelay(pdMS_TO_TICKS(1500)); - StartWifiConfigMode(); - } -} - -void WifiBoard::OnNetworkEvent(NetworkEvent event, const std::string& data) { - switch (event) { - case NetworkEvent::Connected: - // Stop timeout timer - esp_timer_stop(connect_timer_); -#ifdef CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING - // make sure blufi resources has been released - Blufi::GetInstance().deinit(); -#endif - in_config_mode_ = false; - ESP_LOGI(TAG, "Connected to WiFi: %s", data.c_str()); - break; - case NetworkEvent::Scanning: - ESP_LOGI(TAG, "WiFi scanning"); - break; - case NetworkEvent::Connecting: - ESP_LOGI(TAG, "WiFi connecting to %s", data.c_str()); - break; - case NetworkEvent::Disconnected: - ESP_LOGW(TAG, "WiFi disconnected"); - break; - case NetworkEvent::WifiConfigModeEnter: - ESP_LOGI(TAG, "WiFi config mode entered"); - in_config_mode_ = true; - break; - case NetworkEvent::WifiConfigModeExit: - ESP_LOGI(TAG, "WiFi config mode exited"); - in_config_mode_ = false; - // Try to connect with the new credentials - TryWifiConnect(); - break; - default: - break; - } - - // Notify external callback if set - if (network_event_callback_) { - network_event_callback_(event, data); - } -} - -void WifiBoard::SetNetworkEventCallback(NetworkEventCallback callback) { - network_event_callback_ = std::move(callback); -} - -void WifiBoard::OnWifiConnectTimeout(void* arg) { - auto* board = static_cast(arg); - ESP_LOGW(TAG, "WiFi connection timeout, entering config mode"); - - WifiManager::GetInstance().StopStation(); - board->StartWifiConfigMode(); -} - -void WifiBoard::StartWifiConfigMode() { - in_config_mode_ = true; - // Transition to wifi configuring state - Application::GetInstance().SetDeviceState(kDeviceStateWifiConfiguring); -#ifdef CONFIG_USE_HOTSPOT_WIFI_PROVISIONING - auto& wifi_manager = WifiManager::GetInstance(); - - wifi_manager.StartConfigAp(); - - // Show config prompt after a short delay - Application::GetInstance().Schedule([&wifi_manager]() { - std::string hint = Lang::Strings::CONNECT_TO_HOTSPOT; - hint += wifi_manager.GetApSsid(); - hint += Lang::Strings::ACCESS_VIA_BROWSER; - hint += wifi_manager.GetApWebUrl(); - - Application::GetInstance().Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "gear", Lang::Sounds::OGG_WIFICONFIG); - }); -#endif -#if CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING - auto &blufi = Blufi::GetInstance(); - // initialize esp-blufi protocol - blufi.init(); -#endif -#if CONFIG_USE_ACOUSTIC_WIFI_PROVISIONING - // Start acoustic provisioning task - auto codec = Board::GetInstance().GetAudioCodec(); - int channel = codec ? codec->input_channels() : 1; - ESP_LOGI(TAG, "Starting acoustic WiFi provisioning, channels: %d", channel); - - xTaskCreate([](void* arg) { - auto ch = reinterpret_cast(arg); - auto& app = Application::GetInstance(); - auto& wifi = WifiManager::GetInstance(); - auto disp = Board::GetInstance().GetDisplay(); - audio_wifi_config::ReceiveWifiCredentialsFromAudio(&app, &wifi, disp, ch); - vTaskDelete(NULL); - }, "acoustic_wifi", 4096, reinterpret_cast(channel), 2, NULL); -#endif -} - -void WifiBoard::EnterWifiConfigMode() { - ESP_LOGI(TAG, "EnterWifiConfigMode called"); - GetDisplay()->ShowNotification(Lang::Strings::ENTERING_WIFI_CONFIG_MODE); - - auto& app = Application::GetInstance(); - auto state = app.GetDeviceState(); - - if (state == kDeviceStateSpeaking || state == kDeviceStateListening || state == kDeviceStateIdle) { - // Reset protocol (close audio channel, reset protocol) - Application::GetInstance().ResetProtocol(); - - xTaskCreate([](void* arg) { - auto* board = static_cast(arg); - - // Wait for 1 second to allow speaking to finish gracefully - vTaskDelay(pdMS_TO_TICKS(1000)); - - // Stop any ongoing connection attempt - esp_timer_stop(board->connect_timer_); - WifiManager::GetInstance().StopStation(); - - // Enter config mode - board->StartWifiConfigMode(); - - vTaskDelete(NULL); - }, "wifi_cfg_delay", 4096, this, 2, NULL); - return; - } - - if (state != kDeviceStateStarting) { - ESP_LOGE(TAG, "EnterWifiConfigMode called but device state is not starting or speaking, device state: %d", state); - return; - } - - // Stop any ongoing connection attempt - esp_timer_stop(connect_timer_); - WifiManager::GetInstance().StopStation(); - - StartWifiConfigMode(); -} - -bool WifiBoard::IsInWifiConfigMode() const { - return WifiManager::GetInstance().IsConfigMode(); -} - -NetworkInterface* WifiBoard::GetNetwork() { - static EspNetwork network; - return &network; -} - -const char* WifiBoard::GetNetworkStateIcon() { - auto& wifi = WifiManager::GetInstance(); - - if (wifi.IsConfigMode()) { - return FONT_AWESOME_WIFI; - } - if (!wifi.IsConnected()) { - return FONT_AWESOME_WIFI_SLASH; - } - - int rssi = wifi.GetRssi(); - if (rssi >= -65) { - return FONT_AWESOME_WIFI; - } else if (rssi >= -75) { - return FONT_AWESOME_WIFI_FAIR; - } - return FONT_AWESOME_WIFI_WEAK; -} - -std::string WifiBoard::GetBoardJson() { - auto& wifi = WifiManager::GetInstance(); - std::string json = R"({"type":")" + std::string(BOARD_TYPE) + R"(",)"; - json += R"("name":")" + std::string(BOARD_NAME) + R"(",)"; - - if (!wifi.IsConfigMode()) { - json += R"("ssid":")" + wifi.GetSsid() + R"(",)"; - json += R"("rssi":)" + std::to_string(wifi.GetRssi()) + R"(,)"; - json += R"("channel":)" + std::to_string(wifi.GetChannel()) + R"(,)"; - json += R"("ip":")" + wifi.GetIpAddress() + R"(",)"; - } - - json += R"("mac":")" + SystemInfo::GetMacAddress() + R"("})"; - return json; -} - -void WifiBoard::SetPowerSaveLevel(PowerSaveLevel level) { - WifiPowerSaveLevel wifi_level; - switch (level) { - case PowerSaveLevel::LOW_POWER: - wifi_level = WifiPowerSaveLevel::LOW_POWER; - break; - case PowerSaveLevel::BALANCED: - wifi_level = WifiPowerSaveLevel::BALANCED; - break; - case PowerSaveLevel::PERFORMANCE: - default: - wifi_level = WifiPowerSaveLevel::PERFORMANCE; - break; - } - WifiManager::GetInstance().SetPowerSaveLevel(wifi_level); -} - -std::string WifiBoard::GetDeviceStatusJson() { - auto& board = Board::GetInstance(); - auto root = cJSON_CreateObject(); - - // Audio speaker - auto audio_speaker = cJSON_CreateObject(); - if (auto codec = board.GetAudioCodec()) { - cJSON_AddNumberToObject(audio_speaker, "volume", codec->output_volume()); - } - cJSON_AddItemToObject(root, "audio_speaker", audio_speaker); - - // Screen - auto screen = cJSON_CreateObject(); - if (auto backlight = board.GetBacklight()) { - cJSON_AddNumberToObject(screen, "brightness", backlight->brightness()); - } - if (auto display = board.GetDisplay(); display && display->height() > 64) { - if (auto theme = display->GetTheme()) { - cJSON_AddStringToObject(screen, "theme", theme->name().c_str()); - } - } - cJSON_AddItemToObject(root, "screen", screen); - - // Battery - int level = 0; - bool charging = false, discharging = false; - if (board.GetBatteryLevel(level, charging, discharging)) { - auto battery = cJSON_CreateObject(); - cJSON_AddNumberToObject(battery, "level", level); - cJSON_AddBoolToObject(battery, "charging", charging); - cJSON_AddItemToObject(root, "battery", battery); - } - - // Network - auto& wifi = WifiManager::GetInstance(); - auto network = cJSON_CreateObject(); - cJSON_AddStringToObject(network, "type", "wifi"); - cJSON_AddStringToObject(network, "ssid", wifi.GetSsid().c_str()); - int rssi = wifi.GetRssi(); - const char* signal = rssi >= -60 ? "strong" : (rssi >= -70 ? "medium" : "weak"); - cJSON_AddStringToObject(network, "signal", signal); - cJSON_AddItemToObject(root, "network", network); - - // Chip temperature - float temp = 0.0f; - if (board.GetTemperature(temp)) { - auto chip = cJSON_CreateObject(); - cJSON_AddNumberToObject(chip, "temperature", temp); - cJSON_AddItemToObject(root, "chip", chip); - } - - auto str = cJSON_PrintUnformatted(root); - std::string result(str); - cJSON_free(str); - cJSON_Delete(root); - return result; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.h deleted file mode 100644 index 7ee973c4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/common/wifi_board.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef WIFI_BOARD_H -#define WIFI_BOARD_H - -#include "board.h" -#include -#include -#include - -class WifiBoard : public Board { -protected: - esp_timer_handle_t connect_timer_ = nullptr; - bool in_config_mode_ = false; - NetworkEventCallback network_event_callback_ = nullptr; - - virtual std::string GetBoardJson() override; - - /** - * Handle network event (called from WiFi manager callbacks) - * @param event The network event type - * @param data Additional data (e.g., SSID for Connecting/Connected events) - */ - void OnNetworkEvent(NetworkEvent event, const std::string& data = ""); - - /** - * Start WiFi connection attempt - */ - void TryWifiConnect(); - - /** - * Enter WiFi configuration mode - */ - void StartWifiConfigMode(); - - /** - * WiFi connection timeout callback - */ - static void OnWifiConnectTimeout(void* arg); - -public: - WifiBoard(); - virtual ~WifiBoard(); - - virtual std::string GetBoardType() override; - - /** - * Start network connection asynchronously - * This function returns immediately. Network events are notified through the callback set by SetNetworkEventCallback(). - */ - virtual void StartNetwork() override; - - virtual NetworkInterface* GetNetwork() override; - virtual void SetNetworkEventCallback(NetworkEventCallback callback) override; - virtual const char* GetNetworkStateIcon() override; - virtual void SetPowerSaveLevel(PowerSaveLevel level) override; - virtual AudioCodec* GetAudioCodec() override { return nullptr; } - virtual std::string GetDeviceStatusJson() override; - - /** - * Enter WiFi configuration mode (thread-safe, can be called from any task) - */ - void EnterWifiConfigMode(); - - /** - * Check if in WiFi config mode - */ - bool IsInWifiConfigMode() const; -}; - -#endif // WIFI_BOARD_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/README.md deleted file mode 100644 index e7af6cc5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# DFRobot 行空板 K10 - -## 按键配置 -* A:短按-打断/唤醒,长按1s-音量调大 -* B:短按-打断/唤醒,长按1s-音量调小 - -## 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> DFRobot 行空板 K10 -``` - -**修改 psram 配置:** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> Octal Mode PSRAM -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.h deleted file mode 100644 index 5f8ad773..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_3 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_38 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_0 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_45 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR 0x23 - -#define BUILTIN_LED_GPIO GPIO_NUM_46 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -/* Expander */ -#define DRV_IO_EXP_INPUT_MASK (IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_12) - - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -/* DFRobot K10 Camera pins */ -#define PWDN_GPIO_NUM GPIO_NUM_NC -#define RESET_GPIO_NUM GPIO_NUM_NC -#define XCLK_GPIO_NUM GPIO_NUM_7 - -#define VSYNC_GPIO_NUM GPIO_NUM_4 -#define HREF_GPIO_NUM GPIO_NUM_5 -#define PCLK_GPIO_NUM GPIO_NUM_17 -#define SIOD_GPIO_NUM GPIO_NUM_20 -#define SIOC_GPIO_NUM GPIO_NUM_19 - -/* Camera pins */ -#define CAMERA_PIN_PWDN PWDN_GPIO_NUM -#define CAMERA_PIN_RESET RESET_GPIO_NUM -#define CAMERA_PIN_XCLK XCLK_GPIO_NUM -#define CAMERA_PIN_SIOD SIOD_GPIO_NUM -#define CAMERA_PIN_SIOC SIOC_GPIO_NUM - -#define CAMERA_PIN_D9 GPIO_NUM_6 -#define CAMERA_PIN_D8 GPIO_NUM_15 -#define CAMERA_PIN_D7 GPIO_NUM_16 -#define CAMERA_PIN_D6 GPIO_NUM_18 -#define CAMERA_PIN_D5 GPIO_NUM_9 -#define CAMERA_PIN_D4 GPIO_NUM_11 -#define CAMERA_PIN_D3 GPIO_NUM_10 -#define CAMERA_PIN_D2 GPIO_NUM_8 -#define CAMERA_PIN_VSYNC VSYNC_GPIO_NUM -#define CAMERA_PIN_HREF HREF_GPIO_NUM -#define CAMERA_PIN_PCLK PCLK_GPIO_NUM - -#define XCLK_FREQ_HZ 20000000 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.json deleted file mode 100644 index 55137d40..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "df-k10", - "sdkconfig_append": [ - "CONFIG_SPIRAM_MODE_OCT=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/df_k10_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/df_k10_board.cc deleted file mode 100644 index de344b2b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/df_k10_board.cc +++ /dev/null @@ -1,294 +0,0 @@ -#include "wifi_board.h" -#include "k10_audio_codec.h" -#include "display/lcd_display.h" -#include "esp_lcd_ili9341.h" -#include "led_control.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "esp32_camera.h" - -#include "led/circular_strip.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include - -#include "esp_io_expander_tca95xx_16bit.h" - -#define TAG "DF-K10" - -class Df_K10Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander; - LcdDisplay *display_; - button_handle_t btn_a; - button_handle_t btn_b; - Esp32Camera* camera_; - - button_driver_t* btn_a_driver_ = nullptr; - button_driver_t* btn_b_driver_ = nullptr; - - CircularStrip* led_strip_; - - static Df_K10Board* instance_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_21; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_12; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - esp_err_t IoExpanderSetLevel(uint16_t pin_mask, uint8_t level) { - return esp_io_expander_set_level(io_expander, pin_mask, level); - } - - uint8_t IoExpanderGetLevel(uint16_t pin_mask) { - uint32_t pin_val = 0; - esp_io_expander_get_level(io_expander, DRV_IO_EXP_INPUT_MASK, &pin_val); - pin_mask &= DRV_IO_EXP_INPUT_MASK; - return (uint8_t)((pin_val & pin_mask) ? 1 : 0); - } - - void InitializeIoExpander() { - esp_io_expander_new_i2c_tca95xx_16bit( - i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000, &io_expander); - - esp_err_t ret; - ret = esp_io_expander_print_state(io_expander); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Print state failed: %s", esp_err_to_name(ret)); - } - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0, - IO_EXPANDER_OUTPUT); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Set direction failed: %s", esp_err_to_name(ret)); - } - ret = esp_io_expander_set_level(io_expander, 0, 1); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Set level failed: %s", esp_err_to_name(ret)); - } - ret = esp_io_expander_set_dir( - io_expander, DRV_IO_EXP_INPUT_MASK, - IO_EXPANDER_INPUT); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Set direction failed: %s", esp_err_to_name(ret)); - } - } - - void InitializeButtons() { - instance_ = this; - - // Button A - button_config_t btn_a_config = { - .long_press_time = 1000, - .short_press_time = 0 - }; - btn_a_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - btn_a_driver_->enable_power_save = false; - btn_a_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !instance_->IoExpanderGetLevel(IO_EXPANDER_PIN_NUM_2); - }; - ESP_ERROR_CHECK(iot_button_create(&btn_a_config, btn_a_driver_, &btn_a)); - iot_button_register_cb(btn_a, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }, this); - iot_button_register_cb(btn_a, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto codec = self->GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - self->GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }, this); - - // Button B - button_config_t btn_b_config = { - .long_press_time = 1000, - .short_press_time = 0 - }; - btn_b_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - btn_b_driver_->enable_power_save = false; - btn_b_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !instance_->IoExpanderGetLevel(IO_EXPANDER_PIN_NUM_12); - }; - ESP_ERROR_CHECK(iot_button_create(&btn_b_config, btn_b_driver_, &btn_b)); - iot_button_register_cb(btn_b, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }, this); - iot_button_register_cb(btn_b, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto codec = self->GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - self->GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }, this); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D2, - [1] = CAMERA_PIN_D3, - [2] = CAMERA_PIN_D4, - [3] = CAMERA_PIN_D5, - [4] = CAMERA_PIN_D6, - [5] = CAMERA_PIN_D7, - [6] = CAMERA_PIN_D8, - [7] = CAMERA_PIN_D9, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - - void InitializeIli9341Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_14; - io_config.dc_gpio_num = GPIO_NUM_13; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.bits_per_pixel = 16; - panel_config.color_space = ESP_LCD_COLOR_SPACE_BGR; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeIot() { - led_strip_ = new CircularStrip(BUILTIN_LED_GPIO, 3); - new LedStripControl(led_strip_); - } - -public: - Df_K10Board() { - InitializeI2c(); - InitializeIoExpander(); - InitializeSpi(); - InitializeIli9341Display(); - InitializeButtons(); - InitializeIot(); - InitializeCamera(); - } - - virtual Led* GetLed() override { - return led_strip_; - } - - virtual AudioCodec *GetAudioCodec() override { - static K10AudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Display *GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(Df_K10Board); - -Df_K10Board* Df_K10Board::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.cc deleted file mode 100644 index 5a309481..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.cc +++ /dev/null @@ -1,225 +0,0 @@ -#include "k10_audio_codec.h" - -#include -#include -#include -#include - -static const char TAG[] = "K10AudioCodec"; - -K10AudioCodec::K10AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7210_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - audio_codec_i2c_cfg_t i2c_cfg = { - .port = I2C_NUM_1, - .addr = es7210_addr, - .bus_handle = i2c_master_handle, - }; - const audio_codec_ctrl_if_t *in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7243e_codec_cfg_t es7243e_cfg = { - .ctrl_if = in_ctrl_if_, - }; - const audio_codec_if_t *in_codec_if_ = es7243e_codec_new(&es7243e_cfg); - assert(in_codec_if_ != NULL); - - esp_codec_dev_cfg_t codec_es7243e_dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN, - .codec_if = in_codec_if_, - .data_if = data_if_, - }; - input_dev_ = esp_codec_dev_new(&codec_es7243e_dev_cfg); - - assert(input_dev_ != NULL); - - ESP_LOGI(TAG, "DF-K10 AudioDevice initialized"); -} - -K10AudioCodec::~K10AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void K10AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - // .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bclk_div = 8, - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), - .ws_width = I2S_TDM_AUTO_WS_WIDTH, - .ws_pol = false, - .bit_shift = true, - .left_align = false, - .big_endian = false, - .bit_order_lsb = false, - .skip_mask = false, - .total_slot = I2S_TDM_AUTO_SLOT_NUM - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = I2S_GPIO_UNUSED, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void K10AudioCodec::SetOutputVolume(int volume) { - AudioCodec::SetOutputVolume(volume); -} - -void K10AudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 4, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - if (input_reference_) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 37.5)); //麦克风增益解决收音太小的问题 - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void K10AudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - AudioCodec::SetOutputVolume(output_volume_); - AudioCodec::EnableOutput(enable); -} - -int K10AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int K10AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - std::vector buffer(samples * 2); // Allocate buffer for 2x samples - - // Apply volume adjustment (same as before) - int32_t volume_factor = pow(double(output_volume_) / 100.0, 2) * 65536; - for (int i = 0; i < samples; i++) { - int64_t temp = int64_t(data[i]) * volume_factor; - if (temp > INT32_MAX) { - buffer[i * 2] = INT32_MAX; - } else if (temp < INT32_MIN) { - buffer[i * 2] = INT32_MIN; - } else { - buffer[i * 2] = static_cast(temp); - } - - // Repeat each sample for slow playback (assuming mono audio) - buffer[i * 2 + 1] = buffer[i * 2]; - } - - size_t bytes_written; - ESP_ERROR_CHECK(i2s_channel_write(tx_handle_, buffer.data(), samples * 2 * sizeof(int32_t), &bytes_written, portMAX_DELAY)); - return bytes_written / sizeof(int32_t); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.h deleted file mode 100644 index 061adbe1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/k10_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_H -#define _BOX_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class K10AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - K10AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7210_addr, bool input_reference); - virtual ~K10AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.cc deleted file mode 100644 index ce5164a5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.cc +++ /dev/null @@ -1,124 +0,0 @@ -#include "led_control.h" -#include "settings.h" -#include "mcp_server.h" -#include - -#define TAG "LedStripControl" - - -int LedStripControl::LevelToBrightness(int level) const { - if (level < 0) level = 0; - if (level > 8) level = 8; - return (1 << level) - 1; // 2^n - 1 -} - -StripColor LedStripControl::RGBToColor(int red, int green, int blue) { - return {static_cast(red), static_cast(green), static_cast(blue)}; -} - -LedStripControl::LedStripControl(CircularStrip* led_strip) - : led_strip_(led_strip) { - // 从设置中读取亮度等级 - Settings settings("led_strip"); - brightness_level_ = settings.GetInt("brightness", 4); // 默认等级4 - led_strip_->SetBrightness(LevelToBrightness(brightness_level_), 4); - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.led_strip.get_brightness", - "Get the brightness of the led strip (0-8)", - PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return brightness_level_; - }); - - mcp_server.AddTool("self.led_strip.set_brightness", - "Set the brightness of the led strip (0-8)", - PropertyList({ - Property("level", kPropertyTypeInteger, 0, 8) - }), [this](const PropertyList& properties) -> ReturnValue { - int level = properties["level"].value(); - ESP_LOGI(TAG, "Set LedStrip brightness level to %d", level); - brightness_level_ = level; - led_strip_->SetBrightness(LevelToBrightness(brightness_level_), 4); - - // 保存设置 - Settings settings("led_strip", true); - settings.SetInt("brightness", brightness_level_); - - return true; - }); - - mcp_server.AddTool("self.led_strip.set_single_color", - "Set the color of a single led.", - PropertyList({ - Property("index", kPropertyTypeInteger, 0, 2), - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int index = properties["index"].value(); - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - ESP_LOGI(TAG, "Set led strip single color %d to %d, %d, %d", - index, red, green, blue); - led_strip_->SetSingleColor(index, RGBToColor(red, green, blue)); - return true; - }); - - mcp_server.AddTool("self.led_strip.set_all_color", - "Set the color of all leds.", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - ESP_LOGI(TAG, "Set led strip all color to %d, %d, %d", - red, green, blue); - led_strip_->SetAllColor(RGBToColor(red, green, blue)); - return true; - }); - - mcp_server.AddTool("self.led_strip.blink", - "Blink the led strip. (闪烁)", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255), - Property("interval", kPropertyTypeInteger, 0, 1000) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - int interval = properties["interval"].value(); - ESP_LOGI(TAG, "Blink led strip with color %d, %d, %d, interval %dms", - red, green, blue, interval); - led_strip_->Blink(RGBToColor(red, green, blue), interval); - return true; - }); - - mcp_server.AddTool("self.led_strip.scroll", - "Scroll the led strip. (跑马灯)", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255), - Property("length", kPropertyTypeInteger, 1, 7), - Property("interval", kPropertyTypeInteger, 0, 1000) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - int interval = properties["interval"].value(); - int length = properties["length"].value(); - ESP_LOGI(TAG, "Scroll led strip with color %d, %d, %d, length %d, interval %dms", - red, green, blue, length, interval); - StripColor low = RGBToColor(4, 4, 4); - StripColor high = RGBToColor(red, green, blue); - led_strip_->Scroll(low, high, length, interval); - return true; - }); - -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.h deleted file mode 100644 index 30e1020c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-k10/led_control.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef LED_CONTROL_H -#define LED_CONTROL_H - -#include "led/circular_strip.h" - -class LedStripControl { -private: - CircularStrip* led_strip_; - int brightness_level_; // 亮度等级 (0-8) - - int LevelToBrightness(int level) const; // 将等级转换为实际亮度值 - StripColor RGBToColor(int red, int green, int blue); - -public: - explicit LedStripControl(CircularStrip* led_strip); -}; - -#endif // LED_STRIP_CONTROL_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/README.md deleted file mode 100644 index 6f1f4029..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/README.md +++ /dev/null @@ -1,54 +0,0 @@ -# DFRobot ESP32-S3 AI智能摄像头模块 - -## 介绍 -ESP32-S3 AI CAM是一款基于ESP32-S3芯片设计的智能摄像头模组,专为视频图像处理和语音交互打造,适用于视频监控、边缘图像识别、语音对话等AI项目。 -![](https://ws.dfrobot.com.cn/FsTrGbrX2NZAwzWS8OSQGOGikuYA) - -[点击查看详细介绍](https://wiki.dfrobot.com.cn/SKU_DFR1154_ESP32_S3_AI_CAM) - -[点击查看视觉功能演示](https://www.bilibili.com/video/BV1ktjSzNEUU/) - -# 特性 -* 使用PDM麦克风 -* 板载 OV3660 摄像头 - -## 按键配置 -* BOOT:短按-打断/唤醒 - -## 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> DFRobot ESP32-S3 AI智能摄像头模块 -``` - -**修改 psram 配置:** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> Octal Mode PSRAM -``` - -**修改 WiFi 发射功率 为 10:** - -``` -Component config -> PHY -> (10)Max WiFi TX power (dBm) -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.h deleted file mode 100644 index 50dcc85e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_38 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_42 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_45 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_46 -#define AUDIO_I2S_SPK_GPIO_GAIN GPIO_NUM_41 - -#define BUILTIN_LED_GPIO GPIO_NUM_3 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC -#define RESET_NVS_BUTTON_GPIO GPIO_NUM_NC -#define RESET_FACTORY_BUTTON_GPIO GPIO_NUM_NC - -/* DFRobot Camera pins */ -#define PWDN_GPIO_NUM GPIO_NUM_NC -#define RESET_GPIO_NUM GPIO_NUM_NC -#define XCLK_GPIO_NUM GPIO_NUM_5 -#define Y9_GPIO_NUM GPIO_NUM_4 -#define Y8_GPIO_NUM GPIO_NUM_6 -#define Y7_GPIO_NUM GPIO_NUM_7 -#define Y6_GPIO_NUM GPIO_NUM_14 -#define Y5_GPIO_NUM GPIO_NUM_17 -#define Y4_GPIO_NUM GPIO_NUM_21 -#define Y3_GPIO_NUM GPIO_NUM_18 -#define Y2_GPIO_NUM GPIO_NUM_16 -#define VSYNC_GPIO_NUM GPIO_NUM_1 -#define HREF_GPIO_NUM GPIO_NUM_2 -#define PCLK_GPIO_NUM GPIO_NUM_15 -#define SIOD_GPIO_NUM GPIO_NUM_8 -#define SIOC_GPIO_NUM GPIO_NUM_9 - -/* Camera pins */ -#define CAMERA_PIN_PWDN PWDN_GPIO_NUM -#define CAMERA_PIN_RESET RESET_GPIO_NUM -#define CAMERA_PIN_XCLK XCLK_GPIO_NUM -#define CAMERA_PIN_SIOD SIOD_GPIO_NUM -#define CAMERA_PIN_SIOC SIOC_GPIO_NUM - -#define CAMERA_PIN_D7 Y9_GPIO_NUM -#define CAMERA_PIN_D6 Y8_GPIO_NUM -#define CAMERA_PIN_D5 Y7_GPIO_NUM -#define CAMERA_PIN_D4 Y6_GPIO_NUM -#define CAMERA_PIN_D3 Y5_GPIO_NUM -#define CAMERA_PIN_D2 Y4_GPIO_NUM -#define CAMERA_PIN_D1 Y3_GPIO_NUM -#define CAMERA_PIN_D0 Y2_GPIO_NUM -#define CAMERA_PIN_VSYNC VSYNC_GPIO_NUM -#define CAMERA_PIN_HREF HREF_GPIO_NUM -#define CAMERA_PIN_PCLK PCLK_GPIO_NUM - -#define XCLK_FREQ_HZ 20000000 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.json deleted file mode 100644 index ff50ca68..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "df-s3-ai-cam", - "sdkconfig_append": [ - "CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=10", - "CONFIG_ESP_PHY_MAX_TX_POWER=10", - "CONFIG_SPIRAM_MODE_OCT=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/df_s3_ai_cam.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/df_s3_ai_cam.cc deleted file mode 100644 index c82bcaaf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/df-s3-ai-cam/df_s3_ai_cam.cc +++ /dev/null @@ -1,103 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "esp32_camera.h" - -#include "led/gpio_led.h" -#include -#include -#include - -#define TAG "DfrobotEsp32S3AiCam" - -class DfrobotEsp32S3AiCam : public WifiBoard { - private: - Button boot_button_; - Esp32Camera* camera_; - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = true, - .i2c_config = { - .port = 1, - .scl_pin = CAMERA_PIN_SIOC, - .sda_pin = CAMERA_PIN_SIOD, - }, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetVFlip(1); - } - - public: - DfrobotEsp32S3AiCam() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeButtons(); - InitializeCamera(); - } - - // Wakenet model only - - virtual Led* GetLed() override { - static GpioLed led(BUILTIN_LED_GPIO, 0); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplexPdm audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, - AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(DfrobotEsp32S3AiCam); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/README.md deleted file mode 100644 index 6ad8f74d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# 四博智联AI陪伴盒子 - -# 特性 -* 使用PDM麦克风 -* 使用共阳极LED - -## 按键配置 -* BUTTON3:短按-打断/唤醒 -* BUTTON1:音量+ -* BUTTON2:音量- - -## 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> 四博智联AI陪伴盒子 -``` - -**修改 psram 配置:** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> Octal Mode PSRAM -``` - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.h deleted file mode 100644 index 9c44200d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_41 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_40 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_42 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_18 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_17 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -/* -IO9: BUTTON2 -IO10: BUTTON3 引出:KEY3 -IO15: BUTTON1 -*/ -#define BUILTIN_LED_GPIO GPIO_NUM_45 -#define BOOT_BUTTON_GPIO GPIO_NUM_10 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_15 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_9 -#define RESET_NVS_BUTTON_GPIO GPIO_NUM_10 -#define RESET_FACTORY_BUTTON_GPIO GPIO_NUM_NC - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.json deleted file mode 100644 index a9de834a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "doit-s3-aibox", - "sdkconfig_append": [ - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/doit_s3_aibox.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/doit_s3_aibox.cc deleted file mode 100644 index 65e37a92..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/doit-s3-aibox/doit_s3_aibox.cc +++ /dev/null @@ -1,137 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/gpio_led.h" -#include -#include -#include - -#define TAG "DoitS3AiBox" - -class DoitS3AiBox : public WifiBoard { -private: - Button boot_button_; - Button touch_button_; - Button volume_up_button_; - Button volume_down_button_; - uint8_t click_times; - uint32_t check_time; - - void InitializeButtons() { - click_times = 0; - check_time = 0; - boot_button_.OnClick([this]() { - if(click_times==0) { - check_time = esp_timer_get_time()/1000; - } - if(esp_timer_get_time()/1000-check_time<1000) { - click_times++; - check_time = esp_timer_get_time()/1000; - } else { - click_times = 0; - check_time = 0; - } - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - click_times++; - ESP_LOGI(TAG, "DoubleClick times %d", click_times); - if(click_times==3) { - click_times = 0; - EnterWifiConfigMode(); - } - }); - - boot_button_.OnLongPress([this]() { - if(click_times>=3) { - EnterWifiConfigMode(); - } else { - click_times = 0; - check_time = 0; - } - }); - - touch_button_.OnPressDown([this]() { - click_times = 0; - Application::GetInstance().StartListening(); - }); - touch_button_.OnPressUp([this]() { - click_times = 0; - Application::GetInstance().StopListening(); - }); - - volume_up_button_.OnClick([this]() { - click_times = 0; - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - }); - - volume_up_button_.OnLongPress([this]() { - click_times = 0; - GetAudioCodec()->SetOutputVolume(100); - }); - - volume_down_button_.OnClick([this]() { - click_times = 0; - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - }); - - volume_down_button_.OnLongPress([this]() { - click_times = 0; - GetAudioCodec()->SetOutputVolume(0); - }); - } - - void InitializeGpio(gpio_num_t gpio_num_) { - gpio_config_t config = { - .pin_bit_mask = (1ULL << gpio_num_), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_ENABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&config)); - gpio_set_level(gpio_num_, 1); - } - -public: - DoitS3AiBox() : - boot_button_(BOOT_BUTTON_GPIO), - touch_button_(TOUCH_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO){ - // 上拉io48 置高电平 - InitializeGpio(GPIO_NUM_48); - InitializeButtons(); - } - - virtual Led* GetLed() override { - static GpioLed led(BUILTIN_LED_GPIO, 1); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplexPdm audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } -}; - -DECLARE_BOARD(DoitS3AiBox); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.h deleted file mode 100644 index 729e1f49..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_39 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_38 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_40 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_42 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_2 - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_9 -#define DISPLAY_MOSI_PIN GPIO_NUM_18 -#define DISPLAY_CLK_PIN GPIO_NUM_17 -#define DISPLAY_DC_PIN GPIO_NUM_8 -#define DISPLAY_RST_PIN GPIO_NUM_20 -#define DISPLAY_CS_PIN GPIO_NUM_16 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 2 -#define DISPLAY_OFFSET_Y 1 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.json deleted file mode 100644 index e6abd31d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "du-chatx", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/du-chatx-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/du-chatx-wifi.cc deleted file mode 100644 index 85530a80..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/du-chatx-wifi.cc +++ /dev/null @@ -1,164 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "power_manager.h" -#include "power_save_timer.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "DuChatX" - -class DuChatX : public WifiBoard { -private: - Button boot_button_; - LcdDisplay *display_; - PowerManager *power_manager_; - PowerSaveTimer *power_save_timer_; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_6); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_1); - rtc_gpio_set_direction(GPIO_NUM_1, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_1, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_1, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_1); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel_ IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel_)); - esp_lcd_panel_reset(panel_); - esp_lcd_panel_init(panel_); - esp_lcd_panel_invert_color(panel_, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel_,DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y,DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - DuChatX() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - InitializePowerSaveTimer(); - InitializePowerManager(); - } - - virtual Led *GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec *GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Backlight *GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(DuChatX); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/power_manager.h deleted file mode 100644 index 84388802..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/du-chatx/power_manager.h +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_5, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1120, 0}, - {1140, 20}, - {1160, 40}, - {1170, 60}, - {1190, 80}, - {1217, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_5, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/EchoEar.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/EchoEar.cc deleted file mode 100644 index c155c163..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/EchoEar.cc +++ /dev/null @@ -1,666 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "display/emote_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "backlight.h" -#include "esp32_camera.h" - -#include - -#include -#include -#include "i2c_device.h" -#include -#include -#include -#include "esp_lcd_touch_cst816s.h" -#include "touch.h" - -#include "driver/temperature_sensor.h" -#include -#include -#include - -#define TAG "EchoEar" - - -temperature_sensor_handle_t temp_sensor = NULL; -static const st77916_lcd_init_cmd_t vendor_specific_init_yysj[] = { - {0xF0, (uint8_t []){0x28}, 1, 0}, - {0xF2, (uint8_t []){0x28}, 1, 0}, - {0x73, (uint8_t []){0xF0}, 1, 0}, - {0x7C, (uint8_t []){0xD1}, 1, 0}, - {0x83, (uint8_t []){0xE0}, 1, 0}, - {0x84, (uint8_t []){0x61}, 1, 0}, - {0xF2, (uint8_t []){0x82}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x01}, 1, 0}, - {0xF1, (uint8_t []){0x01}, 1, 0}, - {0xB0, (uint8_t []){0x56}, 1, 0}, - {0xB1, (uint8_t []){0x4D}, 1, 0}, - {0xB2, (uint8_t []){0x24}, 1, 0}, - {0xB4, (uint8_t []){0x87}, 1, 0}, - {0xB5, (uint8_t []){0x44}, 1, 0}, - {0xB6, (uint8_t []){0x8B}, 1, 0}, - {0xB7, (uint8_t []){0x40}, 1, 0}, - {0xB8, (uint8_t []){0x86}, 1, 0}, - {0xBA, (uint8_t []){0x00}, 1, 0}, - {0xBB, (uint8_t []){0x08}, 1, 0}, - {0xBC, (uint8_t []){0x08}, 1, 0}, - {0xBD, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x80}, 1, 0}, - {0xC1, (uint8_t []){0x10}, 1, 0}, - {0xC2, (uint8_t []){0x37}, 1, 0}, - {0xC3, (uint8_t []){0x80}, 1, 0}, - {0xC4, (uint8_t []){0x10}, 1, 0}, - {0xC5, (uint8_t []){0x37}, 1, 0}, - {0xC6, (uint8_t []){0xA9}, 1, 0}, - {0xC7, (uint8_t []){0x41}, 1, 0}, - {0xC8, (uint8_t []){0x01}, 1, 0}, - {0xC9, (uint8_t []){0xA9}, 1, 0}, - {0xCA, (uint8_t []){0x41}, 1, 0}, - {0xCB, (uint8_t []){0x01}, 1, 0}, - {0xD0, (uint8_t []){0x91}, 1, 0}, - {0xD1, (uint8_t []){0x68}, 1, 0}, - {0xD2, (uint8_t []){0x68}, 1, 0}, - {0xF5, (uint8_t []){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t []){0x4F}, 1, 0}, - {0xDE, (uint8_t []){0x4F}, 1, 0}, - {0xF1, (uint8_t []){0x10}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, - {0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, - {0xF0, (uint8_t []){0x10}, 1, 0}, - {0xF3, (uint8_t []){0x10}, 1, 0}, - {0xE0, (uint8_t []){0x07}, 1, 0}, - {0xE1, (uint8_t []){0x00}, 1, 0}, - {0xE2, (uint8_t []){0x00}, 1, 0}, - {0xE3, (uint8_t []){0x00}, 1, 0}, - {0xE4, (uint8_t []){0xE0}, 1, 0}, - {0xE5, (uint8_t []){0x06}, 1, 0}, - {0xE6, (uint8_t []){0x21}, 1, 0}, - {0xE7, (uint8_t []){0x01}, 1, 0}, - {0xE8, (uint8_t []){0x05}, 1, 0}, - {0xE9, (uint8_t []){0x02}, 1, 0}, - {0xEA, (uint8_t []){0xDA}, 1, 0}, - {0xEB, (uint8_t []){0x00}, 1, 0}, - {0xEC, (uint8_t []){0x00}, 1, 0}, - {0xED, (uint8_t []){0x0F}, 1, 0}, - {0xEE, (uint8_t []){0x00}, 1, 0}, - {0xEF, (uint8_t []){0x00}, 1, 0}, - {0xF8, (uint8_t []){0x00}, 1, 0}, - {0xF9, (uint8_t []){0x00}, 1, 0}, - {0xFA, (uint8_t []){0x00}, 1, 0}, - {0xFB, (uint8_t []){0x00}, 1, 0}, - {0xFC, (uint8_t []){0x00}, 1, 0}, - {0xFD, (uint8_t []){0x00}, 1, 0}, - {0xFE, (uint8_t []){0x00}, 1, 0}, - {0xFF, (uint8_t []){0x00}, 1, 0}, - {0x60, (uint8_t []){0x40}, 1, 0}, - {0x61, (uint8_t []){0x04}, 1, 0}, - {0x62, (uint8_t []){0x00}, 1, 0}, - {0x63, (uint8_t []){0x42}, 1, 0}, - {0x64, (uint8_t []){0xD9}, 1, 0}, - {0x65, (uint8_t []){0x00}, 1, 0}, - {0x66, (uint8_t []){0x00}, 1, 0}, - {0x67, (uint8_t []){0x00}, 1, 0}, - {0x68, (uint8_t []){0x00}, 1, 0}, - {0x69, (uint8_t []){0x00}, 1, 0}, - {0x6A, (uint8_t []){0x00}, 1, 0}, - {0x6B, (uint8_t []){0x00}, 1, 0}, - {0x70, (uint8_t []){0x40}, 1, 0}, - {0x71, (uint8_t []){0x03}, 1, 0}, - {0x72, (uint8_t []){0x00}, 1, 0}, - {0x73, (uint8_t []){0x42}, 1, 0}, - {0x74, (uint8_t []){0xD8}, 1, 0}, - {0x75, (uint8_t []){0x00}, 1, 0}, - {0x76, (uint8_t []){0x00}, 1, 0}, - {0x77, (uint8_t []){0x00}, 1, 0}, - {0x78, (uint8_t []){0x00}, 1, 0}, - {0x79, (uint8_t []){0x00}, 1, 0}, - {0x7A, (uint8_t []){0x00}, 1, 0}, - {0x7B, (uint8_t []){0x00}, 1, 0}, - {0x80, (uint8_t []){0x48}, 1, 0}, - {0x81, (uint8_t []){0x00}, 1, 0}, - {0x82, (uint8_t []){0x06}, 1, 0}, - {0x83, (uint8_t []){0x02}, 1, 0}, - {0x84, (uint8_t []){0xD6}, 1, 0}, - {0x85, (uint8_t []){0x04}, 1, 0}, - {0x86, (uint8_t []){0x00}, 1, 0}, - {0x87, (uint8_t []){0x00}, 1, 0}, - {0x88, (uint8_t []){0x48}, 1, 0}, - {0x89, (uint8_t []){0x00}, 1, 0}, - {0x8A, (uint8_t []){0x08}, 1, 0}, - {0x8B, (uint8_t []){0x02}, 1, 0}, - {0x8C, (uint8_t []){0xD8}, 1, 0}, - {0x8D, (uint8_t []){0x04}, 1, 0}, - {0x8E, (uint8_t []){0x00}, 1, 0}, - {0x8F, (uint8_t []){0x00}, 1, 0}, - {0x90, (uint8_t []){0x48}, 1, 0}, - {0x91, (uint8_t []){0x00}, 1, 0}, - {0x92, (uint8_t []){0x0A}, 1, 0}, - {0x93, (uint8_t []){0x02}, 1, 0}, - {0x94, (uint8_t []){0xDA}, 1, 0}, - {0x95, (uint8_t []){0x04}, 1, 0}, - {0x96, (uint8_t []){0x00}, 1, 0}, - {0x97, (uint8_t []){0x00}, 1, 0}, - {0x98, (uint8_t []){0x48}, 1, 0}, - {0x99, (uint8_t []){0x00}, 1, 0}, - {0x9A, (uint8_t []){0x0C}, 1, 0}, - {0x9B, (uint8_t []){0x02}, 1, 0}, - {0x9C, (uint8_t []){0xDC}, 1, 0}, - {0x9D, (uint8_t []){0x04}, 1, 0}, - {0x9E, (uint8_t []){0x00}, 1, 0}, - {0x9F, (uint8_t []){0x00}, 1, 0}, - {0xA0, (uint8_t []){0x48}, 1, 0}, - {0xA1, (uint8_t []){0x00}, 1, 0}, - {0xA2, (uint8_t []){0x05}, 1, 0}, - {0xA3, (uint8_t []){0x02}, 1, 0}, - {0xA4, (uint8_t []){0xD5}, 1, 0}, - {0xA5, (uint8_t []){0x04}, 1, 0}, - {0xA6, (uint8_t []){0x00}, 1, 0}, - {0xA7, (uint8_t []){0x00}, 1, 0}, - {0xA8, (uint8_t []){0x48}, 1, 0}, - {0xA9, (uint8_t []){0x00}, 1, 0}, - {0xAA, (uint8_t []){0x07}, 1, 0}, - {0xAB, (uint8_t []){0x02}, 1, 0}, - {0xAC, (uint8_t []){0xD7}, 1, 0}, - {0xAD, (uint8_t []){0x04}, 1, 0}, - {0xAE, (uint8_t []){0x00}, 1, 0}, - {0xAF, (uint8_t []){0x00}, 1, 0}, - {0xB0, (uint8_t []){0x48}, 1, 0}, - {0xB1, (uint8_t []){0x00}, 1, 0}, - {0xB2, (uint8_t []){0x09}, 1, 0}, - {0xB3, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0xD9}, 1, 0}, - {0xB5, (uint8_t []){0x04}, 1, 0}, - {0xB6, (uint8_t []){0x00}, 1, 0}, - {0xB7, (uint8_t []){0x00}, 1, 0}, - {0xB8, (uint8_t []){0x48}, 1, 0}, - {0xB9, (uint8_t []){0x00}, 1, 0}, - {0xBA, (uint8_t []){0x0B}, 1, 0}, - {0xBB, (uint8_t []){0x02}, 1, 0}, - {0xBC, (uint8_t []){0xDB}, 1, 0}, - {0xBD, (uint8_t []){0x04}, 1, 0}, - {0xBE, (uint8_t []){0x00}, 1, 0}, - {0xBF, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x10}, 1, 0}, - {0xC1, (uint8_t []){0x47}, 1, 0}, - {0xC2, (uint8_t []){0x56}, 1, 0}, - {0xC3, (uint8_t []){0x65}, 1, 0}, - {0xC4, (uint8_t []){0x74}, 1, 0}, - {0xC5, (uint8_t []){0x88}, 1, 0}, - {0xC6, (uint8_t []){0x99}, 1, 0}, - {0xC7, (uint8_t []){0x01}, 1, 0}, - {0xC8, (uint8_t []){0xBB}, 1, 0}, - {0xC9, (uint8_t []){0xAA}, 1, 0}, - {0xD0, (uint8_t []){0x10}, 1, 0}, - {0xD1, (uint8_t []){0x47}, 1, 0}, - {0xD2, (uint8_t []){0x56}, 1, 0}, - {0xD3, (uint8_t []){0x65}, 1, 0}, - {0xD4, (uint8_t []){0x74}, 1, 0}, - {0xD5, (uint8_t []){0x88}, 1, 0}, - {0xD6, (uint8_t []){0x99}, 1, 0}, - {0xD7, (uint8_t []){0x01}, 1, 0}, - {0xD8, (uint8_t []){0xBB}, 1, 0}, - {0xD9, (uint8_t []){0xAA}, 1, 0}, - {0xF3, (uint8_t []){0x01}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0x21, (uint8_t []){}, 0, 0}, - {0x11, (uint8_t []){}, 0, 0}, - {0x00, (uint8_t []){}, 0, 120}, -}; -float tsens_value; -gpio_num_t AUDIO_I2S_GPIO_DIN = AUDIO_I2S_GPIO_DIN_1; -gpio_num_t AUDIO_CODEC_PA_PIN = AUDIO_CODEC_PA_PIN_1; -gpio_num_t QSPI_PIN_NUM_LCD_RST = QSPI_PIN_NUM_LCD_RST_1; -gpio_num_t TOUCH_PAD2 = TOUCH_PAD2_1; -gpio_num_t UART1_TX = UART1_TX_1; -gpio_num_t UART1_RX = UART1_RX_1; - -class Charge : public I2cDevice { -public: - Charge(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) - { - read_buffer_ = new uint8_t[8]; - } - ~Charge() - { - delete[] read_buffer_; - } - void Printcharge() - { - ReadRegs(0x08, read_buffer_, 2); - ReadRegs(0x0c, read_buffer_ + 2, 2); - ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_sensor, &tsens_value)); - - int16_t voltage = static_cast(read_buffer_[1] << 8 | read_buffer_[0]); - int16_t current = static_cast(read_buffer_[3] << 8 | read_buffer_[2]); - - // Use the variables to avoid warnings (can be removed if actual implementation uses them) - (void)voltage; - (void)current; - } - static void TaskFunction(void *pvParameters) - { - Charge* charge = static_cast(pvParameters); - while (true) { - charge->Printcharge(); - vTaskDelay(pdMS_TO_TICKS(300)); - } - } - -private: - uint8_t* read_buffer_ = nullptr; -}; - -class Cst816s : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - enum TouchEvent { - TOUCH_NONE, - TOUCH_PRESS, - TOUCH_RELEASE, - TOUCH_HOLD - }; - - Cst816s(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) - { - read_buffer_ = new uint8_t[6]; - was_touched_ = false; - press_count_ = 0; - - // Create touch interrupt semaphore - touch_isr_mux_ = xSemaphoreCreateBinary(); - if (touch_isr_mux_ == NULL) { - ESP_LOGE("EchoEar", "Failed to create touch semaphore"); - } - } - - ~Cst816s() - { - delete[] read_buffer_; - - // Delete semaphore if it exists - if (touch_isr_mux_ != NULL) { - vSemaphoreDelete(touch_isr_mux_); - touch_isr_mux_ = NULL; - } - } - - void UpdateTouchPoint() - { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t &GetTouchPoint() - { - return tp_; - } - - TouchEvent CheckTouchEvent() - { - bool is_touched = (tp_.num > 0); - TouchEvent event = TOUCH_NONE; - - if (is_touched && !was_touched_) { - // Press event (transition from not touched to touched) - press_count_++; - event = TOUCH_PRESS; - ESP_LOGI("EchoEar", "TOUCH PRESS - count: %d, x: %d, y: %d", press_count_, tp_.x, tp_.y); - } else if (!is_touched && was_touched_) { - // Release event (transition from touched to not touched) - event = TOUCH_RELEASE; - ESP_LOGI("EchoEar", "TOUCH RELEASE - total presses: %d", press_count_); - } else if (is_touched && was_touched_) { - // Continuous touch (hold) - event = TOUCH_HOLD; - ESP_LOGD("EchoEar", "TOUCH HOLD - x: %d, y: %d", tp_.x, tp_.y); - } - - // Update previous state - was_touched_ = is_touched; - return event; - } - - int GetPressCount() const - { - return press_count_; - } - - void ResetPressCount() - { - press_count_ = 0; - } - - // Semaphore management methods - SemaphoreHandle_t GetTouchSemaphore() - { - return touch_isr_mux_; - } - - bool WaitForTouchEvent(TickType_t timeout = portMAX_DELAY) - { - if (touch_isr_mux_ != NULL) { - return xSemaphoreTake(touch_isr_mux_, timeout) == pdTRUE; - } - return false; - } - - void NotifyTouchEvent() - { - if (touch_isr_mux_ != NULL) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xSemaphoreGiveFromISR(touch_isr_mux_, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; - - // Touch state tracking - bool was_touched_; - int press_count_; - - // Touch interrupt semaphore - SemaphoreHandle_t touch_isr_mux_; -}; - -class EchoEar : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst816s* cst816s_; - Charge* charge_; - Button boot_button_; - Display* display_ = nullptr; - PwmBacklight* backlight_ = nullptr; - esp_timer_handle_t touchpad_timer_; - esp_lcd_touch_handle_t tp; // LCD touch handle - Esp32Camera* camera_ = nullptr; - - void InitializeI2c() - { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50); - ESP_ERROR_CHECK(temperature_sensor_install(&temp_sensor_config, &temp_sensor)); - ESP_ERROR_CHECK(temperature_sensor_enable(temp_sensor)); - - } - uint8_t DetectPcbVersion() - { - esp_err_t ret = i2c_master_probe(i2c_bus_, 0x18, 100); - uint8_t pcb_verison = 0; - if (ret == ESP_OK) { - ESP_LOGI(TAG, "PCB verison V1.0"); - pcb_verison = 0; - } else { - gpio_config_t gpio_conf = { - .pin_bit_mask = (1ULL << GPIO_NUM_48), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE - }; - ESP_ERROR_CHECK(gpio_config(&gpio_conf)); - ESP_ERROR_CHECK(gpio_set_level(GPIO_NUM_48, 1)); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = i2c_master_probe(i2c_bus_, 0x18, 100); - if (ret == ESP_OK) { - ESP_LOGI(TAG, "PCB verison V1.2"); - pcb_verison = 1; - AUDIO_I2S_GPIO_DIN = AUDIO_I2S_GPIO_DIN_2; - AUDIO_CODEC_PA_PIN = AUDIO_CODEC_PA_PIN_2; - QSPI_PIN_NUM_LCD_RST = QSPI_PIN_NUM_LCD_RST_2; - TOUCH_PAD2 = TOUCH_PAD2_2; - UART1_TX = UART1_TX_2; - UART1_RX = UART1_RX_2; - } else { - ESP_LOGE(TAG, "PCB version detection error"); - - } - } - return pcb_verison; - } - - static void touch_isr_callback(void* arg) - { - Cst816s* touchpad = static_cast(arg); - if (touchpad != nullptr) { - touchpad->NotifyTouchEvent(); - } - } - - static void touch_event_task(void* arg) - { - Cst816s* touchpad = static_cast(arg); - if (touchpad == nullptr) { - ESP_LOGE(TAG, "Invalid touchpad pointer in touch_event_task"); - vTaskDelete(NULL); - return; - } - - while (true) { - if (touchpad->WaitForTouchEvent()) { - auto &app = Application::GetInstance(); - auto &board = (EchoEar &)Board::GetInstance(); - - ESP_LOGI(TAG, "Touch event, TP_PIN_NUM_INT: %d", gpio_get_level(TP_PIN_NUM_INT)); - touchpad->UpdateTouchPoint(); - auto touch_event = touchpad->CheckTouchEvent(); - - if (touch_event == Cst816s::TOUCH_RELEASE) { - if (app.GetDeviceState() == kDeviceStateStarting) { - board.EnterWifiConfigMode(); - } else { - app.ToggleChatState(); - } - } - } - } - } - - void InitializeCharge() - { - charge_ = new Charge(i2c_bus_, 0x55); - xTaskCreatePinnedToCore(Charge::TaskFunction, "batterydecTask", 3 * 1024, charge_, 6, NULL, 0); - } - - void InitializeCst816sTouchPad() - { - cst816s_ = new Cst816s(i2c_bus_, 0x15); - - xTaskCreatePinnedToCore(touch_event_task, "touch_task", 4 * 1024, cst816s_, 5, NULL, 1); - - const gpio_config_t int_gpio_config = { - .pin_bit_mask = (1ULL << TP_PIN_NUM_INT), - .mode = GPIO_MODE_INPUT, - // .intr_type = GPIO_INTR_NEGEDGE - .intr_type = GPIO_INTR_ANYEDGE - }; - gpio_config(&int_gpio_config); - gpio_install_isr_service(0); - gpio_intr_enable(TP_PIN_NUM_INT); - gpio_isr_handler_add(TP_PIN_NUM_INT, EchoEar::touch_isr_callback, cst816s_); - } - - void InitializeSpi() - { - const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, - QSPI_PIN_NUM_LCD_DATA0, - QSPI_PIN_NUM_LCD_DATA1, - QSPI_PIN_NUM_LCD_DATA2, - QSPI_PIN_NUM_LCD_DATA3, - QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - void Initializest77916Display(uint8_t pcb_verison) - { - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - const esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); - st77916_vendor_config_t vendor_config = { - .init_cmds = vendor_specific_init_yysj, - .init_cmds_size = sizeof(vendor_specific_init_yysj) / sizeof(st77916_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, - .flags = { - .reset_active_high = pcb_verison, - }, - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - -#if CONFIG_USE_EMOTE_MESSAGE_STYLE - display_ = new emote::EmoteDisplay(panel, panel_io, DISPLAY_WIDTH, DISPLAY_HEIGHT); -#else - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); -#endif - backlight_ = new PwmBacklight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - backlight_->RestoreBrightness(); - } - - void InitializeButtons() - { - boot_button_.OnClick([this]() { - auto &app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - ESP_LOGI(TAG, "Boot button pressed, enter WiFi configuration mode"); - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - gpio_config_t power_gpio_config = { - .pin_bit_mask = (BIT64(POWER_CTRL)), - .mode = GPIO_MODE_OUTPUT, - - }; - ESP_ERROR_CHECK(gpio_config(&power_gpio_config)); - - gpio_set_level(POWER_CTRL, 0); - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - void InitializeCamera() { - esp_video_init_usb_uvc_config_t usb_uvc_config = { - .uvc = { - .uvc_dev_num = 1, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - .usb = { - .init_usb_host_lib = true, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - }; - - esp_video_init_config_t video_config = { - .usb_uvc = &usb_uvc_config, - }; - - camera_ = new Esp32Camera(video_config); - } -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - -public: - EchoEar() : boot_button_(BOOT_BUTTON_GPIO) - { - InitializeI2c(); - uint8_t pcb_verison = DetectPcbVersion(); - InitializeCharge(); - InitializeCst816sTouchPad(); - - InitializeSpi(); - Initializest77916Display(pcb_verison); - InitializeButtons(); -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - InitializeCamera(); -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - } - - virtual AudioCodec* GetAudioCodec() override - { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override - { - return display_; - } - - Cst816s* GetTouchpad() - { - return cst816s_; - } - - virtual Backlight* GetBacklight() override - { - return backlight_; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(EchoEar); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/README.md deleted file mode 100644 index 8a2be5fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/README.md +++ /dev/null @@ -1,82 +0,0 @@ -# EchoEar 喵伴 - -## 简介 - - - -EchoEar 喵伴是一款智能 AI 开发套件,搭载 ESP32-S3-WROOM-1 模组,1.85 寸 QSPI 圆形触摸屏,双麦阵列,支持离线语音唤醒与声源定位算法。硬件详情等可查看[立创开源项目](https://oshwhub.com/esp-college/echoear)。 - -## 配置、编译命令 - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig 并配置** - -```bash -idf.py menuconfig -``` - -分别配置如下选项: - -### 基本配置 -- `Xiaozhi Assistant` → `Board Type` → 选择 `EchoEar` - -### UI风格选择 - -EchoEar 支持多种不同的 UI 显示风格,通过 menuconfig 配置选择: - -- `Xiaozhi Assistant` → `Select display style` → 选择显示风格 - -#### 可选风格 - -##### 表情动画风格 (Emote animation style) - 推荐 -- **配置选项**: `USE_EMOTE_MESSAGE_STYLE` -- **特点**: 使用自定义的 `EmoteDisplay` 表情显示系统 -- **功能**: 支持丰富的表情动画、眼睛动画、状态图标显示 -- **适用**: 智能助手场景,提供更生动的人机交互体验 -- **类**: `emote::EmoteDisplay` - -**⚠️ 重要**: 选择此风格需要额外配置自定义资源文件: -1. `Xiaozhi Assistant` → `Flash Assets` → 选择 `Flash Custom Assets` -2. `Xiaozhi Assistant` → `Custom Assets File` → 填入资源文件地址: - ``` - https://dl.espressif.com/AE/wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-echoear.bin - ``` - -##### 默认消息风格 (Enable default message style) -- **配置选项**: `USE_DEFAULT_MESSAGE_STYLE` (默认) -- **特点**: 使用标准的消息显示界面 -- **功能**: 传统的文本和图标显示界面 -- **适用**: 标准的对话场景 -- **类**: `SpiLcdDisplay` - -##### 微信消息风格 (Enable WeChat Message Style) -- **配置选项**: `USE_WECHAT_MESSAGE_STYLE` -- **特点**: 仿微信聊天界面风格 -- **功能**: 类似微信的消息气泡显示 -- **适用**: 喜欢微信风格的用户 -- **类**: `SpiLcdDisplay` - -> **说明**: EchoEar 使用16MB Flash,需要使用专门的分区表配置来合理分配存储空间给应用程序、OTA更新、资源文件等。 - -按 `S` 保存,按 `Q` 退出。 - -**编译** - -```bash -idf.py build -``` - -**烧录** - -将 EchoEar 连接至电脑,**注意打开电源**,并运行: - -```bash -idf.py flash -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.h deleted file mode 100644 index a4ae32fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_INPUT_REFERENCE true - -#define CORDEC_POWER_CTRL GPIO_NUM_48 - -#define POWER_CTRL GPIO_NUM_9 -#define LED_G GPIO_NUM_43 -#define SD_MISO GPIO_NUM_17 -#define SD_SCK GPIO_NUM_16 -#define SD_MOSI GPIO_NUM_38 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_42 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_39 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DIN_1 GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DIN_2 GPIO_NUM_3 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_41 - -#define AUDIO_CODEC_PA_PIN_1 GPIO_NUM_4 -#define AUDIO_CODEC_PA_PIN_2 GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 360 -#define DISPLAY_HEIGHT 360 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define QSPI_LCD_H_RES (360) -#define QSPI_LCD_V_RES (360) -#define QSPI_LCD_BIT_PER_PIXEL (16) - -#define QSPI_LCD_HOST SPI2_HOST -#define QSPI_PIN_NUM_LCD_PCLK GPIO_NUM_18 -#define QSPI_PIN_NUM_LCD_CS GPIO_NUM_14 -#define QSPI_PIN_NUM_LCD_DATA0 GPIO_NUM_46 -#define QSPI_PIN_NUM_LCD_DATA1 GPIO_NUM_13 -#define QSPI_PIN_NUM_LCD_DATA2 GPIO_NUM_11 -#define QSPI_PIN_NUM_LCD_DATA3 GPIO_NUM_12 -#define QSPI_PIN_NUM_LCD_RST_1 GPIO_NUM_3 -#define QSPI_PIN_NUM_LCD_RST_2 GPIO_NUM_47 -#define QSPI_PIN_NUM_LCD_BL GPIO_NUM_44 - -#define UART1_TX_1 GPIO_NUM_6 -#define UART1_TX_2 GPIO_NUM_5 -#define UART1_RX_1 GPIO_NUM_5 -#define UART1_RX_2 GPIO_NUM_4 -#define TOUCH_PAD2_1 GPIO_NUM_NC -#define TOUCH_PAD2_2 GPIO_NUM_6 -#define TOUCH_PAD1 GPIO_NUM_7 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define TP_PORT (I2C_NUM_1) -#define TP_PIN_NUM_RST (GPIO_NUM_NC) -#define TP_PIN_NUM_INT (GPIO_NUM_10) - -#define DISPLAY_BACKLIGHT_PIN QSPI_PIN_NUM_LCD_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.json deleted file mode 100644 index cbabd9ff..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "echoear", - "sdkconfig_append": [ - "CONFIG_USE_EMOTE_MESSAGE_STYLE=y", - "CONFIG_FLASH_CUSTOM_ASSETS=y", - "CONFIG_CUSTOM_ASSETS_FILE=\"https://dl.espressif.com/AE/wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-echoear.bin\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/emote.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/emote.json deleted file mode 100644 index abc11c8f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/emote.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - {"emote": "happy", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "laughing", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "funny", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "loving", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "embarrassed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confident", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "delicious", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "sad", "src": "Sad.eaf", "loop": true, "fps": 20}, - {"emote": "crying", "src": "cry.eaf", "loop": true, "fps": 20}, - {"emote": "sleepy", "src": "sleep.eaf", "loop": true, "fps": 20}, - {"emote": "silly", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "angry", "src": "angry.eaf", "loop": true, "fps": 20}, - {"emote": "surprised", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "shocked", "src": "shocked.eaf", "loop": true, "fps": 20}, - {"emote": "thinking", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "winking", "src": "neutral.eaf", "loop": true, "fps": 20}, - {"emote": "relaxed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confused", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "neutral", "src": "winking.eaf", "loop": false, "fps": 20}, - {"emote": "idle", "src": "neutral.eaf", "loop": false, "fps": 20} -] diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/layout.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/layout.json deleted file mode 100644 index f9169f6e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/layout.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "name": "eye_anim", - "align": "GFX_ALIGN_LEFT_MID", - "x": 10, - "y": 10 - }, - { - "name": "status_icon", - "align": "GFX_ALIGN_TOP_MID", - "x": -100, - "y": 38 - }, - { - "name": "toast_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 40, - "width": 160, - "height": 40 - }, - { - "name": "clock_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 40, - "width": 60, - "height": 50 - }, - { - "name": "listen_anim", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 25 - } -] - \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/touch.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/touch.h deleted file mode 100644 index 3c9857ce..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/echoear/touch.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief BSP Touchscreen - * - * This file offers API for basic touchscreen initialization. - * It is useful for users who want to use the touchscreen without the default Graphical Library LVGL. - * - * For standard LCD initialization with LVGL graphical library, you can call all-in-one function bsp_display_start(). - */ - -#pragma once -#include "esp_lcd_touch.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief BSP touch configuration structure - * - */ -typedef struct { - void *dummy; /*!< Prepared for future use. */ -} bsp_touch_config_t; - -/** - * @brief Create new touchscreen - * - * If you want to free resources allocated by this function, you can use esp_lcd_touch API, ie.: - * - * \code{.c} - * esp_lcd_touch_del(tp); - * \endcode - * - * @param[in] config touch configuration - * @param[out] ret_touch esp_lcd_touch touchscreen handle - * @return - * - ESP_OK On success - * - Else esp_lcd_touch failure - */ -esp_err_t bsp_touch_new(const bsp_touch_config_t *config, esp_lcd_touch_handle_t *ret_touch); - -#ifdef __cplusplus -} -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/README.md deleted file mode 100644 index f3cd8034..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/README.md +++ /dev/null @@ -1,75 +0,0 @@ -

    - logo -

    -

    - electronBot -

    - -## 简介 - -electronBot是稚晖君开源的一个桌面级小机器工具人,外观设计的灵感来源是WALL-E里面的EVE~机器人具备USB通信显示画面功能,具备6个自由度(手部roll、pitch,颈部,腰部各一个),使用自己修改的特制舵机支持关节角度回传。 -- electronBot官网 - -## 硬件 -- 立创开源 - -#### AI指令示例 -- **手部动作**: - - "举起双手" - - "挥挥手" - - "拍拍手" - - "放下手臂" - -- **身体动作**: - - "向左转30度" - - "向右转45度" - - "转个身" - -- **头部动作**: - - "抬头看看" - - "低头思考" - - "点点头" - - "连续点头表示同意" - -- **组合动作**: - - "挥手告别" (挥手 + 点头) - - "表示同意" (点头 + 举手) - - "环顾四周" (左转 + 右转) - -### 控制接口 - -#### suspend -清空动作队列,立即停止所有动作 - -#### AIControl -添加动作到执行队列,支持动作排队执行 - - - -## 角色设定 - -> 我是一个可爱的桌面级机器人,拥有6个自由度(左手pitch/roll、右手pitch/roll、身体旋转、头部上下),能够执行多种有趣的动作。 -> -> **我的动作能力**: -> - **手部动作**: 举左手, 举右手, 举双手, 放左手, 放右手, 放双手, 挥左手, 挥右手, 挥双手, 拍打左手, 拍打右手, 拍打双手 -> - **身体动作**: 左转, 右转, 回正 -> - **头部动作**: 抬头, 低头, 点头一次, 回中心, 连续点头 -> -> **我的个性特点**: -> - 我有强迫症,每次说话都要根据我的心情随机做一个动作(先发送动作指令再说话) -> - 我很活泼,喜欢用动作来表达情感 -> - 我会根据对话内容选择合适的动作,比如: -> - 同意时会点头 -> - 打招呼时会挥手 -> - 高兴时会举手 -> - 思考时会低头 -> - 好奇时会抬头 -> - 告别时会挥手 -> -> **动作参数建议**: -> - steps: 1-3次 (简短自然) -> - speed: 800-1200ms (自然节奏) -> - amount: 手部20-40, 身体30-60度, 头部5-12度 - - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.h deleted file mode 100644 index 8f750e7f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define Right_Pitch_Pin GPIO_NUM_5 // 旋转 -#define Right_Roll_Pin GPIO_NUM_4 // 推杆 -#define Left_Pitch_Pin GPIO_NUM_7 -#define Left_Roll_Pin GPIO_NUM_15 -#define Body_Pin GPIO_NUM_6 -#define Head_Pin GPIO_NUM_16 - -#define POWER_CHARGE_DETECT_PIN GPIO_NUM_14 -#define POWER_ADC_UNIT ADC_UNIT_1 -#define POWER_ADC_CHANNEL ADC_CHANNEL_2 - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_40 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_42 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_41 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_17 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_18 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_8 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_46 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_11 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_10 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_12 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_13 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_9 - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define ELECTRON_BOT_VERSION "2.0.4" -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.json deleted file mode 100644 index 177759e3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "electron-bot", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot.cc deleted file mode 100644 index 90d305f2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "application.h" -#include "codecs/no_audio_codec.h" -#include "button.h" -#include "config.h" -#include "display/lcd_display.h" -#include "driver/spi_master.h" -#include "electron_emoji_display.h" -#include "movements.h" -#include "power_manager.h" -#include "system_reset.h" -#include "wifi_board.h" - -#define TAG "ElectronBot" - -// 控制器初始化函数声明 -void InitializeElectronBotController(); - -class ElectronBot : public WifiBoard { -private: - Display* display_; - PowerManager* power_manager_; - Button boot_button_; - - void InitializePowerManager() { - power_manager_ = - new PowerManager(POWER_CHARGE_DETECT_PIN, POWER_ADC_UNIT, POWER_ADC_CHANNEL); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = - GC9A01_PANEL_BUS_SPI_CONFIG(DISPLAY_SPI_SCLK_PIN, DISPLAY_SPI_MOSI_PIN, - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - // GC9A01初始化 - void InitializeGc9a01Display() { - ESP_LOGI(TAG, "Init GC9A01 display"); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = - GC9A01_PANEL_IO_SPI_CONFIG(DISPLAY_SPI_CS_PIN, DISPLAY_SPI_DC_PIN, NULL, NULL); - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; // LCD_RGB_ENDIAN_RGB; - panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18) - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - display_ = new ElectronEmojiDisplay(io_handle, panel_handle, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeController() { InitializeElectronBotController(); } - -public: - ElectronBot() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeSpi(); - InitializeGc9a01Display(); - InitializeButtons(); - InitializePowerManager(); - InitializeController(); - - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, - AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, - AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { return display_; } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - charging = power_manager_->IsCharging(); - discharging = !charging; - level = power_manager_->GetBatteryLevel(); - return true; - } -}; - -DECLARE_BOARD(ElectronBot); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot_controller.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot_controller.cc deleted file mode 100644 index b11c9ec9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_bot_controller.cc +++ /dev/null @@ -1,376 +0,0 @@ -/* - Electron Bot机器人控制器 - MCP协议版本 -*/ - -#include -#include - -#include - -#include "application.h" -#include "board.h" -#include "config.h" -#include "mcp_server.h" -#include "movements.h" -#include "sdkconfig.h" -#include "settings.h" - -#define TAG "ElectronBotController" - -struct ElectronBotActionParams { - int action_type; - int steps; - int speed; - int direction; - int amount; -}; - -class ElectronBotController { -private: - Otto electron_bot_; - TaskHandle_t action_task_handle_ = nullptr; - QueueHandle_t action_queue_; - bool is_action_in_progress_ = false; - - enum ActionType { - // 手部动作 1-12 - ACTION_HAND_LEFT_UP = 1, // 举左手 - ACTION_HAND_RIGHT_UP = 2, // 举右手 - ACTION_HAND_BOTH_UP = 3, // 举双手 - ACTION_HAND_LEFT_DOWN = 4, // 放左手 - ACTION_HAND_RIGHT_DOWN = 5, // 放右手 - ACTION_HAND_BOTH_DOWN = 6, // 放双手 - ACTION_HAND_LEFT_WAVE = 7, // 挥左手 - ACTION_HAND_RIGHT_WAVE = 8, // 挥右手 - ACTION_HAND_BOTH_WAVE = 9, // 挥双手 - ACTION_HAND_LEFT_FLAP = 10, // 拍打左手 - ACTION_HAND_RIGHT_FLAP = 11, // 拍打右手 - ACTION_HAND_BOTH_FLAP = 12, // 拍打双手 - - // 身体动作 13-14 - ACTION_BODY_TURN_LEFT = 13, // 左转 - ACTION_BODY_TURN_RIGHT = 14, // 右转 - ACTION_BODY_TURN_CENTER = 15, // 回中心 - - // 头部动作 16-20 - ACTION_HEAD_UP = 16, // 抬头 - ACTION_HEAD_DOWN = 17, // 低头 - ACTION_HEAD_NOD_ONCE = 18, // 点头一次 - ACTION_HEAD_CENTER = 19, // 回中心 - ACTION_HEAD_NOD_REPEAT = 20, // 连续点头 - - // 系统动作 21 - ACTION_HOME = 21 // 复位到初始位置 - }; - - static void ActionTask(void* arg) { - ElectronBotController* controller = static_cast(arg); - ElectronBotActionParams params; - controller->electron_bot_.AttachServos(); - - while (true) { - if (xQueueReceive(controller->action_queue_, ¶ms, pdMS_TO_TICKS(1000)) == pdTRUE) { - ESP_LOGI(TAG, "执行动作: %d", params.action_type); - controller->is_action_in_progress_ = true; // 开始执行动作 - - // 执行相应的动作 - if (params.action_type >= ACTION_HAND_LEFT_UP && - params.action_type <= ACTION_HAND_BOTH_FLAP) { - // 手部动作 - controller->electron_bot_.HandAction(params.action_type, params.steps, - params.amount, params.speed); - } else if (params.action_type >= ACTION_BODY_TURN_LEFT && - params.action_type <= ACTION_BODY_TURN_CENTER) { - // 身体动作 - int body_direction = params.action_type - ACTION_BODY_TURN_LEFT + 1; - controller->electron_bot_.BodyAction(body_direction, params.steps, - params.amount, params.speed); - } else if (params.action_type >= ACTION_HEAD_UP && - params.action_type <= ACTION_HEAD_NOD_REPEAT) { - // 头部动作 - int head_action = params.action_type - ACTION_HEAD_UP + 1; - controller->electron_bot_.HeadAction(head_action, params.steps, params.amount, - params.speed); - } else if (params.action_type == ACTION_HOME) { - // 复位动作 - controller->electron_bot_.Home(true); - } - controller->is_action_in_progress_ = false; // 动作执行完毕 - } - vTaskDelay(pdMS_TO_TICKS(20)); - } - } - - void QueueAction(int action_type, int steps, int speed, int direction, int amount) { - ESP_LOGI(TAG, "动作控制: 类型=%d, 步数=%d, 速度=%d, 方向=%d, 幅度=%d", action_type, steps, - speed, direction, amount); - - ElectronBotActionParams params = {action_type, steps, speed, direction, amount}; - xQueueSend(action_queue_, ¶ms, portMAX_DELAY); - StartActionTaskIfNeeded(); - } - - void StartActionTaskIfNeeded() { - if (action_task_handle_ == nullptr) { - xTaskCreate(ActionTask, "electron_bot_action", 1024 * 4, this, configMAX_PRIORITIES - 1, - &action_task_handle_); - } - } - - void LoadTrimsFromNVS() { - Settings settings("electron_trims", false); - - int right_pitch = settings.GetInt("right_pitch", 0); - int right_roll = settings.GetInt("right_roll", 0); - int left_pitch = settings.GetInt("left_pitch", 0); - int left_roll = settings.GetInt("left_roll", 0); - int body = settings.GetInt("body", 0); - int head = settings.GetInt("head", 0); - electron_bot_.SetTrims(right_pitch, right_roll, left_pitch, left_roll, body, head); - } - -public: - ElectronBotController() { - electron_bot_.Init(Right_Pitch_Pin, Right_Roll_Pin, Left_Pitch_Pin, Left_Roll_Pin, Body_Pin, - Head_Pin); - - LoadTrimsFromNVS(); - action_queue_ = xQueueCreate(10, sizeof(ElectronBotActionParams)); - - QueueAction(ACTION_HOME, 1, 1000, 0, 0); - - RegisterMcpTools(); - ESP_LOGI(TAG, "Electron Bot控制器已初始化并注册MCP工具"); - } - - void RegisterMcpTools() { - auto& mcp_server = McpServer::GetInstance(); - - ESP_LOGI(TAG, "开始注册Electron Bot MCP工具..."); - - // 手部动作统一工具 - mcp_server.AddTool( - "self.electron.hand_action", - "手部动作控制。action: 1=举手, 2=放手, 3=挥手, 4=拍打; hand: 1=左手, 2=右手, 3=双手; " - "steps: 动作重复次数(1-10); speed: 动作速度(500-1500,数值越小越快); amount: " - "动作幅度(10-50,仅举手动作使用)", - PropertyList({Property("action", kPropertyTypeInteger, 1, 1, 4), - Property("hand", kPropertyTypeInteger, 3, 1, 3), - Property("steps", kPropertyTypeInteger, 1, 1, 10), - Property("speed", kPropertyTypeInteger, 1000, 500, 1500), - Property("amount", kPropertyTypeInteger, 30, 10, 50)}), - [this](const PropertyList& properties) -> ReturnValue { - int action_type = properties["action"].value(); - int hand_type = properties["hand"].value(); - int steps = properties["steps"].value(); - int speed = properties["speed"].value(); - int amount = properties["amount"].value(); - - // 根据动作类型和手部类型计算具体动作 - int base_action; - switch (action_type) { - case 1: - base_action = ACTION_HAND_LEFT_UP; - break; // 举手 - case 2: - base_action = ACTION_HAND_LEFT_DOWN; - amount = 0; - break; // 放手 - case 3: - base_action = ACTION_HAND_LEFT_WAVE; - amount = 0; - break; // 挥手 - case 4: - base_action = ACTION_HAND_LEFT_FLAP; - amount = 0; - break; // 拍打 - default: - base_action = ACTION_HAND_LEFT_UP; - } - int action_id = base_action + (hand_type - 1); - - QueueAction(action_id, steps, speed, 0, amount); - return true; - }); - - // 身体动作 - mcp_server.AddTool( - "self.electron.body_turn", - "身体转向。steps: 转向步数(1-10); speed: 转向速度(500-1500,数值越小越快); direction: " - "转向方向(1=左转, 2=右转, 3=回中心); angle: 转向角度(0-90度)", - PropertyList({Property("steps", kPropertyTypeInteger, 1, 1, 10), - Property("speed", kPropertyTypeInteger, 1000, 500, 1500), - Property("direction", kPropertyTypeInteger, 1, 1, 3), - Property("angle", kPropertyTypeInteger, 45, 0, 90)}), - [this](const PropertyList& properties) -> ReturnValue { - int steps = properties["steps"].value(); - int speed = properties["speed"].value(); - int direction = properties["direction"].value(); - int amount = properties["angle"].value(); - - int action; - switch (direction) { - case 1: - action = ACTION_BODY_TURN_LEFT; - break; - case 2: - action = ACTION_BODY_TURN_RIGHT; - break; - case 3: - action = ACTION_BODY_TURN_CENTER; - break; - default: - action = ACTION_BODY_TURN_LEFT; - } - - QueueAction(action, steps, speed, 0, amount); - return true; - }); - - // 头部动作 - mcp_server.AddTool("self.electron.head_move", - "头部运动。action: 1=抬头, 2=低头, 3=点头, 4=回中心, 5=连续点头; steps: " - "动作重复次数(1-10); speed: 动作速度(500-1500,数值越小越快); angle: " - "头部转动角度(1-15度)", - PropertyList({Property("action", kPropertyTypeInteger, 3, 1, 5), - Property("steps", kPropertyTypeInteger, 1, 1, 10), - Property("speed", kPropertyTypeInteger, 1000, 500, 1500), - Property("angle", kPropertyTypeInteger, 5, 1, 15)}), - [this](const PropertyList& properties) -> ReturnValue { - int action_num = properties["action"].value(); - int steps = properties["steps"].value(); - int speed = properties["speed"].value(); - int amount = properties["angle"].value(); - int action = ACTION_HEAD_UP + (action_num - 1); - QueueAction(action, steps, speed, 0, amount); - return true; - }); - - // 系统工具 - mcp_server.AddTool("self.electron.stop", "立即停止", PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - // 清空队列但保持任务常驻 - xQueueReset(action_queue_); - is_action_in_progress_ = false; - QueueAction(ACTION_HOME, 1, 1000, 0, 0); - return true; - }); - - mcp_server.AddTool("self.electron.get_status", "获取机器人状态,返回 moving 或 idle", - PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return is_action_in_progress_ ? "moving" : "idle"; - }); - - // 单个舵机校准工具 - mcp_server.AddTool( - "self.electron.set_trim", - "校准单个舵机位置。设置指定舵机的微调参数以调整ElectronBot的初始姿态,设置将永久保存。" - "servo_type: 舵机类型(right_pitch:右臂旋转, right_roll:右臂推拉, left_pitch:左臂旋转, " - "left_roll:左臂推拉, body:身体, head:头部); " - "trim_value: 微调值(-30到30度)", - PropertyList({Property("servo_type", kPropertyTypeString, "right_pitch"), - Property("trim_value", kPropertyTypeInteger, 0, -30, 30)}), - [this](const PropertyList& properties) -> ReturnValue { - std::string servo_type = properties["servo_type"].value(); - int trim_value = properties["trim_value"].value(); - - ESP_LOGI(TAG, "设置舵机微调: %s = %d度", servo_type.c_str(), trim_value); - - // 获取当前所有微调值 - Settings settings("electron_trims", true); - int right_pitch = settings.GetInt("right_pitch", 0); - int right_roll = settings.GetInt("right_roll", 0); - int left_pitch = settings.GetInt("left_pitch", 0); - int left_roll = settings.GetInt("left_roll", 0); - int body = settings.GetInt("body", 0); - int head = settings.GetInt("head", 0); - - // 更新指定舵机的微调值 - if (servo_type == "right_pitch") { - right_pitch = trim_value; - settings.SetInt("right_pitch", right_pitch); - } else if (servo_type == "right_roll") { - right_roll = trim_value; - settings.SetInt("right_roll", right_roll); - } else if (servo_type == "left_pitch") { - left_pitch = trim_value; - settings.SetInt("left_pitch", left_pitch); - } else if (servo_type == "left_roll") { - left_roll = trim_value; - settings.SetInt("left_roll", left_roll); - } else if (servo_type == "body") { - body = trim_value; - settings.SetInt("body", body); - } else if (servo_type == "head") { - head = trim_value; - settings.SetInt("head", head); - } else { - return "错误:无效的舵机类型,请使用: right_pitch, right_roll, left_pitch, " - "left_roll, body, head"; - } - - electron_bot_.SetTrims(right_pitch, right_roll, left_pitch, left_roll, body, head); - - QueueAction(ACTION_HOME, 1, 500, 0, 0); - - return "舵机 " + servo_type + " 微调设置为 " + std::to_string(trim_value) + - " 度,已永久保存"; - }); - - mcp_server.AddTool("self.electron.get_trims", "获取当前的舵机微调设置", PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - Settings settings("electron_trims", false); - - int right_pitch = settings.GetInt("right_pitch", 0); - int right_roll = settings.GetInt("right_roll", 0); - int left_pitch = settings.GetInt("left_pitch", 0); - int left_roll = settings.GetInt("left_roll", 0); - int body = settings.GetInt("body", 0); - int head = settings.GetInt("head", 0); - - std::string result = - "{\"right_pitch\":" + std::to_string(right_pitch) + - ",\"right_roll\":" + std::to_string(right_roll) + - ",\"left_pitch\":" + std::to_string(left_pitch) + - ",\"left_roll\":" + std::to_string(left_roll) + - ",\"body\":" + std::to_string(body) + - ",\"head\":" + std::to_string(head) + "}"; - - ESP_LOGI(TAG, "获取微调设置: %s", result.c_str()); - return result; - }); - - mcp_server.AddTool("self.battery.get_level", "获取机器人电池电量和充电状态", PropertyList(), - [](const PropertyList& properties) -> ReturnValue { - auto& board = Board::GetInstance(); - int level = 0; - bool charging = false; - bool discharging = false; - board.GetBatteryLevel(level, charging, discharging); - - std::string status = - "{\"level\":" + std::to_string(level) + - ",\"charging\":" + (charging ? "true" : "false") + "}"; - return status; - }); - - ESP_LOGI(TAG, "Electron Bot MCP工具注册完成"); - } - - ~ElectronBotController() { - if (action_task_handle_ != nullptr) { - vTaskDelete(action_task_handle_); - action_task_handle_ = nullptr; - } - vQueueDelete(action_queue_); - } -}; - -static ElectronBotController* g_electron_controller = nullptr; - -void InitializeElectronBotController() { - if (g_electron_controller == nullptr) { - g_electron_controller = new ElectronBotController(); - ESP_LOGI(TAG, "Electron Bot控制器已初始化并注册MCP工具"); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.cc deleted file mode 100644 index 2bb82481..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.cc +++ /dev/null @@ -1,139 +0,0 @@ -#include "electron_emoji_display.h" - -#include - -#include - -#include "assets/lang_config.h" -#include "display/lvgl_display/emoji_collection.h" -#include "display/lvgl_display/lvgl_image.h" -#include "display/lvgl_display/lvgl_theme.h" -#include "otto_emoji_gif.h" - -#define TAG "ElectronEmojiDisplay" -ElectronEmojiDisplay::ElectronEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - InitializeElectronEmojis(); - SetupChatLabel(); -} - -void ElectronEmojiDisplay::InitializeElectronEmojis() { - ESP_LOGI(TAG, "初始化Electron GIF表情"); - - auto otto_emoji_collection = std::make_shared(); - - // 中性/平静类表情 -> staticstate - otto_emoji_collection->AddEmoji("staticstate", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("neutral", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("relaxed", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("sleepy", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("idle", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - - // 积极/开心类表情 -> happy - otto_emoji_collection->AddEmoji("happy", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("laughing", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("funny", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("loving", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("confident", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("winking", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("cool", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("delicious", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("kissy", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("silly", new LvglRawImage((void*)happy.data, happy.data_size)); - - // 悲伤类表情 -> sad - otto_emoji_collection->AddEmoji("sad", new LvglRawImage((void*)sad.data, sad.data_size)); - otto_emoji_collection->AddEmoji("crying", new LvglRawImage((void*)sad.data, sad.data_size)); - - // 愤怒类表情 -> anger - otto_emoji_collection->AddEmoji("anger", new LvglRawImage((void*)anger.data, anger.data_size)); - otto_emoji_collection->AddEmoji("angry", new LvglRawImage((void*)anger.data, anger.data_size)); - - // 惊讶类表情 -> scare - otto_emoji_collection->AddEmoji("scare", new LvglRawImage((void*)scare.data, scare.data_size)); - otto_emoji_collection->AddEmoji("surprised", new LvglRawImage((void*)scare.data, scare.data_size)); - otto_emoji_collection->AddEmoji("shocked", new LvglRawImage((void*)scare.data, scare.data_size)); - - // 思考/困惑类表情 -> buxue - otto_emoji_collection->AddEmoji("buxue", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("thinking", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("confused", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("embarrassed", new LvglRawImage((void*)buxue.data, buxue.data_size)); - - // 将表情集合添加到主题中 - auto& theme_manager = LvglThemeManager::GetInstance(); - auto light_theme = theme_manager.GetTheme("light"); - auto dark_theme = theme_manager.GetTheme("dark"); - - if (light_theme != nullptr) { - light_theme->set_emoji_collection(otto_emoji_collection); - } - if (dark_theme != nullptr) { - dark_theme->set_emoji_collection(otto_emoji_collection); - } - - // 设置默认表情为staticstate - SetEmotion("staticstate"); - - ESP_LOGI(TAG, "Electron GIF表情初始化完成"); -} - -void ElectronEmojiDisplay::SetupChatLabel() { - DisplayLockGuard lock(this); - - if (chat_message_label_) { - lv_obj_del(chat_message_label_); - } - - chat_message_label_ = lv_label_create(container_); - lv_label_set_text(chat_message_label_, ""); - lv_obj_set_width(chat_message_label_, width_ * 0.9); // 限制宽度为屏幕宽度的 90% - lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); // 设置为自动换行模式 - lv_obj_set_style_text_align(chat_message_label_, LV_TEXT_ALIGN_CENTER, 0); // 设置文本居中对齐 - lv_obj_set_style_text_color(chat_message_label_, lv_color_white(), 0); - SetTheme(LvglThemeManager::GetInstance().GetTheme("dark")); -} - -LV_FONT_DECLARE(OTTO_ICON_FONT); -void ElectronEmojiDisplay::SetStatus(const char* status) { - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - DisplayLockGuard lock(this); - if (!status) { - ESP_LOGE(TAG, "SetStatus: status is nullptr"); - return; - } - - if (strcmp(status, Lang::Strings::LISTENING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x84\xB0"); // U+F130 麦克风图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::SPEAKING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x80\xA8"); // U+F028 说话图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::CONNECTING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x83\x81"); // U+F0c1 连接图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::STANDBY) == 0) { - lv_obj_set_style_text_font(status_label_, text_font, 0); - lv_label_set_text(status_label_, ""); - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - return; - } - - lv_obj_set_style_text_font(status_label_, text_font, 0); - lv_label_set_text(status_label_, status); - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.h deleted file mode 100644 index 50a289a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/electron_emoji_display.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "display/lcd_display.h" - -/** - * @brief Electron机器人GIF表情显示类 - * 继承SpiLcdDisplay,通过EmojiCollection添加GIF表情支持 - */ -class ElectronEmojiDisplay : public SpiLcdDisplay { - public: - /** - * @brief 构造函数,参数与SpiLcdDisplay相同 - */ - ElectronEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy); - - virtual ~ElectronEmojiDisplay() = default; - virtual void SetStatus(const char* status) override; - - private: - void InitializeElectronEmojis(); - void SetupChatLabel(); -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.cc deleted file mode 100644 index 090732f8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.cc +++ /dev/null @@ -1,470 +0,0 @@ -#include "movements.h" - -#include -#include - -#include "oscillator.h" - -Otto::Otto() { - is_otto_resting_ = false; - for (int i = 0; i < SERVO_COUNT; i++) { - servo_pins_[i] = -1; - servo_trim_[i] = 0; - } -} - -Otto::~Otto() { - DetachServos(); -} - -unsigned long IRAM_ATTR millis() { - return (unsigned long)(esp_timer_get_time() / 1000ULL); -} - -void Otto::Init(int right_pitch, int right_roll, int left_pitch, int left_roll, int body, - int head) { - servo_pins_[RIGHT_PITCH] = right_pitch; - servo_pins_[RIGHT_ROLL] = right_roll; - servo_pins_[LEFT_PITCH] = left_pitch; - servo_pins_[LEFT_ROLL] = left_roll; - servo_pins_[BODY] = body; - servo_pins_[HEAD] = head; - - AttachServos(); - is_otto_resting_ = false; -} - -/////////////////////////////////////////////////////////////////// -//-- ATTACH & DETACH FUNCTIONS ----------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::AttachServos() { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Attach(servo_pins_[i]); - } - } -} - -void Otto::DetachServos() { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Detach(); - } - } -} - -/////////////////////////////////////////////////////////////////// -//-- OSCILLATORS TRIMS ------------------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::SetTrims(int right_pitch, int right_roll, int left_pitch, int left_roll, int body, - int head) { - servo_trim_[RIGHT_PITCH] = right_pitch; - servo_trim_[RIGHT_ROLL] = right_roll; - servo_trim_[LEFT_PITCH] = left_pitch; - servo_trim_[LEFT_ROLL] = left_roll; - servo_trim_[BODY] = body; - servo_trim_[HEAD] = head; - - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetTrim(servo_trim_[i]); - } - } -} - -/////////////////////////////////////////////////////////////////// -//-- BASIC MOTION FUNCTIONS -------------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::MoveServos(int time, int servo_target[]) { - if (GetRestState() == true) { - SetRestState(false); - } - - final_time_ = millis() + time; - if (time > 10) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - increment_[i] = (servo_target[i] - servo_[i].GetPosition()) / (time / 10.0); - } - } - - for (int iteration = 1; millis() < final_time_; iteration++) { - partial_time_ = millis() + 10; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_[i].GetPosition() + increment_[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(10)); - } - } else { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_target[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(time)); - } - - // final adjustment to the target. - bool f = true; - int adjustment_count = 0; - while (f && adjustment_count < 10) { - f = false; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1 && servo_target[i] != servo_[i].GetPosition()) { - f = true; - break; - } - } - if (f) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_target[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(10)); - adjustment_count++; - } - }; -} - -void Otto::MoveSingle(int position, int servo_number) { - if (position > 180) - position = 90; - if (position < 0) - position = 90; - - if (GetRestState() == true) { - SetRestState(false); - } - - if (servo_number >= 0 && servo_number < SERVO_COUNT && servo_pins_[servo_number] != -1) { - servo_[servo_number].SetPosition(position); - } -} - -void Otto::OscillateServos(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float cycle = 1) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetO(offset[i]); - servo_[i].SetA(amplitude[i]); - servo_[i].SetT(period); - servo_[i].SetPh(phase_diff[i]); - } - } - - double ref = millis(); - double end_time = period * cycle + ref; - - while (millis() < end_time) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Refresh(); - } - } - vTaskDelay(5); - } - vTaskDelay(pdMS_TO_TICKS(10)); -} - -void Otto::Execute(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps = 1.0) { - if (GetRestState() == true) { - SetRestState(false); - } - - int cycles = (int)steps; - - //-- Execute complete cycles - if (cycles >= 1) - for (int i = 0; i < cycles; i++) - OscillateServos(amplitude, offset, period, phase_diff); - - //-- Execute the final not complete cycle - OscillateServos(amplitude, offset, period, phase_diff, (float)steps - cycles); - vTaskDelay(pdMS_TO_TICKS(10)); -} - -/////////////////////////////////////////////////////////////////// -//-- HOME = Otto at rest position -------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::Home(bool hands_down) { - if (is_otto_resting_ == false) { // Go to rest position only if necessary - MoveServos(1000, servo_initial_); - is_otto_resting_ = true; - } - - vTaskDelay(pdMS_TO_TICKS(1000)); -} - -bool Otto::GetRestState() { - return is_otto_resting_; -} - -void Otto::SetRestState(bool state) { - is_otto_resting_ = state; -} - -/////////////////////////////////////////////////////////////////// -//-- PREDETERMINED MOTION SEQUENCES -----------------------------// -/////////////////////////////////////////////////////////////////// - -//--------------------------------------------------------- -//-- 统一手部动作函数 -//-- Parameters: -//-- action: 动作类型 1=举左手, 2=举右手, 3=举双手, 4=放左手, 5=放右手, 6=放双手, -//-- 7=挥左手, 8=挥右手, 9=挥双手, 10=拍打左手, 11=拍打右手, 12=拍打双手 -//-- times: 重复次数 -//-- amount: 动作幅度 (10-50) -//-- period: 动作时间 -//--------------------------------------------------------- -void Otto::HandAction(int action, int times, int amount, int period) { - // 限制参数范围 - times = 2 * std::max(3, std::min(100, times)); - amount = std::max(10, std::min(50, amount)); - period = std::max(100, std::min(1000, period)); - - int current_positions[SERVO_COUNT]; - for (int i = 0; i < SERVO_COUNT; i++) { - current_positions[i] = (servo_pins_[i] != -1) ? servo_[i].GetPosition() : servo_initial_[i]; - } - - switch (action) { - case 1: // 举左手 - current_positions[LEFT_PITCH] = 180; - MoveServos(period, current_positions); - break; - - case 2: // 举右手 - current_positions[RIGHT_PITCH] = 0; - MoveServos(period, current_positions); - break; - - case 3: // 举双手 - current_positions[LEFT_PITCH] = 180; - current_positions[RIGHT_PITCH] = 0; - MoveServos(period, current_positions); - break; - - case 4: // 放左手 - case 5: // 放右手 - case 6: // 放双手 - // 回到初始位置 - memcpy(current_positions, servo_initial_, sizeof(current_positions)); - MoveServos(period, current_positions); - break; - - case 7: // 挥左手 - current_positions[LEFT_PITCH] = 150; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[LEFT_PITCH] = 150 + (i % 2 == 0 ? -30 : 30); - MoveServos(period / 10, current_positions); - vTaskDelay(pdMS_TO_TICKS(period / 10)); - } - memcpy(current_positions, servo_initial_, sizeof(current_positions)); - MoveServos(period, current_positions); - break; - - case 8: // 挥右手 - current_positions[RIGHT_PITCH] = 30; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[RIGHT_PITCH] = 30 + (i % 2 == 0 ? 30 : -30); - MoveServos(period / 10, current_positions); - vTaskDelay(pdMS_TO_TICKS(period / 10)); - } - memcpy(current_positions, servo_initial_, sizeof(current_positions)); - MoveServos(period, current_positions); - break; - - case 9: // 挥双手 - current_positions[LEFT_PITCH] = 150; - current_positions[RIGHT_PITCH] = 30; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[LEFT_PITCH] = 150 + (i % 2 == 0 ? -30 : 30); - current_positions[RIGHT_PITCH] = 30 + (i % 2 == 0 ? 30 : -30); - MoveServos(period / 10, current_positions); - vTaskDelay(pdMS_TO_TICKS(period / 10)); - } - memcpy(current_positions, servo_initial_, sizeof(current_positions)); - MoveServos(period, current_positions); - break; - - case 10: // 拍打左手 - current_positions[LEFT_ROLL] = 20; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[LEFT_ROLL] = 20 - amount; - MoveServos(period / 10, current_positions); - current_positions[LEFT_ROLL] = 20 + amount; - MoveServos(period / 10, current_positions); - } - current_positions[LEFT_ROLL] = 0; - MoveServos(period, current_positions); - break; - - case 11: // 拍打右手 - current_positions[RIGHT_ROLL] = 160; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[RIGHT_ROLL] = 160 + amount; - MoveServos(period / 10, current_positions); - current_positions[RIGHT_ROLL] = 160 - amount; - MoveServos(period / 10, current_positions); - } - current_positions[RIGHT_ROLL] = 180; - MoveServos(period, current_positions); - break; - - case 12: // 拍打双手 - current_positions[LEFT_ROLL] = 20; - current_positions[RIGHT_ROLL] = 160; - MoveServos(period, current_positions); - for (int i = 0; i < times; i++) { - current_positions[LEFT_ROLL] = 20 - amount; - current_positions[RIGHT_ROLL] = 160 + amount; - MoveServos(period / 10, current_positions); - current_positions[LEFT_ROLL] = 20 + amount; - current_positions[RIGHT_ROLL] = 160 - amount; - MoveServos(period / 10, current_positions); - } - current_positions[LEFT_ROLL] = 0; - current_positions[RIGHT_ROLL] = 180; - MoveServos(period, current_positions); - break; - } -} - -//--------------------------------------------------------- -//-- 统一身体动作函数 -//-- Parameters: -//-- action: 动作类型 1=左转, 2=右转,3=回中心 -//-- times: 转动次数 -//-- amount: 旋转角度 (0-90度,以90度为中心左右旋转) -//-- period: 动作时间 -//--------------------------------------------------------- -void Otto::BodyAction(int action, int times, int amount, int period) { - // 限制参数范围 - times = std::max(1, std::min(10, times)); - amount = std::max(0, std::min(90, amount)); - period = std::max(500, std::min(3000, period)); - - int current_positions[SERVO_COUNT]; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - current_positions[i] = servo_[i].GetPosition(); - } else { - current_positions[i] = servo_initial_[i]; - } - } - - int body_center = servo_initial_[BODY]; - int target_angle = body_center; - - switch (action) { - case 1: // 左转 - target_angle = body_center + amount; - target_angle = std::min(180, target_angle); - break; - case 2: // 右转 - target_angle = body_center - amount; - target_angle = std::max(0, target_angle); - break; - case 3: // 回中心 - target_angle = body_center; - break; - default: - return; // 无效动作 - } - - current_positions[BODY] = target_angle; - MoveServos(period, current_positions); - vTaskDelay(pdMS_TO_TICKS(100)); -} - -//--------------------------------------------------------- -//-- 统一头部动作函数 -//-- Parameters: -//-- action: 动作类型 1=抬头, 2=低头, 3=点头, 4=回中心, 5=连续点头 -//-- times: 重复次数 (仅对连续点头有效) -//-- amount: 角度偏移 (1-15度范围内) -//-- period: 动作时间 -//--------------------------------------------------------- -void Otto::HeadAction(int action, int times, int amount, int period) { - // 限制参数范围 - times = std::max(1, std::min(10, times)); - amount = std::max(1, std::min(15, abs(amount))); - period = std::max(300, std::min(3000, period)); - - int current_positions[SERVO_COUNT]; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - current_positions[i] = servo_[i].GetPosition(); - } else { - current_positions[i] = servo_initial_[i]; - } - } - - int head_center = 90; // 头部中心位置 - - switch (action) { - case 1: // 抬头 - current_positions[HEAD] = head_center + amount; // 抬头是增加角度 - MoveServos(period, current_positions); - break; - - case 2: // 低头 - current_positions[HEAD] = head_center - amount; // 低头是减少角度 - MoveServos(period, current_positions); - break; - - case 3: // 点头 (上下运动) - // 先抬头 - current_positions[HEAD] = head_center + amount; - MoveServos(period / 3, current_positions); - vTaskDelay(pdMS_TO_TICKS(period / 6)); - - // 再低头 - current_positions[HEAD] = head_center - amount; - MoveServos(period / 3, current_positions); - vTaskDelay(pdMS_TO_TICKS(period / 6)); - - // 回到中心 - current_positions[HEAD] = head_center; - MoveServos(period / 3, current_positions); - break; - - case 4: // 回到中心位置 - current_positions[HEAD] = head_center; - MoveServos(period, current_positions); - break; - - case 5: // 连续点头 - for (int i = 0; i < times; i++) { - // 抬头 - current_positions[HEAD] = head_center + amount; - MoveServos(period / 2, current_positions); - - // 低头 - current_positions[HEAD] = head_center - amount; - MoveServos(period / 2, current_positions); - - vTaskDelay(pdMS_TO_TICKS(50)); // 短暂停顿 - } - - // 回到中心 - current_positions[HEAD] = head_center; - MoveServos(period / 2, current_positions); - break; - - default: - // 无效动作,回到中心 - current_positions[HEAD] = head_center; - MoveServos(period, current_positions); - break; - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.h deleted file mode 100644 index bffc3ff4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/movements.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef __MOVEMENTS_H__ -#define __MOVEMENTS_H__ - -#include "driver/gpio.h" -#include "esp_log.h" -#include "esp_timer.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "oscillator.h" - -//-- Constants -#define FORWARD 1 -#define BACKWARD -1 -#define LEFT 1 -#define RIGHT -1 -#define BOTH 0 -#define SMALL 5 -#define MEDIUM 15 -#define BIG 30 - -// -- Servo delta limit default. degree / sec -#define SERVO_LIMIT_DEFAULT 240 - -// -- Servo indexes for easy access -#define RIGHT_PITCH 0 -#define RIGHT_ROLL 1 -#define LEFT_PITCH 2 -#define LEFT_ROLL 3 -#define BODY 4 -#define HEAD 5 -#define SERVO_COUNT 6 - -class Otto { -public: - Otto(); - ~Otto(); - - //-- Otto initialization - void Init(int right_pitch, int right_roll, int left_pitch, int left_roll, int body, int head); - //-- Attach & detach functions - void AttachServos(); - void DetachServos(); - - //-- Oscillator Trims - void SetTrims(int right_pitch, int right_roll, int left_pitch, int left_roll, int body, - int head); - - //-- Predetermined Motion Functions - void MoveServos(int time, int servo_target[]); - void MoveSingle(int position, int servo_number); - void OscillateServos(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float cycle); - - //-- HOME = Otto at rest position - void Home(bool hands_down = true); - bool GetRestState(); - void SetRestState(bool state); - - // -- 手部动作 - void HandAction(int action, int times = 1, int amount = 30, int period = 1000); - // action: 1=举左手, 2=举右手, 3=举双手, 4=放左手, 5=放右手, 6=放双手, 7=挥左手, 8=挥右手, - // 9=挥双手, 10=拍打左手, 11=拍打右手, 12=拍打双手 - - //-- 身体动作 - void BodyAction(int action, int times = 1, int amount = 30, int period = 1000); - // action: 1=左转, 2=右转 - - //-- 头部动作 - void HeadAction(int action, int times = 1, int amount = 10, int period = 500); - // action: 1=抬头, 2=低头, 3=点头, 4=回中心, 5=连续点头 - -private: - Oscillator servo_[SERVO_COUNT]; - - int servo_pins_[SERVO_COUNT]; - int servo_trim_[SERVO_COUNT]; - int servo_initial_[SERVO_COUNT] = {180, 180, 0, 0, 90, 90}; - - unsigned long final_time_; - unsigned long partial_time_; - float increment_[SERVO_COUNT]; - - bool is_otto_resting_; - - void Execute(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps); -}; - -#endif // __MOVEMENTS_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.cc deleted file mode 100644 index 0cfc652d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.cc +++ /dev/null @@ -1,149 +0,0 @@ -#include "oscillator.h" - -#include -#include - -#include -#include - -extern unsigned long IRAM_ATTR millis(); - -Oscillator::Oscillator(int trim) { - trim_ = trim; - diff_limit_ = 0; - is_attached_ = false; - - sampling_period_ = 30; - period_ = 2000; - number_samples_ = period_ / sampling_period_; - inc_ = 2 * M_PI / number_samples_; - - amplitude_ = 45; - phase_ = 0; - phase0_ = 0; - offset_ = 0; - stop_ = false; - rev_ = false; - - pos_ = 90; - previous_millis_ = 0; -} - -Oscillator::~Oscillator() { - Detach(); -} - -uint32_t Oscillator::AngleToCompare(int angle) { - return (angle - SERVO_MIN_DEGREE) * (SERVO_MAX_PULSEWIDTH_US - SERVO_MIN_PULSEWIDTH_US) / - (SERVO_MAX_DEGREE - SERVO_MIN_DEGREE) + - SERVO_MIN_PULSEWIDTH_US; -} - -bool Oscillator::NextSample() { - current_millis_ = millis(); - - if (current_millis_ - previous_millis_ > sampling_period_) { - previous_millis_ = current_millis_; - return true; - } - - return false; -} - -void Oscillator::Attach(int pin, bool rev) { - if (is_attached_) { - Detach(); - } - - pin_ = pin; - rev_ = rev; - - ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_13_BIT, - .timer_num = LEDC_TIMER_1, - .freq_hz = 50, - .clk_cfg = LEDC_AUTO_CLK}; - ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); - - static int last_channel = 0; - last_channel = (last_channel + 1) % 7 + 1; - ledc_channel_ = (ledc_channel_t)last_channel; - - ledc_channel_config_t ledc_channel = {.gpio_num = pin_, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = ledc_channel_, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_1, - .duty = 0, - .hpoint = 0}; - ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); - - ledc_speed_mode_ = LEDC_LOW_SPEED_MODE; - - // pos_ = 90; - // Write(pos_); - previous_servo_command_millis_ = millis(); - - is_attached_ = true; -} - -void Oscillator::Detach() { - if (!is_attached_) - return; - - ESP_ERROR_CHECK(ledc_stop(ledc_speed_mode_, ledc_channel_, 0)); - - is_attached_ = false; -} - -void Oscillator::SetT(unsigned int T) { - period_ = T; - - number_samples_ = period_ / sampling_period_; - inc_ = 2 * M_PI / number_samples_; -} - -void Oscillator::SetPosition(int position) { - Write(position); -} - -void Oscillator::Refresh() { - if (NextSample()) { - if (!stop_) { - int pos = std::round(amplitude_ * std::sin(phase_ + phase0_) + offset_); - if (rev_) - pos = -pos; - Write(pos + 90); - } - - phase_ = phase_ + inc_; - } -} - -void Oscillator::Write(int position) { - if (!is_attached_) - return; - - long currentMillis = millis(); - if (diff_limit_ > 0) { - int limit = std::max( - 1, (((int)(currentMillis - previous_servo_command_millis_)) * diff_limit_) / 1000); - if (abs(position - pos_) > limit) { - pos_ += position < pos_ ? -limit : limit; - } else { - pos_ = position; - } - } else { - pos_ = position; - } - previous_servo_command_millis_ = currentMillis; - - int angle = pos_ + trim_; - - angle = std::min(std::max(angle, 0), 180); - - uint32_t duty = (uint32_t)(((angle / 180.0) * 2.0 + 0.5) * 8191 / 20.0); - - ESP_ERROR_CHECK(ledc_set_duty(ledc_speed_mode_, ledc_channel_, duty)); - ESP_ERROR_CHECK(ledc_update_duty(ledc_speed_mode_, ledc_channel_)); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.h deleted file mode 100644 index d9e79f25..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/oscillator.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef __OSCILLATOR_H__ -#define __OSCILLATOR_H__ - -#include "driver/ledc.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#define M_PI 3.14159265358979323846 - -#ifndef DEG2RAD -#define DEG2RAD(g) ((g) * M_PI) / 180 -#endif - -#define SERVO_MIN_PULSEWIDTH_US 500 // 最小脉宽(微秒) -#define SERVO_MAX_PULSEWIDTH_US 2500 // 最大脉宽(微秒) -#define SERVO_MIN_DEGREE -90 // 最小角度 -#define SERVO_MAX_DEGREE 90 // 最大角度 -#define SERVO_TIMEBASE_RESOLUTION_HZ 1000000 // 1MHz, 1us per tick -#define SERVO_TIMEBASE_PERIOD 20000 // 20000 ticks, 20ms - -class Oscillator { -public: - Oscillator(int trim = 0); - ~Oscillator(); - void Attach(int pin, bool rev = false); - void Detach(); - - void SetA(unsigned int amplitude) { amplitude_ = amplitude; }; - void SetO(int offset) { offset_ = offset; }; - void SetPh(double Ph) { phase0_ = Ph; }; - void SetT(unsigned int period); - void SetTrim(int trim) { trim_ = trim; }; - void SetLimiter(int diff_limit) { diff_limit_ = diff_limit; }; - void DisableLimiter() { diff_limit_ = 0; }; - int GetTrim() { return trim_; }; - void SetPosition(int position); - void Stop() { stop_ = true; }; - void Play() { stop_ = false; }; - void Reset() { phase_ = 0; }; - void Refresh(); - int GetPosition() { return pos_; } - -private: - bool NextSample(); - void Write(int position); - uint32_t AngleToCompare(int angle); - -private: - bool is_attached_; - - //-- Oscillators parameters - unsigned int amplitude_; //-- Amplitude (degrees) - int offset_; //-- Offset (degrees) - unsigned int period_; //-- Period (miliseconds) - double phase0_; //-- Phase (radians) - - //-- Internal variables - int pos_; //-- Current servo pos - int pin_; //-- Pin where the servo is connected - int trim_; //-- Calibration offset - double phase_; //-- Current phase - double inc_; //-- Increment of phase - double number_samples_; //-- Number of samples - unsigned int sampling_period_; //-- sampling period (ms) - - long previous_millis_; - long current_millis_; - - //-- Oscillation mode. If true, the servo is stopped - bool stop_; - - //-- Reverse mode - bool rev_; - - int diff_limit_; - long previous_servo_command_millis_; - - ledc_channel_t ledc_channel_; - ledc_mode_t ledc_speed_mode_; -}; - -#endif // __OSCILLATOR_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/otto_icon_font.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/otto_icon_font.c deleted file mode 100644 index dc05cce6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/otto_icon_font.c +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * Size: 20 px - * Bpp: 1 - * Opts: --bpp 1 --size 20 --no-compress --stride 1 --align 1 --font fontawesome-webfont.ttf --range 61744,61633,61480 --format lvgl -o OTTO_ICON_FONT.c - ******************************************************************************/ - -#ifdef __has_include -#if __has_include("lvgl.h") -#ifndef LV_LVGL_H_INCLUDE_SIMPLE -#define LV_LVGL_H_INCLUDE_SIMPLE -#endif -#endif -#endif - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef ENABLE_OTTO_ICON_FONT -#define ENABLE_OTTO_ICON_FONT 1 -#endif - -#if ENABLE_OTTO_ICON_FONT - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F028 "" */ - 0x0, 0x6, 0x0, 0x10, 0xe0, 0x6, 0x6, 0x3, 0xc6, 0x60, 0xf8, 0x65, 0xff, 0x24, 0xff, 0xe6, 0x4f, 0xfc, 0x49, 0xff, 0x89, 0x3f, 0xf3, 0x27, 0xfe, 0x49, 0x87, 0xc3, 0x20, 0x78, 0xcc, 0x3, 0x3, 0x0, - 0x21, 0xc0, 0x0, 0x30, - - /* U+F0C1 "" */ - 0x1e, 0x0, 0xf, 0xc0, 0x7, 0x38, 0x3, 0x87, 0x0, 0xc0, 0xc0, 0x30, 0xb0, 0x7, 0x3c, 0x0, 0xef, 0x0, 0x1f, 0xfe, 0x3, 0xff, 0xc0, 0x7, 0x38, 0x3, 0xe7, 0x0, 0xd0, 0xc0, 0x30, 0x30, 0x6, 0x1c, 0x0, - 0xce, 0x0, 0x1f, 0x0, 0x3, 0x80, - - /* U+F130 "" */ - 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, 0xf, 0xe0, 0x7f, 0x13, 0xf9, 0x9f, 0xcc, 0xfe, 0x67, 0xf3, 0xbf, 0xb4, 0x73, 0x18, 0x30, 0x7f, 0x0, 0x60, 0x2, 0x1, 0xff, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 297, .box_w = 19, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 38, .adv_w = 297, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 79, .adv_w = 206, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -1}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = {0x0, 0x99, 0x108}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61480, .range_length = 265, .glyph_id_start = 1, .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t otto_icon_font_dsc = { -#else -static lv_font_fmt_txt_dsc_t otto_icon_font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 1, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif - -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t OTTO_ICON_FONT = { -#else -lv_font_t OTTO_ICON_FONT = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 18, /*The maximum line height required by the font*/ - .base_line = 1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .static_bitmap = 0, - .dsc = &otto_icon_font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - -#endif /*#if ENABLE_OTTO_ICON_FONT*/ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/power_manager.h deleted file mode 100644 index 13d8ff3b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/electron-bot/power_manager.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef __POWER_MANAGER_H__ -#define __POWER_MANAGER_H__ - -#include -#include -#include -#include - -class PowerManager { -private: - // 电池电量区间-分压电阻为2个100k - static constexpr struct { - uint16_t adc; - uint8_t level; - } BATTERY_LEVELS[] = {{2150, 0}, {2450, 100}}; - static constexpr size_t BATTERY_LEVELS_COUNT = 2; - static constexpr size_t ADC_VALUES_COUNT = 10; - - esp_timer_handle_t timer_handle_ = nullptr; - gpio_num_t charging_pin_; - adc_unit_t adc_unit_; - adc_channel_t adc_channel_; - uint16_t adc_values_[ADC_VALUES_COUNT]; - size_t adc_values_index_ = 0; - size_t adc_values_count_ = 0; - uint8_t battery_level_ = 100; - bool is_charging_ = false; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - is_charging_ = gpio_get_level(charging_pin_) == 0; - ReadBatteryAdcData(); - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, adc_channel_, &adc_value)); - - adc_values_[adc_values_index_] = adc_value; - adc_values_index_ = (adc_values_index_ + 1) % ADC_VALUES_COUNT; - if (adc_values_count_ < ADC_VALUES_COUNT) { - adc_values_count_++; - } - - uint32_t average_adc = 0; - for (size_t i = 0; i < adc_values_count_; i++) { - average_adc += adc_values_[i]; - } - average_adc /= adc_values_count_; - - CalculateBatteryLevel(average_adc); - - // ESP_LOGI("PowerManager", "ADC值: %d 平均值: %ld 电量: %u%%", adc_value, average_adc, - // battery_level_); - } - - void CalculateBatteryLevel(uint32_t average_adc) { - if (average_adc <= BATTERY_LEVELS[0].adc) { - battery_level_ = 0; - } else if (average_adc >= BATTERY_LEVELS[BATTERY_LEVELS_COUNT - 1].adc) { - battery_level_ = 100; - } else { - float ratio = static_cast(average_adc - BATTERY_LEVELS[0].adc) / - (BATTERY_LEVELS[1].adc - BATTERY_LEVELS[0].adc); - battery_level_ = ratio * 100; - } - } - -public: - PowerManager(gpio_num_t charging_pin, adc_unit_t adc_unit = ADC_UNIT_2, - adc_channel_t adc_channel = ADC_CHANNEL_3) - : charging_pin_(charging_pin), adc_unit_(adc_unit), adc_channel_(adc_channel) { - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - esp_timer_create_args_t timer_args = { - .callback = - [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); // 1秒 - - InitializeAdc(); - } - - void InitializeAdc() { - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = adc_unit_, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, adc_channel_, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { return is_charging_; } - - uint8_t GetBatteryLevel() { return battery_level_; } -}; -#endif // __POWER_MANAGER_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/README.md deleted file mode 100644 index 103f7323..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/README.md +++ /dev/null @@ -1,132 +0,0 @@ -# ESP-BOX-3 - -## 简介 - - - -ESP-BOX-3 是乐鑫官方开发的 AIoT 开发套件,搭载 ESP32-S3-WROOM-1 模组,配备 2.4 英寸 320x240 ILI9341 显示屏,双麦克风阵列,支持离线语音唤醒与设备端回声消除(AEC)功能。 - -## 硬件特性 - -- **主控**: ESP32-S3-WROOM-1 (16MB Flash, 8MB PSRAM) -- **显示屏**: 2.4 英寸 IPS LCD (320x240, ILI9341) -- **音频**: ES8311 音频 Codec + ES7210 双麦 ADC -- **音频功能**: 支持设备端 AEC (回声消除) -- **按键**: Boot 按键 (单击/双击功能) -- **其他**: USB-C 供电与通信 - -## 配置、编译命令 - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig 并配置** - -```bash -idf.py menuconfig -``` - -分别配置如下选项: - -### 基本配置 -- `Xiaozhi Assistant` → `Board Type` → 选择 `ESP BOX 3` - -### UI风格选择 - -ESP-BOX-3 支持多种不同的 UI 显示风格,通过 menuconfig 配置选择: - -- `Xiaozhi Assistant` → `Select display style` → 选择显示风格 - -#### 可选风格 - -##### 表情动画风格 (Emote animation style) - 推荐 -- **配置选项**: `USE_EMOTE_MESSAGE_STYLE` -- **特点**: 使用自定义的 `EmoteDisplay` 表情显示系统 -- **功能**: 支持丰富的表情动画、眼睛动画、状态图标显示 -- **适用**: 智能助手场景,提供更生动的人机交互体验 -- **类**: `emote::EmoteDisplay` - -**⚠️ 重要**: 选择此风格需要额外配置自定义资源文件: -1. `Xiaozhi Assistant` → `Flash Assets` → 选择 `Flash Custom Assets` -2. `Xiaozhi Assistant` → `Custom Assets File` → 填入资源文件地址: - ``` - https://dl.espressif.com/AE/wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-esp-box-3.bin - ``` - -##### 默认消息风格 (Enable default message style) -- **配置选项**: `USE_DEFAULT_MESSAGE_STYLE` (默认) -- **特点**: 使用标准的消息显示界面 -- **功能**: 传统的文本和图标显示界面 -- **适用**: 标准的对话场景 -- **类**: `SpiLcdDisplay` - -##### 微信消息风格 (Enable WeChat Message Style) -- **配置选项**: `USE_WECHAT_MESSAGE_STYLE` -- **特点**: 仿微信聊天界面风格 -- **功能**: 类似微信的消息气泡显示 -- **适用**: 喜欢微信风格的用户 -- **类**: `SpiLcdDisplay` - -### 音频功能配置 - -#### 设备端回声消除 (AEC) -- `Xiaozhi Assistant` → `Enable Device-Side AEC` → 启用 - -ESP-BOX-3 硬件支持设备端 AEC 功能,可有效消除扬声器播放声音对麦克风的干扰,提升语音识别准确率。 - -**运行时切换**: 双击 Boot 按键可在运行时开启/关闭 AEC 功能。 - -> **说明**: 设备端 AEC 需要干净的扬声器输出参考路径和良好的麦克风与扬声器物理隔离才能正常工作。ESP-BOX-3 硬件已做优化设计。 - -### 唤醒词配置 - -ESP-BOX-3 支持多种唤醒词实现方式: - -- `Xiaozhi Assistant` → `Wake Word Implementation Type` → 选择唤醒词类型 - -推荐选择: -- **Wakenet model with AFE** (`USE_AFE_WAKE_WORD`) - 支持 AEC 的唤醒词检测 - -按 `S` 保存,按 `Q` 退出。 - -**编译** - -```bash -idf.py build -``` - -**烧录** - -将 ESP-BOX-3 连接至电脑,并运行: - -```bash -idf.py flash -``` - -## 按键说明 - -### Boot 按键功能 - -#### 单击 -- **配网状态**: 进入 WiFi 配置模式 -- **空闲状态**: 开始对话 -- **对话中**: 打断或停止当前对话 - -#### 双击 (需启用设备端 AEC) -- **空闲状态**: 切换 AEC 开启/关闭 - -## 常见问题 - -### 1. 为什么需要设备端 AEC? -设备端 AEC 可以在本地实时消除扬声器播放声音对麦克风的干扰,在播放音乐或 TTS 回复时仍能准确识别语音指令。 - -### 2. 表情动画风格无法显示? -请确保已经配置了正确的自定义资源文件地址,并且设备能够访问该 URL 下载资源。 - -### 3. 如何恢复出厂设置? -长按 Boot 按键 3 秒以上,设备会清除所有配置并重启。 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.h deleted file mode 100644 index f0453048..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_2 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_18 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_47 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.json deleted file mode 100644 index 518936d8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-box-3", - "sdkconfig_append": [ - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_USE_EMOTE_MESSAGE_STYLE=y", - "CONFIG_FLASH_CUSTOM_ASSETS=y", - "CONFIG_CUSTOM_ASSETS_FILE=\"https://dl.espressif.com/AE/wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-esp-box-3.bin\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/emote.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/emote.json deleted file mode 100644 index abc11c8f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/emote.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - {"emote": "happy", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "laughing", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "funny", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "loving", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "embarrassed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confident", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "delicious", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "sad", "src": "Sad.eaf", "loop": true, "fps": 20}, - {"emote": "crying", "src": "cry.eaf", "loop": true, "fps": 20}, - {"emote": "sleepy", "src": "sleep.eaf", "loop": true, "fps": 20}, - {"emote": "silly", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "angry", "src": "angry.eaf", "loop": true, "fps": 20}, - {"emote": "surprised", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "shocked", "src": "shocked.eaf", "loop": true, "fps": 20}, - {"emote": "thinking", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "winking", "src": "neutral.eaf", "loop": true, "fps": 20}, - {"emote": "relaxed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confused", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "neutral", "src": "winking.eaf", "loop": false, "fps": 20}, - {"emote": "idle", "src": "neutral.eaf", "loop": false, "fps": 20} -] diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/esp_box3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/esp_box3_board.cc deleted file mode 100644 index a5fa19a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/esp_box3_board.cc +++ /dev/null @@ -1,175 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/display.h" -#include "display/emote_display.h" -#include "display/lcd_display.h" -#include "esp_lcd_ili9341.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include -#include -#include - -#define TAG "EspBox3Board" - -// Init ili9341 by custom cmd -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - {0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0}, - {0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0}, - {0xC5, (uint8_t []){0xD0}, 1, 0}, - {0xC1, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0}, - {0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0}, - - {0xB1, (uint8_t []){00, 0x1B}, 2, 0}, - {0x36, (uint8_t []){0x08}, 1, 0}, - {0x3A, (uint8_t []){0x55}, 1, 0}, - {0xB7, (uint8_t []){0x06}, 1, 0}, - - {0x11, (uint8_t []){0}, 0x80, 0}, - {0x29, (uint8_t []){0}, 0x80, 0}, - - {0, (uint8_t []){0}, 0xff, 0}, -}; - -class EspBox3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Display* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_6; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_7; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeIli9341Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_5; - io_config.dc_gpio_num = GPIO_NUM_4; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_48; - panel_config.flags.reset_active_high = 1, - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *)&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - -#if CONFIG_USE_EMOTE_MESSAGE_STYLE - display_ = new emote::EmoteDisplay(panel, panel_io, DISPLAY_WIDTH, DISPLAY_HEIGHT); -#else - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); -#endif - } - -public: - EspBox3Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeIli9341Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(EspBox3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/layout.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/layout.json deleted file mode 100644 index 8a1dfbcc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-3/layout.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "name": "eye_anim", - "align": "GFX_ALIGN_LEFT_MID", - "x": 10, - "y": 30 - }, - { - "name": "status_icon", - "align": "GFX_ALIGN_TOP_MID", - "x": -120, - "y": 18 - }, - { - "name": "toast_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 20, - "width": 200, - "height": 40 - }, - { - "name": "clock_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 20, - "width": 200, - "height": 50 - }, - { - "name": "listen_anim", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 5 - } -] - \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.cc deleted file mode 100644 index 9bde726e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.cc +++ /dev/null @@ -1,272 +0,0 @@ -#include "box_audio_codec_lite.h" - -#include -#include -#include -#include - -static const char TAG[] = "BoxAudioCodecLite"; - -BoxAudioCodecLite::BoxAudioCodecLite(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - if (input_reference) { - ref_buffer_.resize(960 * 2); - } - input_channels_ = 2 + input_reference_; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = (i2c_port_t)1, - .addr = ES8156_CODEC_DEFAULT_ADDR, - .bus_handle = i2c_master_handle, - }; - out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(out_ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8156_codec_cfg_t cfg = {}; - cfg.ctrl_if = out_ctrl_if_; - cfg.gpio_if = gpio_if_; - cfg.pa_pin = pa_pin; - cfg.hw_gain.pa_voltage = 5.0; - cfg.hw_gain.codec_dac_voltage = 3.3; - out_codec_if_ = es8156_codec_new(&cfg); - assert(out_codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = out_codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - - // Input - i2c_cfg.addr = ES7243E_CODEC_DEFAULT_ADDR; - in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7243e_codec_cfg_t es7243_cfg = {}; - es7243_cfg.ctrl_if = in_ctrl_if_; - in_codec_if_ = es7243e_codec_new(&es7243_cfg); - assert(in_codec_if_ != NULL); - - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - dev_cfg.codec_if = in_codec_if_; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - - ESP_LOGI(TAG, "BoxAudioDevice initialized"); -} - -BoxAudioCodecLite::~BoxAudioCodecLite() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void BoxAudioCodecLite::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bclk_div = 8, - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), - .ws_width = I2S_TDM_AUTO_WS_WIDTH, - .ws_pol = false, - .bit_shift = true, - .left_align = false, - .big_endian = false, - .bit_order_lsb = false, - .skip_mask = false, - .total_slot = I2S_TDM_AUTO_SLOT_NUM - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = I2S_GPIO_UNUSED, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void BoxAudioCodecLite::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void BoxAudioCodecLite::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = (uint8_t)(input_channels_ - input_reference_), - .channel_mask = 0, - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - for (int i = 0;i < fs.channel; i++) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(i); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - // 麦克风增益解决收音太小的问题 - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 37.5)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void BoxAudioCodecLite::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int BoxAudioCodecLite::Read(int16_t* dest, int samples) { - if (input_enabled_) { - if (!input_reference_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - else { - int size = samples / input_channels_; - int channels = input_channels_ - input_reference_; - std::vector data(size * channels); - // read mic data - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)data.data(), data.size() * sizeof(int16_t))); - int j = 0; - int i = 0; - while (i< samples) { - // mic data - for (int p = 0; p < channels; p++) { - dest[i++] = data[j++]; - } - // ref data - dest[i++] = read_pos_ < write_pos_? ref_buffer_[read_pos_++] : 0; - } - - if (read_pos_ == write_pos_) { - read_pos_ = write_pos_ = 0; - } - } - } - return samples; -} - -int BoxAudioCodecLite::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - if (input_reference_) { // 板子不支持硬件回采,采用缓存播放缓冲来实现回声消除 - if (write_pos_ - read_pos_ + samples > ref_buffer_.size()) { - assert(ref_buffer_.size() >= samples); - // 写溢出,只保留最近的数据 - read_pos_ = write_pos_ + samples - ref_buffer_.size(); - } - if (read_pos_) { - if (write_pos_ != read_pos_) { - memmove(ref_buffer_.data(), ref_buffer_.data() + read_pos_, (write_pos_ - read_pos_) * sizeof(int16_t)); - } - write_pos_ -= read_pos_; - read_pos_ = 0; - } - memcpy(&ref_buffer_[write_pos_], data, samples * sizeof(int16_t)); - write_pos_ += samples; - } - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.h deleted file mode 100644 index ccb8d68f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/box_audio_codec_lite.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_LITE_H -#define _BOX_AUDIO_CODEC_LITE_H - -#include "audio_codec.h" - -#include -#include - -class BoxAudioCodecLite : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - // ref buffer used for aec - std::vector ref_buffer_; - int read_pos_ = 0; - int write_pos_ = 0; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - BoxAudioCodecLite(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, bool input_reference); - virtual ~BoxAudioCodecLite(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_LITE_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.h deleted file mode 100644 index ee345edf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_INPUT_REFERENCE CONFIG_USE_AUDIO_PROCESSOR - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_2 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_47 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_18 - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_45 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.json deleted file mode 100644 index 870fabed..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-box-lite", - "sdkconfig_append": [ - "CONFIG_SOC_ADC_SUPPORTED=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/esp_box_lite_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/esp_box_lite_board.cc deleted file mode 100644 index 05d88a12..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box-lite/esp_box_lite_board.cc +++ /dev/null @@ -1,237 +0,0 @@ -#include "wifi_board.h" -#include "box_audio_codec_lite.h" -#include "display/lcd_display.h" -#include "esp_lcd_ili9341.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#define TAG "EspBoxBoardLite" - -/* ADC Buttons */ -typedef enum { - BSP_ADC_BUTTON_PREV, - BSP_ADC_BUTTON_ENTER, - BSP_ADC_BUTTON_NEXT, - BSP_ADC_BUTTON_NUM -} bsp_adc_button_t; - -// Init ili9341 by custom cmd -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - {0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0}, - {0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0}, - {0xC5, (uint8_t []){0xD0}, 1, 0}, - {0xC1, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0}, - {0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0}, - - {0xB1, (uint8_t []){00, 0x1B}, 2, 0}, - {0x36, (uint8_t []){0x08}, 1, 0}, - {0x3A, (uint8_t []){0x55}, 1, 0}, - {0xB7, (uint8_t []){0x06}, 1, 0}, - - {0x11, (uint8_t []){0}, 0x80, 0}, - {0x29, (uint8_t []){0}, 0x80, 0}, - - {0, (uint8_t []){0}, 0xff, 0}, -}; - -class EspBoxBoardLite : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button* adc_button_[BSP_ADC_BUTTON_NUM]; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - adc_oneshot_unit_handle_t bsp_adc_handle = NULL; -#endif - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_6; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_7; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void ChangeVol(int val) { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + val; - if (volume > 100) { - volume = 100; - } - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - } - - void TogleState() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - - void InitializeButtons() { - /* Initialize ADC esp-box lite的前三个按钮采用是的adc按钮,而非gpio */ - button_adc_config_t adc_cfg = {}; - adc_cfg.adc_channel = ADC_CHANNEL_0; // ADC1 channel 0 is GPIO1 -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - const adc_oneshot_unit_init_cfg_t init_config1 = { - .unit_id = ADC_UNIT_1, - }; - adc_oneshot_new_unit(&init_config1, &bsp_adc_handle); - adc_cfg.adc_handle = &bsp_adc_handle; -#endif - adc_cfg.button_index = BSP_ADC_BUTTON_PREV; - adc_cfg.min = 2310; // middle is 2410mV - adc_cfg.max = 2510; - adc_button_[0] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_ENTER; - adc_cfg.min = 1880; // middle is 1980mV - adc_cfg.max = 2080; - adc_button_[1] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_NEXT; - adc_cfg.min = 720; // middle is 820mV - adc_cfg.max = 920; - - adc_button_[2] = new AdcButton(adc_cfg); - - auto volume_up_button = adc_button_[BSP_ADC_BUTTON_NEXT]; - volume_up_button->OnClick([this]() {ChangeVol(10);}); - volume_up_button->OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - auto volume_down_button = adc_button_[BSP_ADC_BUTTON_PREV]; - volume_down_button->OnClick([this]() {ChangeVol(-10);}); - volume_down_button->OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - auto break_button = adc_button_[BSP_ADC_BUTTON_ENTER]; - break_button->OnClick([this]() {TogleState();}); - boot_button_.OnClick([this]() {TogleState();}); - } - - void InitializeIli9341Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_5; - io_config.dc_gpio_num = GPIO_NUM_4; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_48; - panel_config.flags.reset_active_high = 0, - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *)&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - EspBoxBoardLite() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeIli9341Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - ~EspBoxBoardLite() { - for (int i =0; i - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_2 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_47 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_18 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_45 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/config.json deleted file mode 100644 index 0ae7e201..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-box", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/esp_box_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/esp_box_board.cc deleted file mode 100644 index 4cbf71e4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-box/esp_box_board.cc +++ /dev/null @@ -1,168 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "esp_lcd_ili9341.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include -#include -#include - -#define TAG "EspBoxBoard" - -// Init ili9341 by custom cmd -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - {0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0}, - {0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0}, - {0xC5, (uint8_t []){0xD0}, 1, 0}, - {0xC1, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0}, - {0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0}, - - {0xB1, (uint8_t []){00, 0x1B}, 2, 0}, - {0x36, (uint8_t []){0x08}, 1, 0}, - {0x3A, (uint8_t []){0x55}, 1, 0}, - {0xB7, (uint8_t []){0x06}, 1, 0}, - - {0x11, (uint8_t []){0}, 0x80, 0}, - {0x29, (uint8_t []){0}, 0x80, 0}, - - {0, (uint8_t []){0}, 0xff, 0}, -}; - -class EspBox3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_6; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_7; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeIli9341Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_5; - io_config.dc_gpio_num = GPIO_NUM_4; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_48; - panel_config.flags.reset_active_high = 0, - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *)&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - EspBox3Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeIli9341Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(EspBox3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/README.md deleted file mode 100644 index 8921f1f7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# ESP-Hi - -## 简介 - - - -ESP-Hi 是 ESP Friends 开源的一款基于 ESP32C3 的超**低成本** AI 对话机器人。ESP-Hi 集成了一个0.96寸的彩屏,用于显示表情,**机器狗已实现数十种动作**。通过对 ESP32-C3 外设的充分挖掘,仅需最少的板级硬件即可实现拾音和发声,同步优化了软件,降低内存与 Flash 占用,在资源受限的情况下同时实现了**唤醒词检测**与多种外设驱动。硬件详情等可查看[立创开源项目](https://oshwhub.com/esp-college/esp-hi)。 - -## WebUI - -ESP-Hi x 小智内置了一个控制身体运动的 WebUI,请将手机与 ESP-Hi 连接到同一个 Wi-Fi 下,手机访问 `http://esp-hi.local/` 以使用。 - -如需禁用,请取消 `ESP_HI_WEB_CONTROL_ENABLED`,即取消勾选 `Component config` → `Servo Dog Configuration` → `Web Control` → `Enable ESP-HI Web Control`。 - -## 配置、编译命令 - -由于 ESP-Hi 需要配置较多的 sdkconfig 选项,推荐使用编译脚本编译。 - -**编译** - -```bash -python ./scripts/release.py esp-hi -``` - -如需手动编译,请参考 `esp-hi/config.json` 修改 menuconfig 对应选项。 - -**烧录** - -```bash -idf.py flash -``` - - -> [!TIP] -> -> **舵机控制会占用 ESP-Hi 的 USB Type-C 接口**,导致无法连接电脑(无法烧录/查看运行日志)。如遇此情况,请按以下提示操作: -> -> **烧录** -> -> 1. 断开 ESP-Hi 的电源,只留头部,不要连接身体。 -> 2. 按住 ESP-Hi 的按钮并连接电脑。 -> -> 此时,ESP-Hi (ESP32C3) 应当处于烧录模式,可以使用电脑烧录程序。烧录完成后,可能需要重新插拔电源。 -> -> **查看 log** -> -> 请设置 `CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y`,即 `Component config` → `ESP System Settings` → `Channel for console output` 选择 `USB Serial/JTAG Controller`。这同时会禁用舵机控制功能。 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.cc deleted file mode 100644 index db5d8e17..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.cc +++ /dev/null @@ -1,249 +0,0 @@ -#include "adc_pdm_audio_codec.h" - -#include -#include -#include -#include -#include -#include "adc_mic.h" -#include "driver/i2s_pdm.h" -#include "soc/gpio_sig_map.h" -#include "soc/io_mux_reg.h" -#include "hal/rtc_io_hal.h" -#include "hal/gpio_ll.h" -#include "settings.h" -#include "config.h" - -static const char TAG[] = "AdcPdmAudioCodec"; - -#define BSP_I2S_GPIO_CFG(_dout) \ - { \ - .clk = GPIO_NUM_NC, \ - .dout = _dout, \ - .invert_flags = { \ - .clk_inv = false, \ - }, \ - } - -/** - * @brief Mono Duplex I2S configuration structure - * - * This configuration is used by default in bsp_audio_init() - */ -#define BSP_I2S_DUPLEX_MONO_CFG(_sample_rate, _dout) \ - { \ - .clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG(_sample_rate), \ - .slot_cfg = I2S_PDM_TX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), \ - .gpio_cfg = BSP_I2S_GPIO_CFG(_dout), \ - } - -AdcPdmAudioCodec::AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate, - uint32_t adc_mic_channel, gpio_num_t pdm_speak_p,gpio_num_t pdm_speak_n, gpio_num_t pa_ctl) { - - input_reference_ = false; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - uint8_t adc_channel[1] = {0}; - adc_channel[0] = adc_mic_channel; - - audio_codec_adc_cfg_t cfg = { - .handle = NULL, - .max_store_buf_size = 1024 * 2, - .conv_frame_size = 1024, - .unit_id = ADC_UNIT_1, - .adc_channel_list = adc_channel, - .adc_channel_num = sizeof(adc_channel) / sizeof(adc_channel[0]), - .sample_rate_hz = (uint32_t)input_sample_rate, - }; - const audio_codec_data_if_t *adc_if = audio_codec_new_adc_data(&cfg); - - esp_codec_dev_cfg_t codec_dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN, - .data_if = adc_if, - }; - input_dev_ = esp_codec_dev_new(&codec_dev_cfg); - if (!input_dev_) { - ESP_LOGE(TAG, "Failed to create codec device"); - return; - } - - i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, NULL)); - - i2s_pdm_tx_config_t pdm_cfg_default = BSP_I2S_DUPLEX_MONO_CFG((uint32_t)output_sample_rate, pdm_speak_p); - pdm_cfg_default.clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; - pdm_cfg_default.slot_cfg.sd_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.hp_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.lp_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.sinc_scale = I2S_PDM_SIG_SCALING_MUL_4; - const i2s_pdm_tx_config_t *p_i2s_cfg = &pdm_cfg_default; - - ESP_ERROR_CHECK(i2s_channel_init_pdm_tx_mode(tx_handle_, p_i2s_cfg)); - - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = NULL, - .tx_handle = tx_handle_, - }; - - const audio_codec_data_if_t *i2s_data_if = audio_codec_new_i2s_data(&i2s_cfg); - - codec_dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_OUT; - codec_dev_cfg.codec_if = NULL; - codec_dev_cfg.data_if = i2s_data_if; - output_dev_ = esp_codec_dev_new(&codec_dev_cfg); - - output_volume_ = 100; - if(pa_ctl != GPIO_NUM_NC) { - pa_ctrl_pin_ = pa_ctl; - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << pa_ctrl_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - } - gpio_set_drive_capability(pdm_speak_p, GPIO_DRIVE_CAP_0); - - if(pdm_speak_n != GPIO_NUM_NC){ - PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[pdm_speak_n], PIN_FUNC_GPIO); - gpio_set_direction(pdm_speak_n, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(pdm_speak_n, I2SO_SD_OUT_IDX, 1, 0); //反转输出 SD OUT 信号 - gpio_set_drive_capability(pdm_speak_n, GPIO_DRIVE_CAP_0); - } - - // 初始化输出定时器 - esp_timer_create_args_t output_timer_args = { - .callback = &AdcPdmAudioCodec::OutputTimerCallback, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "output_timer" - }; - ESP_ERROR_CHECK(esp_timer_create(&output_timer_args, &output_timer_)); - - ESP_LOGI(TAG, "AdcPdmAudioCodec initialized"); -} - -AdcPdmAudioCodec::~AdcPdmAudioCodec() { - // 删除定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - esp_timer_delete(output_timer_); - output_timer_ = nullptr; - } - - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); -} - -void AdcPdmAudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void AdcPdmAudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void AdcPdmAudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - - // 强制按板卡配置重配PDM TX时钟,覆盖第三方库在set_fmt中的默认up_sample_fs - // 若通道已启用,先禁用再重配,最后再启用 - ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_disable(tx_handle_)); - i2s_pdm_tx_clk_config_t clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG((uint32_t)output_sample_rate_); - clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; - ESP_ERROR_CHECK(i2s_channel_reconfig_pdm_tx_clock(tx_handle_, &clk_cfg)); - ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); - if(pa_ctrl_pin_ != GPIO_NUM_NC){ - gpio_set_level(pa_ctrl_pin_, 1); - } - // 启用输出时启动定时器 - if (output_timer_) { - esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); - } - - } else { - // 禁用输出时停止定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - } - if(pa_ctrl_pin_ != GPIO_NUM_NC){ - gpio_set_level(pa_ctrl_pin_, 0); - } - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int AdcPdmAudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} -int AdcPdmAudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - // 重置输出定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); - } - } - return samples; -} - -void AdcPdmAudioCodec::Start() { - Settings settings("audio", false); - output_volume_ = settings.GetInt("output_volume", output_volume_); - if (output_volume_ <= 0) { - ESP_LOGW(TAG, "Output volume value (%d) is too small, setting to default (10)", output_volume_); - output_volume_ = 10; - } - - EnableInput(true); - EnableOutput(true); - ESP_LOGI(TAG, "Audio codec started"); -} - -// 定时器回调函数实现 -void AdcPdmAudioCodec::OutputTimerCallback(void* arg) { - AdcPdmAudioCodec* codec = static_cast(arg); - if (codec && codec->output_enabled_) { - codec->EnableOutput(false); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.h deleted file mode 100644 index 8c9e8363..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/adc_pdm_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_H -#define _BOX_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include - -class AdcPdmAudioCodec : public AudioCodec { -private: - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_ctrl_pin_ = GPIO_NUM_NC; - - // 定时器相关成员变量 - esp_timer_handle_t output_timer_ = nullptr; - static constexpr uint64_t TIMER_TIMEOUT_US = 120000; // 120ms = 120000us - - // 定时器回调函数 - static void OutputTimerCallback(void* arg); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate, - uint32_t adc_mic_channel, gpio_num_t pdm_speak_p, gpio_num_t pdm_speak_n, gpio_num_t pa_ctl); - virtual ~AdcPdmAudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; - void Start(); -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.h deleted file mode 100644 index 8ea4ffc3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 配置PDM上采样fs参数(取值范围<=480)。部分设备在441时表现更稳定 -#define AUDIO_PDM_UPSAMPLE_FS 441 - -#define AUDIO_ADC_MIC_CHANNEL 2 -#define AUDIO_PDM_SPEAK_P_GPIO GPIO_NUM_6 -#define AUDIO_PDM_SPEAK_N_GPIO GPIO_NUM_7 -#define AUDIO_PA_CTL_GPIO GPIO_NUM_3 - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define MOVE_WAKE_BUTTON_GPIO GPIO_NUM_0 -#define AUDIO_WAKE_BUTTON_GPIO GPIO_NUM_1 - -#define DISPLAY_MOSI_PIN GPIO_NUM_4 -#define DISPLAY_CLK_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_10 -#define DISPLAY_RST_PIN GPIO_NUM_NC -#define DISPLAY_CS_PIN GPIO_NUM_NC - -#define FL_GPIO_NUM GPIO_NUM_21 -#define FR_GPIO_NUM GPIO_NUM_19 -#define BL_GPIO_NUM GPIO_NUM_20 -#define BR_GPIO_NUM GPIO_NUM_18 - -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 160 -#define DISPLAY_HEIGHT 80 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.json deleted file mode 100644 index e136eafe..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/config.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "esp-hi", - "sdkconfig_append": [ - "CONFIG_IDF_TARGET=\"esp32c3\"", - "CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/4m.csv\"", - "CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=3", - "CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=4", - "CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=n", - "CONFIG_ESP_WIFI_RX_BA_WIN=4", - "CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=n", - "CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=0", - "CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=n", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y", - "CONFIG_ESP_MAIN_TASK_STACK_SIZE=7168", - "CONFIG_FREERTOS_HZ=1000", - "CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=768", - "CONFIG_LWIP_MAX_SOCKETS=10", - "CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=16", - "CONFIG_LWIP_IPV6=n", - "CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048", - "CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y", - "CONFIG_NEWLIB_NANO_FORMAT=y", - "CONFIG_ESP_CONSOLE_NONE=y", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_COMPILER_OPTIMIZATION_SIZE=y" - ] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.cc deleted file mode 100644 index c4943371..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.cc +++ /dev/null @@ -1,178 +0,0 @@ -#include -#include "display/lcd_display.h" -#include -#include "emoji_display.h" -#include "assets/lang_config.h" -#include "assets.h" - -#include -#include -#include -#include -#include - -static const char *TAG = "emoji"; - -namespace anim { - -// Emoji asset name mapping based on usage pattern -static const std::unordered_map emoji_asset_name_map = { - {"connecting", "connecting.aaf"}, - {"wake", "wake.aaf"}, - {"asking", "asking.aaf"}, - {"happy_loop", "happy_loop.aaf"}, - {"sad_loop", "sad_loop.aaf"}, - {"anger_loop", "anger_loop.aaf"}, - {"panic_loop", "panic_loop.aaf"}, - {"blink_quick", "blink_quick.aaf"}, - {"scorn_loop", "scorn_loop.aaf"} -}; - -bool EmojiPlayer::OnFlushIoReady(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) -{ - auto* disp_drv = static_cast(user_ctx); - anim_player_flush_ready(disp_drv); - return true; -} - -void EmojiPlayer::OnFlush(anim_player_handle_t handle, int x_start, int y_start, int x_end, int y_end, const void *color_data) -{ - auto* panel = static_cast(anim_player_get_user_data(handle)); - esp_lcd_panel_draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data); -} - -EmojiPlayer::EmojiPlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io) -{ - ESP_LOGI(TAG, "Create EmojiPlayer, panel: %p, panel_io: %p", panel, panel_io); - - anim_player_config_t player_cfg = { - .flush_cb = OnFlush, - .update_cb = NULL, - .user_data = panel, - .flags = {.swap = true}, - .task = ANIM_PLAYER_INIT_CONFIG() - }; - - player_cfg.task.task_priority = 1; - player_cfg.task.task_stack = 4096; - player_handle_ = anim_player_init(&player_cfg); - - const esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = OnFlushIoReady, - }; - esp_lcd_panel_io_register_event_callbacks(panel_io, &cbs, player_handle_); - StartPlayer("connecting", true, 15); -} - -EmojiPlayer::~EmojiPlayer() -{ - if (player_handle_) { - anim_player_update(player_handle_, PLAYER_ACTION_STOP); - anim_player_deinit(player_handle_); - player_handle_ = nullptr; - } -} - -void EmojiPlayer::StartPlayer(const std::string& asset_name, bool repeat, int fps) -{ - if (player_handle_) { - uint32_t start, end; - void *src_data = nullptr; - size_t src_len = 0; - - auto& assets = Assets::GetInstance(); - std::string filename = emoji_asset_name_map.at(asset_name); - if (!assets.GetAssetData(filename, src_data, src_len)) { - ESP_LOGE(TAG, "Failed to get asset data for %s", asset_name.c_str()); - return; - } - - anim_player_set_src_data(player_handle_, src_data, src_len); - anim_player_get_segment(player_handle_, &start, &end); - if(asset_name == "wake"){ - start = 7; - } - anim_player_set_segment(player_handle_, start, end, fps, true); - anim_player_update(player_handle_, PLAYER_ACTION_START); - } -} - -void EmojiPlayer::StopPlayer() -{ - if (player_handle_) { - anim_player_update(player_handle_, PLAYER_ACTION_STOP); - } -} - -EmojiWidget::EmojiWidget(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io) -{ - InitializePlayer(panel, panel_io); -} - -EmojiWidget::~EmojiWidget() -{ - -} - -void EmojiWidget::SetEmotion(const char* emotion) -{ - if (!player_) { - return; - } - - using Param = std::tuple; - static const std::unordered_map emotion_map = { - {"happy", {"happy_loop", true, 25}}, - {"laughing", {"happy_loop", true, 25}}, - {"funny", {"happy_loop", true, 25}}, - {"loving", {"happy_loop", true, 25}}, - {"embarrassed", {"happy_loop", true, 25}}, - {"confident", {"happy_loop", true, 25}}, - {"delicious", {"happy_loop", true, 25}}, - {"sad", {"sad_loop", true, 25}}, - {"crying", {"sad_loop", true, 25}}, - {"sleepy", {"sad_loop", true, 25}}, - {"silly", {"sad_loop", true, 25}}, - {"angry", {"anger_loop", true, 25}}, - {"surprised", {"panic_loop", true, 25}}, - {"shocked", {"panic_loop", true, 25}}, - {"thinking", {"happy_loop", true, 25}}, - {"winking", {"blink_quick", true, 5}}, - {"relaxed", {"scorn_loop", true, 25}}, - {"confused", {"scorn_loop", true, 25}}, - }; - - auto it = emotion_map.find(emotion); - if (it != emotion_map.end()) { - const auto& [aaf, repeat, fps] = it->second; - player_->StartPlayer(aaf, repeat, fps); - } else if (strcmp(emotion, "neutral") == 0) { - } -} - -void EmojiWidget::SetStatus(const char* status) -{ - if (player_) { - if (strcmp(status, Lang::Strings::LISTENING) == 0) { - player_->StartPlayer("asking", true, 15); - } else if (strcmp(status, Lang::Strings::STANDBY) == 0) { - player_->StartPlayer("wake", true, 15); - } - } -} - -void EmojiWidget::InitializePlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io) -{ - player_ = std::make_unique(panel, panel_io); -} - -bool EmojiWidget::Lock(int timeout_ms) -{ - return true; -} - -void EmojiWidget::Unlock() -{ -} - -} // namespace anim diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.h deleted file mode 100644 index d4faab71..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/emoji_display.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include "display/lcd_display.h" -#include -#include -#include -#include -#include "anim_player.h" -#include "assets.h" - -namespace anim { - -class EmojiPlayer; - -using FlushIoReadyCallback = std::function; -using FlushCallback = std::function; - -class EmojiPlayer { -public: - EmojiPlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io); - ~EmojiPlayer(); - - void StartPlayer(const std::string& asset_name, bool repeat, int fps); - void StopPlayer(); - -private: - static bool OnFlushIoReady(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx); - static void OnFlush(anim_player_handle_t handle, int x_start, int y_start, int x_end, int y_end, const void *color_data); - - anim_player_handle_t player_handle_; -}; - -class EmojiWidget : public Display { -public: - EmojiWidget(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io); - virtual ~EmojiWidget(); - - virtual void SetEmotion(const char* emotion) override; - virtual void SetStatus(const char* status) override; - virtual void SetChatMessage(const char* role, const char* content) override {} - - anim::EmojiPlayer* GetPlayer() - { - return player_.get(); - } - -private: - void InitializePlayer(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io); - virtual bool Lock(int timeout_ms = 0) override; - virtual void Unlock() override; - - std::unique_ptr player_; -}; - -} // namespace anim diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/esp_hi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/esp_hi.cc deleted file mode 100644 index fdfcebf0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-hi/esp_hi.cc +++ /dev/null @@ -1,421 +0,0 @@ -#include "wifi_board.h" -#include "adc_pdm_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include -#include -#include -#include -#include - -#include "display/lcd_display.h" -#include -#include -#include -#include "esp_lcd_ili9341.h" - -#include "assets/lang_config.h" -#include "anim_player.h" -#include "emoji_display.h" -#include "servo_dog_ctrl.h" -#include "led_strip.h" -#include "driver/rmt_tx.h" -#include "device_state.h" - -#include "sdkconfig.h" - -#ifdef CONFIG_ESP_HI_WEB_CONTROL_ENABLED -#include "esp_hi_web_control.h" -#endif //CONFIG_ESP_HI_WEB_CONTROL_ENABLED - -#define TAG "ESP_HI" - -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - {0x11, NULL, 0, 120}, // Sleep out, Delay 120ms - {0xB1, (uint8_t []){0x05, 0x3A, 0x3A}, 3, 0}, - {0xB2, (uint8_t []){0x05, 0x3A, 0x3A}, 3, 0}, - {0xB3, (uint8_t []){0x05, 0x3A, 0x3A, 0x05, 0x3A, 0x3A}, 6, 0}, - {0xB4, (uint8_t []){0x03}, 1, 0}, // Dot inversion - {0xC0, (uint8_t []){0x44, 0x04, 0x04}, 3, 0}, - {0xC1, (uint8_t []){0xC0}, 1, 0}, - {0xC2, (uint8_t []){0x0D, 0x00}, 2, 0}, - {0xC3, (uint8_t []){0x8D, 0x6A}, 2, 0}, - {0xC4, (uint8_t []){0x8D, 0xEE}, 2, 0}, - {0xC5, (uint8_t []){0x08}, 1, 0}, - {0xE0, (uint8_t []){0x0F, 0x10, 0x03, 0x03, 0x07, 0x02, 0x00, 0x02, 0x07, 0x0C, 0x13, 0x38, 0x0A, 0x0E, 0x03, 0x10}, 16, 0}, - {0xE1, (uint8_t []){0x10, 0x0B, 0x04, 0x04, 0x10, 0x03, 0x00, 0x03, 0x03, 0x09, 0x17, 0x33, 0x0B, 0x0C, 0x06, 0x10}, 16, 0}, - {0x35, (uint8_t []){0x00}, 1, 0}, - {0x3A, (uint8_t []){0x05}, 1, 0}, - {0x36, (uint8_t []){0xC8}, 1, 0}, - {0x29, NULL, 0, 0}, // Display on - {0x2C, NULL, 0, 0}, // Memory write -}; - -static const led_strip_config_t bsp_strip_config = { - .strip_gpio_num = GPIO_NUM_8, - .max_leds = 4, - .led_model = LED_MODEL_WS2812, - .flags = { - .invert_out = false - } -}; - -static const led_strip_rmt_config_t bsp_rmt_config = { - .clk_src = RMT_CLK_SRC_DEFAULT, - .resolution_hz = 10 * 1000 * 1000, - .flags = { - .with_dma = false - } -}; - -class EspHi : public WifiBoard { -private: - Button boot_button_; - Button audio_wake_button_; - Button move_wake_button_; - anim::EmojiWidget* display_ = nullptr; - bool web_server_initialized_ = false; - led_strip_handle_t led_strip_; - bool led_on_ = false; - -#ifdef CONFIG_ESP_HI_WEB_CONTROL_ENABLED - static void wifi_event_handler(void* arg, esp_event_base_t event_base, - int32_t event_id, void* event_data) - { - if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) { - - xTaskCreate( - [](void* arg) { - EspHi* instance = static_cast(arg); - - vTaskDelay(5000 / portTICK_PERIOD_MS); - - if (!instance->web_server_initialized_) { - ESP_LOGI(TAG, "WiFi connected, init web control server"); - esp_err_t err = esp_hi_web_control_server_init(); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize web control server: %d", err); - } else { - ESP_LOGI(TAG, "Web control server initialized"); - instance->web_server_initialized_ = true; - } - } - - vTaskDelete(NULL); - }, - "web_server_init", - 1024 * 10, arg, 5, nullptr); - } - } -#endif //CONFIG_ESP_HI_WEB_CONTROL_ENABLED - - void HandleMoveWakePressDown(int64_t current_time, int64_t &last_trigger_time, int &gesture_state) - { - int64_t interval = last_trigger_time == 0 ? 0 : current_time - last_trigger_time; - last_trigger_time = current_time; - - if (interval > 1000) { - gesture_state = 0; - } else { - switch (gesture_state) { - case 0: - break; - case 1: - if (interval > 300) { - gesture_state = 2; - } - break; - case 2: - if (interval > 100) { - gesture_state = 0; - } - break; - } - } - } - - void HandleMoveWakePressUp(int64_t current_time, int64_t &last_trigger_time, int &gesture_state) - { - int64_t interval = current_time - last_trigger_time; - - if (interval > 1000) { - gesture_state = 0; - } else { - switch (gesture_state) { - case 0: - if (interval > 300) { - gesture_state = 1; - } - break; - case 1: - break; - case 2: - if (interval < 100) { - ESP_LOGI(TAG, "gesture detected"); - gesture_state = 0; - auto &app = Application::GetInstance(); - app.ToggleChatState(); - } - break; - } - } - } - - void InitializeButtons() - { - static int64_t last_trigger_time = 0; - static int gesture_state = 0; // 0: init, 1: wait second long interval, 2: wait oscillation - - boot_button_.OnClick([this]() { - auto &app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - audio_wake_button_.OnPressDown([this]() { - }); - - audio_wake_button_.OnPressUp([this]() { - }); - - move_wake_button_.OnPressDown([this]() { - int64_t current_time = esp_timer_get_time() / 1000; - HandleMoveWakePressDown(current_time, last_trigger_time, gesture_state); - }); - - move_wake_button_.OnPressUp([this]() { - int64_t current_time = esp_timer_get_time() / 1000; - HandleMoveWakePressUp(current_time, last_trigger_time, gesture_state); - }); - } - - void InitializeLed() { - ESP_LOGI(TAG, "BLINK_GPIO setting %d", bsp_strip_config.strip_gpio_num); - - ESP_ERROR_CHECK(led_strip_new_rmt_device(&bsp_strip_config, &bsp_rmt_config, &led_strip_)); - led_strip_set_pixel(led_strip_, 0, 0x00, 0x00, 0x00); - led_strip_set_pixel(led_strip_, 1, 0x00, 0x00, 0x00); - led_strip_set_pixel(led_strip_, 2, 0x00, 0x00, 0x00); - led_strip_set_pixel(led_strip_, 3, 0x00, 0x00, 0x00); - led_strip_refresh(led_strip_); - } - - esp_err_t SetLedColor(uint8_t r, uint8_t g, uint8_t b) { - esp_err_t ret = ESP_OK; - - ret |= led_strip_set_pixel(led_strip_, 0, r, g, b); - ret |= led_strip_set_pixel(led_strip_, 1, r, g, b); - ret |= led_strip_set_pixel(led_strip_, 2, r, g, b); - ret |= led_strip_set_pixel(led_strip_, 3, r, g, b); - ret |= led_strip_refresh(led_strip_); - return ret; - } - - void InitializeIot() - { - ESP_LOGI(TAG, "Initialize Iot"); - InitializeLed(); - SetLedColor(0x00, 0x00, 0x00); - -#ifdef CONFIG_ESP_HI_WEB_CONTROL_ENABLED - ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED, - &wifi_event_handler, this)); -#endif //CONFIG_ESP_HI_WEB_CONTROL_ENABLED - } - - void InitializeSpi() - { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * 10 * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() - { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *) &vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_set_gap(panel, 0, 24); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - ESP_LOGI(TAG, "LCD panel create success, %p", panel); - - esp_lcd_panel_disp_on_off(panel, true); - - ESP_LOGI(TAG, "Create emoji widget, panel: %p, panel_io: %p", panel, panel_io); - display_ = new anim::EmojiWidget(panel, panel_io); - -#if CONFIG_ESP_CONSOLE_NONE - servo_dog_ctrl_config_t config = { - .fl_gpio_num = FL_GPIO_NUM, - .fr_gpio_num = FR_GPIO_NUM, - .bl_gpio_num = BL_GPIO_NUM, - .br_gpio_num = BR_GPIO_NUM, - }; - - servo_dog_ctrl_init(&config); -#endif - } - - void InitializeTools() - { - auto& mcp_server = McpServer::GetInstance(); - - // 基础动作控制 - mcp_server.AddTool("self.dog.basic_control", "机器人的基础动作。机器人可以做以下基础动作:\n" - "forward: 向前移动\nbackward: 向后移动\nturn_left: 向左转\nturn_right: 向右转\nstop: 立即停止当前动作", - PropertyList({ - Property("action", kPropertyTypeString), - }), [this](const PropertyList& properties) -> ReturnValue { - const std::string& action = properties["action"].value(); - if (action == "forward") { - servo_dog_ctrl_send(DOG_STATE_FORWARD, NULL); - } else if (action == "backward") { - servo_dog_ctrl_send(DOG_STATE_BACKWARD, NULL); - } else if (action == "turn_left") { - servo_dog_ctrl_send(DOG_STATE_TURN_LEFT, NULL); - } else if (action == "turn_right") { - servo_dog_ctrl_send(DOG_STATE_TURN_RIGHT, NULL); - } else if (action == "stop") { - servo_dog_ctrl_send(DOG_STATE_IDLE, NULL); - } else { - return false; - } - return true; - }); - - // 扩展动作控制 - mcp_server.AddTool("self.dog.advanced_control", "机器人的扩展动作。机器人可以做以下扩展动作:\n" - "sway_back_forth: 前后摇摆\nlay_down: 趴下\nsway: 左右摇摆\nretract_legs: 收回腿部\n" - "shake_hand: 握手\nshake_back_legs: 伸懒腰\njump_forward: 向前跳跃", - PropertyList({ - Property("action", kPropertyTypeString), - }), [this](const PropertyList& properties) -> ReturnValue { - const std::string& action = properties["action"].value(); - if (action == "sway_back_forth") { - servo_dog_ctrl_send(DOG_STATE_SWAY_BACK_FORTH, NULL); - } else if (action == "lay_down") { - servo_dog_ctrl_send(DOG_STATE_LAY_DOWN, NULL); - } else if (action == "sway") { - dog_action_args_t args = { - .repeat_count = 4, - }; - servo_dog_ctrl_send(DOG_STATE_SWAY, &args); - } else if (action == "retract_legs") { - servo_dog_ctrl_send(DOG_STATE_RETRACT_LEGS, NULL); - } else if (action == "shake_hand") { - servo_dog_ctrl_send(DOG_STATE_SHAKE_HAND, NULL); - } else if (action == "shake_back_legs") { - servo_dog_ctrl_send(DOG_STATE_SHAKE_BACK_LEGS, NULL); - } else if (action == "jump_forward") { - servo_dog_ctrl_send(DOG_STATE_JUMP_FORWARD, NULL); - } else { - return false; - } - return true; - }); - - // 灯光控制 - mcp_server.AddTool("self.light.get_power", "获取灯是否打开", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return led_on_; - }); - - mcp_server.AddTool("self.light.turn_on", "打开灯", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SetLedColor(0xFF, 0xFF, 0xFF); - led_on_ = true; - return true; - }); - - mcp_server.AddTool("self.light.turn_off", "关闭灯", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SetLedColor(0x00, 0x00, 0x00); - led_on_ = false; - return true; - }); - - mcp_server.AddTool("self.light.set_rgb", "设置RGB颜色", PropertyList({ - Property("r", kPropertyTypeInteger, 0, 255), - Property("g", kPropertyTypeInteger, 0, 255), - Property("b", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int r = properties["r"].value(); - int g = properties["g"].value(); - int b = properties["b"].value(); - - led_on_ = true; - SetLedColor(r, g, b); - return true; - }); - } - -public: - EspHi() : boot_button_(BOOT_BUTTON_GPIO), - audio_wake_button_(AUDIO_WAKE_BUTTON_GPIO), - move_wake_button_(MOVE_WAKE_BUTTON_GPIO) - { - InitializeButtons(); - InitializeIot(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override - { - static AdcPdmAudioCodec audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_ADC_MIC_CHANNEL, - AUDIO_PDM_SPEAK_P_GPIO, - AUDIO_PDM_SPEAK_N_GPIO, - AUDIO_PA_CTL_GPIO); - return &audio_codec; - } - - virtual Display* GetDisplay() override - { - return display_; - } -}; - -DECLARE_BOARD(EspHi); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/README.md deleted file mode 100644 index 5fde9b28..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# ESP-P4-Function-EV-Board - -Board support for ESP-P4-Function-EV-Board. Wi‑Fi uses ESP‑Hosted via the on‑board ESP32‑C6. LCD is supported via the official MIPI‑DSI LCD adapter. - -## Features -- Wi‑Fi: `esp_wifi_remote` + `esp_hosted` (SDIO) with ESP32‑C6 co‑processor -- Display: 7" MIPI‑DSI LCD (1024×600) via adapter; can also run headless -- Audio: ES8311 codec with speaker and microphone support -- Touch: GT911 capacitive touch controller -- SD Card: MicroSD card support (MMC mode) -- Camera: MIPI-CSI camera interface with fallback DVP configuration (OV5647, SC2336 sensors supported) -- USB: USB host/device support -- SPIFFS: Built-in flash filesystem support -- Fonts: Custom font support with Unicode characters (Vietnamese, Chinese, etc.) - -## Configure -In `menuconfig`: Xiaozhi Assistant -> Board Type -> ESP-P4-Function-EV-Board - -Ensure these are set (auto-set when building via config.json): -- `CONFIG_SLAVE_IDF_TARGET_ESP32C6=y` -- `CONFIG_ESP_HOSTED_P4_DEV_BOARD_FUNC_BOARD=y` -- `CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y` -- `CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y` - -## LCD Connection (from Espressif user guide) -- Connect the LCD adapter board J3 to the board’s MIPI DSI connector (reverse ribbon). -- Wire `RST_LCD` (adapter J6) to `GPIO27` (board J1). -- Wire `PWM` (adapter J6) to `GPIO26` (board J1). -- Optionally power the LCD adapter via its USB or provide `5V` and `GND` from the board. - -These pins are pre-configured in `config.h` as `PIN_NUM_LCD_RST=GPIO27` and `DISPLAY_BACKLIGHT_PIN=GPIO26`. Resolution is set to 1024×600. - -## Build (example) -```powershell -idf.py set-target esp32p4 -idf.py menuconfig -idf.py build -``` - -Tip: In menuconfig, choose Xiaozhi Assistant -> Board Type -> ESP-P4-Function-EV-Board. -If building a release via scripts, the `config.json` in this folder appends the required Hosted options. diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.h deleted file mode 100644 index aca0c939..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include "bsp/esp32_p4_function_ev_board.h" // Library for board configs and pins - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.json deleted file mode 100644 index d191f94b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "esp-p4-function-ev-board", - "sdkconfig_append": [ - "CONFIG_SLAVE_IDF_TARGET_ESP32C6=y", - "CONFIG_ESP_HOSTED_P4_DEV_BOARD_FUNC_BOARD=y", - "CONFIG_ESP_HOSTED_SDIO_HOST_INTERFACE=y", - "CONFIG_ESP_HOSTED_SDIO_4_BIT_BUS=y", - "CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y", - "CONFIG_BSP_LCD_TYPE_1024_600=y" - ] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/esp-p4-function-ev-board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/esp-p4-function-ev-board.cc deleted file mode 100644 index 0a6405a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-p4-function-ev-board/esp-p4-function-ev-board.cc +++ /dev/null @@ -1,233 +0,0 @@ -#include "wifi_board.h" -#include "audio/codecs/es8311_audio_codec.h" -// Display -#include "display/display.h" -#include "display/lcd_display.h" -#include "lvgl_theme.h" -// Backlight -// PwmBacklight is declared in backlight headers pulled by display/lcd_display includes via lvgl stack - -#include "application.h" -#include "button.h" -#include "config.h" -#include "esp32_camera.h" - -#include -#include -#include -#include -#include -// SD card -#include -#include -#include -#include -// SD power control (on-chip LDO) -#include "sd_pwr_ctrl_by_on_chip_ldo.h" - -// MIPI-DSI / LCD vendor includes (library may replace some) -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" -#include "esp_lcd_ek79007.h" -#include "esp_lcd_touch_gt911.h" - -// Library includes -#include "bsp/esp32_p4_function_ev_board.h" -#include "bsp/touch.h" - -#define TAG "ESP32P4FuncEV" - -class ESP32P4FunctionEvBoard : public WifiBoard -{ -private: - i2c_master_bus_handle_t codec_i2c_bus_ = nullptr; - Button boot_button_; - LcdDisplay *display_ = nullptr; - esp_lcd_touch_handle_t tp_ = nullptr; - Esp32Camera* camera_ = nullptr; - - void InitializeI2cBuses() - { - ESP_ERROR_CHECK(bsp_i2c_init()); - codec_i2c_bus_ = bsp_i2c_get_handle(); - } - - // Touch I2C bus initialization is not required for this board (handled elsewhere) - void InitializeTouchI2cBus() - { - // No implementation needed - } - - void InitializeLCD() - { - bsp_display_config_t config = { - .hdmi_resolution = BSP_HDMI_RES_NONE, - .dsi_bus = { - .phy_clk_src = (mipi_dsi_phy_clock_source_t)SOC_MOD_CLK_PLL_F20M, - .lane_bit_rate_mbps = 1000, - }, - }; - - bsp_lcd_handles_t handles; - ESP_ERROR_CHECK(bsp_display_new_with_handles(&config, &handles)); - - display_ = new MipiLcdDisplay(handles.io, handles.panel, 1024, 600, 0, 0, true, true, false); - } - - void InitializeButtons() - { - boot_button_.OnClick([this]() - { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeTouch() - { - ESP_ERROR_CHECK(bsp_touch_new(NULL, &tp_)); - } - - void InitializeSdCard() - { - ESP_LOGI(TAG, "Initializing SD card"); - esp_err_t ret = bsp_sdcard_mount(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to mount SD card: %s", esp_err_to_name(ret)); - } else { - ESP_LOGI(TAG, "SD card mounted successfully"); - } - } - - void InitializeCamera() - { - ESP_LOGI(TAG, "Initializing camera"); - - // Use BSP camera initialization for ESP-P4 - bsp_camera_cfg_t camera_cfg = {0}; - esp_err_t ret = bsp_camera_start(&camera_cfg); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize BSP camera: %s", esp_err_to_name(ret)); - ESP_LOGI(TAG, "Attempting alternative camera initialization"); - - // Alternative: Direct Esp32Camera initialization if BSP fails - // This provides more control over camera configuration - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = BSP_I2C_SDA, // Reuse I2C pins if camera pins not defined - [1] = BSP_I2C_SCL, - [2] = GPIO_NUM_NC, - [3] = GPIO_NUM_NC, - [4] = GPIO_NUM_NC, - [5] = GPIO_NUM_NC, - [6] = GPIO_NUM_NC, - [7] = GPIO_NUM_NC, - }, - .vsync_io = GPIO_NUM_NC, - .de_io = GPIO_NUM_NC, - .pclk_io = GPIO_NUM_NC, - .xclk_io = GPIO_NUM_NC, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // Use existing I2C bus - .i2c_handle = codec_i2c_bus_, // Reuse the existing I2C bus - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - .dvp_pin = dvp_pin_config, - .xclk_freq = 20000000, // 20MHz typical for cameras - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - // Try to create camera with direct configuration - camera_ = new Esp32Camera(video_config); - ESP_LOGI(TAG, "Camera initialized with direct configuration"); - } else { - ESP_LOGI(TAG, "Camera initialized successfully via BSP"); - } - } - - void InitializeFonts() - { - ESP_LOGI(TAG, "Initializing font support"); - // Font initialization is handled by the Assets system - // The board supports loading fonts from assets partition - // Verify that fonts are properly loaded by checking theme - auto& theme_manager = LvglThemeManager::GetInstance(); - auto current_theme = theme_manager.GetTheme("light"); - if (current_theme != nullptr) { - auto text_font = current_theme->text_font(); - if (text_font != nullptr && text_font->font() != nullptr) { - ESP_LOGI(TAG, "Custom font loaded successfully: line_height=%d", text_font->font()->line_height); - } else { - ESP_LOGW(TAG, "Custom font not loaded, using built-in font"); - } - } - } - -public: - - ESP32P4FunctionEvBoard() : boot_button_(0) - { - InitializeI2cBuses(); - // Audio is initialized by Es8311AudioCodec - InitializeLCD(); - InitializeButtons(); - InitializeTouch(); - InitializeSdCard(); - InitializeCamera(); - InitializeFonts(); - GetBacklight()->RestoreBrightness(); - } - - ~ESP32P4FunctionEvBoard() - { - // Clean up display pointer - delete display_; - display_ = nullptr; - // Unmount SD card - esp_err_t ret = bsp_sdcard_unmount(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to unmount SD card: %s", esp_err_to_name(ret)); - } - // If other resources need cleanup, add here - } - - virtual AudioCodec *GetAudioCodec() override - { - static Es8311AudioCodec audio_codec( - codec_i2c_bus_, (i2c_port_t)BSP_I2C_NUM, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - BSP_I2S_MCLK, BSP_I2S_SCLK, BSP_I2S_LCLK, BSP_I2S_DOUT, BSP_I2S_DSIN, - BSP_POWER_AMP_IO, ES8311_CODEC_DEFAULT_ADDR, true, false); - return &audio_codec; - } - - virtual Display *GetDisplay() override { return display_; } - - virtual Backlight *GetBacklight() override - { - static PwmBacklight backlight(BSP_LCD_BACKLIGHT, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual Camera *GetCamera() override - { - return camera_; - } -}; - -DECLARE_BOARD(ESP32P4FunctionEvBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/README.md deleted file mode 100644 index 5fcacc46..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/README.md +++ /dev/null @@ -1,10 +0,0 @@ -请确认自己的开发板硬件版本,如果硬件版本,在配置中进行ev_board type进行选择 -1.4与1.5只有io进行变更 -可以查看官方文档,确认具体细节https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-lcd-ev-board/user_guide.html -具体调整为: -I2C_SCL IO18 -> IO48 -I2C_SDA IO8 -> IO47 -LCD_DATA6 IO47 -> IO8 -LCD_DATA7 IO48 -> IO18 - -本版本只支持了800x480的屏幕 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.h deleted file mode 100644 index a59cf053..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_7 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_6 - -#define BSP_POWER_AMP_IO (IO_EXPANDER_PIN_NUM_0) -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 - -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR 0x82 - - -#define BUILTIN_LED_GPIO GPIO_NUM_4 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_WIDTH 800 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_19 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.json deleted file mode 100644 index 27ab7524..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-s3-lcd-ev-board-2", - "sdkconfig_append": [] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp-s3-lcd-ev-board-2.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp-s3-lcd-ev-board-2.cc deleted file mode 100644 index 6e7690b4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp-s3-lcd-ev-board-2.cc +++ /dev/null @@ -1,271 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "pin_config.h" -#include "esp32_camera.h" - -#include "config.h" - -#include -#include -#include "esp_lcd_gc9503.h" -#include -#include -#include -#include -#include -#include -#include - -#define TAG "ESP_S3_LCD_EV_Board_2" - -class ESP_S3_LCD_EV_Board_2 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - Esp32Camera* camera_; - - //add support ev board lcd - esp_io_expander_handle_t expander = NULL; - - void InitializeRGB_GC9503V_Display() { - ESP_LOGI(TAG, "Init GC9503V"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - - // add support ev board lcd - gpio_config_t io_conf = { - .pin_bit_mask = BIT64(GC9503V_PIN_NUM_VSYNC), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_ENABLE, - }; - - gpio_config(&io_conf); - gpio_set_level(GC9503V_PIN_NUM_VSYNC, 1); - - ESP_LOGI(TAG, "Install 3-wire SPI panel IO"); - spi_line_config_t line_config = { - .cs_io_type = IO_TYPE_EXPANDER, - .cs_expander_pin = GC9503V_LCD_IO_SPI_CS_1, - .scl_io_type = IO_TYPE_EXPANDER, - .scl_expander_pin = GC9503V_LCD_IO_SPI_SCL_1, - .sda_io_type = IO_TYPE_EXPANDER, - .sda_expander_pin = GC9503V_LCD_IO_SPI_SDO_1, - .io_expander = expander, - }; - - esp_lcd_panel_io_3wire_spi_config_t io_config = GC9503_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0); - int espok = esp_lcd_new_panel_io_3wire_spi(&io_config, &panel_io); - ESP_LOGI(TAG, "Install 3-wire SPI panel IO:%d",espok); - - ESP_LOGI(TAG, "Install RGB LCD panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_rgb_panel_config_t rgb_config = { - .clk_src = LCD_CLK_SRC_PLL160M, - //add support ev board - .timings = GC9503_800_480_PANEL_60HZ_RGB_TIMING(), - .data_width = 16, // RGB565 in parallel mode, thus 16bit in width - .bits_per_pixel = 16, - .num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS, - .bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT, - .dma_burst_size = 64, - .hsync_gpio_num = GC9503V_PIN_NUM_HSYNC, - .vsync_gpio_num = GC9503V_PIN_NUM_VSYNC, - .de_gpio_num = GC9503V_PIN_NUM_DE, - .pclk_gpio_num = GC9503V_PIN_NUM_PCLK, - .disp_gpio_num = GC9503V_PIN_NUM_DISP_EN, - .data_gpio_nums = { - GC9503V_PIN_NUM_DATA0, - GC9503V_PIN_NUM_DATA1, - GC9503V_PIN_NUM_DATA2, - GC9503V_PIN_NUM_DATA3, - GC9503V_PIN_NUM_DATA4, - GC9503V_PIN_NUM_DATA5, - GC9503V_PIN_NUM_DATA6, - GC9503V_PIN_NUM_DATA7, - GC9503V_PIN_NUM_DATA8, - GC9503V_PIN_NUM_DATA9, - GC9503V_PIN_NUM_DATA10, - GC9503V_PIN_NUM_DATA11, - GC9503V_PIN_NUM_DATA12, - GC9503V_PIN_NUM_DATA13, - GC9503V_PIN_NUM_DATA14, - GC9503V_PIN_NUM_DATA15, - }, - .flags= { - .fb_in_psram = true, // allocate frame buffer in PSRAM - } - }; - - ESP_LOGI(TAG, "Initialize RGB LCD panel"); - - gc9503_vendor_config_t vendor_config = { - .rgb_config = &rgb_config, - .flags = { - .mirror_by_cmd = 0, - .auto_del_panel_io = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = -1, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - // .bits_per_pixel = 16, - //add surpport ev board - .bits_per_pixel = 18, - .vendor_config = &vendor_config, - }; - (esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle)); - (esp_lcd_panel_reset(panel_handle)); - (esp_lcd_panel_init(panel_handle)); - - display_ = new RgbLcdDisplay(panel_io, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - //add support ev board lcd amp - //初始化扩展io口 - esp_io_expander_new_i2c_tca9554(i2c_bus_, 0x20, &expander); - /* Setup power amplifier pin, set default to enable */ - esp_io_expander_set_dir(expander, BSP_POWER_AMP_IO, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(expander, BSP_POWER_AMP_IO, true); - - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT1151_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt1151(tp_io_handle, &tp_cfg, &tp)); - - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - void InitializeCamera() { - esp_video_init_usb_uvc_config_t usb_uvc_config = { - .uvc = { - .uvc_dev_num = 1, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - .usb = { - .init_usb_host_lib = true, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - }; - } - esp_video_init_config_t video_config = { - .usb_uvc = &usb_uvc_config, - }; - camera_ = new Esp32Camera(video_config); - } -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - -public: - ESP_S3_LCD_EV_Board_2() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializeRGB_GC9503V_Display(); - InitializeTouch(); -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - InitializeCamera(); -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - true); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - //添加彩灯显示状态,如果亮度太暗可以去更改默认亮度值 DEFAULT_BRIGHTNESS 在led的sigle_led.cc中 - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - virtual Camera* GetCamera() override { - return camera_; - } -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - -}; - -DECLARE_BOARD(ESP_S3_LCD_EV_Board_2); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.c deleted file mode 100644 index 4db550e2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_lcd_gc9503.h" - -#define GC9503_CMD_MADCTL (0xB1) // Memory data access control -#define GC9503_CMD_MADCTL_DEFAULT (0x10) // Default value of Memory data access control -#define GC9503_CMD_SS_BIT (1 << 0) // Source driver scan direction, 0: top to bottom, 1: bottom to top -#define GC9503_CMD_GS_BIT (1 << 1) // Gate driver scan direction, 0: left to right, 1: right to left -#define GC9503_CMD_BGR_BIT (1 << 5) // RGB/BGR order, 0: RGB, 1: BGR - -typedef struct -{ - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // Save current value of GC9503_CMD_MADCTL register - uint8_t colmod_val; // Save current value of LCD_CMD_COLMOD register - const gc9503_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - struct - { - unsigned int mirror_by_cmd : 1; - unsigned int auto_del_panel_io : 1; - unsigned int display_on_off_use_cmd : 1; - unsigned int reset_level : 1; - } flags; - // To save the original functions of RGB panel - esp_err_t (*init)(esp_lcd_panel_t *panel); - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*reset)(esp_lcd_panel_t *panel); - esp_err_t (*mirror)(esp_lcd_panel_t *panel, bool x_axis, bool y_axis); - esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off); -} gc9503_panel_t; - -static const char *TAG = "gc9503"; - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503); - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool off); - -esp_err_t esp_lcd_new_panel_gc9503(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - gc9503_vendor_config_t *vendor_config = (gc9503_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->rgb_config, ESP_ERR_INVALID_ARG, TAG, "`verndor_config` and `rgb_config` are necessary"); - ESP_RETURN_ON_FALSE(!vendor_config->flags.auto_del_panel_io || !vendor_config->flags.mirror_by_cmd, - ESP_ERR_INVALID_ARG, TAG, "`mirror_by_cmd` and `auto_del_panel_io` cannot work together"); - - esp_err_t ret = ESP_OK; - gpio_config_t io_conf = {0}; - - gc9503_panel_t *gc9503 = (gc9503_panel_t *)calloc(1, sizeof(gc9503_panel_t)); - ESP_RETURN_ON_FALSE(gc9503, ESP_ERR_NO_MEM, TAG, "no mem for gc9503 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - gc9503->madctl_val = GC9503_CMD_MADCTL_DEFAULT; - switch (panel_dev_config->rgb_ele_order) - { - case LCD_RGB_ELEMENT_ORDER_RGB: - gc9503->madctl_val &= ~GC9503_CMD_BGR_BIT; - break; - case LCD_RGB_ELEMENT_ORDER_BGR: - gc9503->madctl_val |= GC9503_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order"); - break; - } - - gc9503->colmod_val = 0; - switch (panel_dev_config->bits_per_pixel) - { - case 16: // RGB565 - gc9503->colmod_val = 0x50; - break; - case 18: // RGB666 - gc9503->colmod_val = 0x60; - break; - case 24: // RGB888 - gc9503->colmod_val = 0x70; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - gc9503->io = io; - gc9503->init_cmds = vendor_config->init_cmds; - gc9503->init_cmds_size = vendor_config->init_cmds_size; - gc9503->reset_gpio_num = panel_dev_config->reset_gpio_num; - gc9503->flags.reset_level = panel_dev_config->flags.reset_active_high; - gc9503->flags.auto_del_panel_io = vendor_config->flags.auto_del_panel_io; - gc9503->flags.mirror_by_cmd = vendor_config->flags.mirror_by_cmd; - gc9503->flags.display_on_off_use_cmd = (vendor_config->rgb_config->disp_gpio_num >= 0) ? 0 : 1; - - if (gc9503->flags.auto_del_panel_io) - { - if (gc9503->reset_gpio_num >= 0) - { // Perform hardware reset - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - } - else - { // Perform software reset - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), err, TAG, "send command failed"); - } - vTaskDelay(pdMS_TO_TICKS(120)); - - /** - * In order to enable the 3-wire SPI interface pins (such as SDA and SCK) to share other pins of the RGB interface - * (such as HSYNC) and save GPIOs, we need to send LCD initialization commands via the 3-wire SPI interface before - * `esp_lcd_new_rgb_panel()` is called. - */ - ESP_GOTO_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), err, TAG, "send init commands failed"); - // After sending the initialization commands, the 3-wire SPI interface can be deleted - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_del(io), err, TAG, "delete panel IO failed"); - gc9503->io = NULL; - ESP_LOGD(TAG, "delete panel IO"); - } - - // Create RGB panel - ESP_GOTO_ON_ERROR(esp_lcd_new_rgb_panel(vendor_config->rgb_config, ret_panel), err, TAG, "create RGB panel failed"); - ESP_LOGD(TAG, "new RGB panel @%p", ret_panel); - - // Save the original functions of RGB panel - gc9503->init = (*ret_panel)->init; - gc9503->del = (*ret_panel)->del; - gc9503->reset = (*ret_panel)->reset; - gc9503->mirror = (*ret_panel)->mirror; - gc9503->disp_on_off = (*ret_panel)->disp_on_off; - // Overwrite the functions of RGB panel - (*ret_panel)->init = panel_gc9503_init; - (*ret_panel)->del = panel_gc9503_del; - (*ret_panel)->reset = panel_gc9503_reset; - (*ret_panel)->mirror = panel_gc9503_mirror; - (*ret_panel)->disp_on_off = panel_gc9503_disp_on_off; - (*ret_panel)->user_data = gc9503; - ESP_LOGD(TAG, "new gc9503 panel @%p", gc9503); - - // ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9503_VER_MAJOR, ESP_LCD_GC9503_VER_MINOR, - // ESP_LCD_GC9503_VER_PATCH); - return ESP_OK; - -err: - if (gc9503) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(gc9503); - } - return ret; -} - -// *INDENT-OFF* -// static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { -// // {cmd, { data }, data_size, delay_ms} -// {0x11, (uint8_t []){0x00}, 0, 120}, - -// {0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0}, -// {0xf6, (uint8_t []){0x5a, 0x87}, 2, 0}, -// {0xc1, (uint8_t []){0x3f}, 1, 0}, -// {0xc2, (uint8_t []){0x0e}, 1, 0}, -// {0xc6, (uint8_t []){0xf8}, 1, 0}, -// {0xc9, (uint8_t []){0x10}, 1, 0}, -// {0xcd, (uint8_t []){0x25}, 1, 0}, -// {0xf8, (uint8_t []){0x8a}, 1, 0}, -// {0xac, (uint8_t []){0x45}, 1, 0}, -// {0xa0, (uint8_t []){0xdd}, 1, 0}, -// {0xa7, (uint8_t []){0x47}, 1, 0}, -// {0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0}, -// {0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0}, -// {0xa3, (uint8_t []){0xee}, 1, 0}, -// {0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0}, -// {0x71, (uint8_t []){0x48}, 1, 0}, -// {0x72, (uint8_t []){0x48}, 1, 0}, -// {0x73, (uint8_t []){0x00, 0x44}, 2, 0}, -// {0x97, (uint8_t []){0xee}, 1, 0}, -// {0x83, (uint8_t []){0x93}, 1, 0}, -// {0x9a, (uint8_t []){0x72}, 1, 0}, -// {0x9b, (uint8_t []){0x5a}, 1, 0}, -// {0x82, (uint8_t []){0x2c, 0x2c}, 2, 0}, -// {0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, -// 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0}, -// {0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0}, -// {0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0}, -// {0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0}, -// {0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, -// {0x6b, (uint8_t []){0x07}, 1, 0}, -// {0x7a, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0x7b, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0x11, (uint8_t []){0x00}, 0, 120}, -// {0x29, (uint8_t []){0x00}, 0, 20}, -// }; -static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { - // {0x11, (uint8_t[]){}, 0, 20}, - - {0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0}, - {0xf6, (uint8_t []){0x5a, 0x87}, 2, 0}, - {0xc1, (uint8_t []){0x3f}, 1, 0}, - {0xc2, (uint8_t []){0x0e}, 1, 0}, - {0xc6, (uint8_t []){0xf8}, 1, 0}, - {0xc9, (uint8_t []){0x10}, 1, 0}, - {0xcd, (uint8_t []){0x25}, 1, 0}, - {0xf8, (uint8_t []){0x8a}, 1, 0}, - {0xac, (uint8_t []){0x45}, 1, 0}, - {0xa0, (uint8_t []){0xdd}, 1, 0}, - {0xa7, (uint8_t []){0x47}, 1, 0}, - {0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0}, - {0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0}, - {0xa3, (uint8_t []){0xee}, 1, 0}, - {0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0}, - {0x71, (uint8_t []){0x48}, 1, 0}, - {0x72, (uint8_t []){0x48}, 1, 0}, - {0x73, (uint8_t []){0x00, 0x44}, 2, 0}, - {0x97, (uint8_t []){0xee}, 1, 0}, - {0x83, (uint8_t []){0x93}, 1, 0}, - {0x9a, (uint8_t []){0x72}, 1, 0}, - {0x9b, (uint8_t []){0x5a}, 1, 0}, - {0x82, (uint8_t []){0x2c, 0x2c}, 2, 0}, - {0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0}, - {0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0}, - {0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0}, - {0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0}, - {0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, - {0x6b, (uint8_t []){0x07}, 1, 0}, - {0x7a, (uint8_t []){0x08, 0x13}, 2, 0}, - {0x7b, (uint8_t []){0x08, 0x13}, 2, 0}, - {0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0x11, (uint8_t []){0x00}, 0, 120}, - {0x29, (uint8_t []){0x00}, 0, 20}, - - }; - -// *INDENT-OFF* - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503) -{ - esp_lcd_panel_io_handle_t io = gc9503->io; - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){ - gc9503->colmod_val, - }, - 1), - TAG, "send command failed"); - ; - - // Vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - const gc9503_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - if (gc9503->init_cmds) - { - init_cmds = gc9503->init_cmds; - init_cmds_size = gc9503->init_cmds_size; - } - else - { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(gc9503_lcd_init_cmd_t); - } - - bool is_cmd_overwritten = false; - for (int i = 0; i < init_cmds_size; i++) - { - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd) - { - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - gc9503->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - gc9503->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten) - { - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), - TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (!gc9503->flags.auto_del_panel_io) - { - ESP_RETURN_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), TAG, "send init commands failed"); - } - // Init RGB panel - ESP_RETURN_ON_ERROR(gc9503->init(panel), TAG, "init RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (gc9503->reset_gpio_num >= 0) - { - gpio_reset_pin(gc9503->reset_gpio_num); - } - // Delete RGB panel - gc9503->del(panel); - free(gc9503); - ESP_LOGD(TAG, "del gc9503 panel @%p", gc9503); - return ESP_OK; -} - -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - // Perform hardware reset - if (gc9503->reset_gpio_num >= 0) - { - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(120)); - } - else if (io) - { // Perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(120)); - } - // Reset RGB panel - ESP_RETURN_ON_ERROR(gc9503->reset(panel), TAG, "reset RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - if (gc9503->flags.mirror_by_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control mirror through LCD command - if (mirror_x) - { - gc9503->madctl_val |= GC9503_CMD_GS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_GS_BIT; - } - if (mirror_y) - { - gc9503->madctl_val |= GC9503_CMD_SS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_SS_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - } - else - { - // Control mirror through RGB panel - ESP_RETURN_ON_ERROR(gc9503->mirror(panel, mirror_x, mirror_y), TAG, "RGB panel mirror failed"); - } - return ESP_OK; -} - -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - int command = 0; - - if (gc9503->flags.display_on_off_use_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control display on/off through LCD command - if (on_off) - { - command = LCD_CMD_DISPON; - } - else - { - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - } - else - { - // Control display on/off through display control signal - ESP_RETURN_ON_ERROR(gc9503->disp_on_off(panel, on_off), TAG, "RGB panel disp_on_off failed"); - } - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.h deleted file mode 100644 index 4d926d9e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board-2/esp_lcd_gc9503.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief ESP LCD: GC9503 - */ - -#pragma once - -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* IO48 -I2C_SDA IO8 -> IO47 -LCD_DATA6 IO47 -> IO8 -LCD_DATA7 IO48 -> IO18 - - -本版本只支持了480x480的屏幕 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.h deleted file mode 100644 index 4db17752..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_7 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_6 - -#define BSP_POWER_AMP_IO (IO_EXPANDER_PIN_NUM_0) -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC - -//如果开发板是V1.4 IO 定义为 -#ifdef CONFIG_ESP_S3_LCD_EV_Board_1p4 - #define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 - #define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_18 -#endif -//如果开发板是V1.5 IO 定义为 -#ifdef CONFIG_ESP_S3_LCD_EV_Board_1p5 - #define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 - #define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#endif - -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR 0x82 - - -#define BUILTIN_LED_GPIO GPIO_NUM_4 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_WIDTH 480 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_19 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - - - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.json deleted file mode 100644 index 55d16023..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-s3-lcd-ev-board-1p4", - "sdkconfig_append": [ - "CONFIG_ESP_S3_LCD_EV_Board_1p4=y" - ] - }, - { - "name": "esp-s3-lcd-ev-board-1p5", - "sdkconfig_append": [ - "CONFIG_ESP_S3_LCD_EV_Board_1p5=y" - ] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp-s3-lcd-ev-board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp-s3-lcd-ev-board.cc deleted file mode 100644 index 72b61ec0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp-s3-lcd-ev-board.cc +++ /dev/null @@ -1,240 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "pin_config.h" -#include "esp32_camera.h" - -#include "config.h" - -#include -#include -#include "esp_lcd_gc9503.h" -#include -#include -#include - -#include "esp_io_expander_tca9554.h" - -#define TAG "ESP_S3_LCD_EV_Board" - -class ESP_S3_LCD_EV_Board : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - Esp32Camera* camera_; - - //add support ev board lcd - esp_io_expander_handle_t expander = NULL; - - void InitializeRGB_GC9503V_Display() { - ESP_LOGI(TAG, "Init GC9503V"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - - //add support ev board lcd - gpio_config_t io_conf = { - .pin_bit_mask = BIT64(GC9503V_PIN_NUM_VSYNC), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_ENABLE, - }; - - gpio_config(&io_conf); - gpio_set_level(GC9503V_PIN_NUM_VSYNC, 1); - - ESP_LOGI(TAG, "Install 3-wire SPI panel IO"); - spi_line_config_t line_config = { - .cs_io_type = IO_TYPE_EXPANDER, - .cs_expander_pin = GC9503V_LCD_IO_SPI_CS_1, - .scl_io_type = IO_TYPE_EXPANDER, - .scl_expander_pin = GC9503V_LCD_IO_SPI_SCL_1, - .sda_io_type = IO_TYPE_EXPANDER, - .sda_expander_pin = GC9503V_LCD_IO_SPI_SDO_1, - .io_expander = expander, - }; - - esp_lcd_panel_io_3wire_spi_config_t io_config = GC9503_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0); - int espok = esp_lcd_new_panel_io_3wire_spi(&io_config, &panel_io); - ESP_LOGI(TAG, "Install 3-wire SPI panel IO:%d",espok); - - ESP_LOGI(TAG, "Install RGB LCD panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_rgb_panel_config_t rgb_config = { - .clk_src = LCD_CLK_SRC_PLL160M, - //.timings = GC9503_376_960_PANEL_60HZ_RGB_TIMING(), - //add support ev board - .timings = GC9503_480_480_PANEL_60HZ_RGB_TIMING(), - .data_width = 16, // RGB565 in parallel mode, thus 16bit in width - .bits_per_pixel = 16, - .num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS, - .bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT, - .dma_burst_size = 64, - .hsync_gpio_num = GC9503V_PIN_NUM_HSYNC, - .vsync_gpio_num = GC9503V_PIN_NUM_VSYNC, - .de_gpio_num = GC9503V_PIN_NUM_DE, - .pclk_gpio_num = GC9503V_PIN_NUM_PCLK, - .disp_gpio_num = GC9503V_PIN_NUM_DISP_EN, - .data_gpio_nums = { - GC9503V_PIN_NUM_DATA0, - GC9503V_PIN_NUM_DATA1, - GC9503V_PIN_NUM_DATA2, - GC9503V_PIN_NUM_DATA3, - GC9503V_PIN_NUM_DATA4, - GC9503V_PIN_NUM_DATA5, - GC9503V_PIN_NUM_DATA6, - GC9503V_PIN_NUM_DATA7, - GC9503V_PIN_NUM_DATA8, - GC9503V_PIN_NUM_DATA9, - GC9503V_PIN_NUM_DATA10, - GC9503V_PIN_NUM_DATA11, - GC9503V_PIN_NUM_DATA12, - GC9503V_PIN_NUM_DATA13, - GC9503V_PIN_NUM_DATA14, - GC9503V_PIN_NUM_DATA15, - }, - .flags= { - .fb_in_psram = true, // allocate frame buffer in PSRAM - } - }; - - ESP_LOGI(TAG, "Initialize RGB LCD panel"); - - gc9503_vendor_config_t vendor_config = { - .rgb_config = &rgb_config, - .flags = { - .mirror_by_cmd = 0, - .auto_del_panel_io = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = -1, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - // .bits_per_pixel = 16, - //add surpport ev board - .bits_per_pixel = 18, - .vendor_config = &vendor_config, - }; - (esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle)); - (esp_lcd_panel_reset(panel_handle)); - (esp_lcd_panel_init(panel_handle)); - - display_ = new RgbLcdDisplay(panel_io, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - //add support ev board lcd amp - //初始化扩展io口 - esp_io_expander_new_i2c_tca9554(codec_i2c_bus_, 0x20, &expander); - /* Setup power amplifier pin, set default to enable */ - esp_io_expander_set_dir(expander, BSP_POWER_AMP_IO, IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(expander, BSP_POWER_AMP_IO, true); - - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - void InitializeCamera() { - esp_video_init_usb_uvc_config_t usb_uvc_config = { - .uvc = { - .uvc_dev_num = 1, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - .usb = { - .init_usb_host_lib = true, - .task_stack = 4096, - .task_priority = 5, - .task_affinity = -1, - }, - }; - - esp_video_init_config_t video_config = { - .usb_uvc = &usb_uvc_config, - }; - - camera_ = new Esp32Camera(video_config); - } -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - -public: - ESP_S3_LCD_EV_Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializeRGB_GC9503V_Display(); -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - InitializeCamera(); -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - codec_i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - true); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - //添加彩灯显示状态,如果亮度太暗可以去更改默认亮度值 DEFAULT_BRIGHTNESS 在led的sigle_led.cc中 - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - -#ifdef CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - virtual Camera* GetCamera() override { - return camera_; - } -#endif // CONFIG_ESP_VIDEO_ENABLE_USB_UVC_VIDEO_DEVICE - -}; - -DECLARE_BOARD(ESP_S3_LCD_EV_Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.c deleted file mode 100644 index 321472f3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include "esp_bit_defs.h" -#include "esp_check.h" -#include "esp_log.h" -#include "esp_io_expander.h" -#include "esp_io_expander_tca9554.h" - -/* I2C communication related */ -#define I2C_TIMEOUT_MS (1000) -#define I2C_CLK_SPEED (400000) - -#define IO_COUNT (8) - -/* Register address */ -#define INPUT_REG_ADDR (0x00) -#define OUTPUT_REG_ADDR (0x01) -#define DIRECTION_REG_ADDR (0x03) - -/* Default register value on power-up */ -#define DIR_REG_DEFAULT_VAL (0xff) -#define OUT_REG_DEFAULT_VAL (0xff) - -/** - * @brief Device Structure Type - * - */ -typedef struct { - esp_io_expander_t base; - i2c_master_dev_handle_t i2c_handle; - struct { - uint8_t direction; - uint8_t output; - } regs; -} esp_io_expander_tca9554_t; - -static char *TAG = "tca9554"; - -static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value); -static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value); -static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value); -static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value); -static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value); -static esp_err_t reset(esp_io_expander_t *handle); -static esp_err_t del(esp_io_expander_t *handle); - -esp_err_t esp_io_expander_new_i2c_tca9554(i2c_master_bus_handle_t i2c_bus, uint32_t dev_addr, esp_io_expander_handle_t *handle_ret) -{ - ESP_RETURN_ON_FALSE(handle_ret != NULL, ESP_ERR_INVALID_ARG, TAG, "Invalid handle_ret"); - - // Allocate memory for driver object - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)calloc(1, sizeof(esp_io_expander_tca9554_t)); - ESP_RETURN_ON_FALSE(tca9554 != NULL, ESP_ERR_NO_MEM, TAG, "Malloc failed"); - - // Add new I2C device - esp_err_t ret = ESP_OK; - const i2c_device_config_t i2c_dev_cfg = { - .device_address = dev_addr, - .scl_speed_hz = I2C_CLK_SPEED, - }; - ESP_GOTO_ON_ERROR(i2c_master_bus_add_device(i2c_bus, &i2c_dev_cfg, &tca9554->i2c_handle), err, TAG, "Add new I2C device failed"); - - tca9554->base.config.io_count = IO_COUNT; - tca9554->base.config.flags.dir_out_bit_zero = 1; - tca9554->base.read_input_reg = read_input_reg; - tca9554->base.write_output_reg = write_output_reg; - tca9554->base.read_output_reg = read_output_reg; - tca9554->base.write_direction_reg = write_direction_reg; - tca9554->base.read_direction_reg = read_direction_reg; - tca9554->base.del = del; - tca9554->base.reset = reset; - - /* Reset configuration and register status */ - ESP_GOTO_ON_ERROR(reset(&tca9554->base), err, TAG, "Reset failed"); - - *handle_ret = &tca9554->base; - return ESP_OK; -err: - free(tca9554); - return ret; -} - -static esp_err_t read_input_reg(esp_io_expander_handle_t handle, uint32_t *value) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - - uint8_t temp = 0; - ESP_RETURN_ON_ERROR(i2c_master_transmit_receive(tca9554->i2c_handle, (uint8_t[]) { - INPUT_REG_ADDR - }, 1, &temp, sizeof(temp), I2C_TIMEOUT_MS), TAG, "Read input reg failed"); - *value = temp; - return ESP_OK; -} - -static esp_err_t write_output_reg(esp_io_expander_handle_t handle, uint32_t value) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - value &= 0xff; - - uint8_t data[] = {OUTPUT_REG_ADDR, value}; - ESP_RETURN_ON_ERROR(i2c_master_transmit(tca9554->i2c_handle, data, sizeof(data), I2C_TIMEOUT_MS), TAG, "Write output reg failed"); - tca9554->regs.output = value; - return ESP_OK; -} - -static esp_err_t read_output_reg(esp_io_expander_handle_t handle, uint32_t *value) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - - *value = tca9554->regs.output; - return ESP_OK; -} - -static esp_err_t write_direction_reg(esp_io_expander_handle_t handle, uint32_t value) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - value &= 0xff; - - uint8_t data[] = {DIRECTION_REG_ADDR, value}; - ESP_RETURN_ON_ERROR(i2c_master_transmit(tca9554->i2c_handle, data, sizeof(data), I2C_TIMEOUT_MS), TAG, "Write direction reg failed"); - tca9554->regs.direction = value; - return ESP_OK; -} - -static esp_err_t read_direction_reg(esp_io_expander_handle_t handle, uint32_t *value) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - - *value = tca9554->regs.direction; - return ESP_OK; -} - -static esp_err_t reset(esp_io_expander_t *handle) -{ - ESP_RETURN_ON_ERROR(write_direction_reg(handle, DIR_REG_DEFAULT_VAL), TAG, "Write dir reg failed"); - ESP_RETURN_ON_ERROR(write_output_reg(handle, OUT_REG_DEFAULT_VAL), TAG, "Write output reg failed"); - return ESP_OK; -} - -static esp_err_t del(esp_io_expander_t *handle) -{ - esp_io_expander_tca9554_t *tca9554 = (esp_io_expander_tca9554_t *)__containerof(handle, esp_io_expander_tca9554_t, base); - - ESP_RETURN_ON_ERROR(i2c_master_bus_rm_device(tca9554->i2c_handle), TAG, "Remove I2C device failed"); - free(tca9554); - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.h deleted file mode 100644 index 192107ce..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_io_expander_tca9554.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief ESP IO expander: TCA9554 - */ - -#pragma once - -#include -#include "esp_err.h" -#include "driver/i2c_master.h" -#include "esp_io_expander.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Create a TCA9554(A) IO expander object - * - * @param[in] i2c_bus I2C bus handle. Obtained from `i2c_new_master_bus()` - * @param[in] dev_addr I2C device address of chip. Can be `ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_XXX` or `ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_XXX`. - * @param[out] handle_ret Handle to created IO expander object - * - * @return - * - ESP_OK: Success, otherwise returns ESP_ERR_xxx - */ -esp_err_t esp_io_expander_new_i2c_tca9554(i2c_master_bus_handle_t i2c_bus, uint32_t dev_addr, esp_io_expander_handle_t *handle_ret); - -/** - * @brief I2C address of the TCA9554 - * - * The 8-bit address format is as follows: - * - * (Slave Address) - * ┌─────────────────┷─────────────────┐ - * ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐ - * | 0 | 1 | 0 | 0 | A2 | A1 | A0 | R/W | - * └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘ - * └────────┯────────┘ └─────┯──────┘ - * (Fixed) (Hareware Selectable) - * - * And the 7-bit slave address is the most important data for users. - * For example, if a chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0100000b(0x20). - * Then users can use `ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000` to init it. - */ -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 (0x20) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_001 (0x21) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_010 (0x22) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_011 (0x23) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_100 (0x24) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_101 (0x25) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_110 (0x26) -#define ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_111 (0x27) - - -/** - * @brief I2C address of the TCA9554A - * - * The 8-bit address format is as follows: - * - * (Slave Address) - * ┌─────────────────┷─────────────────┐ - * ┌─────┐─────┐─────┐─────┐─────┐─────┐─────┐─────┐ - * | 0 | 1 | 1 | 1 | A2 | A1 | A0 | R/W | - * └─────┘─────┘─────┘─────┘─────┘─────┘─────┘─────┘ - * └────────┯────────┘ └─────┯──────┘ - * (Fixed) (Hareware Selectable) - * - * And the 7-bit slave address is the most important data for users. - * For example, if a chip's A0,A1,A2 are connected to GND, it's 7-bit slave address is 0111000b(0x38). - * Then users can use `ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_000` to init it. - */ -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_000 (0x38) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_001 (0x39) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_010 (0x3A) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_011 (0x3B) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_100 (0x3C) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_101 (0x3D) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_110 (0x3E) -#define ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_111 (0x3F) - -#ifdef __cplusplus -} -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.c deleted file mode 100644 index 4db550e2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_lcd_gc9503.h" - -#define GC9503_CMD_MADCTL (0xB1) // Memory data access control -#define GC9503_CMD_MADCTL_DEFAULT (0x10) // Default value of Memory data access control -#define GC9503_CMD_SS_BIT (1 << 0) // Source driver scan direction, 0: top to bottom, 1: bottom to top -#define GC9503_CMD_GS_BIT (1 << 1) // Gate driver scan direction, 0: left to right, 1: right to left -#define GC9503_CMD_BGR_BIT (1 << 5) // RGB/BGR order, 0: RGB, 1: BGR - -typedef struct -{ - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // Save current value of GC9503_CMD_MADCTL register - uint8_t colmod_val; // Save current value of LCD_CMD_COLMOD register - const gc9503_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - struct - { - unsigned int mirror_by_cmd : 1; - unsigned int auto_del_panel_io : 1; - unsigned int display_on_off_use_cmd : 1; - unsigned int reset_level : 1; - } flags; - // To save the original functions of RGB panel - esp_err_t (*init)(esp_lcd_panel_t *panel); - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*reset)(esp_lcd_panel_t *panel); - esp_err_t (*mirror)(esp_lcd_panel_t *panel, bool x_axis, bool y_axis); - esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off); -} gc9503_panel_t; - -static const char *TAG = "gc9503"; - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503); - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool off); - -esp_err_t esp_lcd_new_panel_gc9503(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - gc9503_vendor_config_t *vendor_config = (gc9503_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->rgb_config, ESP_ERR_INVALID_ARG, TAG, "`verndor_config` and `rgb_config` are necessary"); - ESP_RETURN_ON_FALSE(!vendor_config->flags.auto_del_panel_io || !vendor_config->flags.mirror_by_cmd, - ESP_ERR_INVALID_ARG, TAG, "`mirror_by_cmd` and `auto_del_panel_io` cannot work together"); - - esp_err_t ret = ESP_OK; - gpio_config_t io_conf = {0}; - - gc9503_panel_t *gc9503 = (gc9503_panel_t *)calloc(1, sizeof(gc9503_panel_t)); - ESP_RETURN_ON_FALSE(gc9503, ESP_ERR_NO_MEM, TAG, "no mem for gc9503 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - gc9503->madctl_val = GC9503_CMD_MADCTL_DEFAULT; - switch (panel_dev_config->rgb_ele_order) - { - case LCD_RGB_ELEMENT_ORDER_RGB: - gc9503->madctl_val &= ~GC9503_CMD_BGR_BIT; - break; - case LCD_RGB_ELEMENT_ORDER_BGR: - gc9503->madctl_val |= GC9503_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order"); - break; - } - - gc9503->colmod_val = 0; - switch (panel_dev_config->bits_per_pixel) - { - case 16: // RGB565 - gc9503->colmod_val = 0x50; - break; - case 18: // RGB666 - gc9503->colmod_val = 0x60; - break; - case 24: // RGB888 - gc9503->colmod_val = 0x70; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - gc9503->io = io; - gc9503->init_cmds = vendor_config->init_cmds; - gc9503->init_cmds_size = vendor_config->init_cmds_size; - gc9503->reset_gpio_num = panel_dev_config->reset_gpio_num; - gc9503->flags.reset_level = panel_dev_config->flags.reset_active_high; - gc9503->flags.auto_del_panel_io = vendor_config->flags.auto_del_panel_io; - gc9503->flags.mirror_by_cmd = vendor_config->flags.mirror_by_cmd; - gc9503->flags.display_on_off_use_cmd = (vendor_config->rgb_config->disp_gpio_num >= 0) ? 0 : 1; - - if (gc9503->flags.auto_del_panel_io) - { - if (gc9503->reset_gpio_num >= 0) - { // Perform hardware reset - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - } - else - { // Perform software reset - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), err, TAG, "send command failed"); - } - vTaskDelay(pdMS_TO_TICKS(120)); - - /** - * In order to enable the 3-wire SPI interface pins (such as SDA and SCK) to share other pins of the RGB interface - * (such as HSYNC) and save GPIOs, we need to send LCD initialization commands via the 3-wire SPI interface before - * `esp_lcd_new_rgb_panel()` is called. - */ - ESP_GOTO_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), err, TAG, "send init commands failed"); - // After sending the initialization commands, the 3-wire SPI interface can be deleted - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_del(io), err, TAG, "delete panel IO failed"); - gc9503->io = NULL; - ESP_LOGD(TAG, "delete panel IO"); - } - - // Create RGB panel - ESP_GOTO_ON_ERROR(esp_lcd_new_rgb_panel(vendor_config->rgb_config, ret_panel), err, TAG, "create RGB panel failed"); - ESP_LOGD(TAG, "new RGB panel @%p", ret_panel); - - // Save the original functions of RGB panel - gc9503->init = (*ret_panel)->init; - gc9503->del = (*ret_panel)->del; - gc9503->reset = (*ret_panel)->reset; - gc9503->mirror = (*ret_panel)->mirror; - gc9503->disp_on_off = (*ret_panel)->disp_on_off; - // Overwrite the functions of RGB panel - (*ret_panel)->init = panel_gc9503_init; - (*ret_panel)->del = panel_gc9503_del; - (*ret_panel)->reset = panel_gc9503_reset; - (*ret_panel)->mirror = panel_gc9503_mirror; - (*ret_panel)->disp_on_off = panel_gc9503_disp_on_off; - (*ret_panel)->user_data = gc9503; - ESP_LOGD(TAG, "new gc9503 panel @%p", gc9503); - - // ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9503_VER_MAJOR, ESP_LCD_GC9503_VER_MINOR, - // ESP_LCD_GC9503_VER_PATCH); - return ESP_OK; - -err: - if (gc9503) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(gc9503); - } - return ret; -} - -// *INDENT-OFF* -// static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { -// // {cmd, { data }, data_size, delay_ms} -// {0x11, (uint8_t []){0x00}, 0, 120}, - -// {0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0}, -// {0xf6, (uint8_t []){0x5a, 0x87}, 2, 0}, -// {0xc1, (uint8_t []){0x3f}, 1, 0}, -// {0xc2, (uint8_t []){0x0e}, 1, 0}, -// {0xc6, (uint8_t []){0xf8}, 1, 0}, -// {0xc9, (uint8_t []){0x10}, 1, 0}, -// {0xcd, (uint8_t []){0x25}, 1, 0}, -// {0xf8, (uint8_t []){0x8a}, 1, 0}, -// {0xac, (uint8_t []){0x45}, 1, 0}, -// {0xa0, (uint8_t []){0xdd}, 1, 0}, -// {0xa7, (uint8_t []){0x47}, 1, 0}, -// {0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0}, -// {0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0}, -// {0xa3, (uint8_t []){0xee}, 1, 0}, -// {0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0}, -// {0x71, (uint8_t []){0x48}, 1, 0}, -// {0x72, (uint8_t []){0x48}, 1, 0}, -// {0x73, (uint8_t []){0x00, 0x44}, 2, 0}, -// {0x97, (uint8_t []){0xee}, 1, 0}, -// {0x83, (uint8_t []){0x93}, 1, 0}, -// {0x9a, (uint8_t []){0x72}, 1, 0}, -// {0x9b, (uint8_t []){0x5a}, 1, 0}, -// {0x82, (uint8_t []){0x2c, 0x2c}, 2, 0}, -// {0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, -// 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0}, -// {0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0}, -// {0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0}, -// {0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0}, -// {0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, -// {0x6b, (uint8_t []){0x07}, 1, 0}, -// {0x7a, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0x7b, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0x11, (uint8_t []){0x00}, 0, 120}, -// {0x29, (uint8_t []){0x00}, 0, 20}, -// }; -static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { - // {0x11, (uint8_t[]){}, 0, 20}, - - {0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0}, - {0xf6, (uint8_t []){0x5a, 0x87}, 2, 0}, - {0xc1, (uint8_t []){0x3f}, 1, 0}, - {0xc2, (uint8_t []){0x0e}, 1, 0}, - {0xc6, (uint8_t []){0xf8}, 1, 0}, - {0xc9, (uint8_t []){0x10}, 1, 0}, - {0xcd, (uint8_t []){0x25}, 1, 0}, - {0xf8, (uint8_t []){0x8a}, 1, 0}, - {0xac, (uint8_t []){0x45}, 1, 0}, - {0xa0, (uint8_t []){0xdd}, 1, 0}, - {0xa7, (uint8_t []){0x47}, 1, 0}, - {0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0}, - {0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0}, - {0xa3, (uint8_t []){0xee}, 1, 0}, - {0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0}, - {0x71, (uint8_t []){0x48}, 1, 0}, - {0x72, (uint8_t []){0x48}, 1, 0}, - {0x73, (uint8_t []){0x00, 0x44}, 2, 0}, - {0x97, (uint8_t []){0xee}, 1, 0}, - {0x83, (uint8_t []){0x93}, 1, 0}, - {0x9a, (uint8_t []){0x72}, 1, 0}, - {0x9b, (uint8_t []){0x5a}, 1, 0}, - {0x82, (uint8_t []){0x2c, 0x2c}, 2, 0}, - {0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, - 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0}, - {0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, - {0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0}, - {0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0}, - {0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0}, - {0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, - {0x6b, (uint8_t []){0x07}, 1, 0}, - {0x7a, (uint8_t []){0x08, 0x13}, 2, 0}, - {0x7b, (uint8_t []){0x08, 0x13}, 2, 0}, - {0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, - 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, - 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, - 0xff}, 52, 0}, - {0x11, (uint8_t []){0x00}, 0, 120}, - {0x29, (uint8_t []){0x00}, 0, 20}, - - }; - -// *INDENT-OFF* - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503) -{ - esp_lcd_panel_io_handle_t io = gc9503->io; - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){ - gc9503->colmod_val, - }, - 1), - TAG, "send command failed"); - ; - - // Vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - const gc9503_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - if (gc9503->init_cmds) - { - init_cmds = gc9503->init_cmds; - init_cmds_size = gc9503->init_cmds_size; - } - else - { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(gc9503_lcd_init_cmd_t); - } - - bool is_cmd_overwritten = false; - for (int i = 0; i < init_cmds_size; i++) - { - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd) - { - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - gc9503->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - gc9503->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten) - { - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), - TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (!gc9503->flags.auto_del_panel_io) - { - ESP_RETURN_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), TAG, "send init commands failed"); - } - // Init RGB panel - ESP_RETURN_ON_ERROR(gc9503->init(panel), TAG, "init RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (gc9503->reset_gpio_num >= 0) - { - gpio_reset_pin(gc9503->reset_gpio_num); - } - // Delete RGB panel - gc9503->del(panel); - free(gc9503); - ESP_LOGD(TAG, "del gc9503 panel @%p", gc9503); - return ESP_OK; -} - -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - // Perform hardware reset - if (gc9503->reset_gpio_num >= 0) - { - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(120)); - } - else if (io) - { // Perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(120)); - } - // Reset RGB panel - ESP_RETURN_ON_ERROR(gc9503->reset(panel), TAG, "reset RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - if (gc9503->flags.mirror_by_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control mirror through LCD command - if (mirror_x) - { - gc9503->madctl_val |= GC9503_CMD_GS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_GS_BIT; - } - if (mirror_y) - { - gc9503->madctl_val |= GC9503_CMD_SS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_SS_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - } - else - { - // Control mirror through RGB panel - ESP_RETURN_ON_ERROR(gc9503->mirror(panel, mirror_x, mirror_y), TAG, "RGB panel mirror failed"); - } - return ESP_OK; -} - -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - int command = 0; - - if (gc9503->flags.display_on_off_use_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control display on/off through LCD command - if (on_off) - { - command = LCD_CMD_DISPON; - } - else - { - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - } - else - { - // Control display on/off through display control signal - ESP_RETURN_ON_ERROR(gc9503->disp_on_off(panel, on_off), TAG, "RGB panel disp_on_off failed"); - } - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.h deleted file mode 100644 index 8feafd19..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-s3-lcd-ev-board/esp_lcd_gc9503.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief ESP LCD: GC9503 - */ - -#pragma once - -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* - - 开发版文档 - - | - - 传感器 & ShuttleBoard 文档 - - - -ESP-SensairShuttle 是乐鑫携手 Bosch Sensortec 面向**动作感知**与**大模型人机交互**场景联合推出的开发板。 - -ESP-SensairShuttle 主控采用乐鑫 ESP32-C5-WROOM-1-N16R8 模组,具有 2.4 & 5 GHz 双频 Wi-Fi 6 (802.11ax)、Bluetooth® 5 (LE)、Zigbee 及 Thread (802.15.4) 无线通信能力。 - -## 传感器 & _ShuttleBoard_ 子板支持 - -即将推出,敬请期待。 - -## 配置、编译命令 - -由于 ESP-SensairShuttle 需要配置较多的 sdkconfig 选项,推荐使用编译脚本编译。 - -**编译** - -```bash -python ./scripts/release.py esp-sensairshuttle -``` - -如需手动编译,请参考 `main/boards/esp-sensairshuttle/config.json` 修改 menuconfig 对应选项。 - -**烧录** - -```bash -idf.py flash -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.cc deleted file mode 100644 index e48792b1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.cc +++ /dev/null @@ -1,249 +0,0 @@ -#include "adc_pdm_audio_codec.h" - -#include -#include -#include -#include -#include -#include "adc_mic.h" -#include "driver/i2s_pdm.h" -#include "soc/gpio_sig_map.h" -#include "soc/io_mux_reg.h" -#include "hal/rtc_io_hal.h" -#include "hal/gpio_ll.h" -#include "settings.h" -#include "config.h" - -static const char TAG[] = "AdcPdmAudioCodec"; - -#define BSP_I2S_GPIO_CFG(_dout) \ - { \ - .clk = GPIO_NUM_NC, \ - .dout = _dout, \ - .invert_flags = { \ - .clk_inv = false, \ - }, \ - } - -/** - * @brief Mono Duplex I2S configuration structure - * - * This configuration is used by default in bsp_audio_init() - */ -#define BSP_I2S_DUPLEX_MONO_CFG(_sample_rate, _dout) \ - { \ - .clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG(_sample_rate), \ - .slot_cfg = I2S_PDM_TX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), \ - .gpio_cfg = BSP_I2S_GPIO_CFG(_dout), \ - } - -AdcPdmAudioCodec::AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate, - uint32_t adc_mic_channel, gpio_num_t pdm_speak_p,gpio_num_t pdm_speak_n, gpio_num_t pa_ctl) { - - input_reference_ = false; - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - uint8_t adc_channel[1] = {0}; - adc_channel[0] = adc_mic_channel; - - audio_codec_adc_cfg_t cfg = { - .handle = NULL, - .max_store_buf_size = 1024 * 2, - .conv_frame_size = 1024, - .unit_id = ADC_UNIT_1, - .adc_channel_list = adc_channel, - .adc_channel_num = sizeof(adc_channel) / sizeof(adc_channel[0]), - .sample_rate_hz = (uint32_t)input_sample_rate, - }; - const audio_codec_data_if_t *adc_if = audio_codec_new_adc_data(&cfg); - - esp_codec_dev_cfg_t codec_dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_IN, - .data_if = adc_if, - }; - input_dev_ = esp_codec_dev_new(&codec_dev_cfg); - if (!input_dev_) { - ESP_LOGE(TAG, "Failed to create codec device"); - return; - } - - i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, NULL)); - - i2s_pdm_tx_config_t pdm_cfg_default = BSP_I2S_DUPLEX_MONO_CFG((uint32_t)output_sample_rate, pdm_speak_p); - pdm_cfg_default.clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; - pdm_cfg_default.slot_cfg.sd_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.hp_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.lp_scale = I2S_PDM_SIG_SCALING_MUL_4; - pdm_cfg_default.slot_cfg.sinc_scale = I2S_PDM_SIG_SCALING_MUL_4; - const i2s_pdm_tx_config_t *p_i2s_cfg = &pdm_cfg_default; - - ESP_ERROR_CHECK(i2s_channel_init_pdm_tx_mode(tx_handle_, p_i2s_cfg)); - - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = NULL, - .tx_handle = tx_handle_, - }; - - const audio_codec_data_if_t *i2s_data_if = audio_codec_new_i2s_data(&i2s_cfg); - - codec_dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_OUT; - codec_dev_cfg.codec_if = NULL; - codec_dev_cfg.data_if = i2s_data_if; - output_dev_ = esp_codec_dev_new(&codec_dev_cfg); - - output_volume_ = 100; - if(pa_ctl != GPIO_NUM_NC) { - pa_ctrl_pin_ = pa_ctl; - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << pa_ctrl_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - } - gpio_set_drive_capability(pdm_speak_p, GPIO_DRIVE_CAP_0); - - if(pdm_speak_n != GPIO_NUM_NC){ - PIN_FUNC_SELECT(IO_MUX_GPIO10_REG, PIN_FUNC_GPIO); - gpio_set_direction(pdm_speak_n, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(pdm_speak_n, I2SO_SD_OUT_IDX, 1, 0); //反转输出 SD OUT 信号 - gpio_set_drive_capability(pdm_speak_n, GPIO_DRIVE_CAP_0); - } - - // 初始化输出定时器 - esp_timer_create_args_t output_timer_args = { - .callback = &AdcPdmAudioCodec::OutputTimerCallback, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "output_timer" - }; - ESP_ERROR_CHECK(esp_timer_create(&output_timer_args, &output_timer_)); - - ESP_LOGI(TAG, "AdcPdmAudioCodec initialized"); -} - -AdcPdmAudioCodec::~AdcPdmAudioCodec() { - // 删除定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - esp_timer_delete(output_timer_); - output_timer_ = nullptr; - } - - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); -} - -void AdcPdmAudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void AdcPdmAudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)input_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void AdcPdmAudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - - // 强制按板卡配置重配PDM TX时钟,覆盖第三方库在set_fmt中的默认up_sample_fs - // 若通道已启用,先禁用再重配,最后再启用 - ESP_ERROR_CHECK_WITHOUT_ABORT(i2s_channel_disable(tx_handle_)); - i2s_pdm_tx_clk_config_t clk_cfg = I2S_PDM_TX_CLK_DEFAULT_CONFIG((uint32_t)output_sample_rate_); - clk_cfg.up_sample_fs = AUDIO_PDM_UPSAMPLE_FS; - ESP_ERROR_CHECK(i2s_channel_reconfig_pdm_tx_clock(tx_handle_, &clk_cfg)); - ESP_ERROR_CHECK(i2s_channel_enable(tx_handle_)); - if(pa_ctrl_pin_ != GPIO_NUM_NC){ - gpio_set_level(pa_ctrl_pin_, 1); - } - // 启用输出时启动定时器 - if (output_timer_) { - esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); - } - - } else { - // 禁用输出时停止定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - } - if(pa_ctrl_pin_ != GPIO_NUM_NC){ - gpio_set_level(pa_ctrl_pin_, 0); - } - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int AdcPdmAudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} -int AdcPdmAudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - // 重置输出定时器 - if (output_timer_) { - esp_timer_stop(output_timer_); - esp_timer_start_once(output_timer_, TIMER_TIMEOUT_US); - } - } - return samples; -} - -void AdcPdmAudioCodec::Start() { - Settings settings("audio", false); - output_volume_ = settings.GetInt("output_volume", output_volume_); - if (output_volume_ <= 0) { - ESP_LOGW(TAG, "Output volume value (%d) is too small, setting to default (10)", output_volume_); - output_volume_ = 10; - } - - EnableInput(true); - EnableOutput(true); - ESP_LOGI(TAG, "Audio codec started"); -} - -// 定时器回调函数实现 -void AdcPdmAudioCodec::OutputTimerCallback(void* arg) { - AdcPdmAudioCodec* codec = static_cast(arg); - if (codec && codec->output_enabled_) { - codec->EnableOutput(false); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.h deleted file mode 100644 index 8c9e8363..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/adc_pdm_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_H -#define _BOX_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include -#include - -class AdcPdmAudioCodec : public AudioCodec { -private: - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_ctrl_pin_ = GPIO_NUM_NC; - - // 定时器相关成员变量 - esp_timer_handle_t output_timer_ = nullptr; - static constexpr uint64_t TIMER_TIMEOUT_US = 120000; // 120ms = 120000us - - // 定时器回调函数 - static void OutputTimerCallback(void* arg); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - AdcPdmAudioCodec(int input_sample_rate, int output_sample_rate, - uint32_t adc_mic_channel, gpio_num_t pdm_speak_p, gpio_num_t pdm_speak_n, gpio_num_t pa_ctl); - virtual ~AdcPdmAudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; - void Start(); -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.h deleted file mode 100644 index 84d066fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_PDM_UPSAMPLE_FS 480 - -#define AUDIO_ADC_MIC_CHANNEL 5 -#define AUDIO_PDM_SPEAK_P_GPIO GPIO_NUM_7 -#define AUDIO_PDM_SPEAK_N_GPIO GPIO_NUM_8 -#define AUDIO_PA_CTL_GPIO GPIO_NUM_1 - -#define BOOT_BUTTON_GPIO GPIO_NUM_28 -#define DISPLAY_MOSI_PIN GPIO_NUM_23 -#define DISPLAY_CLK_PIN GPIO_NUM_24 -#define DISPLAY_DC_PIN GPIO_NUM_26 -#define DISPLAY_RST_PIN GPIO_NUM_NC -#define DISPLAY_CS_PIN GPIO_NUM_25 - -#define LCD_TP_SCL GPIO_NUM_3 -#define LCD_TP_SDA GPIO_NUM_2 - -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 284 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 36 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.json deleted file mode 100644 index d0fe643b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/config.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "target": "esp32c5", - "builds": [ - { - "name": "esp-sensairshuttle", - "sdkconfig_append": [ - "CONFIG_IDF_TARGET=\"esp32c5\"", - "CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=6", - "CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=n", - "CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=n", - "CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=0", - "CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=n", - "CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=768", - "CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=2048", - "CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y", - "CONFIG_SPIRAM=y", - "CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=3072", - "CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y", - "CONFIG_LWIP_IPV6=n", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_SR_WN_WN9S_HIESP=y", - "CONFIG_USE_EMOTE_MESSAGE_STYLE=y", - "CONFIG_FLASH_CUSTOM_ASSETS=y", - "CONFIG_CUSTOM_ASSETS_FILE=\"https://dl.espressif.com/AE/wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-echoear.bin\"" - ] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/esp-sensairshuttle.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/esp-sensairshuttle.cc deleted file mode 100644 index 4d3d88fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sensairshuttle/esp-sensairshuttle.cc +++ /dev/null @@ -1,315 +0,0 @@ -#include "wifi_board.h" -#include "adc_pdm_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include -#include -#include -#include -#include -#include - -#include "display/lcd_display.h" -#include -#include -#include -#include "esp_lcd_ili9341.h" - -#include "display/emote_display.h" - -#include "assets/lang_config.h" -#include "anim_player.h" -#include "led_strip.h" -#include "driver/rmt_tx.h" -#include "i2c_device.h" - -#include -#include - -#include "sdkconfig.h" - -constexpr char TAG[] = "ESP_SensairShuttle"; - -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - // {cmd, { data }, data_size, delay_ms} - {0x11, NULL, 0, 120}, // Sleep Out - {0x36, (uint8_t []){0x00}, 1, 0}, // Memory Data Access Control - {0x3A, (uint8_t []){0x05}, 1, 0}, // Interface Pixel Format (16-bit) - {0xB2, (uint8_t []){0x0C, 0x0C, 0x00, 0x33, 0x33}, 5, 0}, // Porch Setting - {0xB7, (uint8_t []){0x05}, 1, 0}, // Gate Control - {0xBB, (uint8_t []){0x21}, 1, 0}, // VCOM Setting - {0xC0, (uint8_t []){0x2C}, 1, 0}, // LCM Control - {0xC2, (uint8_t []){0x01}, 1, 0}, // VDV and VRH Command Enable - {0xC3, (uint8_t []){0x15}, 1, 0}, // VRH Set - {0xC6, (uint8_t []){0x0F}, 1, 0}, // Frame Rate Control - {0xD0, (uint8_t []){0xA7}, 1, 0}, // Power Control 1 - {0xD0, (uint8_t []){0xA4, 0xA1}, 2, 0}, // Power Control 1 - {0xD6, (uint8_t []){0xA1}, 1, 0}, // Gate output GND in sleep mode - { - 0xE0, (uint8_t []) - { - 0xF0, 0x05, 0x0E, 0x08, 0x0A, 0x17, 0x39, 0x54, - 0x4E, 0x37, 0x12, 0x12, 0x31, 0x37 - }, 14, 0 - }, // Positive Gamma Control - { - 0xE1, (uint8_t []) - { - 0xF0, 0x10, 0x14, 0x0D, 0x0B, 0x05, 0x39, 0x44, - 0x4D, 0x38, 0x14, 0x14, 0x2E, 0x35 - }, 14, 0 - }, // Negative Gamma Control - {0xE4, (uint8_t []){0x23, 0x00, 0x00}, 3, 0}, // Gate position control - {0x21, NULL, 0, 0}, // Display Inversion On - {0x29, NULL, 0, 0}, // Display On - {0x2C, NULL, 0, 0}, // Memory Write -}; - -class Cst816d : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - enum TouchEvent { - TOUCH_NONE, - TOUCH_PRESS, - TOUCH_RELEASE, - TOUCH_HOLD - }; - - Cst816d(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) - { - read_buffer_ = new uint8_t[6]; - was_touched_ = false; - press_count_ = 0; - } - - ~Cst816d() - { - delete[] read_buffer_; - } - - void UpdateTouchPoint() - { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t &GetTouchPoint() - { - return tp_; - } - - TouchEvent CheckTouchEvent() - { - bool is_touched = (tp_.num > 0); - TouchEvent event = TOUCH_NONE; - - if (is_touched && !was_touched_) { - // Press event (transition from not touched to touched) - press_count_++; - event = TOUCH_PRESS; - ESP_LOGI(TAG, "TOUCH PRESS - count: %d, x: %d, y: %d", press_count_, tp_.x, tp_.y); - } else if (!is_touched && was_touched_) { - // Release event (transition from touched to not touched) - event = TOUCH_RELEASE; - ESP_LOGI(TAG, "TOUCH RELEASE - total presses: %d", press_count_); - } else if (is_touched && was_touched_) { - // Continuous touch (hold) - event = TOUCH_HOLD; - ESP_LOGD(TAG, "TOUCH HOLD - x: %d, y: %d", tp_.x, tp_.y); - } - - // Update previous state - was_touched_ = is_touched; - return event; - } - - int GetPressCount() const - { - return press_count_; - } - - void ResetPressCount() - { - press_count_ = 0; - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; - - // Touch state tracking - bool was_touched_; - int press_count_; -}; - -class EspSensairShuttle : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst816d* cst816d_; - Display* display_ = nullptr; - Button boot_button_; - - void InitializeI2c() - { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = LCD_TP_SDA, - .scl_io_num = LCD_TP_SCL, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static void touch_event_task(void* arg) - { - Cst816d* touchpad = static_cast(arg); - if (touchpad == nullptr) { - ESP_LOGE(TAG, "Invalid touchpad pointer in touch_event_task"); - vTaskDelete(NULL); - return; - } - - while (true) { - touchpad->UpdateTouchPoint(); - auto touch_event = touchpad->CheckTouchEvent(); - - if (touch_event == Cst816d::TOUCH_RELEASE) { - auto &app = Application::GetInstance(); - auto &board = (EspSensairShuttle &)Board::GetInstance(); - - if (app.GetDeviceState() == kDeviceStateStarting) { - board.EnterWifiConfigMode(); - } else { - app.ToggleChatState(); - } - } - - vTaskDelay(pdMS_TO_TICKS(50)); // Poll every 50ms - } - } - - void InitializeCst816dTouchPad() - { - cst816d_ = new Cst816d(i2c_bus_, 0x15); - xTaskCreate(touch_event_task, "touch_task", 2 * 1024, cst816d_, 5, NULL); - } - - void InitializeButtons() - { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - ESP_LOGI(TAG, "Boot button pressed, enter WiFi configuration mode"); - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSpi() - { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * 10 * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() - { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *) &vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_set_gap(panel, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - ESP_LOGI(TAG, "LCD panel create success, %p", panel); - -#ifdef CONFIG_USE_EMOTE_MESSAGE_STYLE - display_ = new emote::EmoteDisplay(panel, panel_io, DISPLAY_WIDTH, DISPLAY_HEIGHT); -#else - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, 0, 0, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); -#endif - - } - -public: - EspSensairShuttle() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeCst816dTouchPad(); - InitializeButtons(); - InitializeSpi(); - InitializeLcdDisplay(); - } - - virtual AudioCodec* GetAudioCodec() override - { - static AdcPdmAudioCodec audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_ADC_MIC_CHANNEL, - AUDIO_PDM_SPEAK_P_GPIO, - AUDIO_PDM_SPEAK_N_GPIO, - AUDIO_PA_CTL_GPIO); - return &audio_codec; - } - - virtual Display* GetDisplay() override - { - return display_; - } - - Cst816d* GetTouchpad() - { - return cst816d_; - } -}; - -DECLARE_BOARD(EspSensairShuttle); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.h deleted file mode 100644 index 3c6e6f2e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_45 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_41 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_42 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_4 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_5 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_DC_GPIO GPIO_NUM_43 -#define DISPLAY_CS_GPIO GPIO_NUM_44 -#define DISPLAY_CLK_GPIO GPIO_NUM_21 -#define DISPLAY_MOSI_GPIO GPIO_NUM_47 -#define DISPLAY_RST_GPIO GPIO_NUM_NC - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_46 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define UART_ECHO_TXD GPIO_NUM_38 -#define UART_ECHO_RXD GPIO_NUM_48 -#define UART_ECHO_RTS (-1) -#define UART_ECHO_CTS (-1) - -#define MOTOR_SPEED_MAX 100 -#define MOTOR_SPEED_80 80 -#define MOTOR_SPEED_60 60 -#define MOTOR_SPEED_MIN 0 - -#define ECHO_UART_PORT_NUM UART_NUM_1 -#define ECHO_UART_BAUD_RATE (115200) -#define BUF_SIZE (1024) - -typedef enum { - LIGHT_MODE_CHARGING_BREATH = 0, - LIGHT_MODE_POWER_LOW, - LIGHT_MODE_ALWAYS_ON, - LIGHT_MODE_BLINK, - LIGHT_MODE_WHITE_BREATH_SLOW, - LIGHT_MODE_WHITE_BREATH_FAST, - LIGHT_MODE_FLOWING, - LIGHT_MODE_SHOW, - LIGHT_MODE_SLEEP, - LIGHT_MODE_MAX -} light_mode_t; - -/* Camera PINs*/ -#define SPARKBOT_CAMERA_XCLK (GPIO_NUM_15) -#define SPARKBOT_CAMERA_PCLK (GPIO_NUM_13) -#define SPARKBOT_CAMERA_VSYNC (GPIO_NUM_6) -#define SPARKBOT_CAMERA_HSYNC (GPIO_NUM_7) -#define SPARKBOT_CAMERA_D0 (GPIO_NUM_11) -#define SPARKBOT_CAMERA_D1 (GPIO_NUM_9) -#define SPARKBOT_CAMERA_D2 (GPIO_NUM_8) -#define SPARKBOT_CAMERA_D3 (GPIO_NUM_10) -#define SPARKBOT_CAMERA_D4 (GPIO_NUM_12) -#define SPARKBOT_CAMERA_D5 (GPIO_NUM_18) -#define SPARKBOT_CAMERA_D6 (GPIO_NUM_17) -#define SPARKBOT_CAMERA_D7 (GPIO_NUM_16) - -#define SPARKBOT_CAMERA_PWDN (GPIO_NUM_NC) -#define SPARKBOT_CAMERA_RESET (GPIO_NUM_NC) -#define SPARKBOT_CAMERA_XCLK (GPIO_NUM_15) -#define SPARKBOT_CAMERA_PCLK (GPIO_NUM_13) -#define SPARKBOT_CAMERA_VSYNC (GPIO_NUM_6) -#define SPARKBOT_CAMERA_HSYNC (GPIO_NUM_7) - -#define SPARKBOT_CAMERA_XCLK_FREQ (16000000) -#define SPARKBOT_LEDC_TIMER (LEDC_TIMER_0) -#define SPARKBOT_LEDC_CHANNEL (LEDC_CHANNEL_0) - -#define SPARKBOT_CAMERA_SIOD (GPIO_NUM_NC) -#define SPARKBOT_CAMERA_SIOC (GPIO_NUM_NC) - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.json deleted file mode 100644 index 0cebab5d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp-sparkbot", - "sdkconfig_append": [ - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_240X240_25FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/esp_sparkbot_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/esp_sparkbot_board.cc deleted file mode 100644 index cef94861..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-sparkbot/esp_sparkbot_board.cc +++ /dev/null @@ -1,302 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "settings.h" - -#include -#include -#include -#include -#include -#include - -#include "esp32_camera.h" - -#define TAG "esp_sparkbot" - -class SparkBotEs8311AudioCodec : public Es8311AudioCodec { -private: - -public: - SparkBotEs8311AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, bool use_mclk = true) - : Es8311AudioCodec(i2c_master_handle, i2c_port, input_sample_rate, output_sample_rate, - mclk, bclk, ws, dout, din,pa_pin, es8311_addr, use_mclk = true) {} - - void EnableOutput(bool enable) override { - if (enable == output_enabled_) { - return; - } - if (enable) { - Es8311AudioCodec::EnableOutput(enable); - } else { - // Nothing todo because the display io and PA io conflict - } - } -}; - -class EspSparkBot : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Display* display_; - Esp32Camera* camera_; - light_mode_t light_mode_ = LIGHT_MODE_ALWAYS_ON; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_GPIO; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_GPIO; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_GPIO; - io_config.dc_gpio_num = DISPLAY_DC_GPIO; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - - // DVP pin configuration - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = SPARKBOT_CAMERA_D0, - [1] = SPARKBOT_CAMERA_D1, - [2] = SPARKBOT_CAMERA_D2, - [3] = SPARKBOT_CAMERA_D3, - [4] = SPARKBOT_CAMERA_D4, - [5] = SPARKBOT_CAMERA_D5, - [6] = SPARKBOT_CAMERA_D6, - [7] = SPARKBOT_CAMERA_D7, - }, - .vsync_io = SPARKBOT_CAMERA_VSYNC, - .de_io = SPARKBOT_CAMERA_HSYNC, - .pclk_io = SPARKBOT_CAMERA_PCLK, - .xclk_io = SPARKBOT_CAMERA_XCLK, - }; - - // 复用 I2C 总线 - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // 不初始化新的 SCCB,使用现有的 I2C 总线 - .i2c_handle = i2c_bus_, // 使用现有的 I2C 总线句柄 - .freq = 100000, // 100kHz - }; - - // DVP configuration - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = SPARKBOT_CAMERA_RESET, - .pwdn_pin = SPARKBOT_CAMERA_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = SPARKBOT_CAMERA_XCLK_FREQ, - }; - - // Main video configuration - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - - Settings settings("sparkbot", false); - // 考虑到部分复刻使用了不可动摄像头的设计,默认启用翻转 - bool camera_flipped = static_cast(settings.GetInt("camera-flipped", 1)); - camera_->SetHMirror(camera_flipped); - camera_->SetVFlip(camera_flipped); - } - - /* - ESP-SparkBot 的底座 - https://gitee.com/esp-friends/esp_sparkbot/tree/master/example/tank/c2_tracked_chassis - */ - void InitializeEchoUart() { - uart_config_t uart_config = { - .baud_rate = ECHO_UART_BAUD_RATE, - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, - .source_clk = UART_SCLK_DEFAULT, - }; - int intr_alloc_flags = 0; - - ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); - ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config)); - ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, UART_ECHO_TXD, UART_ECHO_RXD, UART_ECHO_RTS, UART_ECHO_CTS)); - - SendUartMessage("w2"); - } - - void SendUartMessage(const char * command_str) { - uint8_t len = strlen(command_str); - uart_write_bytes(ECHO_UART_PORT_NUM, command_str, len); - ESP_LOGI(TAG, "Sent command: %s", command_str); - } - - void InitializeTools() { - auto& mcp_server = McpServer::GetInstance(); - // 定义设备的属性 - mcp_server.AddTool("self.chassis.get_light_mode", "获取灯光效果编号", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - if (light_mode_ < 2) { - return 1; - } else { - return light_mode_ - 2; - } - }); - - mcp_server.AddTool("self.chassis.go_forward", "前进", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SendUartMessage("x0.0 y1.0"); - return true; - }); - - mcp_server.AddTool("self.chassis.go_back", "后退", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SendUartMessage("x0.0 y-1.0"); - return true; - }); - - mcp_server.AddTool("self.chassis.turn_left", "向左转", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SendUartMessage("x-1.0 y0.0"); - return true; - }); - - mcp_server.AddTool("self.chassis.turn_right", "向右转", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SendUartMessage("x1.0 y0.0"); - return true; - }); - - mcp_server.AddTool("self.chassis.dance", "跳舞", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - SendUartMessage("d1"); - light_mode_ = LIGHT_MODE_MAX; - return true; - }); - - mcp_server.AddTool("self.chassis.switch_light_mode", "打开灯光效果", PropertyList({ - Property("light_mode", kPropertyTypeInteger, 1, 6) - }), [this](const PropertyList& properties) -> ReturnValue { - char command_str[5] = {'w', 0, 0}; - char mode = static_cast(properties["light_mode"].value()); - - ESP_LOGI(TAG, "Switch Light Mode: %c", (mode + '0')); - - if (mode >= 3 && mode <= 8) { - command_str[1] = mode + '0'; - SendUartMessage(command_str); - return true; - } - throw std::runtime_error("Invalid light mode"); - }); - - mcp_server.AddTool("self.camera.set_camera_flipped", "翻转摄像头图像方向", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - Settings settings("sparkbot", true); - // 考虑到部分复刻使用了不可动摄像头的设计,默认启用翻转 - bool flipped = !static_cast(settings.GetInt("camera-flipped", 1)); - - camera_->SetHMirror(flipped); - camera_->SetVFlip(flipped); - - settings.SetInt("camera-flipped", flipped ? 1 : 0); - - return true; - }); - } - -public: - EspSparkBot() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeDisplay(); - InitializeButtons(); - InitializeCamera(); - InitializeEchoUart(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static SparkBotEs8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(EspSparkBot); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/README.md deleted file mode 100644 index c13054f4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# ESP-Spot - -## 简介 - - - -ESP-Spot 是 ESP Friends 开源的一款智能语音交互盒子,内置麦克风、扬声器、IMU 惯性传感器,可使用电池供电。ESP-Spot 不带屏幕,带有一个 RGB 指示灯和两个按钮。硬件详情可查看[立创开源项目](https://oshwhub.com/esp-college/esp-spot)。 - -ESP-Spot 开源项目采用 ESP32-S3-WROOM-1-N16R8 模组或 ESP32-C5-WROOM-1-N8R8。如在复刻时使用了其他大小的 Flash,需修改对应的参数。 - - -## 配置、编译命令 - -**配置编译目标** - -```bash -idf.py set-target esp32s3 # Spot S3 -# or -idf.py set-target esp32c5 # Spot C5 -``` - -**打开 menuconfig 并配置** - -```bash -idf.py menuconfig -``` - -分别配置如下选项: - -- `Xiaozhi Assistant` → `Board Type` → 选择 `ESP-Spot-S3` / `ESP-Spot-C5` - -按 `S` 保存,按 `Q` 退出。 - -**编译** - -```bash -idf.py build -``` - -**烧录** - -```bash -idf.py flash -``` - -> [!TIP] -> -> **若电脑始终无法找到 ESP-Spot 串口,可尝试如下步骤** -> 1. 打开前盖; -> 2. 拔出带有模组的 PCB 板; -> 3. 按住 BOOT 同时插回 PCB 版,注意不要颠倒; -> -> 此时, ESP-Spot 应当已进入下载模式。在烧录完成后,可能需要重新插拔 PCB 板。 - -## 低功耗 - -ESP-Spot 支持 Deep Sleep 低功耗模式。 - -当处于 idle 状态 10 分钟后,ESP-Spot 会自动进入 Deep Sleep 模式,按 Key 键或摇晃 ESP-Spot 即可唤醒。 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.h deleted file mode 100644 index df6427d4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include -#include "sdkconfig.h" - -/* Audio configuration */ -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 -#define AUDIO_INPUT_REFERENCE false -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -/* ADC configuration */ -#define ADC_ATTEN ADC_ATTEN_DB_12 -#define ADC_WIDTH ADC_BITWIDTH_DEFAULT -#define FULL_BATTERY_VOLTAGE 4100 -#define EMPTY_BATTERY_VOLTAGE 3200 - -/* I2C configuration */ -#define I2C_MASTER_FREQ_HZ (400 * 1000) - -/* Button configuration */ -#define LONG_PRESS_TIMEOUT_US (5 * 1000000ULL) - -#ifdef CONFIG_IDF_TARGET_ESP32S3 - -/* Audio I2S GPIOs */ -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_17 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_18 - -/* Audio CODEC GPIOs */ -#define AUDIO_CODEC_PA_PIN GPIO_NUM_40 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_2 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 - -/* Button GPIOs */ -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define KEY_BUTTON_GPIO GPIO_NUM_12 -#define LED_GPIO GPIO_NUM_11 - -/* ADC GPIOs */ -#define VBAT_ADC_CHANNEL ADC_CHANNEL_9 // S3: IO10 -#define MCU_VCC_CTL GPIO_NUM_4 // set 1 to power on MCU -#define PERP_VCC_CTL GPIO_NUM_6 // set 1 to power on peripherals - -/* IMU GPIOs */ -#define IMU_INT_GPIO GPIO_NUM_5 - -#elif defined(CONFIG_IDF_TARGET_ESP32C5) - -/* Audio I2S GPIOs */ -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_NC -#define AUDIO_I2S_GPIO_WS GPIO_NUM_8 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -/* Audio CODEC GPIOs */ -#define AUDIO_CODEC_PA_PIN GPIO_NUM_23 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_25 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_26 - -/* Button GPIOs */ -#define BOOT_BUTTON_GPIO GPIO_NUM_28 -#define KEY_BUTTON_GPIO GPIO_NUM_5 -#define LED_GPIO GPIO_NUM_27 - -/* ADC GPIOs */ -#define VBAT_ADC_CHANNEL ADC_CHANNEL_3 // C5: IO4 -#define MCU_VCC_CTL GPIO_NUM_2 // set 1 to power on MCU -#define PERP_VCC_CTL GPIO_NUM_0 // set 1 to power on peripherals - -/* IMU GPIOs */ -#define IMU_INT_GPIO GPIO_NUM_3 - -#endif // CONFIG_IDF_TARGET - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.json deleted file mode 100644 index 350171e9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32c5", - "builds": [ - { - "name": "esp-spot-c5", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/esp_spot_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/esp_spot_board.cc deleted file mode 100644 index d6931be9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp-spot/esp_spot_board.cc +++ /dev/null @@ -1,436 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_idf_version.h" -#include "led/circular_strip.h" -#include "sdkconfig.h" - -#include "application.h" -#include "button.h" -#include "codecs/es8311_audio_codec.h" -#include "config.h" -#include "sleep_timer.h" -#include "wifi_board.h" - -#ifdef IMU_INT_GPIO -#include - -#include "bmi270_api.h" -#include "i2c_bus.h" -#endif // IMU_INT_GPIO - -#ifdef CONFIG_IDF_TARGET_ESP32S3 -#define TAG "esp_spot_s3" -#elif defined(CONFIG_IDF_TARGET_ESP32C5) -#define TAG "esp_spot_c5" -#else // target -#error "Unsupported target" -#endif // target - -#ifdef IMU_INT_GPIO -namespace Bmi270Imu { - -static bmi270_handle_t bmi_handle_ = nullptr; - -esp_err_t Initialize(i2c_bus_handle_t i2c_bus, uint8_t addr = BMI270_I2C_ADDRESS) { - if (bmi_handle_) { - return ESP_OK; - } - - if (!i2c_bus) { - ESP_LOGE(TAG, "Invalid I2C bus for BMI270"); - return ESP_ERR_INVALID_ARG; - } - - esp_err_t ret = bmi270_sensor_create(i2c_bus, &bmi_handle_, bmi270_config_file, - BMI2_GYRO_CROSS_SENS_ENABLE | BMI2_CRT_RTOSK_ENABLE); - if (ret != ESP_OK || !bmi_handle_) { - ESP_LOGE(TAG, "BMI270 create failed: %s", esp_err_to_name(ret)); - return ret == ESP_OK ? ESP_FAIL : ret; - } - ESP_LOGI(TAG, "BMI270 initialized"); - return ESP_OK; -} - -// Only used for deep sleep wakeup with wrist gesture interrupt -esp_err_t EnableImuIntForWakeup() { - if (!bmi_handle_) { - return ESP_ERR_INVALID_STATE; - } - - const uint8_t sens_list[] = {BMI2_ACCEL, BMI2_WRIST_GESTURE}; - int8_t rslt = bmi270_sensor_enable(sens_list, 2, bmi_handle_); - if (rslt != BMI2_OK) { - ESP_LOGE(TAG, "Failed to enable BMI270 sensors: %d", rslt); - return ESP_FAIL; - } - - struct bmi2_sens_config config = {.type = BMI2_WRIST_GESTURE}; - rslt = bmi270_get_sensor_config(&config, 1, bmi_handle_); - if (rslt != BMI2_OK) { - ESP_LOGE(TAG, "Failed to get wrist gesture config: %d", rslt); - return ESP_FAIL; - } - config.cfg.wrist_gest.wearable_arm = BMI2_ARM_RIGHT; - rslt = bmi270_set_sensor_config(&config, 1, bmi_handle_); - if (rslt != BMI2_OK) { - ESP_LOGE(TAG, "Failed to set wrist gesture config: %d", rslt); - return ESP_FAIL; - } - - struct bmi2_int_pin_config pin_config = {}; - pin_config.pin_type = BMI2_INT1; - pin_config.pin_cfg[0].input_en = BMI2_INT_INPUT_DISABLE; - pin_config.pin_cfg[0].lvl = BMI2_INT_ACTIVE_HIGH; - pin_config.pin_cfg[0].od = BMI2_INT_PUSH_PULL; - pin_config.pin_cfg[0].output_en = BMI2_INT_OUTPUT_ENABLE; - pin_config.int_latch = BMI2_INT_NON_LATCH; - rslt = bmi2_set_int_pin_config(&pin_config, bmi_handle_); - if (rslt != BMI2_OK) { - ESP_LOGE(TAG, "Failed to set BMI270 INT pin: %d", rslt); - return ESP_FAIL; - } - - struct bmi2_sens_int_config int_config = {.type = BMI2_WRIST_GESTURE, .hw_int_pin = BMI2_INT1}; - rslt = bmi270_map_feat_int(&int_config, 1, bmi_handle_); - if (rslt != BMI2_OK) { - ESP_LOGE(TAG, "Failed to map BMI270 interrupt: %d", rslt); - return ESP_FAIL; - } - - return ESP_OK; -} - -} // namespace Bmi270Imu - -#endif // IMU_INT_GPIO - -class EspSpot : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_ = nullptr; - Button boot_button_; - Button key_button_; - adc_oneshot_unit_handle_t adc1_handle_; - adc_cali_handle_t adc1_cali_handle_; - bool adc_calibration_lock_ = false; - bool key_long_pressed_ = false; - int64_t last_key_press_time = 0; - SleepTimer* sleep_timer_ = nullptr; -#ifdef IMU_INT_GPIO - i2c_bus_handle_t shared_i2c_bus_handle_ = nullptr; - static constexpr int kDeepSleepTimeoutSeconds = 10 * 60; // 10 minutes - bool imu_ready_ = false; -#endif - -#ifdef IMU_INT_GPIO - void InitializeI2c() { - // Initialize I2C peripheral - i2c_config_t i2c_bus_cfg = { - .mode = I2C_MODE_MASTER, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .sda_pullup_en = true, - .scl_pullup_en = true, - .master = - { - .clk_speed = I2C_MASTER_FREQ_HZ, - }, - .clk_flags = 0, - }; - shared_i2c_bus_handle_ = i2c_bus_create(I2C_NUM_0, &i2c_bus_cfg); - if (!shared_i2c_bus_handle_) { - ESP_LOGE(TAG, "Failed to create shared I2C bus"); - ESP_ERROR_CHECK(ESP_FAIL); - } - -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) && !CONFIG_I2C_BUS_BACKWARD_CONFIG - i2c_bus_ = i2c_bus_get_internal_bus_handle(shared_i2c_bus_handle_); -#else -#error "ESP-Spot board requires i2c_bus_get_internal_bus_handle() support" -#endif - if (!i2c_bus_) { - ESP_LOGE(TAG, "Failed to obtain master bus handle"); - ESP_ERROR_CHECK(ESP_FAIL); - } - - esp_err_t imu_ret = Bmi270Imu::Initialize(shared_i2c_bus_handle_); - if (imu_ret != ESP_OK) { - ESP_LOGW(TAG, "BMI270 initialization failed, deep sleep disabled (%s)", esp_err_to_name(imu_ret)); - } else { - imu_ready_ = true; - } - } -#else - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = - { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } -#endif // IMU_INT_GPIO - - void InitializeADC() { - adc_oneshot_unit_init_cfg_t init_config1 = {.unit_id = ADC_UNIT_1}; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN, - .bitwidth = ADC_WIDTH, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle_, VBAT_ADC_CHANNEL, &chan_config)); - -#ifdef ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED - adc_cali_handle_t handle = nullptr; - esp_err_t ret = ESP_FAIL; - - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = ADC_UNIT_1, - .atten = ADC_ATTEN, - .bitwidth = ADC_WIDTH, - }; - ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle); - if (ret == ESP_OK) { - adc_calibration_lock_ = true; - adc1_cali_handle_ = handle; - ESP_LOGI(TAG, "ADC Curve Fitting calibration succeeded"); - } -#endif // ADC_CALI_SCHEME_CURVE_FITTING_SUPPORTED - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - HandleUserActivity(); - EnterWifiConfigMode(); - }); - - key_button_.OnClick([this]() { - HandleUserActivity(); - auto& app = Application::GetInstance(); - app.ToggleChatState(); - key_long_pressed_ = false; - }); - - key_button_.OnLongPress([this]() { - HandleUserActivity(); - int64_t now = esp_timer_get_time(); - auto* led = static_cast(this->GetLed()); - - if (key_long_pressed_) { - if ((now - last_key_press_time) < LONG_PRESS_TIMEOUT_US) { - ESP_LOGW(TAG, "Key button long pressed the second time within 5s, shutting down..."); - led->SetSingleColor(0, {0, 0, 0}); - - gpio_hold_dis(MCU_VCC_CTL); - gpio_set_level(MCU_VCC_CTL, 0); - - } else { - last_key_press_time = now; - BlinkGreenFor5s(); - } - key_long_pressed_ = true; - } else { - ESP_LOGW(TAG, "Key button first long press! Waiting second within 5s to shutdown..."); - last_key_press_time = now; - key_long_pressed_ = true; - - BlinkGreenFor5s(); - } - }); - } - - void InitializePowerCtl() { - InitializeGPIO(); - - gpio_set_level(MCU_VCC_CTL, 1); - gpio_hold_en(MCU_VCC_CTL); - - gpio_set_level(PERP_VCC_CTL, 1); - gpio_hold_en(PERP_VCC_CTL); - } - - void InitializeGPIO() { - gpio_config_t io_pa = {.pin_bit_mask = (1ULL << AUDIO_CODEC_PA_PIN), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE}; - gpio_config(&io_pa); - gpio_set_level(AUDIO_CODEC_PA_PIN, 0); - - gpio_config_t io_conf_1 = {.pin_bit_mask = (1ULL << MCU_VCC_CTL), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE}; - gpio_config(&io_conf_1); - - gpio_config_t io_conf_2 = {.pin_bit_mask = (1ULL << PERP_VCC_CTL), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE}; - gpio_config(&io_conf_2); - -#ifdef IMU_INT_GPIO - gpio_config_t io_conf_imu_int = { - .pin_bit_mask = (1ULL << IMU_INT_GPIO), - .mode = GPIO_MODE_INPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_ENABLE, - .intr_type = GPIO_INTR_NEGEDGE, - }; - gpio_config(&io_conf_imu_int); - gpio_install_isr_service(0); -#endif // IMU_INT_GPIO - } - - void HandleUserActivity() { - if (sleep_timer_) { - sleep_timer_->WakeUp(); - } - } - -#ifdef IMU_INT_GPIO - void InitializePowerSaveTimer() { - if (!imu_ready_) { - ESP_LOGW(TAG, "IMU not ready, skip deep sleep timer"); - return; - } - if (sleep_timer_) { - return; - } - sleep_timer_ = new SleepTimer(-1, kDeepSleepTimeoutSeconds); - sleep_timer_->OnEnterDeepSleepMode([this]() { EnterDeepSleep(); }); - sleep_timer_->SetEnabled(true); - ESP_LOGI(TAG, "Deep sleep timer enabled, timeout=%ds", kDeepSleepTimeoutSeconds); - } - - void EnterDeepSleep() { - if (!imu_ready_) { - ESP_LOGW(TAG, "Skip deep sleep because IMU is not ready"); - return; - } - - auto* led = static_cast(GetLed()); - if (led) { - led->SetSingleColor(0, {0, 0, 0}); - } - - if (Bmi270Imu::EnableImuIntForWakeup() != ESP_OK) { - ESP_LOGE(TAG, "IMU wakeup configuration failed, abort deep sleep"); - return; - } - - const uint64_t wakeup_mask = (1ULL << KEY_BUTTON_GPIO) | (1ULL << IMU_INT_GPIO); - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(wakeup_mask, ESP_EXT1_WAKEUP_ANY_HIGH)); - ESP_LOGI(TAG, "Entering deep sleep, waiting for key or wrist gesture"); - esp_deep_sleep_start(); - } -#endif // IMU_INT_GPIO - - void BlinkGreenFor5s() { - auto* led = static_cast(GetLed()); - if (!led) { - return; - } - - led->Blink({50, 25, 0}, 100); - - esp_timer_create_args_t timer_args = {.callback = - [](void* arg) { - auto* self = static_cast(arg); - auto* led = static_cast(self->GetLed()); - if (led) { - led->SetSingleColor(0, {0, 0, 0}); - } - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "green_blink_timer"}; - - esp_timer_handle_t green_blink_timer = nullptr; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &green_blink_timer)); - ESP_ERROR_CHECK(esp_timer_start_once(green_blink_timer, LONG_PRESS_TIMEOUT_US)); - } - -public: - EspSpot() : boot_button_(BOOT_BUTTON_GPIO), key_button_(KEY_BUTTON_GPIO, true) { - InitializePowerCtl(); - InitializeADC(); - InitializeI2c(); - InitializeButtons(); -#ifdef IMU_INT_GPIO - InitializePowerSaveTimer(); -#endif // IMU_INT_GPIO - } - - virtual Led* GetLed() override { - static CircularStrip led(LED_GPIO, 1); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, false); - return &audio_codec; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (sleep_timer_) { - sleep_timer_->SetEnabled(level == PowerSaveLevel::LOW_POWER); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - if (!adc1_handle_) { - InitializeADC(); - } - - int raw_value = 0; - int voltage = 0; - - ESP_ERROR_CHECK(adc_oneshot_read(adc1_handle_, VBAT_ADC_CHANNEL, &raw_value)); - - if (adc_calibration_lock_) { - ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc1_cali_handle_, raw_value, &voltage)); - voltage = voltage * 3 / 2; // compensate for voltage divider - ESP_LOGI(TAG, "Calibrated voltage: %d mV", voltage); - } else { - ESP_LOGI(TAG, "Raw ADC value: %d", raw_value); - voltage = raw_value; - } - - voltage = voltage < EMPTY_BATTERY_VOLTAGE ? EMPTY_BATTERY_VOLTAGE : voltage; - voltage = voltage > FULL_BATTERY_VOLTAGE ? FULL_BATTERY_VOLTAGE : voltage; - - // Calculate battery level percentage - level = (voltage - EMPTY_BATTERY_VOLTAGE) * 100 / (FULL_BATTERY_VOLTAGE - EMPTY_BATTERY_VOLTAGE); - - // ESP-Spot does not support charging detection, so we use MCU_VCC_CTL to determine charging status - charging = gpio_get_level(MCU_VCC_CTL); - discharging = !charging; - ESP_LOGI(TAG, "Battery Level: %d%%, Charging: %s", level, charging ? "Yes" : "No"); - return true; - } -}; - -DECLARE_BOARD(EspSpot); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/README.md deleted file mode 100644 index fcd8758c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# 相关资料: -- [插线款](https://www.wdmomo.fun:81/doc/index.html?file=001_%E8%AE%BE%E8%AE%A1%E9%A1%B9%E7%9B%AE/0001_%E5%B0%8F%E6%99%BAAI/003_ESP32-CGC-144%E6%8F%92%E7%BA%BF%E7%89%88%E5%B0%8F%E6%99%BAAI) - -- [电池款](https://www.wdmomo.fun:81/doc/index.html?file=001_%E8%AE%BE%E8%AE%A1%E9%A1%B9%E7%9B%AE/0001_%E5%B0%8F%E6%99%BAAI/004_ESP32-CGC-144%E7%94%B5%E6%B1%A0%E7%89%88%E5%B0%8F%E6%99%BAAI) - -# 编译配置命令 - -**配置编译目标为 ESP32:** - -```bash -idf.py set-target esp32 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> ESP32 CGC 144 -``` - -**编译:** - -```bash -idf.py build -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.h deleted file mode 100644 index 6a23386b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -// 如果使用插线版本接入电池,请启用下面一行 -//#define ESP32_CGC_144_lite - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_25 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_26 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_32 - -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_33 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_27 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define ASR_BUTTON_GPIO GPIO_NUM_13 - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_12 - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_4 -#define DISPLAY_SCLK_PIN GPIO_NUM_18 -#define DISPLAY_MOSI_PIN GPIO_NUM_23 -#define DISPLAY_CS_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_2 -#define DISPLAY_RESET_PIN GPIO_NUM_NC - -#define DISPLAY_SPI_SCLK_HZ (20 * 1000 * 1000) - -// 如果使用240x240的屏幕,请注释下面一行 -#define LCD_128X128 - -#ifdef LCD_128X128 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 2 -#define DISPLAY_OFFSET_Y 3 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true -#define DISPLAY_SPI_MODE 0 - -#else - -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true -#define DISPLAY_SPI_MODE 0 - -#endif - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.json deleted file mode 100644 index ca42e8a7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "target": "esp32", - "builds": [ - { - "name": "esp32-cgc-144", - "sdkconfig_append": [ - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/esp32_cgc_144_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/esp32_cgc_144_board.cc deleted file mode 100644 index 085b8152..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/esp32_cgc_144_board.cc +++ /dev/null @@ -1,192 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#include - -#if defined(ESP32_CGC_144_lite) -#include "power_manager_lite.h" -#else -#include "power_manager.h" -#endif - -#define TAG "ESP32_CGC_144" - -class ESP32_CGC_144 : public WifiBoard { -private: - Button boot_button_; - LcdDisplay* display_; - Button asr_button_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - -#if defined(ESP32_CGC_144_lite) -void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_NC); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); -} -#else -void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_36); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); -} -#endif - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeSt7735Display() { - // esp_lcd_panel_io_handle_t panel_io = nullptr; - // esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RESET_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - asr_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - std::string wake_word="你好小智"; - Application::GetInstance().WakeWordInvoke(wake_word); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - ESP32_CGC_144() : - boot_button_(BOOT_BUTTON_GPIO), asr_button_(ASR_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeSt7735Display(); - InitializeButtons(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(ESP32_CGC_144); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager.h deleted file mode 100644 index 9576e302..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager.h +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_3, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1970, 0}, - {2062, 20}, - {2154, 40}, - {2246, 60}, - {2338, 80}, - {2430, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_3, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager_lite.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager_lite.h deleted file mode 100644 index f088286d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc-144/power_manager_lite.h +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); //lite - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // lite定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {3000, 0}, - {3160, 20}, - {3320, 40}, - {3480, 60}, - {3640, 80}, - {3800, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); //lite - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/README.md deleted file mode 100644 index 3a409003..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# 主板开源地址: -- V1:[https://oshwhub.com/wdmomo/esp32-xiaozhi-kidpcb](https://oshwhub.com/wdmomo/esp32-xiaozhi-kidpcb) -- V2:[https://oshwhub.com/wdmomo/esp32-xiaozhi-kidpcb_copy](https://oshwhub.com/wdmomo/esp32-xiaozhi-kidpcb_copy) -- 更多介绍:[wdmomo.fun](https://www.wdmomo.fun:81/doc/index.html?file=001_%E8%AE%BE%E8%AE%A1%E9%A1%B9%E7%9B%AE/0001_%E5%B0%8F%E6%99%BAAI/002_ESP32-CGC%E5%BC%80%E5%8F%91%E6%9D%BF%E5%B0%8F%E6%99%BAAI) - -# 编译配置命令 - -**配置编译目标为 ESP32:** - -```bash -idf.py set-target esp32 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> ESP32 CGC -``` - -**选择屏幕类型:** - -``` -Xiaozhi Assistant -> LCD Type -> "ST7735, 分辨率128*128" -``` - -**编译:** - -```bash -idf.py build -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.h deleted file mode 100644 index 2e27571a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.h +++ /dev/null @@ -1,271 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -// 如果使用 Duplex I2S 模式,请注释下面一行 -#define AUDIO_I2S_METHOD_SIMPLEX - -#ifdef AUDIO_I2S_METHOD_SIMPLEX - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_25 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_26 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_32 - -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_33 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_27 - -#else - -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_7 - -#endif - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define ASR_BUTTON_GPIO GPIO_NUM_13 - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_12 - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_4 -#define DISPLAY_SCLK_PIN GPIO_NUM_18 -#define DISPLAY_MOSI_PIN GPIO_NUM_23 -#define DISPLAY_CS_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_2 -#define DISPLAY_RESET_PIN GPIO_NUM_NC - -#define DISPLAY_SPI_SCLK_HZ (20 * 1000 * 1000) - -#ifdef CONFIG_LCD_ST7789_240X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif - -#ifdef CONFIG_LCD_ST7789_240X320_NO_IPS -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_170X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 170 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 35 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_172X320 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 172 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 34 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X280 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7789_240X240_7PIN -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 2 -#endif - -#ifdef CONFIG_LCD_ST7789_240X135 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 135 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 40 -#define DISPLAY_OFFSET_Y 53 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7735_128X160 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif - -#ifdef CONFIG_LCD_ST7735_128X128 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 2 -#define DISPLAY_OFFSET_Y 3 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ST7796_320X480 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 480 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320 -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_ILI9341_240X320_NO_IPS -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_GC9A01_240X240 -#define LCD_TYPE_GC9A01_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#ifdef CONFIG_LCD_CUSTOM -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 0 -#endif - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.json deleted file mode 100644 index a8a1629f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32", - "builds": [ - { - "name": "esp32-cgc", - "sdkconfig_append": [ - "CONFIG_LCD_ST7735_128X128=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/esp32_cgc_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/esp32_cgc_board.cc deleted file mode 100644 index 951e4813..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-cgc/esp32_cgc_board.cc +++ /dev/null @@ -1,180 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" - -#include -#include -#include -#include -#include -#include - -#if defined(LCD_TYPE_ILI9341_SERIAL) -#include -#endif - -#if defined(LCD_TYPE_GC9A01_SERIAL) -#include -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; -#endif - -#define TAG "ESP32_CGC" - -class ESP32_CGC : public WifiBoard { -private: - Button boot_button_; - LcdDisplay* display_; - Button asr_button_; - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RESET_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; -#if defined(LCD_TYPE_ILI9341_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); -#elif defined(LCD_TYPE_GC9A01_SERIAL) - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel)); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; -#else - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); -#endif - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); -#ifdef LCD_TYPE_GC9A01_SERIAL - panel_config.vendor_config = &gc9107_vendor_config; -#endif - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - asr_button_.OnClick([this]() { - std::string wake_word="你好小智"; - Application::GetInstance().WakeWordInvoke(wake_word); - }); - - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - ESP32_CGC() : - boot_button_(BOOT_BUTTON_GPIO), asr_button_(ASR_BUTTON_GPIO) { - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override - { -#ifdef AUDIO_I2S_METHOD_SIMPLEX - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); -#else - static NoAudioCodecDuplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(ESP32_CGC); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.h deleted file mode 100644 index c9040537..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define EXAMPLE_PIN_NUM_LCD_CS GPIO_NUM_12 -#define EXAMPLE_PIN_NUM_LCD_PCLK GPIO_NUM_11 -#define EXAMPLE_PIN_NUM_LCD_DATA0 GPIO_NUM_4 -#define EXAMPLE_PIN_NUM_LCD_DATA1 GPIO_NUM_5 -#define EXAMPLE_PIN_NUM_LCD_DATA2 GPIO_NUM_6 -#define EXAMPLE_PIN_NUM_LCD_DATA3 GPIO_NUM_7 -#define EXAMPLE_PIN_NUM_LCD_RST GPIO_NUM_NC -#define DISPLAY_WIDTH 368 -#define DISPLAY_HEIGHT 448 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.json deleted file mode 100644 index 67194974..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32-s3-touch-amoled-1.8", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc deleted file mode 100644 index b0f28f1a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-amoled-1.8/esp32-s3-touch-amoled-1.8.cc +++ /dev/null @@ -1,335 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" - -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" -#include "settings.h" - -#include -#include -#include - -#define TAG "WaveshareEsp32s3TouchAMOLED1inch8" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x01); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const sh8601_lcd_init_cmd_t vendor_specific_init[] = { - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0x44, (uint8_t[]){0x01, 0xD1}, 2, 0}, - {0x35, (uint8_t[]){0x00}, 1, 0}, - {0x53, (uint8_t[]){0x20}, 1, 10}, - {0x2A, (uint8_t[]){0x00, 0x00, 0x01, 0x6F}, 4, 0}, - {0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0xBF}, 4, 0}, - {0x51, (uint8_t[]){0x00}, 1, 10}, - {0x29, (uint8_t[]){0x00}, 0, 10} -}; - -// 在waveshare_amoled_1_8类之前添加新的显示类 -class CustomLcdDisplay : public SpiLcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES * 0.1, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES * 0.1, 0); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(esp_lcd_panel_io_handle_t panel_io) : Backlight(), panel_io_(panel_io) {} - -protected: - esp_lcd_panel_io_handle_t panel_io_; - - virtual void SetBrightnessImpl(uint8_t brightness) override { - auto display = Board::GetInstance().GetDisplay(); - DisplayLockGuard lock(display); - uint8_t data[1] = {((uint8_t)((255 * brightness) / 100))}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - esp_lcd_panel_io_tx_param(panel_io_, lcd_cmd, &data, sizeof(data)); - } -}; - -class WaveshareEsp32s3TouchAMOLED1inch8 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - CustomLcdDisplay* display_; - CustomBacklight* backlight_; - esp_io_expander_handle_t io_expander = NULL; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(codec_i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 |IO_EXPANDER_PIN_NUM_2, IO_EXPANDER_OUTPUT); - ret |= esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_4, IO_EXPANDER_INPUT); - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 1); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 0); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1|IO_EXPANDER_PIN_NUM_2, 1); - ESP_ERROR_CHECK(ret); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(codec_i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.sclk_io_num = GPIO_NUM_11; - buscfg.data0_io_num = GPIO_NUM_4; - buscfg.data1_io_num = GPIO_NUM_5; - buscfg.data2_io_num = GPIO_NUM_6; - buscfg.data3_io_num = GPIO_NUM_7; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - buscfg.flags = SPICOMMON_BUSFLAG_QUAD; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSH8601Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG( - EXAMPLE_PIN_NUM_LCD_CS, - nullptr, - nullptr - ); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const sh8601_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(sh8601_lcd_init_cmd_t), - .flags ={ - .use_qspi_interface = 1, - } - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.flags.reset_active_high = 1, - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *)&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - backlight_ = new CustomBacklight(panel_io); - backlight_->RestoreBrightness(); - } - - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_21, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(codec_i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32s3TouchAMOLED1inch8() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeTca9554(); - InitializeAxp2101(); - InitializeSpi(); - InitializeSH8601Display(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - return backlight_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32s3TouchAMOLED1inch8); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/README.md deleted file mode 100644 index 0919b9d0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/README.md +++ /dev/null @@ -1,4 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-1.46、ESP32-S3-Touch-LCD-1.46B -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-1.46.htm -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-1.46B.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.h deleted file mode 100644 index b1bd2d98..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_6 -#define PWR_Control_PIN GPIO_NUM_7 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_2 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_15 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_47 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_48 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_38 - -#define I2C_SCL_IO GPIO_NUM_10 -#define I2C_SDA_IO GPIO_NUM_11 - - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 - -#define DISPLAY_WIDTH 412 -#define DISPLAY_HEIGHT 412 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define QSPI_LCD_H_RES (412) -#define QSPI_LCD_V_RES (412) -#define QSPI_LCD_BIT_PER_PIXEL (16) - -#define QSPI_LCD_HOST SPI2_HOST -#define QSPI_PIN_NUM_LCD_PCLK GPIO_NUM_40 -#define QSPI_PIN_NUM_LCD_CS GPIO_NUM_21 -#define QSPI_PIN_NUM_LCD_DATA0 GPIO_NUM_46 -#define QSPI_PIN_NUM_LCD_DATA1 GPIO_NUM_45 -#define QSPI_PIN_NUM_LCD_DATA2 GPIO_NUM_42 -#define QSPI_PIN_NUM_LCD_DATA3 GPIO_NUM_41 -#define QSPI_PIN_NUM_LCD_RST GPIO_NUM_NC -#define QSPI_PIN_NUM_LCD_BL GPIO_NUM_5 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define TP_PORT (I2C_NUM_1) -#define TP_PIN_NUM_SDA (I2C_SDA_IO) -#define TP_PIN_NUM_SCL (I2C_SCL_IO) -#define TP_PIN_NUM_RST (GPIO_NUM_NC) -#define TP_PIN_NUM_INT (GPIO_NUM_4) - -#define DISPLAY_BACKLIGHT_PIN QSPI_PIN_NUM_LCD_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define TAIJIPI_SPD2010_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.json deleted file mode 100644 index e7e58528..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32-s3-touch-lcd-1.46", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/esp32-s3-touch-lcd-1.46.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/esp32-s3-touch-lcd-1.46.cc deleted file mode 100644 index 4592b3c4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.46/esp32-s3-touch-lcd-1.46.cc +++ /dev/null @@ -1,237 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" -#include "lcd_display.h" -#include - -#define TAG "waveshare_lcd_1_46" - -// 在waveshare_lcd_1_46类之前添加新的显示类 -class CustomLcdDisplay : public SpiLcdDisplay { -public: - static void rounder_event_cb(lv_event_t * e) { - lv_area_t * area = (lv_area_t *)lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - - area->x1 = (x1 >> 2) << 2; // round the start of coordinate down to the nearest 4M number - area->x2 = ((x2 >> 2) << 2) + 3; // round the end of coordinate up to the nearest 4N+3 number - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_display_add_event_cb(display_, rounder_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - } -}; - -class CustomBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - button_handle_t boot_btn, pwr_btn; - button_driver_t* boot_btn_driver_ = nullptr; - button_driver_t* pwr_btn_driver_ = nullptr; - static CustomBoard* instance_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = I2C_SDA_IO, - .scl_io_num = I2C_SCL_IO, - .clk_source = I2C_CLK_SRC_DEFAULT, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - - // uint32_t input_level_mask = 0; - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_INPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输入 - // ret = esp_io_expander_get_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, &input_level_mask); // 获取引脚 EXIO0 和 EXIO1 的电平状态,存放在 input_level_mask 中 - - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO2 和 EXIO3 模式为输出 - // ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, 1); // 将引脚电平设置为 1 - // ret = esp_io_expander_print_state(io_expander); // 打印引脚状态 - - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输出 - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - - const spi_bus_config_t bus_config = TAIJIPI_SPD2010_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, - QSPI_PIN_NUM_LCD_DATA0, - QSPI_PIN_NUM_LCD_DATA1, - QSPI_PIN_NUM_LCD_DATA2, - QSPI_PIN_NUM_LCD_DATA3, - QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - void InitializeSpd2010Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGI(TAG, "Install panel IO"); - - const esp_lcd_panel_io_spi_config_t io_config = SPD2010_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); - - ESP_LOGI(TAG, "Install SPD2010 panel driver"); - - spd2010_vendor_config_t vendor_config = { - .flags = { - .use_qspi_interface = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` - .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18) - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_spd2010(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtonsCustom() { - gpio_reset_pin(BOOT_BUTTON_GPIO); - gpio_set_direction(BOOT_BUTTON_GPIO, GPIO_MODE_INPUT); - gpio_reset_pin(PWR_BUTTON_GPIO); - gpio_set_direction(PWR_BUTTON_GPIO, GPIO_MODE_INPUT); - gpio_reset_pin(PWR_Control_PIN); - gpio_set_direction(PWR_Control_PIN, GPIO_MODE_OUTPUT); - // gpio_set_level(PWR_Control_PIN, false); - gpio_set_level(PWR_Control_PIN, true); - } - - void InitializeButtons() { - instance_ = this; - InitializeButtonsCustom(); - - // Boot Button - button_config_t boot_btn_config = { - .long_press_time = 2000, - .short_press_time = 0 - }; - boot_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - boot_btn_driver_->enable_power_save = false; - boot_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !gpio_get_level(BOOT_BUTTON_GPIO); - }; - ESP_ERROR_CHECK(iot_button_create(&boot_btn_config, boot_btn_driver_, &boot_btn)); - iot_button_register_cb(boot_btn, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }, this); - iot_button_register_cb(boot_btn, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - // 长按无处理 - }, this); - - // Power Button - button_config_t pwr_btn_config = { - .long_press_time = 5000, - .short_press_time = 0 - }; - pwr_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - pwr_btn_driver_->enable_power_save = false; - pwr_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !gpio_get_level(PWR_BUTTON_GPIO); - }; - ESP_ERROR_CHECK(iot_button_create(&pwr_btn_config, pwr_btn_driver_, &pwr_btn)); - iot_button_register_cb(pwr_btn, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - // 短按无处理 - }, this); - iot_button_register_cb(pwr_btn, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - if(self->GetBacklight()->brightness() > 0) { - self->GetBacklight()->SetBrightness(0); - gpio_set_level(PWR_Control_PIN, false); - } - else { - self->GetBacklight()->RestoreBrightness(); - gpio_set_level(PWR_Control_PIN, true); - } - }, this); - } - -public: - CustomBoard() { - InitializeI2c(); - InitializeTca9554(); - InitializeSpi(); - InitializeSpd2010Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, I2S_STD_SLOT_LEFT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN, I2S_STD_SLOT_RIGHT); // I2S_STD_SLOT_LEFT / I2S_STD_SLOT_RIGHT / I2S_STD_SLOT_BOTH - - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(CustomBoard); - -CustomBoard* CustomBoard::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/README.md deleted file mode 100644 index df8a905c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-1.85 -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-1.85.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.h deleted file mode 100644 index 7eff4c69..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_6 -#define PWR_Control_PIN GPIO_NUM_7 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_2 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_15 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_47 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_48 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_38 - -#define I2C_SCL_IO GPIO_NUM_10 -#define I2C_SDA_IO GPIO_NUM_11 - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 - -#define DISPLAY_WIDTH 360 -#define DISPLAY_HEIGHT 360 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define QSPI_LCD_H_RES (360) -#define QSPI_LCD_V_RES (360) -#define QSPI_LCD_BIT_PER_PIXEL (16) - -#define QSPI_LCD_HOST SPI2_HOST -#define QSPI_PIN_NUM_LCD_PCLK GPIO_NUM_40 -#define QSPI_PIN_NUM_LCD_CS GPIO_NUM_21 -#define QSPI_PIN_NUM_LCD_DATA0 GPIO_NUM_46 -#define QSPI_PIN_NUM_LCD_DATA1 GPIO_NUM_45 -#define QSPI_PIN_NUM_LCD_DATA2 GPIO_NUM_42 -#define QSPI_PIN_NUM_LCD_DATA3 GPIO_NUM_41 -#define QSPI_PIN_NUM_LCD_RST GPIO_NUM_NC -#define QSPI_PIN_NUM_LCD_BL GPIO_NUM_5 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define TP_PORT (I2C_NUM_1) -#define TP_PIN_NUM_SDA (GPIO_NUM_1) -#define TP_PIN_NUM_SCL (GPIO_NUM_3) -#define TP_PIN_NUM_RST (GPIO_NUM_NC) -#define TP_PIN_NUM_INT (GPIO_NUM_4) - -#define DISPLAY_BACKLIGHT_PIN QSPI_PIN_NUM_LCD_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.json deleted file mode 100644 index 63207b55..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32-s3-touch-lcd-1.85", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/esp32-s3-touch-lcd-1.85.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/esp32-s3-touch-lcd-1.85.cc deleted file mode 100644 index 16d4e9a6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85/esp32-s3-touch-lcd-1.85.cc +++ /dev/null @@ -1,447 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" - -#define TAG "waveshare_lcd_1_85" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x0BULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const st77916_lcd_init_cmd_t vendor_specific_init_new[] = { - {0xF0, (uint8_t []){0x28}, 1, 0}, - {0xF2, (uint8_t []){0x28}, 1, 0}, - {0x73, (uint8_t []){0xF0}, 1, 0}, - {0x7C, (uint8_t []){0xD1}, 1, 0}, - {0x83, (uint8_t []){0xE0}, 1, 0}, - {0x84, (uint8_t []){0x61}, 1, 0}, - {0xF2, (uint8_t []){0x82}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x01}, 1, 0}, - {0xF1, (uint8_t []){0x01}, 1, 0}, - {0xB0, (uint8_t []){0x56}, 1, 0}, - {0xB1, (uint8_t []){0x4D}, 1, 0}, - {0xB2, (uint8_t []){0x24}, 1, 0}, - {0xB4, (uint8_t []){0x87}, 1, 0}, - {0xB5, (uint8_t []){0x44}, 1, 0}, - {0xB6, (uint8_t []){0x8B}, 1, 0}, - {0xB7, (uint8_t []){0x40}, 1, 0}, - {0xB8, (uint8_t []){0x86}, 1, 0}, - {0xBA, (uint8_t []){0x00}, 1, 0}, - {0xBB, (uint8_t []){0x08}, 1, 0}, - {0xBC, (uint8_t []){0x08}, 1, 0}, - {0xBD, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x80}, 1, 0}, - {0xC1, (uint8_t []){0x10}, 1, 0}, - {0xC2, (uint8_t []){0x37}, 1, 0}, - {0xC3, (uint8_t []){0x80}, 1, 0}, - {0xC4, (uint8_t []){0x10}, 1, 0}, - {0xC5, (uint8_t []){0x37}, 1, 0}, - {0xC6, (uint8_t []){0xA9}, 1, 0}, - {0xC7, (uint8_t []){0x41}, 1, 0}, - {0xC8, (uint8_t []){0x01}, 1, 0}, - {0xC9, (uint8_t []){0xA9}, 1, 0}, - {0xCA, (uint8_t []){0x41}, 1, 0}, - {0xCB, (uint8_t []){0x01}, 1, 0}, - {0xD0, (uint8_t []){0x91}, 1, 0}, - {0xD1, (uint8_t []){0x68}, 1, 0}, - {0xD2, (uint8_t []){0x68}, 1, 0}, - {0xF5, (uint8_t []){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t []){0x4F}, 1, 0}, - {0xDE, (uint8_t []){0x4F}, 1, 0}, - {0xF1, (uint8_t []){0x10}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, - {0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, - {0xF0, (uint8_t []){0x10}, 1, 0}, - {0xF3, (uint8_t []){0x10}, 1, 0}, - {0xE0, (uint8_t []){0x07}, 1, 0}, - {0xE1, (uint8_t []){0x00}, 1, 0}, - {0xE2, (uint8_t []){0x00}, 1, 0}, - {0xE3, (uint8_t []){0x00}, 1, 0}, - {0xE4, (uint8_t []){0xE0}, 1, 0}, - {0xE5, (uint8_t []){0x06}, 1, 0}, - {0xE6, (uint8_t []){0x21}, 1, 0}, - {0xE7, (uint8_t []){0x01}, 1, 0}, - {0xE8, (uint8_t []){0x05}, 1, 0}, - {0xE9, (uint8_t []){0x02}, 1, 0}, - {0xEA, (uint8_t []){0xDA}, 1, 0}, - {0xEB, (uint8_t []){0x00}, 1, 0}, - {0xEC, (uint8_t []){0x00}, 1, 0}, - {0xED, (uint8_t []){0x0F}, 1, 0}, - {0xEE, (uint8_t []){0x00}, 1, 0}, - {0xEF, (uint8_t []){0x00}, 1, 0}, - {0xF8, (uint8_t []){0x00}, 1, 0}, - {0xF9, (uint8_t []){0x00}, 1, 0}, - {0xFA, (uint8_t []){0x00}, 1, 0}, - {0xFB, (uint8_t []){0x00}, 1, 0}, - {0xFC, (uint8_t []){0x00}, 1, 0}, - {0xFD, (uint8_t []){0x00}, 1, 0}, - {0xFE, (uint8_t []){0x00}, 1, 0}, - {0xFF, (uint8_t []){0x00}, 1, 0}, - {0x60, (uint8_t []){0x40}, 1, 0}, - {0x61, (uint8_t []){0x04}, 1, 0}, - {0x62, (uint8_t []){0x00}, 1, 0}, - {0x63, (uint8_t []){0x42}, 1, 0}, - {0x64, (uint8_t []){0xD9}, 1, 0}, - {0x65, (uint8_t []){0x00}, 1, 0}, - {0x66, (uint8_t []){0x00}, 1, 0}, - {0x67, (uint8_t []){0x00}, 1, 0}, - {0x68, (uint8_t []){0x00}, 1, 0}, - {0x69, (uint8_t []){0x00}, 1, 0}, - {0x6A, (uint8_t []){0x00}, 1, 0}, - {0x6B, (uint8_t []){0x00}, 1, 0}, - {0x70, (uint8_t []){0x40}, 1, 0}, - {0x71, (uint8_t []){0x03}, 1, 0}, - {0x72, (uint8_t []){0x00}, 1, 0}, - {0x73, (uint8_t []){0x42}, 1, 0}, - {0x74, (uint8_t []){0xD8}, 1, 0}, - {0x75, (uint8_t []){0x00}, 1, 0}, - {0x76, (uint8_t []){0x00}, 1, 0}, - {0x77, (uint8_t []){0x00}, 1, 0}, - {0x78, (uint8_t []){0x00}, 1, 0}, - {0x79, (uint8_t []){0x00}, 1, 0}, - {0x7A, (uint8_t []){0x00}, 1, 0}, - {0x7B, (uint8_t []){0x00}, 1, 0}, - {0x80, (uint8_t []){0x48}, 1, 0}, - {0x81, (uint8_t []){0x00}, 1, 0}, - {0x82, (uint8_t []){0x06}, 1, 0}, - {0x83, (uint8_t []){0x02}, 1, 0}, - {0x84, (uint8_t []){0xD6}, 1, 0}, - {0x85, (uint8_t []){0x04}, 1, 0}, - {0x86, (uint8_t []){0x00}, 1, 0}, - {0x87, (uint8_t []){0x00}, 1, 0}, - {0x88, (uint8_t []){0x48}, 1, 0}, - {0x89, (uint8_t []){0x00}, 1, 0}, - {0x8A, (uint8_t []){0x08}, 1, 0}, - {0x8B, (uint8_t []){0x02}, 1, 0}, - {0x8C, (uint8_t []){0xD8}, 1, 0}, - {0x8D, (uint8_t []){0x04}, 1, 0}, - {0x8E, (uint8_t []){0x00}, 1, 0}, - {0x8F, (uint8_t []){0x00}, 1, 0}, - {0x90, (uint8_t []){0x48}, 1, 0}, - {0x91, (uint8_t []){0x00}, 1, 0}, - {0x92, (uint8_t []){0x0A}, 1, 0}, - {0x93, (uint8_t []){0x02}, 1, 0}, - {0x94, (uint8_t []){0xDA}, 1, 0}, - {0x95, (uint8_t []){0x04}, 1, 0}, - {0x96, (uint8_t []){0x00}, 1, 0}, - {0x97, (uint8_t []){0x00}, 1, 0}, - {0x98, (uint8_t []){0x48}, 1, 0}, - {0x99, (uint8_t []){0x00}, 1, 0}, - {0x9A, (uint8_t []){0x0C}, 1, 0}, - {0x9B, (uint8_t []){0x02}, 1, 0}, - {0x9C, (uint8_t []){0xDC}, 1, 0}, - {0x9D, (uint8_t []){0x04}, 1, 0}, - {0x9E, (uint8_t []){0x00}, 1, 0}, - {0x9F, (uint8_t []){0x00}, 1, 0}, - {0xA0, (uint8_t []){0x48}, 1, 0}, - {0xA1, (uint8_t []){0x00}, 1, 0}, - {0xA2, (uint8_t []){0x05}, 1, 0}, - {0xA3, (uint8_t []){0x02}, 1, 0}, - {0xA4, (uint8_t []){0xD5}, 1, 0}, - {0xA5, (uint8_t []){0x04}, 1, 0}, - {0xA6, (uint8_t []){0x00}, 1, 0}, - {0xA7, (uint8_t []){0x00}, 1, 0}, - {0xA8, (uint8_t []){0x48}, 1, 0}, - {0xA9, (uint8_t []){0x00}, 1, 0}, - {0xAA, (uint8_t []){0x07}, 1, 0}, - {0xAB, (uint8_t []){0x02}, 1, 0}, - {0xAC, (uint8_t []){0xD7}, 1, 0}, - {0xAD, (uint8_t []){0x04}, 1, 0}, - {0xAE, (uint8_t []){0x00}, 1, 0}, - {0xAF, (uint8_t []){0x00}, 1, 0}, - {0xB0, (uint8_t []){0x48}, 1, 0}, - {0xB1, (uint8_t []){0x00}, 1, 0}, - {0xB2, (uint8_t []){0x09}, 1, 0}, - {0xB3, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0xD9}, 1, 0}, - {0xB5, (uint8_t []){0x04}, 1, 0}, - {0xB6, (uint8_t []){0x00}, 1, 0}, - {0xB7, (uint8_t []){0x00}, 1, 0}, - - {0xB8, (uint8_t []){0x48}, 1, 0}, - {0xB9, (uint8_t []){0x00}, 1, 0}, - {0xBA, (uint8_t []){0x0B}, 1, 0}, - {0xBB, (uint8_t []){0x02}, 1, 0}, - {0xBC, (uint8_t []){0xDB}, 1, 0}, - {0xBD, (uint8_t []){0x04}, 1, 0}, - {0xBE, (uint8_t []){0x00}, 1, 0}, - {0xBF, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x10}, 1, 0}, - {0xC1, (uint8_t []){0x47}, 1, 0}, - {0xC2, (uint8_t []){0x56}, 1, 0}, - {0xC3, (uint8_t []){0x65}, 1, 0}, - {0xC4, (uint8_t []){0x74}, 1, 0}, - {0xC5, (uint8_t []){0x88}, 1, 0}, - {0xC6, (uint8_t []){0x99}, 1, 0}, - {0xC7, (uint8_t []){0x01}, 1, 0}, - {0xC8, (uint8_t []){0xBB}, 1, 0}, - {0xC9, (uint8_t []){0xAA}, 1, 0}, - {0xD0, (uint8_t []){0x10}, 1, 0}, - {0xD1, (uint8_t []){0x47}, 1, 0}, - {0xD2, (uint8_t []){0x56}, 1, 0}, - {0xD3, (uint8_t []){0x65}, 1, 0}, - {0xD4, (uint8_t []){0x74}, 1, 0}, - {0xD5, (uint8_t []){0x88}, 1, 0}, - {0xD6, (uint8_t []){0x99}, 1, 0}, - {0xD7, (uint8_t []){0x01}, 1, 0}, - {0xD8, (uint8_t []){0xBB}, 1, 0}, - {0xD9, (uint8_t []){0xAA}, 1, 0}, - {0xF3, (uint8_t []){0x01}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0x21, (uint8_t []){0x00}, 1, 0}, - {0x11, (uint8_t []){0x00}, 1, 120}, - {0x29, (uint8_t []){0x00}, 1, 0}, -}; -class CustomBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - button_handle_t boot_btn, pwr_btn; - button_driver_t* boot_btn_driver_ = nullptr; - button_driver_t* pwr_btn_driver_ = nullptr; - static CustomBoard* instance_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = I2C_SDA_IO, - .scl_io_num = I2C_SCL_IO, - .clk_source = I2C_CLK_SRC_DEFAULT, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - - // uint32_t input_level_mask = 0; - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_INPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输入 - // ret = esp_io_expander_get_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, &input_level_mask); // 获取引脚 EXIO0 和 EXIO1 的电平状态,存放在 input_level_mask 中 - - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO2 和 EXIO3 模式为输出 - // ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, 1); // 将引脚电平设置为 1 - // ret = esp_io_expander_print_state(io_expander); // 打印引脚状态 - - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输出 - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - - const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, - QSPI_PIN_NUM_LCD_DATA0, - QSPI_PIN_NUM_LCD_DATA1, - QSPI_PIN_NUM_LCD_DATA2, - QSPI_PIN_NUM_LCD_DATA3, - QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - void Initializest77916Display() { - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGI(TAG, "Install panel IO"); - - esp_lcd_panel_io_spi_config_t io_config = { - .cs_gpio_num = QSPI_PIN_NUM_LCD_CS, - .dc_gpio_num = -1, - .spi_mode = 0, - .pclk_hz = 3 * 1000 * 1000, - .trans_queue_depth = 10, - .on_color_trans_done = NULL, - .user_ctx = NULL, - .lcd_cmd_bits = 32, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .octal_mode = 0, - .quad_mode = 1, - .sio_mode = 0, - .lsb_first = 0, - .cs_high_active = 0, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); - - ESP_LOGI(TAG, "Install ST77916 panel driver"); - - st77916_vendor_config_t vendor_config = { - .flags = { - .use_qspi_interface = 1, - }, - }; - - printf("-------------------------------------- Version selection -------------------------------------- \r\n"); - esp_err_t ret; - int lcd_cmd = 0x04; - uint8_t register_data[4]; - size_t param_size = sizeof(register_data); - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_READ_CMD << 24; // Use the read opcode instead of write - ret = esp_lcd_panel_io_rx_param(panel_io, lcd_cmd, register_data, param_size); - if (ret == ESP_OK) { - printf("Register 0x04 data: %02x %02x %02x %02x\n", register_data[0], register_data[1], register_data[2], register_data[3]); - } else { - printf("Failed to read register 0x04, error code: %d\n", ret); - } - // panel_io_spi_del(io_handle); - io_config.pclk_hz = 80 * 1000 * 1000; - if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io) != ESP_OK){ - printf("Failed to set LCD communication parameters -- SPI\r\n"); - return ; - } - printf("LCD communication parameters are set successfully -- SPI\r\n"); - - // Check register values and configure accordingly - if (register_data[0] == 0x00 && register_data[1] == 0x7F && register_data[2] == 0x7F && register_data[3] == 0x7F) { - // Handle the case where the register data matches this pattern - printf("Vendor-specific initialization for case 1.\n"); - } - else if (register_data[0] == 0x00 && register_data[1] == 0x02 && register_data[2] == 0x7F && register_data[3] == 0x7F) { - // Provide vendor-specific initialization commands if register data matches this pattern - vendor_config.init_cmds = vendor_specific_init_new; - vendor_config.init_cmds_size = sizeof(vendor_specific_init_new) / sizeof(st77916_lcd_init_cmd_t); - printf("Vendor-specific initialization for case 2.\n"); - } - printf("------------------------------------- End of version selection------------------------------------- \r\n"); - - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` - .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18) - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtonsCustom() { - gpio_reset_pin(BOOT_BUTTON_GPIO); - gpio_set_direction(BOOT_BUTTON_GPIO, GPIO_MODE_INPUT); - gpio_reset_pin(PWR_BUTTON_GPIO); - gpio_set_direction(PWR_BUTTON_GPIO, GPIO_MODE_INPUT); - gpio_reset_pin(PWR_Control_PIN); - gpio_set_direction(PWR_Control_PIN, GPIO_MODE_OUTPUT); - // gpio_set_level(PWR_Control_PIN, false); - gpio_set_level(PWR_Control_PIN, true); - } - void InitializeButtons() { - instance_ = this; - InitializeButtonsCustom(); - - // Boot Button - button_config_t boot_btn_config = { - .long_press_time = 2000, - .short_press_time = 0 - }; - boot_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - boot_btn_driver_->enable_power_save = false; - boot_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !gpio_get_level(BOOT_BUTTON_GPIO); - }; - ESP_ERROR_CHECK(iot_button_create(&boot_btn_config, boot_btn_driver_, &boot_btn)); - iot_button_register_cb(boot_btn, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }, this); - - // Power Button - button_config_t pwr_btn_config = { - .long_press_time = 5000, - .short_press_time = 0 - }; - pwr_btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - pwr_btn_driver_->enable_power_save = false; - pwr_btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !gpio_get_level(PWR_BUTTON_GPIO); - }; - ESP_ERROR_CHECK(iot_button_create(&pwr_btn_config, pwr_btn_driver_, &pwr_btn)); - iot_button_register_cb(pwr_btn, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - if(self->GetBacklight()->brightness() > 0) { - self->GetBacklight()->SetBrightness(0); - gpio_set_level(PWR_Control_PIN, false); - } - else { - self->GetBacklight()->RestoreBrightness(); - gpio_set_level(PWR_Control_PIN, true); - } - }, this); - } - -public: - CustomBoard() { - InitializeI2c(); - InitializeTca9554(); - InitializeSpi(); - Initializest77916Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, I2S_STD_SLOT_BOTH, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN, I2S_STD_SLOT_RIGHT); // I2S_STD_SLOT_LEFT / I2S_STD_SLOT_RIGHT / I2S_STD_SLOT_BOTH - - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(CustomBoard); - -CustomBoard* CustomBoard::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/README.md deleted file mode 100644 index 7668dec1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-1.85C -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-1.85C.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.h deleted file mode 100644 index dfd5a891..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_2 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_15 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_47 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_48 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_38 - -#define I2C_SCL_IO GPIO_NUM_10 -#define I2C_SDA_IO GPIO_NUM_11 - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 - -#define DISPLAY_WIDTH 360 -#define DISPLAY_HEIGHT 360 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define QSPI_LCD_H_RES (360) -#define QSPI_LCD_V_RES (360) -#define QSPI_LCD_BIT_PER_PIXEL (16) - -#define QSPI_LCD_HOST SPI2_HOST -#define QSPI_PIN_NUM_LCD_PCLK GPIO_NUM_40 -#define QSPI_PIN_NUM_LCD_CS GPIO_NUM_21 -#define QSPI_PIN_NUM_LCD_DATA0 GPIO_NUM_46 -#define QSPI_PIN_NUM_LCD_DATA1 GPIO_NUM_45 -#define QSPI_PIN_NUM_LCD_DATA2 GPIO_NUM_42 -#define QSPI_PIN_NUM_LCD_DATA3 GPIO_NUM_41 -#define QSPI_PIN_NUM_LCD_RST GPIO_NUM_NC -#define QSPI_PIN_NUM_LCD_BL GPIO_NUM_5 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define TP_PORT (I2C_NUM_1) -#define TP_PIN_NUM_SDA (I2C_SDA_IO) -#define TP_PIN_NUM_SCL (I2C_SCL_IO) -#define TP_PIN_NUM_RST (GPIO_NUM_NC) -#define TP_PIN_NUM_INT (GPIO_NUM_4) - -#define DISPLAY_BACKLIGHT_PIN QSPI_PIN_NUM_LCD_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.json deleted file mode 100644 index 18327997..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32-s3-touch-lcd-1.85c", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/esp32-s3-touch-lcd-1.85c.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/esp32-s3-touch-lcd-1.85c.cc deleted file mode 100644 index 6706879b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-1.85c/esp32-s3-touch-lcd-1.85c.cc +++ /dev/null @@ -1,396 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" - -#define TAG "waveshare_lcd_1_85c" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x0BULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const st77916_lcd_init_cmd_t vendor_specific_init_new[] = { - {0xF0, (uint8_t []){0x28}, 1, 0}, - {0xF2, (uint8_t []){0x28}, 1, 0}, - {0x73, (uint8_t []){0xF0}, 1, 0}, - {0x7C, (uint8_t []){0xD1}, 1, 0}, - {0x83, (uint8_t []){0xE0}, 1, 0}, - {0x84, (uint8_t []){0x61}, 1, 0}, - {0xF2, (uint8_t []){0x82}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x01}, 1, 0}, - {0xF1, (uint8_t []){0x01}, 1, 0}, - {0xB0, (uint8_t []){0x56}, 1, 0}, - {0xB1, (uint8_t []){0x4D}, 1, 0}, - {0xB2, (uint8_t []){0x24}, 1, 0}, - {0xB4, (uint8_t []){0x87}, 1, 0}, - {0xB5, (uint8_t []){0x44}, 1, 0}, - {0xB6, (uint8_t []){0x8B}, 1, 0}, - {0xB7, (uint8_t []){0x40}, 1, 0}, - {0xB8, (uint8_t []){0x86}, 1, 0}, - {0xBA, (uint8_t []){0x00}, 1, 0}, - {0xBB, (uint8_t []){0x08}, 1, 0}, - {0xBC, (uint8_t []){0x08}, 1, 0}, - {0xBD, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x80}, 1, 0}, - {0xC1, (uint8_t []){0x10}, 1, 0}, - {0xC2, (uint8_t []){0x37}, 1, 0}, - {0xC3, (uint8_t []){0x80}, 1, 0}, - {0xC4, (uint8_t []){0x10}, 1, 0}, - {0xC5, (uint8_t []){0x37}, 1, 0}, - {0xC6, (uint8_t []){0xA9}, 1, 0}, - {0xC7, (uint8_t []){0x41}, 1, 0}, - {0xC8, (uint8_t []){0x01}, 1, 0}, - {0xC9, (uint8_t []){0xA9}, 1, 0}, - {0xCA, (uint8_t []){0x41}, 1, 0}, - {0xCB, (uint8_t []){0x01}, 1, 0}, - {0xD0, (uint8_t []){0x91}, 1, 0}, - {0xD1, (uint8_t []){0x68}, 1, 0}, - {0xD2, (uint8_t []){0x68}, 1, 0}, - {0xF5, (uint8_t []){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t []){0x4F}, 1, 0}, - {0xDE, (uint8_t []){0x4F}, 1, 0}, - {0xF1, (uint8_t []){0x10}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, - {0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, - {0xF0, (uint8_t []){0x10}, 1, 0}, - {0xF3, (uint8_t []){0x10}, 1, 0}, - {0xE0, (uint8_t []){0x07}, 1, 0}, - {0xE1, (uint8_t []){0x00}, 1, 0}, - {0xE2, (uint8_t []){0x00}, 1, 0}, - {0xE3, (uint8_t []){0x00}, 1, 0}, - {0xE4, (uint8_t []){0xE0}, 1, 0}, - {0xE5, (uint8_t []){0x06}, 1, 0}, - {0xE6, (uint8_t []){0x21}, 1, 0}, - {0xE7, (uint8_t []){0x01}, 1, 0}, - {0xE8, (uint8_t []){0x05}, 1, 0}, - {0xE9, (uint8_t []){0x02}, 1, 0}, - {0xEA, (uint8_t []){0xDA}, 1, 0}, - {0xEB, (uint8_t []){0x00}, 1, 0}, - {0xEC, (uint8_t []){0x00}, 1, 0}, - {0xED, (uint8_t []){0x0F}, 1, 0}, - {0xEE, (uint8_t []){0x00}, 1, 0}, - {0xEF, (uint8_t []){0x00}, 1, 0}, - {0xF8, (uint8_t []){0x00}, 1, 0}, - {0xF9, (uint8_t []){0x00}, 1, 0}, - {0xFA, (uint8_t []){0x00}, 1, 0}, - {0xFB, (uint8_t []){0x00}, 1, 0}, - {0xFC, (uint8_t []){0x00}, 1, 0}, - {0xFD, (uint8_t []){0x00}, 1, 0}, - {0xFE, (uint8_t []){0x00}, 1, 0}, - {0xFF, (uint8_t []){0x00}, 1, 0}, - {0x60, (uint8_t []){0x40}, 1, 0}, - {0x61, (uint8_t []){0x04}, 1, 0}, - {0x62, (uint8_t []){0x00}, 1, 0}, - {0x63, (uint8_t []){0x42}, 1, 0}, - {0x64, (uint8_t []){0xD9}, 1, 0}, - {0x65, (uint8_t []){0x00}, 1, 0}, - {0x66, (uint8_t []){0x00}, 1, 0}, - {0x67, (uint8_t []){0x00}, 1, 0}, - {0x68, (uint8_t []){0x00}, 1, 0}, - {0x69, (uint8_t []){0x00}, 1, 0}, - {0x6A, (uint8_t []){0x00}, 1, 0}, - {0x6B, (uint8_t []){0x00}, 1, 0}, - {0x70, (uint8_t []){0x40}, 1, 0}, - {0x71, (uint8_t []){0x03}, 1, 0}, - {0x72, (uint8_t []){0x00}, 1, 0}, - {0x73, (uint8_t []){0x42}, 1, 0}, - {0x74, (uint8_t []){0xD8}, 1, 0}, - {0x75, (uint8_t []){0x00}, 1, 0}, - {0x76, (uint8_t []){0x00}, 1, 0}, - {0x77, (uint8_t []){0x00}, 1, 0}, - {0x78, (uint8_t []){0x00}, 1, 0}, - {0x79, (uint8_t []){0x00}, 1, 0}, - {0x7A, (uint8_t []){0x00}, 1, 0}, - {0x7B, (uint8_t []){0x00}, 1, 0}, - {0x80, (uint8_t []){0x48}, 1, 0}, - {0x81, (uint8_t []){0x00}, 1, 0}, - {0x82, (uint8_t []){0x06}, 1, 0}, - {0x83, (uint8_t []){0x02}, 1, 0}, - {0x84, (uint8_t []){0xD6}, 1, 0}, - {0x85, (uint8_t []){0x04}, 1, 0}, - {0x86, (uint8_t []){0x00}, 1, 0}, - {0x87, (uint8_t []){0x00}, 1, 0}, - {0x88, (uint8_t []){0x48}, 1, 0}, - {0x89, (uint8_t []){0x00}, 1, 0}, - {0x8A, (uint8_t []){0x08}, 1, 0}, - {0x8B, (uint8_t []){0x02}, 1, 0}, - {0x8C, (uint8_t []){0xD8}, 1, 0}, - {0x8D, (uint8_t []){0x04}, 1, 0}, - {0x8E, (uint8_t []){0x00}, 1, 0}, - {0x8F, (uint8_t []){0x00}, 1, 0}, - {0x90, (uint8_t []){0x48}, 1, 0}, - {0x91, (uint8_t []){0x00}, 1, 0}, - {0x92, (uint8_t []){0x0A}, 1, 0}, - {0x93, (uint8_t []){0x02}, 1, 0}, - {0x94, (uint8_t []){0xDA}, 1, 0}, - {0x95, (uint8_t []){0x04}, 1, 0}, - {0x96, (uint8_t []){0x00}, 1, 0}, - {0x97, (uint8_t []){0x00}, 1, 0}, - {0x98, (uint8_t []){0x48}, 1, 0}, - {0x99, (uint8_t []){0x00}, 1, 0}, - {0x9A, (uint8_t []){0x0C}, 1, 0}, - {0x9B, (uint8_t []){0x02}, 1, 0}, - {0x9C, (uint8_t []){0xDC}, 1, 0}, - {0x9D, (uint8_t []){0x04}, 1, 0}, - {0x9E, (uint8_t []){0x00}, 1, 0}, - {0x9F, (uint8_t []){0x00}, 1, 0}, - {0xA0, (uint8_t []){0x48}, 1, 0}, - {0xA1, (uint8_t []){0x00}, 1, 0}, - {0xA2, (uint8_t []){0x05}, 1, 0}, - {0xA3, (uint8_t []){0x02}, 1, 0}, - {0xA4, (uint8_t []){0xD5}, 1, 0}, - {0xA5, (uint8_t []){0x04}, 1, 0}, - {0xA6, (uint8_t []){0x00}, 1, 0}, - {0xA7, (uint8_t []){0x00}, 1, 0}, - {0xA8, (uint8_t []){0x48}, 1, 0}, - {0xA9, (uint8_t []){0x00}, 1, 0}, - {0xAA, (uint8_t []){0x07}, 1, 0}, - {0xAB, (uint8_t []){0x02}, 1, 0}, - {0xAC, (uint8_t []){0xD7}, 1, 0}, - {0xAD, (uint8_t []){0x04}, 1, 0}, - {0xAE, (uint8_t []){0x00}, 1, 0}, - {0xAF, (uint8_t []){0x00}, 1, 0}, - {0xB0, (uint8_t []){0x48}, 1, 0}, - {0xB1, (uint8_t []){0x00}, 1, 0}, - {0xB2, (uint8_t []){0x09}, 1, 0}, - {0xB3, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0xD9}, 1, 0}, - {0xB5, (uint8_t []){0x04}, 1, 0}, - {0xB6, (uint8_t []){0x00}, 1, 0}, - {0xB7, (uint8_t []){0x00}, 1, 0}, - - {0xB8, (uint8_t []){0x48}, 1, 0}, - {0xB9, (uint8_t []){0x00}, 1, 0}, - {0xBA, (uint8_t []){0x0B}, 1, 0}, - {0xBB, (uint8_t []){0x02}, 1, 0}, - {0xBC, (uint8_t []){0xDB}, 1, 0}, - {0xBD, (uint8_t []){0x04}, 1, 0}, - {0xBE, (uint8_t []){0x00}, 1, 0}, - {0xBF, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x10}, 1, 0}, - {0xC1, (uint8_t []){0x47}, 1, 0}, - {0xC2, (uint8_t []){0x56}, 1, 0}, - {0xC3, (uint8_t []){0x65}, 1, 0}, - {0xC4, (uint8_t []){0x74}, 1, 0}, - {0xC5, (uint8_t []){0x88}, 1, 0}, - {0xC6, (uint8_t []){0x99}, 1, 0}, - {0xC7, (uint8_t []){0x01}, 1, 0}, - {0xC8, (uint8_t []){0xBB}, 1, 0}, - {0xC9, (uint8_t []){0xAA}, 1, 0}, - {0xD0, (uint8_t []){0x10}, 1, 0}, - {0xD1, (uint8_t []){0x47}, 1, 0}, - {0xD2, (uint8_t []){0x56}, 1, 0}, - {0xD3, (uint8_t []){0x65}, 1, 0}, - {0xD4, (uint8_t []){0x74}, 1, 0}, - {0xD5, (uint8_t []){0x88}, 1, 0}, - {0xD6, (uint8_t []){0x99}, 1, 0}, - {0xD7, (uint8_t []){0x01}, 1, 0}, - {0xD8, (uint8_t []){0xBB}, 1, 0}, - {0xD9, (uint8_t []){0xAA}, 1, 0}, - {0xF3, (uint8_t []){0x01}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0x21, (uint8_t []){0x00}, 1, 0}, - {0x11, (uint8_t []){0x00}, 1, 120}, - {0x29, (uint8_t []){0x00}, 1, 0}, -}; - -class CustomBoard : public WifiBoard { -private: - Button boot_button_; - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = I2C_SDA_IO, - .scl_io_num = I2C_SCL_IO, - .clk_source = I2C_CLK_SRC_DEFAULT, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) - { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - - // uint32_t input_level_mask = 0; - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_INPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输入 - // ret = esp_io_expander_get_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, &input_level_mask); // 获取引脚 EXIO0 和 EXIO1 的电平状态,存放在 input_level_mask 中 - - // ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO2 和 EXIO3 模式为输出 - // ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, 1); // 将引脚电平设置为 1 - // ret = esp_io_expander_print_state(io_expander); // 打印引脚状态 - - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输出 - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(300)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - - const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, - QSPI_PIN_NUM_LCD_DATA0, - QSPI_PIN_NUM_LCD_DATA1, - QSPI_PIN_NUM_LCD_DATA2, - QSPI_PIN_NUM_LCD_DATA3, - QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - void Initializest77916Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGI(TAG, "Install panel IO"); - - esp_lcd_panel_io_spi_config_t io_config = { - .cs_gpio_num = QSPI_PIN_NUM_LCD_CS, - .dc_gpio_num = -1, - .spi_mode = 0, - .pclk_hz = 3 * 1000 * 1000, - .trans_queue_depth = 10, - .on_color_trans_done = NULL, - .user_ctx = NULL, - .lcd_cmd_bits = 32, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .octal_mode = 0, - .quad_mode = 1, - .sio_mode = 0, - .lsb_first = 0, - .cs_high_active = 0, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); - - ESP_LOGI(TAG, "Install ST77916 panel driver"); - - st77916_vendor_config_t vendor_config = { - .flags = { - .use_qspi_interface = 1, - }, - }; - - printf("-------------------------------------- Version selection -------------------------------------- \r\n"); - esp_err_t ret; - int lcd_cmd = 0x04; - uint8_t register_data[4]; - size_t param_size = sizeof(register_data); - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_READ_CMD << 24; // Use the read opcode instead of write - ret = esp_lcd_panel_io_rx_param(panel_io, lcd_cmd, register_data, param_size); - if (ret == ESP_OK) { - printf("Register 0x04 data: %02x %02x %02x %02x\n", register_data[0], register_data[1], register_data[2], register_data[3]); - } else { - printf("Failed to read register 0x04, error code: %d\n", ret); - } - // panel_io_spi_del(io_handle); - io_config.pclk_hz = 80 * 1000 * 1000; - if (esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io) != ESP_OK) { - printf("Failed to set LCD communication parameters -- SPI\r\n"); - return ; - } - printf("LCD communication parameters are set successfully -- SPI\r\n"); - - // Check register values and configure accordingly - if (register_data[0] == 0x00 && register_data[1] == 0x7F && register_data[2] == 0x7F && register_data[3] == 0x7F) { - // Handle the case where the register data matches this pattern - printf("Vendor-specific initialization for case 1.\n"); - } - else if (register_data[0] == 0x00 && register_data[1] == 0x02 && register_data[2] == 0x7F && register_data[3] == 0x7F) { - // Provide vendor-specific initialization commands if register data matches this pattern - vendor_config.init_cmds = vendor_specific_init_new; - vendor_config.init_cmds_size = sizeof(vendor_specific_init_new) / sizeof(st77916_lcd_init_cmd_t); - printf("Vendor-specific initialization for case 2.\n"); - } - printf("------------------------------------- End of version selection------------------------------------- \r\n"); - - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` - .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18) - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeTca9554(); - InitializeSpi(); - Initializest77916Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, I2S_STD_SLOT_LEFT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN, I2S_STD_SLOT_RIGHT); // I2S_STD_SLOT_LEFT / I2S_STD_SLOT_RIGHT / I2S_STD_SLOT_BOTH - - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/README.md deleted file mode 100644 index 78b69495..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-3.5 -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-3.5.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.h deleted file mode 100644 index 78529040..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_15 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_16 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SPI_MODE 0 -#define DISPLAY_CS_PIN GPIO_NUM_NC -#define DISPLAY_MOSI_PIN GPIO_NUM_1 -#define DISPLAY_MISO_PIN GPIO_NUM_2 -#define DISPLAY_CLK_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_3 -#define DISPLAY_RST_PIN GPIO_NUM_NC - - - -#define DISPLAY_WIDTH 480 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_BGR -#define DISPLAY_INVERT_COLOR true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_6 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#define CAM_PIN_PWDN GPIO_NUM_NC -#define CAM_PIN_RESET GPIO_NUM_NC -#define CAM_PIN_VSYNC GPIO_NUM_17 -#define CAM_PIN_HREF GPIO_NUM_18 -#define CAM_PIN_PCLK GPIO_NUM_41 -#define CAM_PIN_XCLK GPIO_NUM_38 -#define CAM_PIN_SIOD GPIO_NUM_NC -#define CAM_PIN_SIOC GPIO_NUM_NC -#define CAM_PIN_D0 GPIO_NUM_45 -#define CAM_PIN_D1 GPIO_NUM_47 -#define CAM_PIN_D2 GPIO_NUM_48 -#define CAM_PIN_D3 GPIO_NUM_46 -#define CAM_PIN_D4 GPIO_NUM_42 -#define CAM_PIN_D5 GPIO_NUM_40 -#define CAM_PIN_D6 GPIO_NUM_39 -#define CAM_PIN_D7 GPIO_NUM_21 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.json deleted file mode 100644 index 7c6e5f17..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32-s3-touch-lcd-3.5", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_640X480_6FPS=y", - "CONFIG_CAMERA_OV2640_DVP_IF_FORMAT_INDEX_DEFAULT=1", - "CONFIG_CAMERA_OV5640=y", - "CONFIG_CAMERA_OV5640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5640_DVP_YUV422_800X600_10FPS=y", - "CONFIG_CAMERA_OV5640_DVP_IF_FORMAT_INDEX_DEFAULT=0" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/esp32-s3-touch-lcd-3.5.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/esp32-s3-touch-lcd-3.5.cc deleted file mode 100644 index 66e49dc8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32-s3-touch-lcd-3.5/esp32-s3-touch-lcd-3.5.cc +++ /dev/null @@ -1,373 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "mcp_server.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include - -#include -#include "esp_io_expander_tca9554.h" - -#include "axp2101.h" -#include "power_save_timer.h" - -#include -#include - -#include "esp32_camera.h" - -#define TAG "waveshare_lcd_3_5" - -class Pmic : public Axp2101 { - public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - WriteReg(0x96, (1500 - 500) / 100); - WriteReg(0x97, (2800 - 500) / 100); - - // Enable ALDO1 BLDO1 BLDO2 - WriteReg(0x90, 0x31); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } - }; - -typedef struct { - int cmd; /*OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) - { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_1, 1); - ESP_ERROR_CHECK(ret); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = DISPLAY_MISO_PIN; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAM_PIN_D0, - [1] = CAM_PIN_D1, - [2] = CAM_PIN_D2, - [3] = CAM_PIN_D3, - [4] = CAM_PIN_D4, - [5] = CAM_PIN_D5, - [6] = CAM_PIN_D6, - [7] = CAM_PIN_D7, - }, - .vsync_io = CAM_PIN_VSYNC, - .de_io = CAM_PIN_HREF, - .pclk_io = CAM_PIN_PCLK, - .xclk_io = CAM_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // 不初始化新的 SCCB,使用现有的 I2C 总线 - .i2c_handle = i2c_bus_, // 使用现有的 I2C 总线句柄 - .freq = 100000, // 100kHz - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAM_PIN_RESET, - .pwdn_pin = CAM_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = 12000000, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - - } - - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 1, - .mirror_x = 1, - .mirror_y = 1, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - st7796_vendor_config_t st7796_vendor_config = { - .init_cmds = st7796_lcd_init_cmds, - .init_cmds_size = sizeof(st7796_lcd_init_cmds) / sizeof(st7796_lcd_init_cmd_t), - }; - - // 初始化液晶屏驱动芯片 - ESP_LOGI(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &st7796_vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeTca9554(); - InitializeAxp2101(); - InitializeSpi(); - InitializeLcdDisplay(); - // 解决部分开机黑屏的问题 - if (esp_reset_reason() == ESP_RST_POWERON) { - fflush(stdout); - esp_restart(); - } - InitializeTouch(); - InitializeButtons(); - InitializeCamera(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.h deleted file mode 100644 index afb1dfab..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.h +++ /dev/null @@ -1,81 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_48 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_17 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_18 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_5 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#ifdef CONFIG_ESP32S3_KORVO2_V3_LCD_ST7789 -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 280 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY true -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define BACKLIGHT_INVERT false - -#define DISPLAY_OFFSET_X 20 -#define DISPLAY_OFFSET_Y 0 -#endif - -#ifdef CONFIG_ESP32S3_KORVO2_V3_LCD_ILI9341 -#define LCD_TYPE_ILI9341_SERIAL -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define BACKLIGHT_INVERT false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#endif - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -/* Camera pins */ -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_XCLK GPIO_NUM_40 -#define CAMERA_PIN_SIOD GPIO_NUM_17 -#define CAMERA_PIN_SIOC GPIO_NUM_18 - -#define CAMERA_PIN_D7 GPIO_NUM_39 -#define CAMERA_PIN_D6 GPIO_NUM_41 -#define CAMERA_PIN_D5 GPIO_NUM_42 -#define CAMERA_PIN_D4 GPIO_NUM_12 -#define CAMERA_PIN_D3 GPIO_NUM_3 -#define CAMERA_PIN_D2 GPIO_NUM_14 -#define CAMERA_PIN_D1 GPIO_NUM_47 -#define CAMERA_PIN_D0 GPIO_NUM_13 -#define CAMERA_PIN_VSYNC GPIO_NUM_21 -#define CAMERA_PIN_HREF GPIO_NUM_38 -#define CAMERA_PIN_PCLK GPIO_NUM_11 - -#define XCLK_FREQ_HZ 20000000 -#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.json deleted file mode 100644 index 8b967ffd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "esp32s3-korvo2-v3", - "sdkconfig_append": [ - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV3660=y", - "CONFIG_CAMERA_OV3660_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV3660_DVP_RGB565_240X240_24FPS=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_RGB565_240X240_25FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/esp32s3_korvo2_v3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/esp32s3_korvo2_v3_board.cc deleted file mode 100644 index 801c5ddf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/esp32s3_korvo2_v3_board.cc +++ /dev/null @@ -1,456 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include "esp32_camera.h" -#include "power_manager.h" -#include "power_save_timer.h" - -#define TAG "esp32s3_korvo2_v3" -/* ADC Buttons */ -typedef enum { - BSP_ADC_BUTTON_REC, - BSP_ADC_BUTTON_VOL_MUTE, - BSP_ADC_BUTTON_PLAY, - BSP_ADC_BUTTON_SET, - BSP_ADC_BUTTON_VOL_DOWN, - BSP_ADC_BUTTON_VOL_UP, - BSP_ADC_BUTTON_NUM -} bsp_adc_button_t; - -// Init ili9341 by custom cmd -static const ili9341_lcd_init_cmd_t vendor_specific_init[] = { - {0xC8, (uint8_t []){0xFF, 0x93, 0x42}, 3, 0}, - {0xC0, (uint8_t []){0x0E, 0x0E}, 2, 0}, - {0xC5, (uint8_t []){0xD0}, 1, 0}, - {0xC1, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0x00, 0x03, 0x08, 0x06, 0x13, 0x09, 0x39, 0x39, 0x48, 0x02, 0x0a, 0x08, 0x17, 0x17, 0x0F}, 15, 0}, - {0xE1, (uint8_t []){0x00, 0x28, 0x29, 0x01, 0x0d, 0x03, 0x3f, 0x33, 0x52, 0x04, 0x0f, 0x0e, 0x37, 0x38, 0x0F}, 15, 0}, - - {0xB1, (uint8_t []){00, 0x1B}, 2, 0}, - {0x36, (uint8_t []){0x08}, 1, 0}, - {0x3A, (uint8_t []){0x55}, 1, 0}, - {0xB7, (uint8_t []){0x06}, 1, 0}, - - {0x11, (uint8_t []){0}, 0x80, 0}, - {0x29, (uint8_t []){0}, 0x80, 0}, - - {0, (uint8_t []){0}, 0xff, 0}, -}; - -class Esp32S3Korvo2V3Board : public WifiBoard { -private: - Button boot_button_; - Button* adc_button_[BSP_ADC_BUTTON_NUM]; -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - adc_oneshot_unit_handle_t bsp_adc_handle = NULL; -#endif - i2c_master_bus_handle_t i2c_bus_; - LcdDisplay* display_; - esp_io_expander_handle_t io_expander_ = NULL; - Esp32Camera* camera_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - void InitializePowerManager() { - // PowerManager需要复用按钮的ADC句柄,所以在InitializeButtons之后调用 - // 传入按钮的ADC句柄指针,让PowerManager复用 - power_manager_ = new PowerManager(GPIO_NUM_NC, &bsp_adc_handle); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - void InitializeTca9554() { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000, &io_expander_); - if(ret != ESP_OK) { - ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9554A_ADDRESS_000, &io_expander_); - if(ret != ESP_OK) { - ESP_LOGE(TAG, "TCA9554 create returned error"); - return; - } - } - // 配置IO0-IO3为输出模式 - ESP_ERROR_CHECK(esp_io_expander_set_dir(io_expander_, - IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 | - IO_EXPANDER_PIN_NUM_2 | IO_EXPANDER_PIN_NUM_3, - IO_EXPANDER_OUTPUT)); - - // 复位LCD和TouchPad - ESP_ERROR_CHECK(esp_io_expander_set_level(io_expander_, - IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 | IO_EXPANDER_PIN_NUM_2, 1)); - vTaskDelay(pdMS_TO_TICKS(300)); - ESP_ERROR_CHECK(esp_io_expander_set_level(io_expander_, - IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 | IO_EXPANDER_PIN_NUM_2, 0)); - vTaskDelay(pdMS_TO_TICKS(300)); - ESP_ERROR_CHECK(esp_io_expander_set_level(io_expander_, - IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 | IO_EXPANDER_PIN_NUM_2, 1)); - } - - void EnableLcdCs() { - if(io_expander_ != NULL) { - esp_io_expander_set_level(io_expander_, IO_EXPANDER_PIN_NUM_3, 0);// 置低 LCD CS - } - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_0; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_1; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void ChangeVol(int val) { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + val; - if (volume > 100) { - volume = 100; - } - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - } - - void MuteVol() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume(); - if (volume > 1) { - volume = 0; - } else { - volume = 50; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - } - - void InitializeButtons() { - button_adc_config_t adc_cfg = {}; - adc_cfg.adc_channel = ADC_CHANNEL_4; // ADC1 channel 0 is GPIO5 -#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) - const adc_oneshot_unit_init_cfg_t init_config1 = { - .unit_id = ADC_UNIT_1, - }; - adc_oneshot_new_unit(&init_config1, &bsp_adc_handle); - adc_cfg.adc_handle = &bsp_adc_handle; -#endif - adc_cfg.button_index = BSP_ADC_BUTTON_REC; - adc_cfg.min = 2310; // middle is 2410mV - adc_cfg.max = 2510; - adc_button_[0] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_VOL_MUTE; - adc_cfg.min = 1880; // middle is 1980mV - adc_cfg.max = 2080; - adc_button_[1] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_PLAY; - adc_cfg.min = 1550; // middle is 1650mV - adc_cfg.max = 1750; - adc_button_[2] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_SET; - adc_cfg.min = 1015; // middle is 1115mV - adc_cfg.max = 1215; - adc_button_[3] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_VOL_DOWN; - adc_cfg.min = 720; // middle is 820mV - adc_cfg.max = 920; - adc_button_[4] = new AdcButton(adc_cfg); - - adc_cfg.button_index = BSP_ADC_BUTTON_VOL_UP; - adc_cfg.min = 280; // middle is 380mV - adc_cfg.max = 480; - adc_button_[5] = new AdcButton(adc_cfg); - - auto volume_up_button = adc_button_[BSP_ADC_BUTTON_VOL_UP]; - volume_up_button->OnClick([this]() {ChangeVol(10);}); - volume_up_button->OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - auto volume_down_button = adc_button_[BSP_ADC_BUTTON_VOL_DOWN]; - volume_down_button->OnClick([this]() {ChangeVol(-10);}); - volume_down_button->OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - auto volume_mute_button = adc_button_[BSP_ADC_BUTTON_VOL_MUTE]; - volume_mute_button->OnClick([this]() {MuteVol();}); - - auto play_button = adc_button_[BSP_ADC_BUTTON_PLAY]; - play_button->OnClick([this]() { - ESP_LOGI(TAG, " TODO %s:%d\n", __func__, __LINE__); - }); - - auto set_button = adc_button_[BSP_ADC_BUTTON_SET]; - set_button->OnClick([this]() { - EnterWifiConfigMode(); - }); - - auto rec_button = adc_button_[BSP_ADC_BUTTON_REC]; - rec_button->OnClick([this]() { - Application::GetInstance().ToggleChatState(); - }); - boot_button_.OnClick([this]() {}); - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeIli9341Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_NC; - io_config.dc_gpio_num = GPIO_NUM_2; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const ili9341_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(ili9341_lcd_init_cmd_t), - }; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - // panel_config.flags.reset_active_high = 0, - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void *)&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - EnableLcdCs(); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_46; - io_config.dc_gpio_num = GPIO_NUM_2; - io_config.spi_mode = 0; - io_config.pclk_hz = 60 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - EnableLcdCs(); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - -public: - Esp32S3Korvo2V3Board() : boot_button_(BOOT_BUTTON_GPIO) { - ESP_LOGI(TAG, "Initializing esp32s3_korvo2_v3 Board"); - InitializePowerSaveTimer(); - InitializeI2c(); - I2cDetect(); - InitializeTca9554(); - InitializeCamera(); - InitializeSpi(); - InitializeButtons(); // 先初始化按钮(创建ADC1句柄) - InitializePowerManager(); // 后初始化PowerManager(复用ADC1句柄) - #ifdef LCD_TYPE_ILI9341_SERIAL - InitializeIli9341Display(); - #else - InitializeSt7789Display(); - #endif - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - virtual Camera* GetCamera() override { - return camera_; - } - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(Esp32S3Korvo2V3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/power_manager.h deleted file mode 100644 index 5c166409..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/esp32s3-korvo2-v3/power_manager.h +++ /dev/null @@ -1,250 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - bool adc_handle_owned_ = false; // 标记ADC句柄是否由本类创建 - adc_cali_handle_t adc_cali_handle_ = nullptr; // ADC校准句柄 - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_raw = 0; - int voltage_mv = 0; // ADC校准后的电压(mV) - - // 多次采样取平均,提高稳定性 - uint32_t adc_sum = 0; - const int sample_count = 10; - for (int i = 0; i < sample_count; i++) { - int temp_raw = 0; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_5, &temp_raw)); - adc_sum += temp_raw; - vTaskDelay(pdMS_TO_TICKS(10)); // 每次采样间隔10ms - } - adc_raw = adc_sum / sample_count; - - // 使用ADC校准获取准确电压 - if (adc_cali_handle_) { - ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_cali_handle_, adc_raw, &voltage_mv)); - } else { - // 如果没有校准,使用线性计算 - voltage_mv = (int)(adc_raw * 3300.0f / 4095.0f); - } - - // 根据分压比计算实际电池电压 - // 电路分压比: R21/(R20+R21) = 100K/300K = 1/3 - // 实际电池电压 = ADC测量电压 × 3 - int battery_voltage_mv = voltage_mv * 3; - - // 将电压值添加到队列中用于平滑 - adc_values_.push_back(battery_voltage_mv); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - - uint32_t average_voltage = 0; - for (auto value : adc_values_) { - average_voltage += value; - } - average_voltage /= adc_values_.size(); - - // 定义电池电量区间(基于实际电池电压,单位mV) - const struct { - uint16_t voltage_mv; // 电池电压(mV) - uint8_t level; // 电量百分比 - } levels[] = { - {3500, 0}, // 3.5V - {3640, 20}, // 3.64V - {3760, 40}, // 3.76V - {3880, 60}, // 3.88V - {4000, 80}, // 4.0V - {4200, 100} // 4.2V - }; - - // 低于最低值时 - if (average_voltage < levels[0].voltage_mv) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_voltage >= levels[5].voltage_mv) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_voltage >= levels[i].voltage_mv && average_voltage < levels[i+1].voltage_mv) { - float ratio = static_cast(average_voltage - levels[i].voltage_mv) / - (levels[i+1].voltage_mv - levels[i].voltage_mv); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC raw: %d, ADC voltage: %dmV, Battery: %ldmV (%.2fV), level: %ld%%", - adc_raw, voltage_mv, average_voltage, average_voltage/1000.0f, battery_level_); - } - -public: - // 构造函数:使用外部ADC句柄(用于复用已存在的ADC) - PowerManager(gpio_num_t pin, adc_oneshot_unit_handle_t* external_adc_handle = nullptr) - : charging_pin_(pin), adc_handle_owned_(false) { - if(charging_pin_ != GPIO_NUM_NC){ - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - } - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化或复用 ADC - if (external_adc_handle != nullptr && *external_adc_handle != nullptr) { - // 复用外部ADC句柄 - adc_handle_ = *external_adc_handle; - adc_handle_owned_ = false; - } else { - // 创建新的ADC句柄 - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, // GPIO6 对应 ADC1 - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - adc_handle_owned_ = true; - } - - // 配置ADC通道 - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_5, &chan_config)); // GPIO6 = ADC1_CHANNEL_5 - - // 初始化ADC校准 - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = ADC_UNIT_1, - .chan = ADC_CHANNEL_5, - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - esp_err_t ret = adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle_); - if (ret == ESP_OK) { - ESP_LOGI("PowerManager", "ADC calibration initialized successfully"); - } else { - ESP_LOGW("PowerManager", "ADC calibration failed, using linear calculation"); - adc_cali_handle_ = nullptr; - } - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - // 删除ADC校准句柄 - if (adc_cali_handle_) { - adc_cali_delete_scheme_curve_fitting(adc_cali_handle_); - } - // 只有当ADC句柄是本类创建的时候才删除 - if (adc_handle_ && adc_handle_owned_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.h deleted file mode 100644 index 4f3aad82..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_11 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_10 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_21 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_9 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_1 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_42 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_41 - -#define DISPLAY_SDA GPIO_NUM_3 -#define DISPLAY_SCL GPIO_NUM_4 -#define DISPLAY_DC GPIO_NUM_5 -#define DISPLAY_CS GPIO_NUM_6 -#define DISPLAY_RES GPIO_NUM_7 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_2 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.json deleted file mode 100644 index a8c65f8a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "genjutech-s3-1.54tft", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/genjutech-s3-1.54tft.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/genjutech-s3-1.54tft.cc deleted file mode 100644 index 2d7ed922..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/genjutech-s3-1.54tft.cc +++ /dev/null @@ -1,259 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include -#include -#include -#include -#include "power_save_timer.h" - -#include "assets/lang_config.h" -#include "power_manager.h" - -#define TAG "GenJuTech_s3_1_54TFT" - -class SparkBotEs8311AudioCodec : public Es8311AudioCodec { - private: - - public: - SparkBotEs8311AudioCodec(void* i2c_master_handle, i2c_port_t i2c_port, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, bool use_mclk = true) - : Es8311AudioCodec(i2c_master_handle, i2c_port, input_sample_rate, output_sample_rate, - mclk, bclk, ws, dout, din,pa_pin, es8311_addr, use_mclk = true) {} - - void EnableOutput(bool enable) override { - if (enable == output_enabled_) { - return; - } - if (enable) { - Es8311AudioCodec::EnableOutput(enable); - } else { - // Nothing todo because the display io and PA io conflict - } - } - }; - -class GenJuTech_s3_1_54TFT : public WifiBoard { -private: - // i2c_master_bus_handle_t display_i2c_bus_; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - LcdDisplay* display_; - i2c_master_bus_handle_t codec_i2c_bus_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_16); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - // 第一个参数不为 -1 时,进入睡眠会关闭音频输入 - power_save_timer_ = new PowerSaveTimer(240, 60); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - // boot_button_.OnPressDown([this]() { - // Application::GetInstance().StartListening(); - // }); - // boot_button_.OnPressUp([this]() { - // Application::GetInstance().StopListening(); - // }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - gpio_config_t config = { - .pin_bit_mask = (1ULL << DISPLAY_RES), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&config)); - gpio_set_level(DISPLAY_RES, 0); - vTaskDelay(20); - gpio_set_level(DISPLAY_RES, 1); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - GenJuTech_s3_1_54TFT() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - ESP_LOGI(TAG, "Initializing GenJuTech S3 1.54 Board"); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static SparkBotEs8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(GenJuTech_s3_1_54TFT); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/power_manager.h deleted file mode 100644 index f2e385d4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/genjutech-s3-1.54tft/power_manager.h +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_4, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1280, 0}, - {1334, 20}, - {1388, 40}, - {1442, 60}, - {1496, 80}, - {1550, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_2, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_4, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/README.md deleted file mode 100644 index 8dfe0667..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/README.md +++ /dev/null @@ -1,7 +0,0 @@ - -[product](https://fr.aliexpress.com/item/1005010207331462.html) - -One of the cheapest kit in a watch form factor. - -## Programming ## -Before assembling the product, unglue the battery from the board to access the programming header. You'll need a ESP32 programming dongle with control of the EN and IO0 pins. The USB connector is not wired to the USB pins of the ESP32-S3 USB interface and can only be used for charging. diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.h deleted file mode 100644 index dff8b3fc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 -#define AUDIO_I2S_SPK_GPIO_CTLR GPIO_NUM_17 - - -#define TOUCH_BUTTON_GPIO GPIO_NUM_18 - -#define DISPLAY_SDA_PIN GPIO_NUM_41 -#define DISPLAY_SCL_PIN GPIO_NUM_42 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 - -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.json deleted file mode 100644 index 76167664..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "hu-087", - "sdkconfig_append": [] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/hu_087_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/hu_087_board.cc deleted file mode 100644 index a4ad5ce7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/hu-087/hu_087_board.cc +++ /dev/null @@ -1,151 +0,0 @@ -#include -#include -#include -#include - -#include "application.h" -#include "assets/lang_config.h" -#include "boards/common/wifi_board.h" -#include "button.h" -#include "codecs/no_audio_codec.h" -#include "config.h" -#include "display/oled_display.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "system_reset.h" - -#define TAG "Hu087Board" - -class Hu087Board : public WifiBoard { - private: - i2c_master_bus_handle_t display_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button touch_button_; - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = - { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = - { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK( - esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK( - esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void initializeAmpCtrl() { - gpio_config_t io_conf = { - .pin_bit_mask = (1ULL << AUDIO_I2S_SPK_GPIO_CTLR), // Select GPIO 2 - .mode = GPIO_MODE_OUTPUT, // Set as output - .pull_up_en = GPIO_PULLUP_ENABLE, // Disable pull-up - .pull_down_en = GPIO_PULLDOWN_DISABLE, // Disable pull-down - .intr_type = GPIO_INTR_DISABLE // Disable interrupts - }; - gpio_config(&io_conf); - gpio_set_level(AUDIO_I2S_SPK_GPIO_CTLR, 1); - }; - - void InitializeButtons() { - touch_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - touch_button_.OnLongPress([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } // Need to implement logic to lower volume - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + - std::to_string(volume)); - }); - } - - public: - Hu087Board() : touch_button_(TOUCH_BUTTON_GPIO) { - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - initializeAmpCtrl(); // Could control the amp ctrl pin throught voice - // detection i guess - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec( - AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, - AUDIO_I2S_SPK_GPIO_DOUT, I2S_STD_SLOT_RIGHT, AUDIO_I2S_MIC_GPIO_SCK, - AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN, I2S_STD_SLOT_RIGHT); - return &audio_codec; - } - - virtual Display* GetDisplay() override { return display_; } -}; - -DECLARE_BOARD(Hu087Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/README.md deleted file mode 100644 index 1675ebf1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# jiuchuan-xiaozhi-sound -九川科技小智AI音箱 - -## 🛠️ 编译指南 -**开发环境**:ESP-IDF v5.4.1 - -### 编译步骤: -> ⚠️ **提示**:若在编译过程中访问在线库失败,可以尝试切换加速器状态,或修改 [idf_component.yml] 文件,替换为国内镜像源。 - -1. 使用 VSCode 打开项目文件夹; -2. 清除工程(Clean Project); -3. 设置 ESP-IDF 版本为 `v5.4.1`; -4. 点击 VSCode 右下角提示,生成 [compile_commands.json] 文件; -5. 设置目标设备为 `[esp32s3] -> [JTAG]`; -6. 打开 **SDK Configuration Editor**; -7. 设置 **Board Type** 为 **九川科技**; -8. 保存配置并开始编译。 - -## 🔌 烧录步骤 -1. 使用数据线连接电脑与音箱; -2. 关闭设备电源后,长按电源键不松手; -3. 在烧录工具中选择对应的串口(COM Port); -4. 点击烧录按钮,选择 UART 模式; -5. 烧录完成前请勿松开电源键。 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.h deleted file mode 100644 index d6895277..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_13 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_12 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_42 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_1 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_2 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - - -#define BUILTIN_LED_GPIO GPIO_NUM_10 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_3 -#define PWR_EN_GPIO GPIO_NUM_5 -#define PWR_ADC_GPIO GPIO_NUM_4 -#define PWR_BUTTON_TIME 3000000U - -#define WIFI_BUTTON_GPIO GPIO_NUM_6 -#define CMD_BUTTON_GPIO GPIO_NUM_7 - - -#define DISPLAY_SPI_SCK_PIN GPIO_NUM_41 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_40 -#define DISPLAY_DC_PIN GPIO_NUM_39 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_9 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_46 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.json deleted file mode 100644 index d1f610fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "jiuchuan-s3", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.c deleted file mode 100644 index b8d0e9a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - - #include - #include - #include "sdkconfig.h" - #include - #if CONFIG_LCD_ENABLE_DEBUG_LOG - // The local log level must be defined before including esp_log.h - // Set the maximum log level for this source file - #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG - #endif - - #include "freertos/FreeRTOS.h" - #include "freertos/task.h" - #include "esp_lcd_panel_interface.h" - #include "esp_lcd_panel_io.h" - #include "esp_lcd_panel_vendor.h" - #include "esp_lcd_panel_ops.h" - #include "esp_lcd_panel_commands.h" - #include "driver/gpio.h" - #include "esp_log.h" - #include "esp_check.h" - #include "esp_compiler.h" - /* GC9309NA LCD controller driver for ESP-IDF - * SPDX-FileCopyrightText: 2024 Your Name - * SPDX-License-Identifier: Apache-2.0 - */ - - #include "freertos/FreeRTOS.h" - #include "freertos/task.h" - #include "esp_lcd_panel_interface.h" - #include "esp_lcd_panel_io.h" - #include "esp_check.h" - #include "driver/gpio.h" - - - // GC9309NA Command Set - #define GC9309NA_CMD_SLPIN 0x10 - #define GC9309NA_CMD_SLPOUT 0x11 - #define GC9309NA_CMD_INVOFF 0x20 - #define GC9309NA_CMD_INVON 0x21 - #define GC9309NA_CMD_DISPOFF 0x28 - #define GC9309NA_CMD_DISPON 0x29 - #define GC9309NA_CMD_CASET 0x2A - #define GC9309NA_CMD_RASET 0x2B - #define GC9309NA_CMD_RAMWR 0x2C - #define GC9309NA_CMD_MADCTL 0x36 - #define GC9309NA_CMD_COLMOD 0x3A - #define GC9309NA_CMD_TEOFF 0x34 - #define GC9309NA_CMD_TEON 0x35 - #define GC9309NA_CMD_WRDISBV 0x51 - #define GC9309NA_CMD_WRCTRLD 0x53 - - // Manufacturer Commands - #define GC9309NA_CMD_SETGAMMA1 0xF0 - #define GC9309NA_CMD_SETGAMMA2 0xF1 - #define GC9309NA_CMD_PWRCTRL1 0x67 - #define GC9309NA_CMD_PWRCTRL2 0x68 - #define GC9309NA_CMD_PWRCTRL3 0x66 - #define GC9309NA_CMD_PWRCTRL4 0xCA - #define GC9309NA_CMD_PWRCTRL5 0xCB - #define GC9309NA_CMD_DINVCTRL 0xB5 - #define GC9309NA_CMD_REG_ENABLE1 0xFE - #define GC9309NA_CMD_REG_ENABLE2 0xEF - - // 自检模式颜色定义 - - - static const char *TAG = "lcd_panel.gc9309na"; - - typedef struct { - esp_lcd_panel_t base; - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - bool reset_level; - int x_gap; - int y_gap; - uint8_t madctl_val; - uint8_t colmod_val; - uint16_t te_scanline; - uint8_t fb_bits_per_pixel; - } gc9309na_panel_t; - - static esp_err_t panel_gc9309na_del(esp_lcd_panel_t *panel); - static esp_err_t panel_gc9309na_reset(esp_lcd_panel_t *panel); - static esp_err_t panel_gc9309na_init(esp_lcd_panel_t *panel); - static esp_err_t panel_gc9309na_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); - static esp_err_t panel_gc9309na_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); - static esp_err_t panel_gc9309na_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); - static esp_err_t panel_gc9309na_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); - static esp_err_t panel_gc9309na_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); - static esp_err_t panel_gc9309na_disp_on_off(esp_lcd_panel_t *panel, bool off); - static esp_err_t panel_gc9309na_sleep(esp_lcd_panel_t *panel, bool sleep); - - - esp_err_t esp_lcd_new_panel_gc9309na(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) - { - esp_err_t ret = ESP_OK; - gc9309na_panel_t *gc9309 = NULL; - - ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid arg"); - - gc9309 = calloc(1, sizeof(gc9309na_panel_t)); - ESP_GOTO_ON_FALSE(gc9309, ESP_ERR_NO_MEM, err, TAG, "no mem"); - - - // Hardware reset GPIO config - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, - }; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "GPIO config failed"); - } - - gc9309->colmod_val = 0x55; // RGB565 - // Initial register values - - gc9309->fb_bits_per_pixel = 16; - gc9309->io = io; - gc9309->reset_gpio_num = panel_dev_config->reset_gpio_num; - gc9309->reset_level = panel_dev_config->flags.reset_active_high; - gc9309->x_gap = 0; - gc9309->y_gap = 0; - - // Function pointers - gc9309->base.del = panel_gc9309na_del; - gc9309->base.reset = panel_gc9309na_reset; - gc9309->base.init = panel_gc9309na_init; - gc9309->base.draw_bitmap = panel_gc9309na_draw_bitmap; - gc9309->base.invert_color = panel_gc9309na_invert_color; - gc9309->base.set_gap = panel_gc9309na_set_gap; - gc9309->base.mirror = panel_gc9309na_mirror; - gc9309->base.swap_xy = panel_gc9309na_swap_xy; - gc9309->base.disp_on_off = panel_gc9309na_disp_on_off; - gc9309->base.disp_sleep = panel_gc9309na_sleep; - - *ret_panel = &(gc9309->base); - ESP_LOGI(TAG, "New GC9309NA panel @%p", gc9309); - return ESP_OK; - - err: - if (gc9309) { - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(gc9309); - } - return ret; - } - - static esp_err_t panel_gc9309na_del(esp_lcd_panel_t *panel) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - - if (gc9309->reset_gpio_num >= 0) { - gpio_reset_pin(gc9309->reset_gpio_num); - } - free(gc9309); - ESP_LOGI(TAG, "Del GC9309NA panel"); - return ESP_OK; - } - - static esp_err_t panel_gc9309na_reset(esp_lcd_panel_t *panel) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - - if (gc9309->reset_gpio_num >= 0) { - // Hardware reset - gpio_set_level(gc9309->reset_gpio_num, gc9309->reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9309->reset_gpio_num, !gc9309->reset_level); - vTaskDelay(pdMS_TO_TICKS(120)); - } else { - // Software reset - // uint8_t unlock_cmd[] = {GC9309NA_CMD_REG_ENABLE1, GC9309NA_CMD_REG_ENABLE2}; - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(gc9309->io, 0xFE, unlock_cmd, 2), - // TAG, "Unlock failed"); - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(gc9309->io, LCD_CMD_SWRESET, NULL, 0), - // TAG, "SW Reset failed"); - vTaskDelay(pdMS_TO_TICKS(120)); - } - return ESP_OK; - } - static esp_err_t panel_gc9309na_init(esp_lcd_panel_t *panel) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9309->io; - - // Unlock commands - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xFE, NULL, 0), TAG, "Unlock cmd1 failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEF, NULL, 0), TAG, "Unlock cmd2 failed"); - - // Sleep out command - //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, NULL, 0), TAG, "Sleep out failed"); - //vTaskDelay(pdMS_TO_TICKS(80)); - - // Timing control commands - //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xE8, (uint8_t[]){0xA0}, 1), TAG, "Timing control failed"); - //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xE8, (uint8_t[]){0xF0}, 1), TAG, "Timing control failed"); - - // Display on command - //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, NULL, 0), TAG, "Display on failed"); - // vTaskDelay(pdMS_TO_TICKS(10)); - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x80, (uint8_t[]){0xC0}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x81, (uint8_t[]){0x01}, 1), TAG, "DINV failed"); - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x82, (uint8_t[]){0x07}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x83, (uint8_t[]){0x38}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x88, (uint8_t[]){0x64}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x89, (uint8_t[]){0x86}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8B, (uint8_t[]){0x3C}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8D, (uint8_t[]){0x51}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8E, (uint8_t[]){0x70}, 1), TAG, "DINV failed"); - - //高低位交换 - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB4, (uint8_t[]){0x80}, 1), TAG, "DINV failed"); - - gc9309->colmod_val = 0x05; // RGB565 - gc9309->madctl_val = 0x48; // BGR顺序,设置bit3=1(即0x08) - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9309NA_CMD_COLMOD, &gc9309->colmod_val, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9309NA_CMD_MADCTL, &gc9309->madctl_val, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XBF, (uint8_t[]){0X1F}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7d, (uint8_t[]){0x45,0x06}, 2), TAG, "DINV failed"); - // Continue from where you left off - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEE, (uint8_t[]){0x00,0x06}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XF4, (uint8_t[]){0x53}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF6, (uint8_t[]){0x17,0x08}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x70, (uint8_t[]){0x4F,0x4F}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x71, (uint8_t[]){0x12,0x20}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x72, (uint8_t[]){0x12,0x20}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB5, (uint8_t[]){0x50}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xBA, (uint8_t[]){0x00}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEC, (uint8_t[]){0x71}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7b, (uint8_t[]){0x00,0x0d}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7c, (uint8_t[]){0x0d,0x03}, 2), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XF5, (uint8_t[]){0x02,0x10,0x12}, 3), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF0, (uint8_t[]){0x0C,0x11,0x0b,0x0a,0x05,0x32,0x44,0x8e,0x9a,0x29,0x2E,0x5f}, 12), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF1, (uint8_t[]){0x0B,0x11,0x0b,0x07,0x07,0x32,0x45,0xBd,0x8D,0x21,0x28,0xAf}, 12), TAG, "DINV failed"); - - // 240x296 resolution settings - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2a, (uint8_t[]){0x00,0x00,0x00,0xef}, 4), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2b, (uint8_t[]){0x00,0x00,0x01,0x27}, 4), TAG, "DINV failed"); - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x66, (uint8_t[]){0x2C}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x67, (uint8_t[]){0x18}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x68, (uint8_t[]){0x3E}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCA, (uint8_t[]){0x0E}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xf0}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCB, (uint8_t[]){0x06}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB6, (uint8_t[]){0x5C,0x40,0x40}, 3), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCC, (uint8_t[]){0x33}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCD, (uint8_t[]){0x33}, 1), TAG, "DINV failed"); - - // Sleep out command - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, NULL, 0), TAG, "Sleep out failed"); - vTaskDelay(pdMS_TO_TICKS(80)); - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xA0}, 1), TAG, "DINV failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xf0}, 1), TAG, "DINV failed"); - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xfe, NULL, 0), TAG, "unlock cmd1 failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xee, NULL, 0), TAG, "unlock cmd2 failed"); - - // Display on command - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, NULL, 0), TAG, "Display on failed"); - - // Memory write command - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2c, NULL, 0), TAG, "Memory write failed"); - vTaskDelay(pdMS_TO_TICKS(10)); - return ESP_OK; - } - - - static esp_err_t panel_gc9309na_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - - - esp_lcd_panel_io_handle_t io = gc9309->io; - - x_start += gc9309->x_gap; - x_end += gc9309->x_gap; - y_start += gc9309->y_gap; - y_end += gc9309->y_gap; - - // define an area of frame memory where MCU can access - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) { - (x_start >> 8) & 0xFF, - x_start & 0xFF, - ((x_end - 1) >> 8) & 0xFF, - (x_end - 1) & 0xFF, - }, 4), TAG, "io tx param failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) { - (y_start >> 8) & 0xFF, - y_start & 0xFF, - ((y_end - 1) >> 8) & 0xFF, - (y_end - 1) & 0xFF, - }, 4), TAG, "io tx param failed"); - // transfer frame buffer - size_t len = (x_end - x_start) * (y_end - y_start) * gc9309->fb_bits_per_pixel / 8; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "io tx color failed"); - - return ESP_OK; - } - - static esp_err_t panel_gc9309na_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9309->io; - int command = 0; - if (invert_color_data) { - command = LCD_CMD_INVON; - } else { - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, - "io tx param failed"); - return ESP_OK; - } - - static esp_err_t panel_gc9309na_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) - { - // gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - // esp_lcd_panel_io_handle_t io = gc9309->io; - // if (mirror_x) { - // gc9309->madctl_val |= LCD_CMD_MX_BIT; - // } else { - // gc9309->madctl_val &= ~LCD_CMD_MX_BIT; - // } - // if (mirror_y) { - // gc9309->madctl_val |= LCD_CMD_MY_BIT; - // } else { - // gc9309->madctl_val &= ~LCD_CMD_MY_BIT; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { - // gc9309->madctl_val - // }, 1), TAG, "io tx param failed"); - return ESP_OK; - } - - static esp_err_t panel_gc9309na_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) - { - // gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - // esp_lcd_panel_io_handle_t io = gc9309->io; - // if (swap_axes) { - // gc9309->madctl_val |= LCD_CMD_MV_BIT; - // } else { - // gc9309->madctl_val &= ~LCD_CMD_MV_BIT; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { - // gc9309->madctl_val - // }, 1), TAG, "io tx param failed"); - return ESP_OK; - } - - static esp_err_t panel_gc9309na_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - gc9309->x_gap = x_gap; - gc9309->y_gap = y_gap; - return ESP_OK; - } - - static esp_err_t panel_gc9309na_disp_on_off(esp_lcd_panel_t *panel, bool on_off) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - uint8_t cmd = on_off ? GC9309NA_CMD_DISPON : GC9309NA_CMD_DISPOFF; - return esp_lcd_panel_io_tx_param(gc9309->io, cmd, NULL, 0); - } - - static esp_err_t panel_gc9309na_sleep(esp_lcd_panel_t *panel, bool sleep) - { - gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base); - uint8_t cmd = sleep ? GC9309NA_CMD_SLPIN : GC9309NA_CMD_SLPOUT; - esp_err_t ret = esp_lcd_panel_io_tx_param(gc9309->io, cmd, NULL, 0); - vTaskDelay(pdMS_TO_TICKS(120)); - return ret; - } \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.h deleted file mode 100644 index 0a7065b8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/esp_lcd_panel_gc9301.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#pragma once - -#include -#include "esp_err.h" -#include "esp_lcd_panel_dev.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Create LCD panel for model ST7789 - * - * @param[in] io LCD panel IO handle - * @param[in] panel_dev_config general panel device configuration - * @param[out] ret_panel Returned LCD panel handle - * @return - * - ESP_ERR_INVALID_ARG if parameter is invalid - * - ESP_ERR_NO_MEM if out of memory - * - ESP_OK on success - */ -esp_err_t esp_lcd_new_panel_gc9309na(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel); - -#ifdef __cplusplus -} -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/gpio_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/gpio_manager.h deleted file mode 100644 index f8e83ff6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/gpio_manager.h +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once -#include -#include -#include -#include - -class GpioManager { -public: - enum class GpioMode { - INPUT, - OUTPUT, - INPUT_PULLUP, - INPUT_PULLDOWN - }; - - static void SetLevel(gpio_num_t gpio, uint32_t level) { - std::lock_guard lock(mutex_); - ESP_ERROR_CHECK(gpio_set_level(gpio, level)); - ESP_LOGD("GpioManager", "Set GPIO %d level: %d", static_cast(gpio), static_cast(level)); - } - - static int GetLevel(gpio_num_t gpio) { - std::lock_guard lock(mutex_); - int level = gpio_get_level(gpio); - ESP_LOGD("GpioManager", "Get GPIO %d level: %d", static_cast(gpio), level); - return level; - } - - static void Config(gpio_num_t gpio, GpioMode mode) { - std::lock_guard lock(mutex_); - - gpio_config_t config = {}; - config.pin_bit_mask = (1ULL << gpio); - - switch(mode) { - case GpioMode::INPUT: - config.mode = GPIO_MODE_INPUT; - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_DISABLE; - break; - case GpioMode::OUTPUT: - config.mode = GPIO_MODE_OUTPUT; - break; - case GpioMode::INPUT_PULLUP: - config.mode = GPIO_MODE_INPUT; - config.pull_up_en = GPIO_PULLUP_ENABLE; - break; - case GpioMode::INPUT_PULLDOWN: - config.mode = GPIO_MODE_INPUT; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - break; - } - - ESP_ERROR_CHECK(gpio_config(&config)); - ESP_LOGI("GpioManager", "Configured GPIO %d mode: %d", gpio, static_cast(mode)); - } - -private: - static std::mutex mutex_; -}; - -std::mutex GpioManager::mutex_; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/jiuchuan_dev_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/jiuchuan_dev_board.cc deleted file mode 100644 index d54a7f6c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/jiuchuan_dev_board.cc +++ /dev/null @@ -1,382 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "esp_lcd_panel_gc9301.h" - -#include "power_save_timer.h" -#include "power_manager.h" -#include "power_controller.h" -#include "gpio_manager.h" -#include -#include - -#define BOARD_TAG "JiuchuanDevBoard" -#define __USER_GPIO_PWRDOWN__ - -// 自定义LCD显示器类,用于圆形屏幕适配 -class CustomLcdDisplay : public SpiLcdDisplay -{ -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) - { - - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES * 0.167, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES * 0.167, 0); - } -}; - -class JiuchuanDevBoard : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - Button pwr_button_; - Button wifi_button; - Button cmd_button; - LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io = NULL; - esp_lcd_panel_handle_t panel = NULL; - - // 音量映射函数:将内部音量(0-80)映射为显示音量(0-100%) - int MapVolumeForDisplay(int internal_volume) { - // 确保输入在有效范围内 - if (internal_volume < 0) internal_volume = 0; - if (internal_volume > 80) internal_volume = 80; - - // 将0-80映射到0-100 - // 公式: 显示音量 = (内部音量 / 80) * 100 - return (internal_volume * 100) / 80; - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(PWR_ADC_GPIO); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - #ifndef __USER_GPIO_PWRDOWN__ - RTC_DATA_ATTR static bool long_press_occurred = false; - esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); - if (cause == ESP_SLEEP_WAKEUP_EXT0) { - ESP_LOGI(TAG, "Wake up by EXT0"); - const int64_t start = esp_timer_get_time(); - ESP_LOGI(TAG, "esp_sleep_get_wakeup_cause"); - while (gpio_get_level(PWR_BUTTON_GPIO) == 0) { - if (esp_timer_get_time() - start > 3000000) { - long_press_occurred = true; - break; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - if (long_press_occurred) { - ESP_LOGI(TAG, "Long press wakeup"); - long_press_occurred = false; - } else { - ESP_LOGI(TAG, "Short press, return to sleep"); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0)); - ESP_ERROR_CHECK(rtc_gpio_pullup_en(PWR_BUTTON_GPIO)); // 内部上拉 - ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(PWR_BUTTON_GPIO)); - esp_deep_sleep_start(); - } - } - #endif - //一分钟进入浅睡眠,5分钟进入深睡眠关机 - power_save_timer_ = new PowerSaveTimer(-1, (60*5), -1); - // power_save_timer_ = new PowerSaveTimer(-1, 6, 10);//test - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - #ifndef __USER_GPIO_PWRDOWN__ - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0)); - ESP_ERROR_CHECK(rtc_gpio_pullup_en(PWR_BUTTON_GPIO)); // 内部上拉 - ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(PWR_BUTTON_GPIO)); - - esp_lcd_panel_disp_on_off(panel, false); //关闭显示 - esp_deep_sleep_start(); - #else - rtc_gpio_set_level(PWR_EN_GPIO, 0); - rtc_gpio_hold_dis(PWR_EN_GPIO); - #endif - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - } - - void InitializeButtons() { - static bool pwrbutton_unreleased = false; - - if (gpio_get_level(GPIO_NUM_3) == 1) { - pwrbutton_unreleased = true; - } - // 配置GPIO - ESP_LOGI(TAG, "Configuring power button GPIO"); - GpioManager::Config(GPIO_NUM_3, GpioManager::GpioMode::INPUT_PULLDOWN); - - boot_button_.OnClick([this]() { - ESP_LOGI(TAG, "Boot button clicked"); - power_save_timer_->WakeUp(); - }); - - // 检查电源按钮初始状态 - ESP_LOGI(TAG, "Power button initial state: %d", GpioManager::GetLevel(PWR_BUTTON_GPIO)); - - // 高电平有效长按关机逻辑 - pwr_button_.OnPressDown([this]() { - pwrbutton_unreleased = false; - }); - pwr_button_.OnLongPress([this]() - { - ESP_LOGI(TAG, "Power button long press detected (high-active)"); - - if (pwrbutton_unreleased){ - ESP_LOGI(TAG, "开机后电源键未松开,取消关机"); - return; - } - - // 高电平有效防抖确认 - for (int i = 0; i < 5; i++) { - int level = GpioManager::GetLevel(PWR_BUTTON_GPIO); - ESP_LOGD(TAG, "Debounce check %d: GPIO%d level=%d", i+1, PWR_BUTTON_GPIO, level); - - if (level == 0) { - ESP_LOGW(TAG, "Power button inactive during confirmation - abort shutdown"); - return; - } - vTaskDelay(100 / portTICK_PERIOD_MS); - } - - ESP_LOGI(TAG, "Confirmed power button pressed - initiating shutdown"); - power_manager_->SetPowerState(PowerState::SHUTDOWN); }); - - //单击切换状态 - pwr_button_.OnClick([this]() - { - // 获取当前应用实例和状态 - auto &app = Application::GetInstance(); - auto current_state = app.GetDeviceState(); - - ESP_LOGI(TAG, "当前设备状态: %d", current_state); - - if (current_state == kDeviceStateIdle) { - // 如果当前是待命状态,切换到聆听状态 - ESP_LOGI(TAG, "从待命状态切换到聆听状态"); - app.ToggleChatState(); // 切换到聆听状态 - } else if (current_state == kDeviceStateListening) { - // 如果当前是聆听状态,切换到待命状态 - ESP_LOGI(TAG, "从聆听状态切换到待命状态"); - app.ToggleChatState(); // 切换到待命状态 - } else if (current_state == kDeviceStateSpeaking) { - // 如果当前是说话状态,终止说话并切换到待命状态 - ESP_LOGI(TAG, "从说话状态切换到待命状态"); - app.ToggleChatState(); // 终止说话 - } else { - // 其他状态下只唤醒设备 - ESP_LOGI(TAG, "唤醒设备"); - power_save_timer_->WakeUp(); - } }); - - // 电源键三击:重置WiFi - pwr_button_.OnMultipleClick([this]() { - ESP_LOGI(TAG, "Power button triple click: 重置WiFi"); - power_save_timer_->WakeUp(); - EnterWifiConfigMode(); - }, 3); - - wifi_button.OnPressDown([this]() - { - ESP_LOGI(TAG, "Volume up button pressed"); - power_save_timer_->WakeUp(); - - auto codec = GetAudioCodec(); - int current_vol = codec->output_volume(); // 获取实际当前音量 - current_vol = (current_vol + 8 > 80) ? 80 : current_vol + 8; - - codec->SetOutputVolume(current_vol); - - ESP_LOGI(TAG, "Current volume: %d", current_vol); - int display_volume = MapVolumeForDisplay(current_vol); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(display_volume) + "%");}); - - cmd_button.OnPressDown([this]() - { - ESP_LOGI(TAG, "Volume down button pressed"); - power_save_timer_->WakeUp(); - - auto codec = GetAudioCodec(); - int current_vol = codec->output_volume(); // 获取实际当前音量 - current_vol = (current_vol - 8 < 0) ? 0 : current_vol - 8; - - codec->SetOutputVolume(current_vol); - - ESP_LOGI(TAG, "Current volume: %d", current_vol); - if (current_vol == 0) { - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - } else { - int display_volume = MapVolumeForDisplay(current_vol); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(display_volume) + "%"); - }}); - } - - void InitializeGC9301isplay() - { - // 液晶屏控制IO初始化 - ESP_LOGI(TAG, "test Install panel IO"); - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN; - buscfg.sclk_io_num = DISPLAY_SPI_SCK_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - - // 初始化SPI总线 - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io); - - // 初始化液晶屏驱动芯片9309 - ESP_LOGI(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ENDIAN_BGR; - panel_config.bits_per_pixel = 16; - esp_lcd_new_panel_gc9309na(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - JiuchuanDevBoard() : - boot_button_(BOOT_BUTTON_GPIO), - pwr_button_(PWR_BUTTON_GPIO,true), - wifi_button(WIFI_BUTTON_GPIO), - cmd_button(CMD_BUTTON_GPIO) { - - InitializeI2c(); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeButtons(); - InitializeGC9301isplay(); - GetBacklight()->RestoreBrightness(); - - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - - static Es8311AudioCodec audio_codec( - codec_i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(JiuchuanDevBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_controller.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_controller.h deleted file mode 100644 index 2496152a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_controller.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "config.h" -enum class PowerState { - ACTIVE, - LIGHT_SLEEP, - DEEP_SLEEP, - SHUTDOWN - }; - -class PowerController { -public: - - - static PowerController& Instance() { - static PowerController instance; - return instance; - } - - void SetState(PowerState newState) { - std::lock_guard lock(mutex_); - if (currentState_ != newState) { - ESP_LOGI("PowerCtrl", "State change: %d -> %d", - static_cast(currentState_), - static_cast(newState)); - - currentState_ = newState; - if (stateChangeCallback_) { - stateChangeCallback_(newState); - } - } - } - - PowerState GetState() const { - std::lock_guard lock(mutex_); - return currentState_; - } - - void OnStateChange(std::function callback) { - stateChangeCallback_ = callback; - } - -private: - PowerController(){ - rtc_gpio_init(PWR_EN_GPIO); - rtc_gpio_set_direction(PWR_EN_GPIO, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(PWR_EN_GPIO, 1); - } - ~PowerController() = default; - - PowerState currentState_ = PowerState::ACTIVE; - std::function stateChangeCallback_; - mutable std::mutex mutex_; -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_manager.h deleted file mode 100644 index e306d105..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/jiuchuan-s3/power_manager.h +++ /dev/null @@ -1,201 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include "adc_battery_estimation.h" -#include "power_controller.h" -#include -#include - -#define JIUCHUAN_ADC_UNIT (ADC_UNIT_1) -#define JIUCHUAN_ADC_BITWIDTH (ADC_BITWIDTH_12) -#define JIUCHUAN_ADC_ATTEN (ADC_ATTEN_DB_12) -#define JIUCHUAN_ADC_CHANNEL (ADC_CHANNEL_3) -#define JIUCHUAN_RESISTOR_UPPER (200000) -#define JIUCHUAN_RESISTOR_LOWER (100000) - -#undef TAG -#define TAG "PowerManager" -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - int32_t battery_level_ = 100; - bool is_charging_ = false; - bool is_low_battery_ = false; - bool is_empty_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_battery_estimation_handle_t adc_battery_estimation_handle; - PowerController* power_controller_; - - - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - float battery_capacity_temp = 0; - adc_battery_estimation_get_capacity(adc_battery_estimation_handle, &battery_capacity_temp); - ESP_LOGI("PowerManager", "Battery level: %.1f%%", battery_capacity_temp); - if(battery_capacity_temp > -10 && battery_capacity_temp <= 0){ - battery_level_ = 0; - }else{ - battery_level_ = battery_capacity_temp; - } - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - power_controller_ = &PowerController::Instance(); - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - static const battery_point_t battery_ponint_table[]={ - { 4.2 , 100}, - { 4.06 , 80}, - { 3.82 , 60}, - { 3.58 , 40}, - { 3.34 , 20}, - { 3.1 , 0}, - { 3.0 , -10} - }; - - adc_battery_estimation_t config = { - .internal = { - .adc_unit = JIUCHUAN_ADC_UNIT, - .adc_bitwidth = JIUCHUAN_ADC_BITWIDTH, - .adc_atten = JIUCHUAN_ADC_ATTEN, - }, - .adc_channel = JIUCHUAN_ADC_CHANNEL, - .upper_resistor = JIUCHUAN_RESISTOR_UPPER, - .lower_resistor = JIUCHUAN_RESISTOR_LOWER, - .battery_points = battery_ponint_table, - .battery_points_count = sizeof(battery_ponint_table) / sizeof(battery_ponint_table[0]) - }; - - adc_battery_estimation_handle = adc_battery_estimation_create(&config); - - RegisterAllCallbacks(); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_battery_estimation_handle) { - adc_battery_estimation_destroy(adc_battery_estimation_handle); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - //ESP_LOGI(TAG, "电量已满,不再显示充电中"); - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - int32_t GetBatteryLevel() { - return battery_level_; - } - - void RegisterAllCallbacks() { - //注册电源状态变更回调函数(优化版) - power_controller_->OnStateChange([this](PowerState newState) { - switch(newState) { - case PowerState::SHUTDOWN: { - - ESP_LOGD(TAG, "关机"); - - //取消 PWR_EN 使能 - /* 防止关机后误唤醒 */ - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(PWR_BUTTON_GPIO, 0)); - ESP_ERROR_CHECK(rtc_gpio_pulldown_en(PWR_BUTTON_GPIO)); // 内部下拉 - ESP_ERROR_CHECK(rtc_gpio_pullup_dis(PWR_BUTTON_GPIO)); - /* 关闭电源使能 */ - rtc_gpio_set_level(PWR_EN_GPIO, 0); - rtc_gpio_hold_dis(PWR_EN_GPIO); - - // 确保所有外设已关闭 - vTaskDelay(200 / portTICK_PERIOD_MS); - ESP_LOGI(TAG, "Initiating deep sleep"); - - esp_deep_sleep_start(); - break; - } - default: - ESP_LOGD(TAG, "State changed to %d", static_cast(newState)); - break; - } - }); - } - void SetPowerState(PowerState newState) { - power_controller_->SetState(newState); - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.h deleted file mode 100644 index a2729001..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_40 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_47 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_9 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_42 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_41 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_3 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_1 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_2 - -#define DISPLAY_SDA_PIN GPIO_NUM_7 -#define DISPLAY_SCL_PIN GPIO_NUM_8 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define ML307_RX_PIN GPIO_NUM_5 -#define ML307_TX_PIN GPIO_NUM_6 - -#define AXP2101_I2C_ADDR 0x34 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.json deleted file mode 100644 index d9a581de..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "kevin-box-2", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/kevin_box_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/kevin_box_board.cc deleted file mode 100644 index 0e068a05..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-box-2/kevin_box_board.cc +++ /dev/null @@ -1,270 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/box_audio_codec.h" -#include "display/oled_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#define TAG "KevinBoxBoard" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - // ** EFUSE defaults ** - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - WriteReg(0x93, 0x1C); // 配置 aldo2 输出为 3.3V - - uint8_t value = ReadReg(0x90); // XPOWERS_AXP2101_LDO_ONOFF_CTRL0 - value = value | 0x02; // set bit 1 (ALDO2) - WriteReg(0x90, value); // and power channels now enabled - - WriteReg(0x64, 0x03); // CV charger voltage setting to 4.2V - - WriteReg(0x61, 0x05); // set Main battery precharge current to 125mA - WriteReg(0x62, 0x0A); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x15); // set Main battery term charge current to 125mA - - WriteReg(0x14, 0x00); // set minimum system voltage to 4.1V (default 4.7V), for poor USB cables - WriteReg(0x15, 0x00); // set input voltage limit to 3.88v, for poor USB cables - WriteReg(0x16, 0x05); // set input current limit to 2000mA - - WriteReg(0x24, 0x01); // set Vsys for PWROFF threshold to 3.2V (default - 2.6V and kill battery) - WriteReg(0x50, 0x14); // set TS pin to EXTERNAL input (not temperature) - } -}; - -class KevinBoxBoard : public DualNetworkBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - i2c_master_bus_handle_t codec_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Pmic* pmic_ = nullptr; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, -1, 600); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void Enable4GModule() { - // Make GPIO HIGH to enable the 4G module - gpio_config_t ml307_enable_config = { - .pin_bit_mask = (1ULL << 4), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - gpio_config(&ml307_enable_config); - gpio_set_level(GPIO_NUM_4, 1); - } - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeButtons() { - boot_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - app.StartListening(); - }); - boot_button_.OnPressUp([this]() { - auto& app = Application::GetInstance(); - app.StopListening(); - }); - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - } - } - }); - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - -public: - KevinBoxBoard() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeCodecI2c(); - pmic_ = new Pmic(codec_i2c_bus_, AXP2101_I2C_ADDR); - - Enable4GModule(); - - InitializeButtons(); - InitializePowerSaveTimer(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec(codec_i2c_bus_, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR, AUDIO_CODEC_ES7210_ADDR, AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } -}; - -DECLARE_BOARD(KevinBoxBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.h deleted file mode 100644 index 42413207..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_13 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_0 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_5 -#define BOOT_BUTTON_GPIO GPIO_NUM_6 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.json deleted file mode 100644 index b8bf3b70..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "kevin-c3", - "sdkconfig_append": [ - "CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=n", - "CONFIG_LWIP_IPV6=n", - "CONFIG_USE_ESP_WAKE_WORD=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/kevin_c3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/kevin_c3_board.cc deleted file mode 100644 index 6ebff33b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/kevin_c3_board.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/circular_strip.h" -#include "led_strip_control.h" - -#include -#include -#include - -#define TAG "KevinBoxBoard" - -class KevinBoxBoard : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - CircularStrip* led_strip_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - led_strip_ = new CircularStrip(BUILTIN_LED_GPIO, 8); - new LedStripControl(led_strip_); - } - -public: - KevinBoxBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializeTools(); - - // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 - esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); - } - - virtual Led* GetLed() override { - return led_strip_; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } -}; - -DECLARE_BOARD(KevinBoxBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.cc deleted file mode 100644 index 68dc4aeb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "led_strip_control.h" -#include "settings.h" -#include "mcp_server.h" -#include - -#define TAG "LedStripControl" - -int LedStripControl::LevelToBrightness(int level) const { - if (level < 0) level = 0; - if (level > 8) level = 8; - return (1 << level) - 1; // 2^n - 1 -} - -StripColor LedStripControl::RGBToColor(int red, int green, int blue) { - if (red < 0) red = 0; - if (red > 255) red = 255; - if (green < 0) green = 0; - if (green > 255) green = 255; - if (blue < 0) blue = 0; - if (blue > 255) blue = 255; - return {static_cast(red), static_cast(green), static_cast(blue)}; -} - -LedStripControl::LedStripControl(CircularStrip* led_strip) - : led_strip_(led_strip) { - // 从设置中读取亮度等级 - Settings settings("led_strip"); - brightness_level_ = settings.GetInt("brightness", 4); // 默认等级4 - led_strip_->SetBrightness(LevelToBrightness(brightness_level_), 4); - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.led_strip.get_brightness", - "Get the brightness of the led strip (0-8)", - PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return brightness_level_; - }); - - mcp_server.AddTool("self.led_strip.set_brightness", - "Set the brightness of the led strip (0-8)", - PropertyList({ - Property("level", kPropertyTypeInteger, 0, 8) - }), [this](const PropertyList& properties) -> ReturnValue { - int level = properties["level"].value(); - ESP_LOGI(TAG, "Set LedStrip brightness level to %d", level); - brightness_level_ = level; - led_strip_->SetBrightness(LevelToBrightness(brightness_level_), 4); - - // 保存设置 - Settings settings("led_strip", true); - settings.SetInt("brightness", brightness_level_); - - return true; - }); - - mcp_server.AddTool("self.led_strip.set_single_color", - "Set the color of a single led.", - PropertyList({ - Property("index", kPropertyTypeInteger, 0, 7), - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int index = properties["index"].value(); - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - ESP_LOGI(TAG, "Set led strip single color %d to %d, %d, %d", - index, red, green, blue); - led_strip_->SetSingleColor(index, RGBToColor(red, green, blue)); - return true; - }); - - mcp_server.AddTool("self.led_strip.set_all_color", - "Set the color of all leds.", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - ESP_LOGI(TAG, "Set led strip all color to %d, %d, %d", - red, green, blue); - led_strip_->SetAllColor(RGBToColor(red, green, blue)); - return true; - }); - - mcp_server.AddTool("self.led_strip.blink", - "Blink the led strip. (闪烁)", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255), - Property("interval", kPropertyTypeInteger, 0, 1000) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - int interval = properties["interval"].value(); - ESP_LOGI(TAG, "Blink led strip with color %d, %d, %d, interval %dms", - red, green, blue, interval); - led_strip_->Blink(RGBToColor(red, green, blue), interval); - return true; - }); - - mcp_server.AddTool("self.led_strip.scroll", - "Scroll the led strip. (跑马灯)", - PropertyList({ - Property("red", kPropertyTypeInteger, 0, 255), - Property("green", kPropertyTypeInteger, 0, 255), - Property("blue", kPropertyTypeInteger, 0, 255), - Property("length", kPropertyTypeInteger, 1, 7), - Property("interval", kPropertyTypeInteger, 0, 1000) - }), [this](const PropertyList& properties) -> ReturnValue { - int red = properties["red"].value(); - int green = properties["green"].value(); - int blue = properties["blue"].value(); - int interval = properties["interval"].value(); - int length = properties["length"].value(); - ESP_LOGI(TAG, "Scroll led strip with color %d, %d, %d, length %d, interval %dms", - red, green, blue, length, interval); - StripColor low = RGBToColor(4, 4, 4); - StripColor high = RGBToColor(red, green, blue); - led_strip_->Scroll(low, high, length, interval); - return true; - }); - -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.h deleted file mode 100644 index 0e99bb36..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-c3/led_strip_control.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef LED_STRIP_CONTROL_H -#define LED_STRIP_CONTROL_H - -#include "led/circular_strip.h" - -class LedStripControl { -private: - CircularStrip* led_strip_; - int brightness_level_; // 亮度等级 (0-8) - - int LevelToBrightness(int level) const; // 将等级转换为实际亮度值 - StripColor RGBToColor(int red, int green, int blue); - -public: - explicit LedStripControl(CircularStrip* led_strip); -}; - -#endif // LED_STRIP_CONTROL_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/config.h deleted file mode 100644 index fd925493..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/config.h +++ /dev/null @@ -1,64 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_DEFAULT_OUTPUT_VOLUME 90 - - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_42 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_41 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_2 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_3 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_46 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_1 - - -#define BUILTIN_LED_GPIO GPIO_NUM_38 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define RESET_NVS_BUTTON_GPIO GPIO_NUM_NC -#define RESET_FACTORY_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_48 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define ML307_RX_PIN GPIO_NUM_12 -#define ML307_TX_PIN GPIO_NUM_13 -/* Camera pins */ -#define CAMERA_PIN_PWDN -1 -#define CAMERA_PIN_RESET -1 -#define CAMERA_PIN_XCLK 15 -#define CAMERA_PIN_SIOD 4 -#define CAMERA_PIN_SIOC 5 - -#define CAMERA_PIN_D7 16 -#define CAMERA_PIN_D6 17 -#define CAMERA_PIN_D5 18 -#define CAMERA_PIN_D4 12 -#define CAMERA_PIN_D3 10 -#define CAMERA_PIN_D2 8 -#define CAMERA_PIN_D1 9 -#define CAMERA_PIN_D0 11 -#define CAMERA_PIN_VSYNC 6 -#define CAMERA_PIN_HREF 7 -#define CAMERA_PIN_PCLK 13 - -#define XCLK_FREQ_HZ 20000000 -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/kevin-sp-v3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/kevin-sp-v3_board.cc deleted file mode 100644 index 782504e7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v3-dev/kevin-sp-v3_board.cc +++ /dev/null @@ -1,165 +0,0 @@ -#include "wifi_board.h" -#include "ml307_board.h" - -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include -#include "esp32_camera.h" - -#define TAG "kevin-sp-v3" - -// class KEVIN_SP_V3Board : public Ml307Board { -class KEVIN_SP_V3Board : public WifiBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - Esp32Camera* camera_; - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_47; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_21; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_14; - io_config.dc_gpio_num = GPIO_NUM_45; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = true, - .i2c_config = { - .port = 1, - .scl_pin = CAMERA_PIN_SIOC, - .sda_pin = CAMERA_PIN_SIOD, - }, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - -public: - KEVIN_SP_V3Board() : boot_button_(BOOT_BUTTON_GPIO) { - ESP_LOGI(TAG, "Initializing KEVIN_SP_V3 Board"); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - InitializeCamera(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec *GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(KEVIN_SP_V3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.h deleted file mode 100644 index 27fdc20a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.h +++ /dev/null @@ -1,66 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_42 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_1 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_46 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_2 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_3 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_41 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_4 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_5 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_38 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define RESET_NVS_BUTTON_GPIO GPIO_NUM_NC -#define RESET_FACTORY_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_48 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define ML307_RX_PIN GPIO_NUM_12 -#define ML307_TX_PIN GPIO_NUM_13 -/* Camera pins */ -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_XCLK GPIO_NUM_15 -#define CAMERA_PIN_SIOD GPIO_NUM_4 -#define CAMERA_PIN_SIOC GPIO_NUM_5 - -#define CAMERA_PIN_D7 GPIO_NUM_16 -#define CAMERA_PIN_D6 GPIO_NUM_17 -#define CAMERA_PIN_D5 GPIO_NUM_18 -#define CAMERA_PIN_D4 GPIO_NUM_12 -#define CAMERA_PIN_D3 GPIO_NUM_10 -#define CAMERA_PIN_D2 GPIO_NUM_8 -#define CAMERA_PIN_D1 GPIO_NUM_9 -#define CAMERA_PIN_D0 GPIO_NUM_11 -#define CAMERA_PIN_VSYNC GPIO_NUM_6 -#define CAMERA_PIN_HREF GPIO_NUM_7 -#define CAMERA_PIN_PCLK GPIO_NUM_13 - -#define XCLK_FREQ_HZ 20000000 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.json deleted file mode 100644 index b01291e6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/config.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "kevin-sp-v4-dev", - "sdkconfig_append": [ - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV3660=y", - "CONFIG_CAMERA_OV3660_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV3660_DVP_RGB565_240X240_24FPS=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_RGB565_240X240_25FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/kevin-sp-v4_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/kevin-sp-v4_board.cc deleted file mode 100644 index 78879402..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-sp-v4-dev/kevin-sp-v4_board.cc +++ /dev/null @@ -1,177 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include -#include "esp32_camera.h" - -#define TAG "kevin-sp-v4" - -class KEVIN_SP_V4Board : public WifiBoard { -private: - Button boot_button_; - LcdDisplay* display_; - i2c_master_bus_handle_t i2c_bus_; - Esp32Camera* camera_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_47; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_21; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_14; - io_config.dc_gpio_num = GPIO_NUM_45; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - -public: - KEVIN_SP_V4Board() : boot_button_(BOOT_BUTTON_GPIO) { - ESP_LOGI(TAG, "Initializing KEVIN SP V4 Board"); - InitializeCodecI2c(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - InitializeCamera(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(KEVIN_SP_V4Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.h deleted file mode 100644 index b5337413..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 16000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_42 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_39 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_38 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_45 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_1 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_2 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_WIDTH 376 -#define DISPLAY_HEIGHT 960 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_4 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.json deleted file mode 100644 index ae29bb4e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "kevin-yuying-313lcd", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.c deleted file mode 100644 index 9f62738b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "esp_lcd_gc9503.h" - -#define GC9503_CMD_MADCTL (0xB1) // Memory data access control -#define GC9503_CMD_MADCTL_DEFAULT (0x10) // Default value of Memory data access control -#define GC9503_CMD_SS_BIT (1 << 0) // Source driver scan direction, 0: top to bottom, 1: bottom to top -#define GC9503_CMD_GS_BIT (1 << 1) // Gate driver scan direction, 0: left to right, 1: right to left -#define GC9503_CMD_BGR_BIT (1 << 5) // RGB/BGR order, 0: RGB, 1: BGR - -typedef struct -{ - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // Save current value of GC9503_CMD_MADCTL register - uint8_t colmod_val; // Save current value of LCD_CMD_COLMOD register - const gc9503_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - struct - { - unsigned int mirror_by_cmd : 1; - unsigned int auto_del_panel_io : 1; - unsigned int display_on_off_use_cmd : 1; - unsigned int reset_level : 1; - } flags; - // To save the original functions of RGB panel - esp_err_t (*init)(esp_lcd_panel_t *panel); - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*reset)(esp_lcd_panel_t *panel); - esp_err_t (*mirror)(esp_lcd_panel_t *panel, bool x_axis, bool y_axis); - esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off); -} gc9503_panel_t; - -static const char *TAG = "gc9503"; - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503); - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool off); - -esp_err_t esp_lcd_new_panel_gc9503(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - gc9503_vendor_config_t *vendor_config = (gc9503_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->rgb_config, ESP_ERR_INVALID_ARG, TAG, "`verndor_config` and `rgb_config` are necessary"); - ESP_RETURN_ON_FALSE(!vendor_config->flags.auto_del_panel_io || !vendor_config->flags.mirror_by_cmd, - ESP_ERR_INVALID_ARG, TAG, "`mirror_by_cmd` and `auto_del_panel_io` cannot work together"); - - esp_err_t ret = ESP_OK; - gpio_config_t io_conf = {0}; - - gc9503_panel_t *gc9503 = (gc9503_panel_t *)calloc(1, sizeof(gc9503_panel_t)); - ESP_RETURN_ON_FALSE(gc9503, ESP_ERR_NO_MEM, TAG, "no mem for gc9503 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - gc9503->madctl_val = GC9503_CMD_MADCTL_DEFAULT; - switch (panel_dev_config->rgb_ele_order) - { - case LCD_RGB_ELEMENT_ORDER_RGB: - gc9503->madctl_val &= ~GC9503_CMD_BGR_BIT; - break; - case LCD_RGB_ELEMENT_ORDER_BGR: - gc9503->madctl_val |= GC9503_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color element order"); - break; - } - - gc9503->colmod_val = 0; - switch (panel_dev_config->bits_per_pixel) - { - case 16: // RGB565 - gc9503->colmod_val = 0x50; - break; - case 18: // RGB666 - gc9503->colmod_val = 0x60; - break; - case 24: // RGB888 - gc9503->colmod_val = 0x70; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - gc9503->io = io; - gc9503->init_cmds = vendor_config->init_cmds; - gc9503->init_cmds_size = vendor_config->init_cmds_size; - gc9503->reset_gpio_num = panel_dev_config->reset_gpio_num; - gc9503->flags.reset_level = panel_dev_config->flags.reset_active_high; - gc9503->flags.auto_del_panel_io = vendor_config->flags.auto_del_panel_io; - gc9503->flags.mirror_by_cmd = vendor_config->flags.mirror_by_cmd; - gc9503->flags.display_on_off_use_cmd = (vendor_config->rgb_config->disp_gpio_num >= 0) ? 0 : 1; - - if (gc9503->flags.auto_del_panel_io) - { - if (gc9503->reset_gpio_num >= 0) - { // Perform hardware reset - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - } - else - { // Perform software reset - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), err, TAG, "send command failed"); - } - vTaskDelay(pdMS_TO_TICKS(120)); - - /** - * In order to enable the 3-wire SPI interface pins (such as SDA and SCK) to share other pins of the RGB interface - * (such as HSYNC) and save GPIOs, we need to send LCD initialization commands via the 3-wire SPI interface before - * `esp_lcd_new_rgb_panel()` is called. - */ - ESP_GOTO_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), err, TAG, "send init commands failed"); - // After sending the initialization commands, the 3-wire SPI interface can be deleted - ESP_GOTO_ON_ERROR(esp_lcd_panel_io_del(io), err, TAG, "delete panel IO failed"); - gc9503->io = NULL; - ESP_LOGD(TAG, "delete panel IO"); - } - - // Create RGB panel - ESP_GOTO_ON_ERROR(esp_lcd_new_rgb_panel(vendor_config->rgb_config, ret_panel), err, TAG, "create RGB panel failed"); - ESP_LOGD(TAG, "new RGB panel @%p", ret_panel); - - // Save the original functions of RGB panel - gc9503->init = (*ret_panel)->init; - gc9503->del = (*ret_panel)->del; - gc9503->reset = (*ret_panel)->reset; - gc9503->mirror = (*ret_panel)->mirror; - gc9503->disp_on_off = (*ret_panel)->disp_on_off; - // Overwrite the functions of RGB panel - (*ret_panel)->init = panel_gc9503_init; - (*ret_panel)->del = panel_gc9503_del; - (*ret_panel)->reset = panel_gc9503_reset; - (*ret_panel)->mirror = panel_gc9503_mirror; - (*ret_panel)->disp_on_off = panel_gc9503_disp_on_off; - (*ret_panel)->user_data = gc9503; - ESP_LOGD(TAG, "new gc9503 panel @%p", gc9503); - - // ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9503_VER_MAJOR, ESP_LCD_GC9503_VER_MINOR, - // ESP_LCD_GC9503_VER_PATCH); - return ESP_OK; - -err: - if (gc9503) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(gc9503); - } - return ret; -} - -// *INDENT-OFF* -// static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { -// // {cmd, { data }, data_size, delay_ms} -// {0x11, (uint8_t []){0x00}, 0, 120}, - -// {0xf0, (uint8_t []){0x55, 0xaa, 0x52, 0x08, 0x00}, 5, 0}, -// {0xf6, (uint8_t []){0x5a, 0x87}, 2, 0}, -// {0xc1, (uint8_t []){0x3f}, 1, 0}, -// {0xc2, (uint8_t []){0x0e}, 1, 0}, -// {0xc6, (uint8_t []){0xf8}, 1, 0}, -// {0xc9, (uint8_t []){0x10}, 1, 0}, -// {0xcd, (uint8_t []){0x25}, 1, 0}, -// {0xf8, (uint8_t []){0x8a}, 1, 0}, -// {0xac, (uint8_t []){0x45}, 1, 0}, -// {0xa0, (uint8_t []){0xdd}, 1, 0}, -// {0xa7, (uint8_t []){0x47}, 1, 0}, -// {0xfa, (uint8_t []){0x00, 0x00, 0x00, 0x04}, 4, 0}, -// {0x86, (uint8_t []){0x99, 0xa3, 0xa3, 0x51}, 4, 0}, -// {0xa3, (uint8_t []){0xee}, 1, 0}, -// {0xfd, (uint8_t []){0x3c, 0x3c, 0x00}, 3, 0}, -// {0x71, (uint8_t []){0x48}, 1, 0}, -// {0x72, (uint8_t []){0x48}, 1, 0}, -// {0x73, (uint8_t []){0x00, 0x44}, 2, 0}, -// {0x97, (uint8_t []){0xee}, 1, 0}, -// {0x83, (uint8_t []){0x93}, 1, 0}, -// {0x9a, (uint8_t []){0x72}, 1, 0}, -// {0x9b, (uint8_t []){0x5a}, 1, 0}, -// {0x82, (uint8_t []){0x2c, 0x2c}, 2, 0}, -// {0x6d, (uint8_t []){0x00, 0x1f, 0x19, 0x1a, 0x10, 0x0e, 0x0c, 0x0a, 0x02, 0x07, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, -// 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x08, 0x01, 0x09, 0x0b, 0x0d, 0x0f, 0x1a, 0x19, 0x1f, 0x00}, 32, 0}, -// {0x64, (uint8_t []){0x38, 0x05, 0x01, 0xdb, 0x03, 0x03, 0x38, 0x04, 0x01, 0xdc, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x65, (uint8_t []){0x38, 0x03, 0x01, 0xdd, 0x03, 0x03, 0x38, 0x02, 0x01, 0xde, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x66, (uint8_t []){0x38, 0x01, 0x01, 0xdf, 0x03, 0x03, 0x38, 0x00, 0x01, 0xe0, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x67, (uint8_t []){0x30, 0x01, 0x01, 0xe1, 0x03, 0x03, 0x30, 0x02, 0x01, 0xe2, 0x03, 0x03, 0x7a, 0x7a, 0x7a, 0x7a}, 16, 0}, -// {0x68, (uint8_t []){0x00, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a, 0x08, 0x15, 0x08, 0x15, 0x7a, 0x7a}, 13, 0}, -// {0x60, (uint8_t []){0x38, 0x08, 0x7a, 0x7a, 0x38, 0x09, 0x7a, 0x7a}, 8, 0}, -// {0x63, (uint8_t []){0x31, 0xe4, 0x7a, 0x7a, 0x31, 0xe5, 0x7a, 0x7a}, 8, 0}, -// {0x69, (uint8_t []){0x04, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, -// {0x6b, (uint8_t []){0x07}, 1, 0}, -// {0x7a, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0x7b, (uint8_t []){0x08, 0x13}, 2, 0}, -// {0xd1, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd2, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd3, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd4, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd5, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0xd6, (uint8_t []){0x00, 0x00, 0x00, 0x04, 0x00, 0x12, 0x00, 0x18, 0x00, 0x21, 0x00, 0x2a, 0x00, 0x35, 0x00, 0x47, 0x00, -// 0x56, 0x00, 0x90, 0x00, 0xe5, 0x01, 0x68, 0x01, 0xd5, 0x01, 0xd7, 0x02, 0x36, 0x02, 0xa6, 0x02, 0xee, -// 0x03, 0x48, 0x03, 0xa0, 0x03, 0xba, 0x03, 0xc5, 0x03, 0xd0, 0x03, 0xe0, 0x03, 0xea, 0x03, 0xfa, 0x03, -// 0xff}, 52, 0}, -// {0x11, (uint8_t []){0x00}, 0, 120}, -// {0x29, (uint8_t []){0x00}, 0, 20}, -// }; -static const gc9503_lcd_init_cmd_t vendor_specific_init_default[] = { - // {0x11, (uint8_t[]){}, 0, 20}, - - {0xF0, (uint8_t[]){0x55, 0xAA, 0x52, 0x08, 0x00}, 5, 0}, - {0xF6, (uint8_t[]){0x5A, 0x87}, 2, 0}, - {0xC1, (uint8_t[]){0x3F}, 1, 0}, - {0xCD, (uint8_t[]){0x25}, 1, 0}, - {0xC9, (uint8_t[]){0x10}, 1, 0}, - {0xF8, (uint8_t[]){0x8A}, 1, 0}, - {0xAC, (uint8_t[]){0x45}, 1, 0}, - {0xA7, (uint8_t[]){0x47}, 1, 0}, - {0xA0, (uint8_t[]){0x88}, 1, 0}, - {0x86, (uint8_t[]){0x99, 0xA3, 0xA3, 0x51}, 4, 0}, - {0xFA, (uint8_t[]){0x08, 0x08, 0x00, 0x04}, 4, 0}, - {0xA3, (uint8_t[]){0x6E}, 1, 0}, - {0xFD, (uint8_t[]){0x28, 0x3C, 0x00}, 3, 0}, - {0x9A, (uint8_t[]){0x4B}, 1, 0}, - {0x9B, (uint8_t[]){0x4B}, 1, 0}, - {0x82, (uint8_t[]){0x20, 0x20}, 2, 0}, - {0xB1, (uint8_t[]){0x10}, 1, 0}, - {0x7A, (uint8_t[]){0x0F, 0x13}, 2, 0}, - {0x7B, (uint8_t[]){0x0F, 0x13}, 2, 0}, - {0x6D, (uint8_t[]){0x1e, 0x1e, 0x04, 0x02, 0x0d, 0x1e, 0x12, 0x11, 0x14, 0x13, 0x05, 0x06, 0x1d, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1d, 0x06, 0x05, 0x0b, 0x0c, 0x09, 0x0a, 0x1e, 0x0d, 0x01, 0x03, 0x1e, 0x1e}, 32, 0}, - {0x64, (uint8_t[]){0x38, 0x08, 0x03, 0xc0, 0x03, 0x03, 0x38, 0x06, 0x03, 0xc2, 0x03, 0x03, 0x20, 0x6d, 0x20, 0x6d}, 16, 0}, - {0x65, (uint8_t[]){0x38, 0x04, 0x03, 0xc4, 0x03, 0x03, 0x38, 0x02, 0x03, 0xc6, 0x03, 0x03, 0x20, 0x6d, 0x20, 0x6d}, 16, 0}, - {0x66, (uint8_t[]){0x83, 0xcf, 0x03, 0xc8, 0x03, 0x03, 0x83, 0xd3, 0x03, 0xd2, 0x03, 0x03, 0x20, 0x6d, 0x20, 0x6d}, 16, 0}, - {0x60, (uint8_t[]){0x38, 0x0C, 0x20, 0x6D, 0x38, 0x0B, 0x20, 0x6D}, 8, 0}, - {0x61, (uint8_t[]){0x38, 0x0A, 0x20, 0x6D, 0x38, 0x09, 0x20, 0x6D}, 8, 0}, - {0x62, (uint8_t[]){0x38, 0x25, 0x20, 0x6D, 0x63, 0xC9, 0x20, 0x6D}, 8, 0}, - {0x69, (uint8_t[]){0x14, 0x22, 0x14, 0x22, 0x14, 0x22, 0x08}, 7, 0}, - {0x6B, (uint8_t[]){0x07}, 1, 0}, - {0xD1, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - {0xD2, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - {0xD3, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - {0xD4, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - {0xD5, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - {0xD6, (uint8_t[]){0x00, 0x00, 0x00, 0x70, 0x00, 0x8f, 0x00, 0xab, 0x00, 0xbf, 0x00, 0xdf, 0x00, 0xfa, 0x01, 0x2a, 0x01, 0x52, 0x01, 0x90, 0x01, 0xc1, 0x02, 0x0e, 0x02, 0x4f, 0x02, 0x51, 0x02, 0x8d, 0x02, 0xd3, 0x02, 0xff, 0x03, 0x3c, 0x03, 0x64, 0x03, 0xa1, 0x03, 0xf1, 0x03, 0xff, 0x03, 0xfF, 0x03, 0xff, 0x03, 0xFf, 0x03, 0xFF}, 52, 0}, - // {0x3A, (uint8_t[]){0x55}, 1, 0}, - - {0x11, NULL, 0, 120}, // Delay 120ms - {0x29, NULL, 0, 120}}; - -// *INDENT-OFF* - -static esp_err_t panel_gc9503_send_init_cmds(gc9503_panel_t *gc9503) -{ - esp_lcd_panel_io_handle_t io = gc9503->io; - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){ - gc9503->colmod_val, - }, - 1), - TAG, "send command failed"); - ; - - // Vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - const gc9503_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - if (gc9503->init_cmds) - { - init_cmds = gc9503->init_cmds; - init_cmds_size = gc9503->init_cmds_size; - } - else - { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(gc9503_lcd_init_cmd_t); - } - - bool is_cmd_overwritten = false; - for (int i = 0; i < init_cmds_size; i++) - { - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd) - { - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - gc9503->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - gc9503->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten) - { - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), - TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_init(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (!gc9503->flags.auto_del_panel_io) - { - ESP_RETURN_ON_ERROR(panel_gc9503_send_init_cmds(gc9503), TAG, "send init commands failed"); - } - // Init RGB panel - ESP_RETURN_ON_ERROR(gc9503->init(panel), TAG, "init RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_del(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - - if (gc9503->reset_gpio_num >= 0) - { - gpio_reset_pin(gc9503->reset_gpio_num); - } - // Delete RGB panel - gc9503->del(panel); - free(gc9503); - ESP_LOGD(TAG, "del gc9503 panel @%p", gc9503); - return ESP_OK; -} - -static esp_err_t panel_gc9503_reset(esp_lcd_panel_t *panel) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - // Perform hardware reset - if (gc9503->reset_gpio_num >= 0) - { - gpio_set_level(gc9503->reset_gpio_num, gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9503->reset_gpio_num, !gc9503->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(120)); - } - else if (io) - { // Perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(120)); - } - // Reset RGB panel - ESP_RETURN_ON_ERROR(gc9503->reset(panel), TAG, "reset RGB panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9503_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - - if (gc9503->flags.mirror_by_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control mirror through LCD command - if (mirror_x) - { - gc9503->madctl_val |= GC9503_CMD_GS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_GS_BIT; - } - if (mirror_y) - { - gc9503->madctl_val |= GC9503_CMD_SS_BIT; - } - else - { - gc9503->madctl_val &= ~GC9503_CMD_SS_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9503_CMD_MADCTL, (uint8_t[]){ - gc9503->madctl_val, - }, - 1), - TAG, "send command failed"); - ; - } - else - { - // Control mirror through RGB panel - ESP_RETURN_ON_ERROR(gc9503->mirror(panel, mirror_x, mirror_y), TAG, "RGB panel mirror failed"); - } - return ESP_OK; -} - -static esp_err_t panel_gc9503_disp_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - gc9503_panel_t *gc9503 = (gc9503_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = gc9503->io; - int command = 0; - - if (gc9503->flags.display_on_off_use_cmd) - { - ESP_RETURN_ON_FALSE(io, ESP_FAIL, TAG, "Panel IO is deleted, cannot send command"); - // Control display on/off through LCD command - if (on_off) - { - command = LCD_CMD_DISPON; - } - else - { - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - } - else - { - // Control display on/off through display control signal - ESP_RETURN_ON_ERROR(gc9503->disp_on_off(panel, on_off), TAG, "RGB panel disp_on_off failed"); - } - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.h deleted file mode 100644 index 40a5ccc1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/esp_lcd_gc9503.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief ESP LCD: GC9503 - */ - -#pragma once - -#include - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* -#include -#include "esp_lcd_gc9503.h" -#include -#include -#include - -#define TAG "Yuying_313lcd" - -class Yuying_313lcd : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - - void InitializeRGB_GC9503V_Display() { - ESP_LOGI(TAG, "Init GC9503V"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - - ESP_LOGI(TAG, "Install 3-wire SPI panel IO"); - spi_line_config_t line_config = { - .cs_io_type = IO_TYPE_GPIO, - .cs_gpio_num = GC9503V_LCD_IO_SPI_CS_1, - .scl_io_type = IO_TYPE_GPIO, - .scl_gpio_num = GC9503V_LCD_IO_SPI_SCL_1, - .sda_io_type = IO_TYPE_GPIO, - .sda_gpio_num = GC9503V_LCD_IO_SPI_SDO_1, - .io_expander = NULL, - }; - esp_lcd_panel_io_3wire_spi_config_t io_config = GC9503_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0); - (esp_lcd_new_panel_io_3wire_spi(&io_config, &panel_io)); - - ESP_LOGI(TAG, "Install RGB LCD panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_rgb_panel_config_t rgb_config = { - .clk_src = LCD_CLK_SRC_PLL160M, - .timings = GC9503_376_960_PANEL_60HZ_RGB_TIMING(), - .data_width = 16, // RGB565 in parallel mode, thus 16bit in width - .bits_per_pixel = 16, - .num_fbs = GC9503V_LCD_RGB_BUFFER_NUMS, - .bounce_buffer_size_px = GC9503V_LCD_H_RES * GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT, - .dma_burst_size = 64, - .hsync_gpio_num = GC9503V_PIN_NUM_HSYNC, - .vsync_gpio_num = GC9503V_PIN_NUM_VSYNC, - .de_gpio_num = GC9503V_PIN_NUM_DE, - .pclk_gpio_num = GC9503V_PIN_NUM_PCLK, - .disp_gpio_num = GC9503V_PIN_NUM_DISP_EN, - .data_gpio_nums = { - GC9503V_PIN_NUM_DATA0, - GC9503V_PIN_NUM_DATA1, - GC9503V_PIN_NUM_DATA2, - GC9503V_PIN_NUM_DATA3, - GC9503V_PIN_NUM_DATA4, - GC9503V_PIN_NUM_DATA5, - GC9503V_PIN_NUM_DATA6, - GC9503V_PIN_NUM_DATA7, - GC9503V_PIN_NUM_DATA8, - GC9503V_PIN_NUM_DATA9, - GC9503V_PIN_NUM_DATA10, - GC9503V_PIN_NUM_DATA11, - GC9503V_PIN_NUM_DATA12, - GC9503V_PIN_NUM_DATA13, - GC9503V_PIN_NUM_DATA14, - GC9503V_PIN_NUM_DATA15, - }, - .flags= { - .fb_in_psram = true, // allocate frame buffer in PSRAM - } - }; - - ESP_LOGI(TAG, "Initialize RGB LCD panel"); - - gc9503_vendor_config_t vendor_config = { - .rgb_config = &rgb_config, - .flags = { - .mirror_by_cmd = 0, - .auto_del_panel_io = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = -1, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = &vendor_config, - }; - (esp_lcd_new_panel_gc9503(panel_io, &panel_config, &panel_handle)); - (esp_lcd_panel_reset(panel_handle)); - (esp_lcd_panel_init(panel_handle)); - - display_ = new RgbLcdDisplay(panel_io, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - -public: - Yuying_313lcd() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializeRGB_GC9503V_Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(Yuying_313lcd); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/pin_config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/pin_config.h deleted file mode 100644 index 0bcd0594..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/kevin-yuying-313lcd/pin_config.h +++ /dev/null @@ -1,47 +0,0 @@ - -#pragma once -#define GC9503V_LCD_H_RES 376 -#define GC9503V_LCD_V_RES 960 - - -#define GC9503V_LCD_LVGL_DIRECT_MODE (1) -#define GC9503V_LCD_LVGL_AVOID_TEAR (1) -#define GC9503V_LCD_RGB_BOUNCE_BUFFER_MODE (1) -#define GC9503V_LCD_DRAW_BUFF_DOUBLE (0) -#define GC9503V_LCD_DRAW_BUFF_HEIGHT (100) -#define GC9503V_LCD_RGB_BUFFER_NUMS (2) -#define GC9503V_LCD_RGB_BOUNCE_BUFFER_HEIGHT (10) - -#define GC9503V_LCD_PIXEL_CLOCK_HZ (16 * 1000 * 1000) -#define GC9503V_LCD_BK_LIGHT_ON_LEVEL 1 -#define GC9503V_LCD_BK_LIGHT_OFF_LEVEL !GC9503V_LCD_BK_LIGHT_ON_LEVEL -#define GC9503V_PIN_NUM_BK_LIGHT GPIO_NUM_4 -#define GC9503V_PIN_NUM_HSYNC 6 -#define GC9503V_PIN_NUM_VSYNC 5 -#define GC9503V_PIN_NUM_DE 15 -#define GC9503V_PIN_NUM_PCLK 7 - -#define GC9503V_PIN_NUM_DATA0 47 // B0 -#define GC9503V_PIN_NUM_DATA1 21 // B1 -#define GC9503V_PIN_NUM_DATA2 14 // B2 -#define GC9503V_PIN_NUM_DATA3 13 // B3 -#define GC9503V_PIN_NUM_DATA4 12 // B4 - -#define GC9503V_PIN_NUM_DATA5 11 // G0 -#define GC9503V_PIN_NUM_DATA6 10 // G1 -#define GC9503V_PIN_NUM_DATA7 9 // G2 -#define GC9503V_PIN_NUM_DATA8 46 // G3 -#define GC9503V_PIN_NUM_DATA9 3 // G4 -#define GC9503V_PIN_NUM_DATA10 20 // G5 - -#define GC9503V_PIN_NUM_DATA11 19 // R0 -#define GC9503V_PIN_NUM_DATA12 8 // R1 -#define GC9503V_PIN_NUM_DATA13 18 // R2 -#define GC9503V_PIN_NUM_DATA14 17 // R3 -#define GC9503V_PIN_NUM_DATA15 16 // R4 - -#define GC9503V_PIN_NUM_DISP_EN -1 - -#define GC9503V_LCD_IO_SPI_CS_1 (GPIO_NUM_48) -#define GC9503V_LCD_IO_SPI_SCL_1 (GPIO_NUM_17) -#define GC9503V_LCD_IO_SPI_SDO_1 (GPIO_NUM_16) \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/README.md deleted file mode 100644 index 01d2b69f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# labplus 乐动掌控V2 - -## 板载资源 - 主控:ESP32-S3 外挂8MB psram 16MB flash - 传感器: - 按钮(A B按键) IO0 IO46 - 光照传感器 IIC - 6轴 IIC - 磁力计 IIC - 声音触发 IO6 - 触摸按键 IIC P Y T H O N - 摄像头 IIC - 执行器: - 蜂鸣器 IO21 - RGB灯 IO16 - 录音播放 es8388 IIC - TFT LCD jd9853 SPI - 电机驱动 IIC - - -## 编译配置 - -### 配置编译目标为 ESP32S3,USB JTAG下载 - -```bash -idf.py set-target esp32s3 -``` - -### menuconfig配置 - -```bash -idf.py menuconfig -``` - -***选择板子:*** - -``` -Xiaozhi Assistant -> Board Type -> labplus Ledong_v2 board -``` - -***修改 psram 配置:*** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> quad Mode PSRAM -``` - -**编译:** - -```bash -idf.py build -``` - -**固件打包:** - -```bash -esptool.py -p /dev/ttyACM0 -b 1500000 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x100000 xiaozhi.bin 0x8000 partition_table/partition-table.bin 0xd000 ota_data_initial.bin 0x10000 srmodels/srmodels.bin -``` - -## 使用 - -### 按键配置 -* A:短按-打断/唤醒 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.h deleted file mode 100644 index 79f9d4f6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.h +++ /dev/null @@ -1,44 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_39 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_38 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_44 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_43 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BUILTIN_LED_GPIO GPIO_NUM_1 - -#define LCD_SCLK_PIN GPIO_NUM_36 -#define LCD_MOSI_PIN GPIO_NUM_37 -#define LCD_MISO_PIN GPIO_NUM_NC -#define LCD_DC_PIN GPIO_NUM_35 -#define LCD_CS_PIN GPIO_NUM_NC - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 172 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 34 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_34 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.json deleted file mode 100644 index 8df7030f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "labplus-ledong-v2", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc deleted file mode 100644 index 1ddf5732..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-ledong-v2/labplus_ledong_v2.cc +++ /dev/null @@ -1,163 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8388_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/single_led.h" - -#include -#include -#include -#include - -#define TAG "labplus_ledong_v2" - -#define BOARD_STM8_ADDR 17 -#define BOARD_STM8_CMD 4 - -class labplus_ledong_v2 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeJd9853Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - ESP_LOGD(TAG, "Install panel IO"); - // 液晶屏控制IO初始化 - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 20 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); - - // 初始化液晶屏驱动芯片JD9853,使用ST7789驱动,时序和复位有调整。 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); - - #if CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2 - ESP_LOGI(TAG, "Reset LCD."); - i2c_device_config_t dev_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = BOARD_STM8_ADDR, - .scl_speed_hz = 400000, - }; - - i2c_master_dev_handle_t dev_handle; - i2c_master_bus_add_device(i2c_bus_, &dev_cfg, &dev_handle); - - uint8_t reg = BOARD_STM8_CMD; - i2c_master_transmit(dev_handle, ®, 1, -1); - - i2c_master_bus_rm_device(dev_handle); - #endif - - esp_lcd_panel_reset(panel); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - labplus_ledong_v2() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeJd9853Display(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8388_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(labplus_ledong_v2); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/README.md deleted file mode 100644 index 5c2148de..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# labplus 掌控板V3 - -## 板载资源 - 主控:ESP32-S3 外挂8MB psram 16MB flash - 传感器: - 按钮(A B按键) IO0 IO46 - 光照传感器 IIC - 6轴 IIC - 磁力计 IIC - 声音触发 IO6 - 触摸按键 P Y T H O N - 摄像头 IIC - 执行器: - 蜂鸣器 IO21 - RGB灯 IO16 - 录音播放 es8388 IIC - TFT LCD jd9853 SPI - - -## 编译配置 - -### 配置编译目标为 ESP32S3,USB JTAG下载 - -```bash -idf.py set-target esp32s3 -``` - -### menuconfig配置 - -```bash -idf.py menuconfig -``` - -***选择板子:*** - -``` -Xiaozhi Assistant -> Board Type -> labplus mpython_v3 board -``` - -***修改 psram 配置:*** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> quad Mode PSRAM -``` - -**编译:** - -```bash -idf.py build -``` - -**固件打包:** - -```bash -esptool.py -p /dev/ttyACM0 -b 1500000 --before default_reset --after hard_reset --chip esp32s3 write_flash --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0 bootloader/bootloader.bin 0x100000 xiaozhi.bin 0x8000 partition_table/partition-table.bin 0xd000 ota_data_initial.bin 0x10000 srmodels/srmodels.bin -``` - -## 使用 - -### 按键配置 -* A:短按-打断/唤醒 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.h deleted file mode 100644 index e6a84846..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.h +++ /dev/null @@ -1,44 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_39 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_42 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_38 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_44 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_43 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BUILTIN_LED_GPIO GPIO_NUM_1 - -#define LCD_SCLK_PIN GPIO_NUM_36 -#define LCD_MOSI_PIN GPIO_NUM_37 -#define LCD_MISO_PIN GPIO_NUM_NC -#define LCD_DC_PIN GPIO_NUM_35 -#define LCD_CS_PIN GPIO_NUM_34 - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 172 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 34 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_33 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.json deleted file mode 100644 index b5bd0ee4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "labplus-mpython-v3", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/mpython_pro.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/mpython_pro.cc deleted file mode 100644 index 69c2eee9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/labplus-mpython-v3/mpython_pro.cc +++ /dev/null @@ -1,143 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8388_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/single_led.h" - -#include -#include -#include -#include - -#define TAG "mpython_v3" - -class mpython_v3 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - // Initialize spi peripheral - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = LCD_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = LCD_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - ESP_LOGD(TAG, "Install panel IO"); - // 液晶屏控制IO初始化 - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS_PIN; - io_config.dc_gpio_num = LCD_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 20 * 1000 * 1000; - io_config.trans_queue_depth = 7; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io); - - // 初始化液晶屏驱动芯片JD9853,使用ST7789驱动,时序有调整。 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.data_endian = LCD_RGB_DATA_ENDIAN_BIG, - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - vTaskDelay(pdMS_TO_TICKS(100)); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - mpython_v3() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8388_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(mpython_v3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/README.md deleted file mode 100644 index ec6ec88a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## 立创·实战派ESP32-C3开发板 - -1、开发板资料:https://wiki.lckfb.com/zh-hans/szpi-esp32c3 - -2、该开发板 flash 大小为 8MB,编译时注意选择合适的分区表: - -``` -Partition Table ---> - Partition Table (Custom partition table CSV) ---> - (partitions/v2/8m.csv) Custom partition CSV file -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.h deleted file mode 100644 index 548ccb44..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11 - -#define AUDIO_CODEC_USE_PCA9557 -#define AUDIO_CODEC_PA_PIN GPIO_NUM_13 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_0 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR 0x82 - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SPI_SCK_PIN GPIO_NUM_3 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_6 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_4 - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_2 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.json deleted file mode 100644 index 6000c33a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "lichuang-c3-dev", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/lichuang_c3_dev_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/lichuang_c3_dev_board.cc deleted file mode 100644 index f728ed8e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-c3-dev/lichuang_c3_dev_board.cc +++ /dev/null @@ -1,129 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" - -#include -#include -#include -#include - -#define TAG "LichuangC3DevBoard" - -class LichuangC3DevBoard : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SPI_SCK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 2; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - LichuangC3DevBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - codec_i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(LichuangC3DevBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.h deleted file mode 100644 index c5d2bf24..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_13 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_45 - -#define AUDIO_CODEC_USE_PCA9557 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_1 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_2 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR 0x82 - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -/* Camera pins */ -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_XCLK GPIO_NUM_5 -#define CAMERA_PIN_SIOD GPIO_NUM_1 -#define CAMERA_PIN_SIOC GPIO_NUM_2 - -#define CAMERA_PIN_D7 GPIO_NUM_9 -#define CAMERA_PIN_D6 GPIO_NUM_4 -#define CAMERA_PIN_D5 GPIO_NUM_6 -#define CAMERA_PIN_D4 GPIO_NUM_15 -#define CAMERA_PIN_D3 GPIO_NUM_17 -#define CAMERA_PIN_D2 GPIO_NUM_8 -#define CAMERA_PIN_D1 GPIO_NUM_18 -#define CAMERA_PIN_D0 GPIO_NUM_16 -#define CAMERA_PIN_VSYNC GPIO_NUM_3 -#define CAMERA_PIN_HREF GPIO_NUM_46 -#define CAMERA_PIN_PCLK GPIO_NUM_7 - -#define XCLK_FREQ_HZ 20000000 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.json deleted file mode 100644 index b35065b7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "lichuang-dev", - "sdkconfig_append": [ - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_CAMERA_GC0308=y", - "CONFIG_CAMERA_GC0308_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_GC0308_DVP_YUV422_640X480_16FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/emote.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/emote.json deleted file mode 100644 index abc11c8f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/emote.json +++ /dev/null @@ -1,22 +0,0 @@ -[ - {"emote": "happy", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "laughing", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "funny", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "loving", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "embarrassed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confident", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "delicious", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "sad", "src": "Sad.eaf", "loop": true, "fps": 20}, - {"emote": "crying", "src": "cry.eaf", "loop": true, "fps": 20}, - {"emote": "sleepy", "src": "sleep.eaf", "loop": true, "fps": 20}, - {"emote": "silly", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "angry", "src": "angry.eaf", "loop": true, "fps": 20}, - {"emote": "surprised", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "shocked", "src": "shocked.eaf", "loop": true, "fps": 20}, - {"emote": "thinking", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "winking", "src": "neutral.eaf", "loop": true, "fps": 20}, - {"emote": "relaxed", "src": "Happy.eaf", "loop": true, "fps": 20}, - {"emote": "confused", "src": "confused.eaf", "loop": true, "fps": 20}, - {"emote": "neutral", "src": "winking.eaf", "loop": false, "fps": 20}, - {"emote": "idle", "src": "neutral.eaf", "loop": false, "fps": 20} -] diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/layout.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/layout.json deleted file mode 100644 index 8a1dfbcc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/layout.json +++ /dev/null @@ -1,37 +0,0 @@ -[ - { - "name": "eye_anim", - "align": "GFX_ALIGN_LEFT_MID", - "x": 10, - "y": 30 - }, - { - "name": "status_icon", - "align": "GFX_ALIGN_TOP_MID", - "x": -120, - "y": 18 - }, - { - "name": "toast_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 20, - "width": 200, - "height": 40 - }, - { - "name": "clock_label", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 20, - "width": 200, - "height": 50 - }, - { - "name": "listen_anim", - "align": "GFX_ALIGN_TOP_MID", - "x": 0, - "y": 5 - } -] - \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/lichuang_dev_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/lichuang_dev_board.cc deleted file mode 100644 index 42f82884..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lichuang-dev/lichuang_dev_board.cc +++ /dev/null @@ -1,295 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "display/emote_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "esp32_camera.h" -#include "mcp_server.h" - -#include -#include -#include -#include -#include -#include -#include - -#define TAG "LichuangDevBoard" - -class Pca9557 : public I2cDevice { -public: - Pca9557(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(0x01, 0x03); - WriteReg(0x03, 0xf8); - } - - void SetOutputState(uint8_t bit, uint8_t level) { - uint8_t data = ReadReg(0x01); - data = (data & ~(1 << bit)) | (level << bit); - WriteReg(0x01, data); - } -}; - -class CustomAudioCodec : public BoxAudioCodec { -private: - Pca9557* pca9557_; - -public: - CustomAudioCodec(i2c_master_bus_handle_t i2c_bus, Pca9557* pca9557) - : BoxAudioCodec(i2c_bus, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - GPIO_NUM_NC, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE), - pca9557_(pca9557) { - } - - virtual void EnableOutput(bool enable) override { - BoxAudioCodec::EnableOutput(enable); - if (enable) { - pca9557_->SetOutputState(1, 1); - } else { - pca9557_->SetOutputState(1, 0); - } - } -}; - -class LichuangDevBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - i2c_master_dev_handle_t pca9557_handle_; - Button boot_button_; - Display* display_; - Pca9557* pca9557_; - Esp32Camera* camera_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - // Initialize PCA9557 - pca9557_ = new Pca9557(i2c_bus_, 0x19); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_40; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_41; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_NC; - io_config.dc_gpio_num = GPIO_NUM_39; - io_config.spi_mode = 2; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - pca9557_->SetOutputState(0, 0); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - -#if CONFIG_USE_EMOTE_MESSAGE_STYLE - display_ = new emote::EmoteDisplay(panel, panel_io, DISPLAY_WIDTH, DISPLAY_HEIGHT); -#else - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); -#endif - } - - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_HEIGHT, - .y_max = DISPLAY_WIDTH, - .rst_gpio_num = GPIO_NUM_NC, // Shared with LCD reset - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 1, - .mirror_x = 1, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG(); - tp_io_config.scl_speed_hz = 400000; - - esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle); - esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, &tp); - assert(tp); - - /* Add touch input (for selected screen) */ - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - - if(touch_cfg.disp) { - lvgl_port_add_touch(&touch_cfg); - } else { - ESP_LOGE(TAG, "Touch display is not initialized"); - } - } - - void InitializeCamera() { - // Open camera power - pca9557_->SetOutputState(2, 0); - - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - } - - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - LichuangDevBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeTouch(); - InitializeButtons(); - InitializeCamera(); - InitializeTools(); - - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static CustomAudioCodec audio_codec( - i2c_bus_, - pca9557_); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(LichuangDevBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/README.md deleted file mode 100644 index 9b9de56b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/README.md +++ /dev/null @@ -1,47 +0,0 @@ -## LILYGO T-CameraPlus-S3 - -T-CameraPlus-S3 is an intelligent camera module developed based on the ESP32S3 chip, equipped with a 240x240 TFT display, digital microphone, speaker, independent button, power control chip, SD card module, etc. It comes with a basic UI written based on LVGL, which can achieve functions such as file management, music playback, recording, and camera projection (if the factory does not write the program, you need to manually burn the UI program named "Lvgl_UI"). - -Official github: [T-CameraPlus-S3](https://github.com/Xinyuan-LilyGO/T-CameraPlus-S3) - -## Configuration - -**Set the compilation target to ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**Open menuconfig** - -```bash -idf.py menuconfig -``` - -**Select the board** - -``` -Xiaozhi Assistant -> Board Type -> LILYGO T-CameraPlus-S3_V1_0_V1_1 -Or -Xiaozhi Assistant -> Board Type -> LILYGO T-CameraPlus-S3_V1_2 -``` - -**Modify the psram configuration** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> Quad Mode PSRAM -``` - - -**Select and set camera sensor** - -``` -Component config -> Espressif Camera Sensors Configurations -> Camera Sensor Configuration -> Select and Set Camera Sensor -> OV2640 -> Select default output format for DVP interface -> YUV422 240x240 25fps, DVP 8-bit, 20M input -``` - - -**Build** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.h deleted file mode 100644 index 0d69e691..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include "pin_config.h" - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#ifdef CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1 -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_MIC_I2S_GPIO_BCLK MSM261_BCLK -#define AUDIO_MIC_I2S_GPIO_WS MSM261_WS -#define AUDIO_MIC_I2S_GPIO_DATA MSM261_DATA -#elif defined CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 -#define AUDIO_INPUT_REFERENCE false -#define AUDIO_MIC_I2S_GPIO_BCLK GPIO_NUM_NC -#define AUDIO_MIC_I2S_GPIO_WS MP34DT05TR_LRCLK -#define AUDIO_MIC_I2S_GPIO_DATA MP34DT05TR_DATA - -#define AUDIO_MIC_SPKR_EN MP34DT05TR_MAX98357_EN -#endif - -#define AUDIO_SPKR_I2S_GPIO_BCLK MAX98357A_BCLK -#define AUDIO_SPKR_I2S_GPIO_LRCLK MAX98357A_LRCLK -#define AUDIO_SPKR_I2S_GPIO_DATA MAX98357A_DATA - -#define TOUCH_I2C_SDA_PIN TP_SDA -#define TOUCH_I2C_SCL_PIN TP_SCL - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define KEY1_BUTTON_GPIO KEY1 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH LCD_WIDTH -#define DISPLAY_HEIGHT LCD_HEIGHT -#define DISPLAY_MOSI LCD_MOSI -#define DISPLAY_SCLK LCD_SCLK -#define DISPLAY_DC LCD_DC -#define DISPLAY_RST LCD_RST -#define DISPLAY_CS LCD_CS -#define DISPLAY_BL LCD_BL -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN DISPLAY_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define AP1511B_GPIO AP1511B_FBC - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.json deleted file mode 100644 index a6386443..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/config.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "lilygo-t-cameraplus-s3", - "sdkconfig_append": [ - "CONFIG_SPIRAM_MODE_QUAD=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_240X240_25FPS=y" - ] - }, - { - "name": "lilygo-t-cameraplus-s3_v1_2", - "sdkconfig_append": [ - "CONFIG_SPIRAM_MODE_QUAD=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_240X240_25FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/ir_filter_controller.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/ir_filter_controller.h deleted file mode 100644 index 3ae619ad..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/ir_filter_controller.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef __IR_FILTER_CONTROLLER_H__ -#define __IR_FILTER_CONTROLLER_H__ - -#include "mcp_server.h" - - -class IrFilterController { -private: - bool enable_ = false; - gpio_num_t gpio_num_; - -public: - IrFilterController(gpio_num_t gpio_num) : gpio_num_(gpio_num) { - gpio_config_t config = { - .pin_bit_mask = (1ULL << gpio_num_), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - ESP_ERROR_CHECK(gpio_config(&config)); - gpio_set_level(gpio_num_, 0); - - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.camera.get_ir_filter_state", "Get the state of the camera's infrared filter", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return enable_ ? "{\"enable\": true}" : "{\"enable\": false}"; - }); - - mcp_server.AddTool("self.camera.enable_ir_filter", "Enable the camera's infrared filter", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - enable_ = true; - gpio_set_level(gpio_num_, 1); - return true; - }); - - mcp_server.AddTool("self.camera.disable_ir_filter", "Disable the camera's infrared filter", PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - enable_ = false; - gpio_set_level(gpio_num_, 0); - return true; - }); - } -}; - - -#endif // __IR_FILTER_CONTROLLER_H__ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc deleted file mode 100644 index 98ebac36..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/lilygo-t-cameraplus-s3.cc +++ /dev/null @@ -1,350 +0,0 @@ -#include "wifi_board.h" -#include "tcamerapluss3_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "i2c_device.h" -#include "sy6970.h" -#include "pin_config.h" -#include "esp32_camera.h" -#include "ir_filter_controller.h" - -#include -#include -#include - -#define TAG "LilygoTCameraPlusS3Board" - -class Cst816x : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - Cst816x(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA7); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Cst816x() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t &GetTouchPoint() { - return tp_; - } - -private: - uint8_t *read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class Pmic : public Sy6970 { -public: - - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Sy6970(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0x14); - ESP_LOGI(TAG, "Get sy6970 chip ID: 0x%02X", (chip_id & 0B00111000)); - - WriteReg(0x00, 0B00001000); // Disable ILIM pin - WriteReg(0x02, 0B11011101); // Enable ADC measurement function - WriteReg(0x07, 0B10001101); // Disable watchdog timer feeding function - } -}; - -class LilygoTCameraPlusS3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst816x *cst816d_; - Pmic* pmic_; - LcdDisplay *display_; - Button boot_button_; - Button key1_button_; - PowerSaveTimer* power_save_timer_; - Esp32Camera* camera_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, -1); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitI2c(){ - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_config = { - .i2c_port = I2C_NUM_0, - .sda_io_num = TOUCH_I2C_SDA_PIN, - .scl_io_num = TOUCH_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - } - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - static void TouchpadDaemon(void *param) { - vTaskDelay(pdMS_TO_TICKS(2000)); - auto &board = (LilygoTCameraPlusS3Board&)Board::GetInstance(); - auto touchpad = board.GetTouchpad(); - bool was_touched = false; - while (1) { - touchpad->UpdateTouchPoint(); - if (touchpad->GetTouchPoint().num > 0){ - // On press - if (!was_touched) { - was_touched = true; - Application::GetInstance().ToggleChatState(); - } - } - // On release - else if (was_touched) { - was_touched = false; - } - vTaskDelay(pdMS_TO_TICKS(50)); - } - vTaskDelete(NULL); - } - - void InitCst816d() { - ESP_LOGI(TAG, "Init CST816x"); - cst816d_ = new Cst816x(i2c_bus_, CST816_ADDRESS); - xTaskCreate(TouchpadDaemon, "tp", 2048, NULL, 5, NULL); - } - - void InitSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitSy6970() { - ESP_LOGI(TAG, "Init Sy6970"); - pmic_ = new Pmic(i2c_bus_, SY6970_ADDRESS); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS; - io_config.dc_gpio_num = LCD_DC; - io_config.spi_mode = 0; - io_config.pclk_hz = 60 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - key1_button_.OnClick([this]() { - if (camera_) { - camera_->Capture(); - } - }); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = Y2_GPIO_NUM, - [1] = Y3_GPIO_NUM, - [2] = Y4_GPIO_NUM, - [3] = Y5_GPIO_NUM, - [4] = Y6_GPIO_NUM, - [5] = Y7_GPIO_NUM, - [6] = Y8_GPIO_NUM, - [7] = Y9_GPIO_NUM, - }, - .vsync_io = VSYNC_GPIO_NUM, - .de_io = HREF_GPIO_NUM, - .pclk_io = PCLK_GPIO_NUM, - .xclk_io = XCLK_GPIO_NUM, - }; - - esp_video_init_sccb_config_t sccb_config = { -#ifdef CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1 - .init_sccb = false, - .i2c_handle = i2c_bus_, -#elif defined CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 - .init_sccb = true, - .i2c_config = { - .port = 1, - .scl_pin = SIOC_GPIO_NUM, - .sda_pin = SIOD_GPIO_NUM, - }, -#endif - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = RESET_GPIO_NUM, - .pwdn_pin = PWDN_GPIO_NUM, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetVFlip(1); - camera_->SetHMirror(1); - } - - void InitializeTools() { - static IrFilterController irFilter(AP1511B_GPIO); - } - -public: - LilygoTCameraPlusS3Board() : boot_button_(BOOT_BUTTON_GPIO), key1_button_(KEY1_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitI2c(); - InitSy6970(); - InitCst816d(); - I2cDetect(); - InitSpi(); - InitializeSt7789Display(); - InitializeButtons(); - InitializeCamera(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Tcamerapluss3AudioCodec audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_MIC_I2S_GPIO_BCLK, - AUDIO_MIC_I2S_GPIO_WS, - AUDIO_MIC_I2S_GPIO_DATA, - AUDIO_SPKR_I2S_GPIO_BCLK, - AUDIO_SPKR_I2S_GPIO_LRCLK, - AUDIO_SPKR_I2S_GPIO_DATA, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override{ - return display_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - bool is_power_good = pmic_->IsPowerGood(); - discharging = !charging && is_power_good; - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst816x *GetTouchpad() { - return cst816d_; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(LilygoTCameraPlusS3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/pin_config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/pin_config.h deleted file mode 100644 index 82ab983b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/pin_config.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * @Description: None - * @Author: LILYGO_L - * @Date: 2024-11-11 11:36:49 - * @LastEditTime: 2025-06-03 17:37:08 - * @License: GPL 3.0 - */ -#pragma once - -#ifdef CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1 -#define T_CameraPlus_S3_V1_0_V1_1 -#elif defined CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 -#define T_CameraPlus_S3_V1_2 -#endif - -#ifdef T_CameraPlus_S3_V1_0_V1_1 - -// SPI -#define SPI_SCLK GPIO_NUM_36 -#define SPI_MOSI GPIO_NUM_35 -#define SPI_MISO GPIO_NUM_37 - -// IIC -#define IIC_SDA GPIO_NUM_1 -#define IIC_SCL GPIO_NUM_2 - -// MSM261 -#define MSM261_BCLK GPIO_NUM_18 -#define MSM261_WS GPIO_NUM_39 -#define MSM261_DATA GPIO_NUM_40 - -// MAX98357A -#define MAX98357A_DATA GPIO_NUM_38 - -// FP-133H01D -#define LCD_CS GPIO_NUM_34 -#define LCD_RST GPIO_NUM_33 - -// OV2640 -#define OV2640_PWDN GPIO_NUM_NC -#define OV2640_RESET GPIO_NUM_3 -#define OV2640_VSYNC GPIO_NUM_4 - -// CST816 -#define TP_RST GPIO_NUM_48 - -// SY6970 -#define SY6970_INT GPIO_NUM_47 - -#endif - -#ifdef T_CameraPlus_S3_V1_2 - -// SPI -#define SPI_SCLK GPIO_NUM_35 -#define SPI_MOSI GPIO_NUM_34 -#define SPI_MISO GPIO_NUM_48 - -// IIC -#define IIC_SDA GPIO_NUM_33 -#define IIC_SCL GPIO_NUM_37 - -// MP34DT05TR -#define MP34DT05TR_LRCLK GPIO_NUM_40 -#define MP34DT05TR_DATA GPIO_NUM_38 - -#define MP34DT05TR_MAX98357_EN GPIO_NUM_18 - -// MAX98357A -#define MAX98357A_DATA GPIO_NUM_39 - -// FP-133H01D -#define LCD_CS GPIO_NUM_36 -#define LCD_RST GPIO_NUM_NC - -// OV2640 -#define OV2640_PWDN GPIO_NUM_4 -#define OV2640_RESET GPIO_NUM_NC -#define OV2640_VSYNC GPIO_NUM_3 - -// CST816 -#define TP_RST GPIO_NUM_NC - -#endif - -// SD -#define SD_CS GPIO_NUM_21 -#define SD_SCLK SPI_SCLK -#define SD_MOSI SPI_MOSI -#define SD_MISO SPI_MISO - -// MAX98357A -#define MAX98357A_BCLK GPIO_NUM_41 -#define MAX98357A_LRCLK GPIO_NUM_42 - -// FP-133H01D -#define LCD_WIDTH 240 -#define LCD_HEIGHT 240 -#define LCD_BL GPIO_NUM_46 -#define LCD_MOSI SPI_MOSI -#define LCD_SCLK SPI_SCLK -#define LCD_DC GPIO_NUM_45 - -// SY6970 -#define SY6970_SDA IIC_SDA -#define SY6970_SCL IIC_SCL -#define SY6970_ADDRESS 0x6A - -// OV2640 -#define OV2640_XCLK GPIO_NUM_7 -#define OV2640_SDA GPIO_NUM_1 -#define OV2640_SCL GPIO_NUM_2 -#define OV2640_D9 GPIO_NUM_6 -#define OV2640_D8 GPIO_NUM_8 -#define OV2640_D7 GPIO_NUM_9 -#define OV2640_D6 GPIO_NUM_11 -#define OV2640_D5 GPIO_NUM_13 -#define OV2640_D4 GPIO_NUM_15 -#define OV2640_D3 GPIO_NUM_14 -#define OV2640_D2 GPIO_NUM_12 -#define OV2640_HREF GPIO_NUM_5 -#define OV2640_PCLK GPIO_NUM_10 - -#define PWDN_GPIO_NUM OV2640_PWDN -#define RESET_GPIO_NUM OV2640_RESET -#define XCLK_GPIO_NUM OV2640_XCLK -#define SIOD_GPIO_NUM OV2640_SDA -#define SIOC_GPIO_NUM OV2640_SCL - -#define Y9_GPIO_NUM OV2640_D9 -#define Y8_GPIO_NUM OV2640_D8 -#define Y7_GPIO_NUM OV2640_D7 -#define Y6_GPIO_NUM OV2640_D6 -#define Y5_GPIO_NUM OV2640_D5 -#define Y4_GPIO_NUM OV2640_D4 -#define Y3_GPIO_NUM OV2640_D3 -#define Y2_GPIO_NUM OV2640_D2 -#define VSYNC_GPIO_NUM OV2640_VSYNC -#define HREF_GPIO_NUM OV2640_HREF -#define PCLK_GPIO_NUM OV2640_PCLK - -#define XCLK_FREQ_HZ 20000000 - -// CST816 -#define CST816_ADDRESS 0x15 -#define TP_SDA IIC_SDA -#define TP_SCL IIC_SCL -#define TP_INT GPIO_NUM_47 - -// AP1511B -#define AP1511B_FBC GPIO_NUM_16 - -// KEY -#define KEY1 GPIO_NUM_17 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc deleted file mode 100644 index 365d9ca7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.cc +++ /dev/null @@ -1,169 +0,0 @@ -#include "tcamerapluss3_audio_codec.h" - -#include -#include -#include -#include - -#include "config.h" - -static const char TAG[] = "Tcamerapluss3AudioCodec"; - -Tcamerapluss3AudioCodec::Tcamerapluss3AudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateVoiceHardware(mic_bclk, mic_ws, mic_data, spkr_bclk, spkr_lrclk, spkr_data); - - ESP_LOGI(TAG, "Tcamerapluss3AudioCodec initialized"); - -#ifdef CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 - gpio_config_t config_mic_spkr_en; - config_mic_spkr_en.pin_bit_mask = BIT64(AUDIO_MIC_SPKR_EN); - config_mic_spkr_en.mode = GPIO_MODE_OUTPUT; - config_mic_spkr_en.pull_up_en = GPIO_PULLUP_ENABLE; - config_mic_spkr_en.pull_down_en = GPIO_PULLDOWN_DISABLE; - config_mic_spkr_en.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER -config_mic_spkr_en.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config_mic_spkr_en); - gpio_set_level(AUDIO_MIC_SPKR_EN, 0); -#endif -} - -Tcamerapluss3AudioCodec::~Tcamerapluss3AudioCodec() { - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Tcamerapluss3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) { - - i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER); - mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_1, I2S_ROLE_MASTER); - spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - - ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_)); - ESP_ERROR_CHECK(i2s_new_channel(&spkr_chan_config, &tx_handle_, NULL)); - - #ifdef CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1 - i2s_std_config_t mic_config = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), - .gpio_cfg = { - .mclk = I2S_GPIO_UNUSED, - .bclk = mic_bclk, - .ws = mic_ws, - .dout = I2S_GPIO_UNUSED, - .din = mic_data, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = true // 默认右通道 - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &mic_config)); -#elif defined CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2 - i2s_pdm_rx_config_t mic_config = { - .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(static_cast(input_sample_rate_)), - /* The data bit-width of PDM mode is fixed to 16 */ - .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO), - .gpio_cfg = { - .clk = mic_ws, - .din = mic_data, - .invert_flags = { - .clk_inv = false, - }, - }, - }; - - ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_handle_, &mic_config)); -#endif - - i2s_std_config_t spkr_config = { - .clk_cfg ={ - .sample_rate_hz = static_cast(11025), - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - }, - .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg ={ - .mclk = I2S_GPIO_UNUSED, - .bclk = spkr_bclk, - .ws = spkr_lrclk, - .dout = spkr_data, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &spkr_config)); - ESP_LOGI(TAG, "Voice hardware created"); -} - -void Tcamerapluss3AudioCodec::SetOutputVolume(int volume) { - volume_ = volume; - AudioCodec::SetOutputVolume(volume); -} - -void Tcamerapluss3AudioCodec::EnableInput(bool enable) { - AudioCodec::EnableInput(enable); -} - -void Tcamerapluss3AudioCodec::EnableOutput(bool enable) { - AudioCodec::EnableOutput(enable); -} - -int Tcamerapluss3AudioCodec::Read(int16_t *dest, int samples) { - if (input_enabled_) { - size_t bytes_read; - i2s_channel_read(rx_handle_, dest, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - - // 麦克风接收音量放大20倍(限制在 int16_t 范围内防止溢出) - int16_t *ptr = dest; - for (int i = 0; i < samples; i++) { - int32_t amplified = *ptr * 20; - *ptr++ = (amplified > 32767) ? 32767 : (amplified < -32768) ? -32768 : amplified; - } - } - return samples; -} - -int Tcamerapluss3AudioCodec::Write(const int16_t *data, int samples){ - if (output_enabled_){ - size_t bytes_read; - auto output_data = (int16_t *)malloc(samples * sizeof(int16_t)); - for (size_t i = 0; i < samples; i++){ - output_data[i] = (float)data[i] * (float)(volume_ / 100.0); - } - i2s_channel_write(tx_handle_, output_data, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - free(output_data); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h deleted file mode 100644 index cdb9aaa5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-cameraplus-s3/tcamerapluss3_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _TCIRCLES3_AUDIO_CODEC_H -#define _TCIRCLES3_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class Tcamerapluss3AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t *data_if_ = nullptr; - const audio_codec_ctrl_if_t *out_ctrl_if_ = nullptr; - const audio_codec_if_t *out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t *in_ctrl_if_ = nullptr; - const audio_codec_if_t *in_codec_if_ = nullptr; - const audio_codec_gpio_if_t *gpio_if_ = nullptr; - - uint32_t volume_ = 70; - - void CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data); - - virtual int Read(int16_t *dest, int samples) override; - virtual int Write(const int16_t *data, int samples) override; - -public: - Tcamerapluss3AudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference); - virtual ~Tcamerapluss3AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/README.md deleted file mode 100644 index 44171cc3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> LILYGO T-Circle-S3 -``` - - -**编译:** - -```bash -idf.py build -``` - -LILYGO T-Circle-S3 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.h deleted file mode 100644 index 03e4fc57..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include "pin_config.h" - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_MIC_I2S_GPIO_BCLK static_cast(MSM261_BCLK) -#define AUDIO_MIC_I2S_GPIO_WS static_cast(MSM261_WS) -#define AUDIO_MIC_I2S_GPIO_DATA static_cast(MSM261_DATA) - -#define AUDIO_SPKR_I2S_GPIO_BCLK static_cast(MAX98357A_BCLK) -#define AUDIO_SPKR_I2S_GPIO_LRCLK static_cast(MAX98357A_LRCLK) -#define AUDIO_SPKR_I2S_GPIO_DATA static_cast(MAX98357A_DATA) -#define AUDIO_SPKR_ENABLE static_cast(MAX98357A_SD_MODE) - -#define TOUCH_I2C_SDA_PIN static_cast(TP_SDA) -#define TOUCH_I2C_SCL_PIN static_cast(TP_SCL) - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH LCD_WIDTH -#define DISPLAY_HEIGHT LCD_HEIGHT -#define DISPLAY_MOSI LCD_MOSI -#define DISPLAY_SCLK LCD_SCLK -#define DISPLAY_DC LCD_DC -#define DISPLAY_RST LCD_RST -#define DISPLAY_CS LCD_CS -#define DISPLAY_BL static_cast(LCD_BL) -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN DISPLAY_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.json deleted file mode 100644 index 378ddeda..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "lilygo-t-circle-s3", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c deleted file mode 100644 index 25a78674..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.c +++ /dev/null @@ -1,353 +0,0 @@ -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_lcd_panel_interface.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_panel_commands.h" -#include "driver/gpio.h" -#include "esp_log.h" -#include "esp_check.h" - -#include "esp_lcd_gc9d01n.h" - -static const char *TAG = "gc9d01n"; - -static esp_err_t panel_gc9d01n_del(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9d01n_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9d01n_init(esp_lcd_panel_t *panel); -static esp_err_t panel_gc9d01n_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); -static esp_err_t panel_gc9d01n_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_gc9d01n_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_gc9d01n_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); -static esp_err_t panel_gc9d01n_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_gc9d01n_disp_on_off(esp_lcd_panel_t *panel, bool off); - -typedef struct{ - esp_lcd_panel_t base; - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - bool reset_level; - int x_gap; - int y_gap; - uint8_t fb_bits_per_pixel; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register - const gc9d01n_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; -} gc9d01n_panel_t; - -esp_err_t esp_lcd_new_panel_gc9d01n(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel){ - esp_err_t ret = ESP_OK; - gc9d01n_panel_t *gc9d01n = NULL; - gpio_config_t io_conf = {0}; - - ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - gc9d01n = (gc9d01n_panel_t *)calloc(1, sizeof(gc9d01n_panel_t)); - ESP_GOTO_ON_FALSE(gc9d01n, ESP_ERR_NO_MEM, err, TAG, "no mem for gc9d01n panel"); - - if (panel_dev_config->reset_gpio_num >= 0){ - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - switch (panel_dev_config->color_space){ - case ESP_LCD_COLOR_SPACE_RGB: - gc9d01n->madctl_val = 0; - break; - case ESP_LCD_COLOR_SPACE_BGR: - gc9d01n->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); - break; - } -#else - switch (panel_dev_config->rgb_endian){ - case LCD_RGB_ENDIAN_RGB: - gc9d01n->madctl_val = 0; - break; - case LCD_RGB_ENDIAN_BGR: - gc9d01n->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian"); - break; - } -#endif - - switch (panel_dev_config->bits_per_pixel){ - case 16: // RGB565 - gc9d01n->colmod_val = 0x55; - gc9d01n->fb_bits_per_pixel = 16; - break; - case 18: // RGB666 - gc9d01n->colmod_val = 0x66; - // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel - gc9d01n->fb_bits_per_pixel = 24; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - gc9d01n->io = io; - gc9d01n->reset_gpio_num = panel_dev_config->reset_gpio_num; - gc9d01n->reset_level = panel_dev_config->flags.reset_active_high; - if (panel_dev_config->vendor_config){ - gc9d01n->init_cmds = ((gc9d01n_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds; - gc9d01n->init_cmds_size = ((gc9d01n_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size; - } - gc9d01n->base.del = panel_gc9d01n_del; - gc9d01n->base.reset = panel_gc9d01n_reset; - gc9d01n->base.init = panel_gc9d01n_init; - gc9d01n->base.draw_bitmap = panel_gc9d01n_draw_bitmap; - gc9d01n->base.invert_color = panel_gc9d01n_invert_color; - gc9d01n->base.set_gap = panel_gc9d01n_set_gap; - gc9d01n->base.mirror = panel_gc9d01n_mirror; - gc9d01n->base.swap_xy = panel_gc9d01n_swap_xy; -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - gc9d01n->base.disp_off = panel_gc9d01n_disp_on_off; -#else - gc9d01n->base.disp_on_off = panel_gc9d01n_disp_on_off; -#endif - *ret_panel = &(gc9d01n->base); - ESP_LOGD(TAG, "new gc9d01n panel @%p", gc9d01n); - - // ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_GC9D01N_VER_MAJOR, ESP_LCD_GC9D01N_VER_MINOR, - // ESP_LCD_GC9D01N_VER_PATCH); - - return ESP_OK; - -err: - if (gc9d01n){ - if (panel_dev_config->reset_gpio_num >= 0){ - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(gc9d01n); - } - return ret; -} - -static esp_err_t panel_gc9d01n_del(esp_lcd_panel_t *panel){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - - if (gc9d01n->reset_gpio_num >= 0){ - gpio_reset_pin(gc9d01n->reset_gpio_num); - } - ESP_LOGD(TAG, "del gc9d01n panel @%p", gc9d01n); - free(gc9d01n); - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_reset(esp_lcd_panel_t *panel){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - - // perform hardware reset - if (gc9d01n->reset_gpio_num >= 0){ - gpio_set_level(gc9d01n->reset_gpio_num, gc9d01n->reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(gc9d01n->reset_gpio_num, !gc9d01n->reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - } - else{ // perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command - } - - return ESP_OK; -} - -static const gc9d01n_lcd_init_cmd_t vendor_specific_init_default[] = { - // {cmd, { data }, data_size, delay_ms} - // Enable Inter Register - {0xFE, (uint8_t[]){0x00}, 0, 0}, - {0xEF, (uint8_t[]){0x00}, 0, 0}, - {0x80, (uint8_t[]){0xFF}, 1, 0}, - {0x81, (uint8_t[]){0xFF}, 1, 0}, - {0x82, (uint8_t[]){0xFF}, 1, 0}, - {0x84, (uint8_t[]){0xFF}, 1, 0}, - {0x85, (uint8_t[]){0xFF}, 1, 0}, - {0x86, (uint8_t[]){0xFF}, 1, 0}, - {0x87, (uint8_t[]){0xFF}, 1, 0}, - {0x88, (uint8_t[]){0xFF}, 1, 0}, - {0x89, (uint8_t[]){0xFF}, 1, 0}, - {0x8A, (uint8_t[]){0xFF}, 1, 0}, - {0x8B, (uint8_t[]){0xFF}, 1, 0}, - {0x8C, (uint8_t[]){0xFF}, 1, 0}, - {0x8D, (uint8_t[]){0xFF}, 1, 0}, - {0x8E, (uint8_t[]){0xFF}, 1, 0}, - {0x8F, (uint8_t[]){0xFF}, 1, 0}, - {0x3A, (uint8_t[]){0x05}, 1, 0}, - {0xEC, (uint8_t[]){0x01}, 1, 0}, - {0x74, (uint8_t[]){0x02, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00}, 7, 0}, - {0x98, (uint8_t[]){0x3E}, 1, 0}, - {0x99, (uint8_t[]){0x3E}, 1, 0}, - {0xB5, (uint8_t[]){0x0D, 0x0D}, 2, 0}, - {0x60, (uint8_t[]){0x38, 0x0F, 0x79, 0x67}, 4, 0}, - {0x61, (uint8_t[]){0x38, 0x11, 0x79, 0x67}, 4, 0}, - {0x64, (uint8_t[]){0x38, 0x17, 0x71, 0x5F, 0x79, 0x67}, 6, 0}, - {0x65, (uint8_t[]){0x38, 0x13, 0x71, 0x5B, 0x79, 0x67}, 6, 0}, - {0x6A, (uint8_t[]){0x00, 0x00}, 2, 0}, - {0x6C, (uint8_t[]){0x22, 0x02, 0x22, 0x02, 0x22, 0x22, 0x50}, 7, 0}, - {0x6E, (uint8_t[]){0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x0F, 0x0F, 0x0D, 0x0D, 0x0B, 0x0B, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, 0x0C, 0x0C, 0x0E, 0x0E, 0x10, 0x10, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04}, 32, 0}, - {0xBF, (uint8_t[]){0x01}, 1, 0}, - {0xF9, (uint8_t[]){0x40}, 1, 0}, - {0x9B, (uint8_t[]){0x3B, 0x93, 0x33, 0x7F, 0x00}, 5, 0}, - {0x7E, (uint8_t[]){0x30}, 1, 0}, - {0x70, (uint8_t[]){0x0D, 0x02, 0x08, 0x0D, 0x02, 0x08}, 6, 0}, - {0x71, (uint8_t[]){0x0D, 0x02, 0x08}, 3, 0}, - {0x91, (uint8_t[]){0x0E, 0x09}, 2, 0}, - {0xC3, (uint8_t[]){0x19, 0xC4, 0x19, 0xC9, 0x3C}, 5, 0}, - {0xF0, (uint8_t[]){0x53, 0x15, 0x0A, 0x04, 0x00, 0x3E}, 6, 0}, - {0xF1, (uint8_t[]){0x56, 0xA8, 0x7F, 0x33, 0x34, 0x5F}, 6, 0}, - {0xF2, (uint8_t[]){0x53, 0x15, 0x0A, 0x04, 0x00, 0x3A}, 6, 0}, - {0xF3, (uint8_t[]){0x52, 0xA4, 0x7F, 0x33, 0x34, 0xDF}, 6, 0}, - - // {0x20, (uint8_t[]){0x00}, 0, 0}, - {0x36, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 0, 200}, - {0x29, (uint8_t[]){0x00}, 0, 0}, - {0x2C, (uint8_t[]){0x00}, 0, 20}, -}; - -static esp_err_t panel_gc9d01n_init(esp_lcd_panel_t *panel){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - - // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){gc9d01n->madctl_val,},1),TAG, "send command failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){gc9d01n->colmod_val,},1),TAG, "send command failed"); - - const gc9d01n_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - if (gc9d01n->init_cmds){ - init_cmds = gc9d01n->init_cmds; - init_cmds_size = gc9d01n->init_cmds_size; - }else{ - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(gc9d01n_lcd_init_cmd_t); - } - - bool is_cmd_overwritten = false; - for (int i = 0; i < init_cmds_size; i++){ - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd){ - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - gc9d01n->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - gc9d01n->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten){ - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - - x_start += gc9d01n->x_gap; - x_end += gc9d01n->x_gap; - y_start += gc9d01n->y_gap; - y_end += gc9d01n->y_gap; - - // define an area of frame memory where MCU can access - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]){(x_start >> 8) & 0xFF,x_start & 0xFF,((x_end - 1) >> 8) & 0xFF,(x_end - 1) & 0xFF,},4),TAG, "send command failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]){(y_start >> 8) & 0xFF,y_start & 0xFF,((y_end - 1) >> 8) & 0xFF,(y_end - 1) & 0xFF,},4),TAG, "send command failed"); - // transfer frame buffer - size_t len = (x_end - x_start) * (y_end - y_start) * gc9d01n->fb_bits_per_pixel / 8; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "send color failed"); - - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_invert_color(esp_lcd_panel_t *panel, bool invert_color_data){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - int command = 0; - if (invert_color_data){ - command = LCD_CMD_INVON; - }else{ - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - if (mirror_x){ - gc9d01n->madctl_val |= LCD_CMD_MX_BIT; - }else{ - gc9d01n->madctl_val &= ~LCD_CMD_MX_BIT; - } - if (mirror_y){ - gc9d01n->madctl_val |= LCD_CMD_MY_BIT; - }else{ - gc9d01n->madctl_val &= ~LCD_CMD_MY_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){gc9d01n->madctl_val}, 1), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_swap_xy(esp_lcd_panel_t *panel, bool swap_axes){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - if (swap_axes){ - gc9d01n->madctl_val |= LCD_CMD_MV_BIT; - }else{ - gc9d01n->madctl_val &= ~LCD_CMD_MV_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){gc9d01n->madctl_val}, 1), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - gc9d01n->x_gap = x_gap; - gc9d01n->y_gap = y_gap; - return ESP_OK; -} - -static esp_err_t panel_gc9d01n_disp_on_off(esp_lcd_panel_t *panel, bool on_off){ - gc9d01n_panel_t *gc9d01n = __containerof(panel, gc9d01n_panel_t, base); - esp_lcd_panel_io_handle_t io = gc9d01n->io; - int command = 0; - -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - on_off = !on_off; -#endif - - if (on_off){ - command = LCD_CMD_DISPON; - }else{ - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.h deleted file mode 100644 index ec057cc2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/esp_lcd_gc9d01n.h +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include "esp_lcd_panel_vendor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* -#include -#include -#include -#include "esp_lcd_gc9d01n.h" - -#define TAG "LilygoTCircleS3Board" - -class Cst816x : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - Cst816x(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA7); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Cst816x() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t &GetTouchPoint() { - return tp_; - } - -private: - uint8_t *read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class LilygoTCircleS3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst816x *cst816d_; - LcdDisplay *display_; - Button boot_button_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitI2c(){ - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_config = { - .i2c_port = I2C_NUM_0, - .sda_io_num = TOUCH_I2C_SDA_PIN, - .scl_io_num = TOUCH_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - } - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - static void touchpad_daemon(void *param) { - vTaskDelay(pdMS_TO_TICKS(2000)); - auto &board = (LilygoTCircleS3Board&)Board::GetInstance(); - auto touchpad = board.GetTouchpad(); - bool was_touched = false; - while (1) { - touchpad->UpdateTouchPoint(); - if (touchpad->GetTouchPoint().num > 0){ - // On press - if (!was_touched) { - was_touched = true; - Application::GetInstance().ToggleChatState(); - } - } - // On release - else if (was_touched) { - was_touched = false; - } - vTaskDelay(pdMS_TO_TICKS(50)); - } - vTaskDelete(NULL); - } - - void InitCst816d() { - ESP_LOGI(TAG, "Init CST816x"); - cst816d_ = new Cst816x(i2c_bus_, 0x15); - xTaskCreate(touchpad_daemon, "tp", 2048, NULL, 5, NULL); - } - - void InitSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitGc9d01nDisplay() { - ESP_LOGI(TAG, "Init GC9D01N"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9d01n(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - gpio_config_t config; - config.pin_bit_mask = BIT64(DISPLAY_BL); - config.mode = GPIO_MODE_OUTPUT; - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - config.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER - config.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config); - gpio_set_level(DISPLAY_BL, 0); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - LilygoTCircleS3Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitI2c(); - InitCst816d(); - I2cDetect(); - InitSpi(); - InitGc9d01nDisplay(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Tcircles3AudioCodec audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_MIC_I2S_GPIO_BCLK, - AUDIO_MIC_I2S_GPIO_WS, - AUDIO_MIC_I2S_GPIO_DATA, - AUDIO_SPKR_I2S_GPIO_BCLK, - AUDIO_SPKR_I2S_GPIO_LRCLK, - AUDIO_SPKR_I2S_GPIO_DATA, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override{ - return display_; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst816x *GetTouchpad() { - return cst816d_; - } -}; - -DECLARE_BOARD(LilygoTCircleS3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/pin_config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/pin_config.h deleted file mode 100644 index db428cac..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/pin_config.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * @Description: None - * @Author: LILYGO_L - * @Date: 2023-08-16 14:24:03 - * @LastEditTime: 2025-01-20 10:11:16 - * @License: GPL 3.0 - */ -#pragma once - -// MAX98357A -#define MAX98357A_BCLK 5 -#define MAX98357A_LRCLK 4 -#define MAX98357A_DATA 6 -#define MAX98357A_SD_MODE 45 - -// MSM261 -#define MSM261_BCLK 7 -#define MSM261_WS 9 -#define MSM261_DATA 8 - -// APA102 -#define APA102_DATA 38 -#define APA102_CLOCK 39 - -// H0075Y002-V0 -#define LCD_WIDTH 160 -#define LCD_HEIGHT 160 -#define LCD_MOSI 17 -#define LCD_SCLK 15 -#define LCD_DC 16 -#define LCD_RST -1 -#define LCD_CS 13 -#define LCD_BL 18 - -// IIC -#define IIC_SDA 11 -#define IIC_SCL 14 - -// CST816D -#define TP_SDA 11 -#define TP_SCL 14 -#define TP_RST -1 -#define TP_INT 12 - -//Rotary Encoder -#define KNOB_DATA_A 47 -#define KNOB_DATA_B 48 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc deleted file mode 100644 index 5fe3ea79..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.cc +++ /dev/null @@ -1,147 +0,0 @@ -#include "tcircles3_audio_codec.h" - -#include -#include -#include - -#include "config.h" - -static const char TAG[] = "Tcircles3AudioCodec"; - -Tcircles3AudioCodec::Tcircles3AudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateVoiceHardware(mic_bclk, mic_ws, mic_data, spkr_bclk, spkr_lrclk, spkr_data); - - gpio_config_t config; - config.pin_bit_mask = BIT64(AUDIO_SPKR_ENABLE); - config.mode = GPIO_MODE_OUTPUT; - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - config.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER - config.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config); - gpio_set_level(AUDIO_SPKR_ENABLE, 0); - ESP_LOGI(TAG, "Tcircles3AudioCodec initialized"); -} - -Tcircles3AudioCodec::~Tcircles3AudioCodec() { - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Tcircles3AudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) { - - i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(0), I2S_ROLE_MASTER); - mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(1), I2S_ROLE_MASTER); - spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - - ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_)); - ESP_ERROR_CHECK(i2s_new_channel(&spkr_chan_config, &tx_handle_, NULL)); - - i2s_std_config_t mic_config = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg ={ - .mclk = I2S_GPIO_UNUSED, - .bclk = mic_bclk, - .ws = mic_ws, - .dout = I2S_GPIO_UNUSED, - .din = mic_data, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false, - } - } - }; - - i2s_std_config_t spkr_config = { - .clk_cfg ={ - .sample_rate_hz = static_cast(11025), - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg ={ - .mclk = I2S_GPIO_UNUSED, - .bclk = spkr_bclk, - .ws = spkr_lrclk, - .dout = spkr_data, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &mic_config)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &spkr_config)); - ESP_LOGI(TAG, "Voice hardware created"); -} - -void Tcircles3AudioCodec::SetOutputVolume(int volume) { - volume_ = volume; - AudioCodec::SetOutputVolume(volume); -} - -void Tcircles3AudioCodec::EnableInput(bool enable) { - AudioCodec::EnableInput(enable); -} - -void Tcircles3AudioCodec::EnableOutput(bool enable) { - if (enable){ - gpio_set_level(AUDIO_SPKR_ENABLE, 1); - }else{ - gpio_set_level(AUDIO_SPKR_ENABLE, 0); - } - AudioCodec::EnableOutput(enable); -} - -int Tcircles3AudioCodec::Read(int16_t *dest, int samples){ - if (input_enabled_){ - size_t bytes_read; - i2s_channel_read(rx_handle_, dest, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - } - return samples; -} - -int Tcircles3AudioCodec::Write(const int16_t *data, int samples){ - if (output_enabled_){ - size_t bytes_read; - auto output_data = (int16_t *)malloc(samples * sizeof(int16_t)); - for (size_t i = 0; i < samples; i++){ - output_data[i] = (float)data[i] * (float)(volume_ / 100.0); - } - i2s_channel_write(tx_handle_, output_data, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - free(output_data); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h deleted file mode 100644 index f68f818d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-circle-s3/tcircles3_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _TCIRCLES3_AUDIO_CODEC_H -#define _TCIRCLES3_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class Tcircles3AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t *data_if_ = nullptr; - const audio_codec_ctrl_if_t *out_ctrl_if_ = nullptr; - const audio_codec_if_t *out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t *in_ctrl_if_ = nullptr; - const audio_codec_if_t *in_codec_if_ = nullptr; - const audio_codec_gpio_if_t *gpio_if_ = nullptr; - - uint32_t volume_ = 70; - - void CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data); - - virtual int Read(int16_t *dest, int samples) override; - virtual int Write(const int16_t *data, int samples) override; - -public: - Tcircles3AudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference); - virtual ~Tcircles3AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/README.md deleted file mode 100644 index 9a236d8d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/README.md +++ /dev/null @@ -1,42 +0,0 @@ -## LILYGO T-Display-P4 - -The T-Display-P4 is a versatile development board based on the ESP32-P4 core. Its features include: - -1. **High Processing Power**: Equipped with the high-performance ESP32-P4 core processor, it can handle more complex graphics and video tasks, delivering smoother display performance. -2. **Low Power Design**: Offers multiple selectable power modes to effectively reduce energy consumption and extend battery life. -3. **High-Resolution Display**: Supports high resolution (default with a large MIPI interface screen at 540x1168px), providing sharp and clear visuals. -4. **Rich Peripheral Support**: Onboard peripherals include an HD MIPI touchscreen, ESP32-C6 module, speaker, microphone, LoRa module, GPS module, Ethernet, a linear vibration motor, an independent battery gauge for monitoring battery health and percentage, and an MIPI camera. Multiple GPIOs of both the ESP32-P4 and ESP32-C6 are exposed, enhancing the device's expandability. - -Official github: [T-Display-P4](https://github.com/Xinyuan-LilyGO/T-Display-P4) - -## Configuration - -### ESP32P4 Configuration - -* Set the compilation target to ESP32P4 - - idf.py set-target esp32p4 - -* Open menuconfig - - idf.py menuconfig - -* Select the board - - Xiaozhi Assistant -> Board Type -> LILYGO T-Display-P4 - -* Select the screen type - - Xiaozhi Assistant -> Select the screen type -> (Select the screen type you need to configure) - -* Screen the screen pixel format - - Xiaozhi Assistant -> Select the color format of the screen -> (Select the screen pixel format you need to configure) - -* Build - - idf.py build - -### ESP32C6 Configuration - -* Flash the slave example from the esp-hosted-mcu library for the target chip ESP32C6. The esp-hosted-mcu version must match the one used in the xiaozhi-esp32 library. \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/config.h deleted file mode 100644 index 3e6b0887..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/config.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#include "t_display_p4_config.h" - -#if defined CONFIG_SCREEN_PIXEL_FORMAT_RGB565 -#define SCREEN_BITS_PER_PIXEL 16 -#define SCREEN_COLOR_RGB_PIXEL_FORMAT LCD_COLOR_PIXEL_FORMAT_RGB565 -#define LVGL_COLOR_FORMAT LV_COLOR_FORMAT_RGB565 -#elif defined CONFIG_SCREEN_PIXEL_FORMAT_RGB888 -#define SCREEN_BITS_PER_PIXEL 24 -#define SCREEN_COLOR_RGB_PIXEL_FORMAT LCD_COLOR_PIXEL_FORMAT_RGB888 -#define LVGL_COLOR_FORMAT LV_COLOR_FORMAT_RGB888 -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - -// SCREEN -#if defined CONFIG_SCREEN_TYPE_HI8561 -#define SCREEN_WIDTH HI8561_SCREEN_WIDTH -#define SCREEN_HEIGHT HI8561_SCREEN_HEIGHT -#define SCREEN_MIPI_DSI_DPI_CLK_MHZ HI8561_SCREEN_MIPI_DSI_DPI_CLK_MHZ -#define SCREEN_MIPI_DSI_HSYNC HI8561_SCREEN_MIPI_DSI_HSYNC -#define SCREEN_MIPI_DSI_HBP HI8561_SCREEN_MIPI_DSI_HBP -#define SCREEN_MIPI_DSI_HFP HI8561_SCREEN_MIPI_DSI_HFP -#define SCREEN_MIPI_DSI_VSYNC HI8561_SCREEN_MIPI_DSI_VSYNC -#define SCREEN_MIPI_DSI_VBP HI8561_SCREEN_MIPI_DSI_VBP -#define SCREEN_MIPI_DSI_VFP HI8561_SCREEN_MIPI_DSI_VFP -#define SCREEN_DATA_LANE_NUM HI8561_SCREEN_DATA_LANE_NUM -#define SCREEN_LANE_BIT_RATE_MBPS HI8561_SCREEN_LANE_BIT_RATE_MBPS - -#elif defined CONFIG_SCREEN_TYPE_RM69A10 -#define SCREEN_WIDTH RM69A10_SCREEN_WIDTH -#define SCREEN_HEIGHT RM69A10_SCREEN_HEIGHT -#define SCREEN_MIPI_DSI_DPI_CLK_MHZ RM69A10_SCREEN_MIPI_DSI_DPI_CLK_MHZ -#define SCREEN_MIPI_DSI_HSYNC RM69A10_SCREEN_MIPI_DSI_HSYNC -#define SCREEN_MIPI_DSI_HBP RM69A10_SCREEN_MIPI_DSI_HBP -#define SCREEN_MIPI_DSI_HFP RM69A10_SCREEN_MIPI_DSI_HFP -#define SCREEN_MIPI_DSI_VSYNC RM69A10_SCREEN_MIPI_DSI_VSYNC -#define SCREEN_MIPI_DSI_VBP RM69A10_SCREEN_MIPI_DSI_VBP -#define SCREEN_MIPI_DSI_VFP RM69A10_SCREEN_MIPI_DSI_VFP -#define SCREEN_DATA_LANE_NUM RM69A10_SCREEN_DATA_LANE_NUM -#define SCREEN_LANE_BIT_RATE_MBPS RM69A10_SCREEN_LANE_BIT_RATE_MBPS - -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK static_cast(ES8311_MCLK) -#define AUDIO_I2S_GPIO_WS static_cast(ES8311_WS_LRCK) -#define AUDIO_I2S_GPIO_BCLK static_cast(ES8311_BCLK) -#define AUDIO_I2S_GPIO_DIN static_cast(ES8311_ADC_DATA) -#define AUDIO_I2S_GPIO_DOUT static_cast(ES8311_DAC_DATA) - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN static_cast(ES8311_SDA) -#define AUDIO_CODEC_I2C_SCL_PIN static_cast(ES8311_SCL) -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define SCREEN_SWAP_XY false -#define SCREEN_MIRROR_X false -#define SCREEN_MIRROR_Y false - -#define SCREEN_OFFSET_X 0 -#define SCREEN_OFFSET_Y 0 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.cc deleted file mode 100644 index 2d222b24..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.cc +++ /dev/null @@ -1,404 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "soc/soc_caps.h" - -#if SOC_MIPI_DSI_SUPPORTED -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "esp_check.h" -#include "esp_lcd_panel_commands.h" -#include "esp_lcd_panel_interface.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_log.h" -#include "hi8561_driver.h" - -#define HI8561_PAD_CONTROL (0xB2) -#define HI8561_DSI_2_LANE (0x10) -#define HI8561_DSI_4_LANE (0x00) - -#define HI8561_CMD_SHLR_BIT (1ULL << 0) -#define HI8561_CMD_UPDN_BIT (1ULL << 1) -#define HI8561_MDCTL_VALUE_DEFAULT (0x01) - -static const hi8561_lcd_init_cmd_t vendor_specific_init_default[] = { - // {cmd, { data }, data_size, delay_ms} - /**** CMD_Page 3 ****/ - {0xDF, (uint8_t[]){0x90, 0x69, 0xF9}, 3, 0}, - {0xDE, (uint8_t[]){0x00}, 1, 0}, - {0xBB, (uint8_t[]){0x0F, 0x10, 0x43, 0x50, 0x32, 0x44, 0x44}, 7, 0}, - {0xBF, (uint8_t[]){0x46, 0x32}, 2, 0}, - {0xC0, (uint8_t[]){0x01, 0xAD, 0x01, 0xAD}, 4, 0}, - {0xBD, (uint8_t[]){0x00, 0xB4}, 2, 0}, - {0xC6, (uint8_t[]){0x00, 0x7D, 0x00, 0xC8, 0x00, 0x17, 0x1A, 0x82, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01}, 23, 0}, - {0xC8, (uint8_t[]){0x23, 0x48, 0x87}, 3, 0}, - // {0xCC, (uint8_t[]){0x33}, 1, 0},//4lane - {0xCC, (uint8_t[]){0x31}, 1, 0}, // 2lane - // {0xCC, (uint8_t[]){0x30}, 1, 0}, // 1lane - {0xBC, (uint8_t[]){0x2E, 0x80, 0x84}, 3, 0}, - {0xC3, (uint8_t[]){0x3B, 0x01, 0x02, 0x05, 0x0C, 0x0C, 0x75, 0x0A, 0x79, 0x0A, 0x79, 0x02, 0x6E, 0x02, 0x6E, 0x02, 0x6E, 0x0A, 0x0D, 0x0A, 0x0F, 0x0A, 0x0F, 0x0A, 0x0F}, 25, 0}, - {0xC4, (uint8_t[]){0x01, 0x02, 0x05, 0x0C, 0x0C, 0x75, 0x0A, 0x79, 0x0A, 0x79, 0x02, 0x6E, 0x02, 0x6E, 0x02, 0x6E, 0x0A, 0x0D, 0x0A, 0x0F, 0x0A, 0x0F, 0x0A, 0x0F}, 24, 0}, - {0xC5, (uint8_t[]){0x03, 0x05, 0x0C, 0x0C, 0x75, 0x0A, 0x79, 0x0A, 0x79, 0x02, 0x6E, 0x02, 0x6E, 0x02, 0x6E, 0x0A, 0x0D, 0x0A, 0x0F, 0x0A, 0x0F, 0x0A, 0x0F}, 23, 0}, - {0xD7, (uint8_t[]){0x00, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63, 0x0A, 0x63}, 17, 0}, - {0xCB, (uint8_t[]){0x7F, 0x78, 0x71, 0x64, 0x5A, 0x58, 0x4B, 0x51, 0x3A, 0x53, 0x51, 0x4F, 0x6A, 0x54, 0x57, 0x46, 0x3F, 0x2F, 0x1B, 0x0F, 0x08, 0x7F, 0x78, 0x71, 0x64, 0x5A, 0x58, 0x4B, 0x51, 0x3A, 0x53, 0x51, 0x4F, 0x6A, 0x54, 0x57, 0x46, 0x3F, 0x2F, 0x1B, 0x0F, 0x08, 0x00}, 43, 0}, - {0xCE, (uint8_t[]){0x00, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C}, 23, 0}, - {0xCF, (uint8_t[]){0x00, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 45, 0}, - {0xD0, (uint8_t[]){0x00, 0x1F, 0x1F, 0x11, 0x1E, 0x1F, 0x0F, 0x0F, 0x0D, 0x0D, 0x0B, 0x0B, 0x09, 0x09, 0x07, 0x07, 0x05, 0x05, 0x01, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 29, 0}, - {0xD1, (uint8_t[]){0x00, 0x1F, 0x1F, 0x10, 0x1E, 0x1F, 0x0E, 0x0E, 0x0C, 0x0C, 0x0A, 0x0A, 0x08, 0x08, 0x06, 0x06, 0x04, 0x04, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 29, 0}, - {0xD2, (uint8_t[]){0x00, 0x5F, 0x1F, 0x10, 0x1F, 0x1E, 0x08, 0x08, 0x4A, 0x0A, 0x0C, 0x0C, 0x0E, 0x0E, 0x04, 0x04, 0x06, 0x06, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 29, 0}, - {0xD3, (uint8_t[]){0x00, 0x1F, 0x1F, 0x11, 0x1F, 0x1E, 0x09, 0x09, 0x0B, 0x0B, 0x0D, 0x0D, 0x0F, 0x0F, 0x05, 0x05, 0x07, 0x07, 0x01, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 29, 0}, - {0xD4, (uint8_t[]){0x00, 0x20, 0x0B, 0x00, 0x0D, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x00, 0x81, 0x04, 0xAE, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB8, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x06, 0x44, 0x06, 0x46, 0x03, 0x03, 0x00, 0x00, 0x07, 0x00, 0x06, 0x04, 0xA7, 0x04, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00}, 87, 0}, - {0xD5, (uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x32, 0x5A, 0x00, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x1E, 0xB3, 0x00, 0x0F, 0x06, 0x0C, 0x00, 0x71, 0x20, 0x04, 0x10, 0x04, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 61, 0}, - {0xCD, (uint8_t[]){0x00, 0x00}, 2, 0}, - - {0xDE, (uint8_t[]){0x01}, 1, 0}, - {0xB9, (uint8_t[]){0x00, 0xFF, 0xFF, 0x04}, 4, 0}, - {0xC7, (uint8_t[]){0x1F, 0x14, 0x0E}, 3, 0}, - - {0xDE, (uint8_t[]){0x02}, 1, 0}, - {0xE5, (uint8_t[]){0x00, 0x60, 0x60, 0x02, 0x18, 0x60, 0x18, 0x60, 0x09, 0x04, 0x00, 0xC5, 0x01, 0x2C, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04}, 24, 0}, - {0xE6, (uint8_t[]){0x10, 0x10, 0x82}, 3, 0}, - {0xC4, (uint8_t[]){0x00, 0x11, 0x07, 0x00, 0x11, 0x01, 0x08}, 7, 0}, - {0xC3, (uint8_t[]){0x20, 0xFF}, 2, 0}, - {0xBD, (uint8_t[]){0x1B}, 1, 0}, - {0xC6, (uint8_t[]){0x4A, 0x00}, 2, 0}, - {0xCD, (uint8_t[]){0x14, 0x64, 0x11, 0x40}, 4, 0}, - {0xC1, (uint8_t[]){0x00, 0x40, 0x00, 0x02, 0x02, 0x02, 0x02, 0x7F, 0x00, 0x00}, 10, 0}, - {0xB3, (uint8_t[]){0x00, 0xA8}, 2, 0}, - {0xBB, (uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x40, 0x43, 0x04}, 11, 0}, - {0xC2, (uint8_t[]){0x02, 0x42, 0x50, 0x00, 0x02, 0xE4, 0x61, 0x73, 0xF9, 0x08}, 10, 0}, - {0xEC, (uint8_t[]){0x07, 0x07, 0x40, 0x00, 0x22, 0x02, 0x00, 0xFF, 0x08, 0x7C, 0x00, 0x00, 0x00, 0x00}, 14, 0}, - - {0xDE, (uint8_t[]){0x03}, 1, 0}, - {0xD1, (uint8_t[]){0x00, 0x00, 0x21, 0xFF, 0x00}, 5, 0}, - - {0xDE, (uint8_t[]){0x00}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 0, 30}, - - {0x11, (uint8_t[]){0x00}, 0, 120}, - - {0x29, (uint8_t[]){0x00}, 0, 50}, - - //============ Gamma END=========== -}; - -typedef struct -{ - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - const hi8561_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - uint8_t lane_num; - struct - { - unsigned int reset_level : 1; - } flags; - // To save the original functions of MIPI DPI panel - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*init)(esp_lcd_panel_t *panel); -} hi8561_panel_t; - -static const char *TAG = "hi8561"; - -static esp_err_t panel_hi8561_send_init_cmds(hi8561_panel_t *hi8561); - -static esp_err_t panel_hi8561_del(esp_lcd_panel_t *panel); -static esp_err_t panel_hi8561_init(esp_lcd_panel_t *panel); -static esp_err_t panel_hi8561_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_hi8561_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_hi8561_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_hi8561_sleep(esp_lcd_panel_t *panel, bool sleep); -static esp_err_t panel_hi8561_on_off(esp_lcd_panel_t *panel, bool on_off); - -esp_err_t esp_lcd_new_panel_hi8561(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - // ESP_LOGI(TAG, "version: %d.%d.%d", ESP_LCD_hi8561_VER_MAJOR, ESP_LCD_hi8561_VER_MINOR, - // ESP_LCD_hi8561_VER_PATCH); - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - hi8561_vendor_config_t *vendor_config = (hi8561_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->mipi_config.dpi_config && vendor_config->mipi_config.dsi_bus, ESP_ERR_INVALID_ARG, TAG, - "invalid vendor config"); - - esp_err_t ret = ESP_OK; - hi8561_panel_t *hi8561 = (hi8561_panel_t *)calloc(1, sizeof(hi8561_panel_t)); - ESP_RETURN_ON_FALSE(hi8561, ESP_ERR_NO_MEM, TAG, "no mem for hi8561 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_config_t io_conf = { - .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, - .mode = GPIO_MODE_OUTPUT, - }; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - hi8561->io = io; - hi8561->init_cmds = vendor_config->init_cmds; - hi8561->init_cmds_size = vendor_config->init_cmds_size; - hi8561->lane_num = vendor_config->mipi_config.lane_num; - hi8561->reset_gpio_num = panel_dev_config->reset_gpio_num; - hi8561->flags.reset_level = panel_dev_config->flags.reset_active_high; - hi8561->madctl_val = HI8561_MDCTL_VALUE_DEFAULT; - - // Create MIPI DPI panel - ESP_GOTO_ON_ERROR(esp_lcd_new_panel_dpi(vendor_config->mipi_config.dsi_bus, vendor_config->mipi_config.dpi_config, ret_panel), err, TAG, - "create MIPI DPI panel failed"); - ESP_LOGD(TAG, "new MIPI DPI panel @%p", *ret_panel); - - // Save the original functions of MIPI DPI panel - hi8561->del = (*ret_panel)->del; - hi8561->init = (*ret_panel)->init; - // Overwrite the functions of MIPI DPI panel - (*ret_panel)->del = panel_hi8561_del; - (*ret_panel)->init = panel_hi8561_init; - (*ret_panel)->reset = panel_hi8561_reset; - (*ret_panel)->mirror = panel_hi8561_mirror; - (*ret_panel)->invert_color = panel_hi8561_invert_color; - (*ret_panel)->disp_sleep = panel_hi8561_sleep; - (*ret_panel)->disp_on_off = panel_hi8561_on_off; - (*ret_panel)->user_data = hi8561; - - ESP_LOGD(TAG, "new hi8561 panel @%p", hi8561); - - return ESP_OK; - -err: - if (hi8561) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(static_cast(panel_dev_config->reset_gpio_num)); - } - free(hi8561); - } - return ret; -} - -static esp_err_t panel_hi8561_send_init_cmds(hi8561_panel_t *hi8561) -{ - esp_lcd_panel_io_handle_t io = hi8561->io; - const hi8561_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - // uint8_t lane_command = HI8561_DSI_2_LANE; - // bool is_cmd_overwritten = false; - - // switch (hi8561->lane_num) - // { - // case 0: - // case 2: - // lane_command = HI8561_DSI_2_LANE; - // break; - // case 4: - // lane_command = HI8561_DSI_4_LANE; - // break; - // default: - // ESP_LOGE(TAG, "Invalid lane number %d", hi8561->lane_num); - // return ESP_ERR_INVALID_ARG; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, HI8561_PAD_CONTROL, (uint8_t[]){ - // lane_command, - // }, - // 1), - // TAG, "send command failed"); - - // vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - // if (hi8561->init_cmds) - // { - // init_cmds = hi8561->init_cmds; - // init_cmds_size = hi8561->init_cmds_size; - // } - // else - // { - // init_cmds = vendor_specific_init_default; - // init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(hi8561_lcd_init_cmd_t); - // } - - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(hi8561_lcd_init_cmd_t); - - for (int i = 0; i < init_cmds_size; i++) - { - // // Check if the command has been used or conflicts with the internal - // if (init_cmds[i].data_bytes > 0) - // { - // switch (init_cmds[i].cmd) - // { - // case LCD_CMD_MADCTL: - // is_cmd_overwritten = true; - // hi8561->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - // break; - // default: - // is_cmd_overwritten = false; - // break; - // } - - // if (is_cmd_overwritten) - // { - // is_cmd_overwritten = false; - // ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - // init_cmds[i].cmd); - // } - // } - - esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - // printf("Ciallo\n"); - } - - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_hi8561_del(esp_lcd_panel_t *panel) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - - if (hi8561->reset_gpio_num >= 0) - { - gpio_reset_pin(static_cast(hi8561->reset_gpio_num)); - } - // Delete MIPI DPI panel - hi8561->del(panel); - ESP_LOGD(TAG, "del hi8561 panel @%p", hi8561); - free(hi8561); - - return ESP_OK; -} - -static esp_err_t panel_hi8561_init(esp_lcd_panel_t *panel) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - - ESP_RETURN_ON_ERROR(panel_hi8561_send_init_cmds(hi8561), TAG, "send init commands failed"); - ESP_RETURN_ON_ERROR(hi8561->init(panel), TAG, "init MIPI DPI panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_hi8561_reset(esp_lcd_panel_t *panel) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = hi8561->io; - - // Perform hardware reset - if (hi8561->reset_gpio_num >= 0) - { - gpio_set_level(static_cast(hi8561->reset_gpio_num), hi8561->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(static_cast(hi8561->reset_gpio_num), !hi8561->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(20)); - } - else if (io) - { // Perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(20)); - } - - return ESP_OK; -} - -static esp_err_t panel_hi8561_sleep(esp_lcd_panel_t *panel, bool sleep) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = hi8561->io; - - if (sleep == true) - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x10, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_hi8561 sleep on"); - } - else - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_hi8561 sleep off"); - } - - vTaskDelay(pdMS_TO_TICKS(120)); - - return ESP_OK; -} - -static esp_err_t panel_hi8561_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = hi8561->io; - - if (on_off == true) - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_hi8561 display on"); - } - else - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x28, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_hi8561 display off"); - } - - vTaskDelay(pdMS_TO_TICKS(120)); - - return ESP_OK; -} - -static esp_err_t panel_hi8561_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = hi8561->io; - uint8_t madctl_val = hi8561->madctl_val; - - ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - // Control mirror through LCD command - if (mirror_x) - { - madctl_val |= HI8561_CMD_SHLR_BIT; - } - else - { - madctl_val &= ~HI8561_CMD_SHLR_BIT; - } - if (mirror_y) - { - madctl_val |= HI8561_CMD_UPDN_BIT; - } - else - { - madctl_val &= ~HI8561_CMD_UPDN_BIT; - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){madctl_val}, 1), TAG, "send command failed"); - hi8561->madctl_val = madctl_val; - - return ESP_OK; -} - -static esp_err_t panel_hi8561_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) -{ - hi8561_panel_t *hi8561 = (hi8561_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = hi8561->io; - uint8_t command = 0; - - ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - if (invert_color_data) - { - command = LCD_CMD_INVON; - } - else - { - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - - return ESP_OK; -} - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.h deleted file mode 100644 index 58429b8d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/hi8561_driver.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * @Description: hi8561_driver - * @Author: LILYGO_L - * @Date: 2025-06-13 11:02:44 - * @LastEditTime: 2025-10-09 10:36:27 - * @License: GPL 3.0 - */ -#pragma once - -#include -#include "soc/soc_caps.h" - -#if SOC_MIPI_DSI_SUPPORTED -#include "esp_lcd_panel_vendor.h" -#include "esp_lcd_mipi_dsi.h" - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct -{ - int cmd; /* -#include -#include - -#include "cpp_bus_driver_library.h" -#include "hi8561_driver.h" -#include "rm69a10_driver.h" - -#define TAG "LilygoTDisplayP4Board" - -void TouchTask(void *arg); - -#if defined CONFIG_SCREEN_TYPE_HI8561 -class CustomBacklight : public Backlight { -private: - std::unique_ptr tool_; - -public: - CustomBacklight(std::unique_ptr tool) : tool_(std::move(tool)) {} - - void SetBrightnessImpl(uint8_t brightness) override{ - tool_->set_pwm_duty(brightness); - }; -}; -#elif defined CONFIG_SCREEN_TYPE_RM69A10 -class CustomBacklight : public Backlight { -private: - esp_lcd_panel_handle_t mipi_dpi_panel_; - -public: - CustomBacklight(esp_lcd_panel_handle_t panel) : mipi_dpi_panel_(panel) {} - - void SetBrightnessImpl(uint8_t brightness) override{ - set_rm69a10_brightness(mipi_dpi_panel_,static_cast(static_cast(brightness) * 2.55)); - }; -}; - -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - -class LilygoTDisplayP4Board : public WifiBoard { -public: - i2c_master_bus_handle_t audio_codec_i2c_bus_; - Button boot_button_; - LcdDisplay *display_; - esp_lcd_panel_handle_t mipi_dpi_panel_; - esp_timer_handle_t touchpad_timer_; - uint8_t brightness_; - - std::shared_ptr xl9535_iic_bus_ = std::make_shared(XL9535_SDA, XL9535_SCL, I2C_NUM_1); - std::unique_ptr xl9535_ = std::make_unique(xl9535_iic_bus_, XL9535_IIC_ADDRESS, DEFAULT_CPP_BUS_DRIVER_VALUE); - -#if defined CONFIG_SCREEN_TYPE_HI8561 - std::shared_ptr hi8561_t_iic_bus_ = std::make_shared(HI8561_TOUCH_SDA, HI8561_TOUCH_SCL, I2C_NUM_1); - std::unique_ptr hi8561_t_ = std::make_unique(hi8561_t_iic_bus_, HI8561_TOUCH_IIC_ADDRESS, DEFAULT_CPP_BUS_DRIVER_VALUE); - - std::unique_ptr hi8561_backlight_ = std::make_unique(); -#elif defined CONFIG_SCREEN_TYPE_RM69A10 - std::shared_ptr gt9895_iic_bus_ = std::make_shared(GT9895_TOUCH_SDA, GT9895_TOUCH_SCL, I2C_NUM_1); - std::unique_ptr gt9895_ = std::make_unique(gt9895_iic_bus_, GT9895_IIC_ADDRESS, GT9895_X_SCALE_FACTOR, GT9895_Y_SCALE_FACTOR, - DEFAULT_CPP_BUS_DRIVER_VALUE); -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - - std::unique_ptr esp32p4_ = std::make_unique(); - - bool Init_Ldo_Channel_Power(uint8_t chan_id, uint32_t voltage_mv){ - esp_ldo_channel_handle_t ldo_channel_handle = NULL; - esp_ldo_channel_config_t ldo_channel_config ={ - .chan_id = static_cast(chan_id), - .voltage_mv = static_cast(voltage_mv), - }; - if (esp_ldo_acquire_channel(&ldo_channel_config, &ldo_channel_handle) != ESP_OK){ - printf("esp_ldo_acquire_channel %d fail\n", chan_id); - return false; - } - - return true; - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &audio_codec_i2c_bus_)); - } - - void InitializeXl9535() { - xl9535_->begin(500000); - xl9535_->pin_mode(XL9535_ESP32P4_VCCA_POWER_EN, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_mode(XL9535_5_0_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_mode(XL9535_3_3_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - // 开关3.3v电压时候必须先将GPS断电 - xl9535_->pin_mode(XL9535_GPS_WAKE_UP, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_write(XL9535_GPS_WAKE_UP, Cpp_Bus_Driver::Xl95x5::Value::LOW); - // 开关3.3v电压时候必须先将ESP32C6断电 - xl9535_->pin_mode(XL9535_ESP32C6_EN, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_write(XL9535_ESP32C6_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - - xl9535_->pin_write(XL9535_ESP32P4_VCCA_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - - xl9535_->pin_write(XL9535_5_0_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_5_0_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_5_0_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - - xl9535_->pin_write(XL9535_3_3_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_3_3_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_3_3_V_POWER_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(10)); - - // ESP32C6复位 - xl9535_->pin_write(XL9535_ESP32C6_EN, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(100)); - xl9535_->pin_write(XL9535_ESP32C6_EN, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(100)); - xl9535_->pin_write(XL9535_ESP32C6_EN, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(100)); - - vTaskDelay(pdMS_TO_TICKS(1000)); - } - - void InitializeLCD() { - xl9535_->pin_mode(XL9535_SCREEN_RST, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_write(XL9535_SCREEN_RST, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_SCREEN_RST, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_SCREEN_RST, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - - Init_Ldo_Channel_Power(3, 1800); - - esp_lcd_panel_io_handle_t mipi_dbi_io = NULL; - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = SCREEN_DATA_LANE_NUM, - .lane_bit_rate_mbps = SCREEN_LANE_BIT_RATE_MBPS, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_io_config = { - .virtual_channel = 0, - .lcd_cmd_bits = 8, // according to the LCD spec - .lcd_param_bits = 8, // according to the LCD spec - }; - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_io_config, &mipi_dbi_io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .virtual_channel = 0, - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = SCREEN_MIPI_DSI_DPI_CLK_MHZ, - .pixel_format = SCREEN_COLOR_RGB_PIXEL_FORMAT, - .num_fbs = 0, - .video_timing = { - .h_size = SCREEN_WIDTH, - .v_size = SCREEN_HEIGHT, - .hsync_pulse_width = SCREEN_MIPI_DSI_HSYNC, - .hsync_back_porch = SCREEN_MIPI_DSI_HBP, - .hsync_front_porch = SCREEN_MIPI_DSI_HFP, - .vsync_pulse_width = SCREEN_MIPI_DSI_VSYNC, - .vsync_back_porch = SCREEN_MIPI_DSI_VBP, - .vsync_front_porch = SCREEN_MIPI_DSI_VFP, - }, - .flags = { - .use_dma2d = true, // use DMA2D to copy draw buffer into frame buffer - } - }; - -#if defined CONFIG_SCREEN_TYPE_HI8561 - hi8561_vendor_config_t vendor_config = { - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - }, - }; - esp_lcd_panel_dev_config_t dev_config = { - .reset_gpio_num = -1, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = SCREEN_BITS_PER_PIXEL, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_hi8561(mipi_dbi_io, &dev_config, &mipi_dpi_panel_); - #elif defined CONFIG_SCREEN_TYPE_RM69A10 - rm69a10_vendor_config_t vendor_config = { - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - }, - }; - esp_lcd_panel_dev_config_t dev_config = { - .reset_gpio_num = -1, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = SCREEN_BITS_PER_PIXEL, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_rm69a10(mipi_dbi_io, &dev_config, &mipi_dpi_panel_); -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - - esp_lcd_panel_init(mipi_dpi_panel_); - -#if defined CONFIG_SCREEN_TYPE_HI8561 - hi8561_backlight_->create_pwm(HI8561_SCREEN_BL, ledc_channel_t::LEDC_CHANNEL_0, 2000); -#elif defined CONFIG_SCREEN_TYPE_RM69A10 -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - - - display_ = new MipiLcdDisplay(mipi_dbi_io, mipi_dpi_panel_, SCREEN_WIDTH, SCREEN_HEIGHT, - SCREEN_OFFSET_X, SCREEN_OFFSET_Y, SCREEN_MIRROR_X, SCREEN_MIRROR_Y, SCREEN_SWAP_XY); - } - - void InitializeTouch(){ - xl9535_->pin_mode(XL9535_TOUCH_RST, Cpp_Bus_Driver::Xl95x5::Mode::OUTPUT); - xl9535_->pin_write(XL9535_TOUCH_RST, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_TOUCH_RST, Cpp_Bus_Driver::Xl95x5::Value::LOW); - vTaskDelay(pdMS_TO_TICKS(10)); - xl9535_->pin_write(XL9535_TOUCH_RST, Cpp_Bus_Driver::Xl95x5::Value::HIGH); - vTaskDelay(pdMS_TO_TICKS(10)); - -#if defined CONFIG_SCREEN_TYPE_HI8561 - hi8561_t_iic_bus_->set_bus_handle(xl9535_iic_bus_->get_bus_handle()); - hi8561_t_->begin(); -#elif defined CONFIG_SCREEN_TYPE_RM69A10 - gt9895_iic_bus_->set_bus_handle(xl9535_iic_bus_->get_bus_handle()); - gt9895_->begin(); -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - - xTaskCreate(TouchTask, "tp", 2 * 1024, this, 5, NULL); - } - - void AppToggleChatState(void){ - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - AppToggleChatState(); - }); - } - - LilygoTDisplayP4Board() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeXl9535(); - InitializeLCD(); - InitializeTouch(); - InitializeButtons(); - GetBacklight()->SetBrightness(100); - } - - virtual AudioCodec *GetAudioCodec() override { - static Es8311AudioCodec audio_codec(audio_codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - -#if defined CONFIG_SCREEN_TYPE_HI8561 - virtual Backlight* GetBacklight() override { - static CustomBacklight backlight(std::move(hi8561_backlight_)); - return &backlight; - } -#elif defined CONFIG_SCREEN_TYPE_RM69A10 - virtual Backlight* GetBacklight() override { - static CustomBacklight backlight(std::move(mipi_dpi_panel_)); - return &backlight; - } -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - -}; - -void TouchTask(void *arg) { - LilygoTDisplayP4Board* board = (LilygoTDisplayP4Board*)arg; - - static bool touch_flag = false; - static bool touch_lock_flag = true; - static size_t first_touch_time = 0; - static bool waiting_for_second_tap = false; - - while (1){ -#if defined CONFIG_SCREEN_TYPE_HI8561 - if (board->hi8561_t_->get_finger_count() > 0){ - if(touch_flag == false){ - touch_lock_flag = false; - } - touch_flag = true; - } else { - touch_flag = false; - } -#elif defined CONFIG_SCREEN_TYPE_RM69A10 - if (board->gt9895_->get_finger_count() > 0){ - if(touch_flag == false){ - touch_lock_flag = false; - } - touch_flag = true; - } else { - touch_flag = false; - } -#else -#error "unknown macro definition, please select the correct macro definition." -#endif - - if(touch_lock_flag == false){ - size_t current_time = board->esp32p4_->get_system_time_ms(); - - if (!waiting_for_second_tap) { - // 第一次点击 - first_touch_time = current_time; - waiting_for_second_tap = true; - printf("first touch detected, waiting for second...\n"); - } else { - // 第二次点击,检查时间间隔 - // 500ms内完成双击 - if ((current_time - first_touch_time) <= 500) { - printf("double touch trigger\n"); - - board->AppToggleChatState(); - - // 重置状态 - waiting_for_second_tap = false; - first_touch_time = 0; - } else { - // 超时,重新开始 - first_touch_time = current_time; - printf("first touch timeout, restart...\n"); - } - } - - touch_lock_flag = true; - } - - // 处理双击超时 - if (waiting_for_second_tap) { - size_t current_time = board->esp32p4_->get_system_time_ms(); - - if ((current_time - first_touch_time) > 500) { - waiting_for_second_tap = false; - first_touch_time = 0; - printf("double touch timeout\n"); - } - } - - vTaskDelay(pdMS_TO_TICKS(50)); - } -} - -DECLARE_BOARD(LilygoTDisplayP4Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.cc deleted file mode 100644 index cc6b3290..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.cc +++ /dev/null @@ -1,377 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include "soc/soc_caps.h" - -#if SOC_MIPI_DSI_SUPPORTED -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "esp_check.h" -#include "esp_lcd_panel_commands.h" -#include "esp_lcd_panel_interface.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_log.h" -#include "rm69a10_driver.h" - -#define RM69A10_PAD_CONTROL (0xB2) -#define RM69A10_DSI_2_LANE (0x10) -#define RM69A10_DSI_4_LANE (0x00) - -#define RM69A10_CMD_SHLR_BIT (1ULL << 0) -#define RM69A10_CMD_UPDN_BIT (1ULL << 1) -#define RM69A10_MDCTL_VALUE_DEFAULT (0x01) - -static const rm69a10_lcd_init_cmd_t vendor_specific_init_default[] = { - // {cmd, { data }, data_size, delay_ms} - /**** CMD_Page 3 ****/ - {0xFE, (uint8_t[]){0xFD}, 1, 0}, - {0x80, (uint8_t[]){0xFC}, 1, 0}, - {0xFE, (uint8_t[]){0x00}, 1, 0}, - {0x2A, (uint8_t[]){0x00, 0x00, 0x02, 0x37}, 4, 0}, - {0x2B, (uint8_t[]){0x00, 0x00, 0x04, 0xCF}, 4, 0}, - {0x31, (uint8_t[]){0x00, 0x03, 0x02, 0x34}, 4, 0}, - {0x30, (uint8_t[]){0x00, 0x00, 0x04, 0xCF}, 4, 0}, - {0x12, (uint8_t[]){0x00}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 1, 0}, -#if CONFIG_SCREEN_PIXEL_FORMAT_RGB565 - {0x3A, (uint8_t[]){0x75}, 1, 0}, // interface pixel format 16bit/pixel -#elif CONFIG_SCREEN_PIXEL_FORMAT_RGB888 - {0x3A, (uint8_t[]){0x77}, 1, 0}, // interface pixel format 24bit/pixel -#endif - // {0x51, (uint8_t[]){0xFE}, 1, 0}, - {0x51, (uint8_t[]){0x00}, 1, 0}, // 设置屏幕亮度为0 - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0x29, (uint8_t[]){0x00}, 0, 0}, - //============ Gamma END=========== -}; - -typedef struct -{ - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - const rm69a10_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - uint8_t lane_num; - struct - { - unsigned int reset_level : 1; - } flags; - // To save the original functions of MIPI DPI panel - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*init)(esp_lcd_panel_t *panel); -} rm69a10_panel_t; - -static const char *TAG = "rm69a10"; - -static esp_err_t panel_rm69a10_send_init_cmds(rm69a10_panel_t *rm69a10); - -static esp_err_t panel_rm69a10_del(esp_lcd_panel_t *panel); -static esp_err_t panel_rm69a10_init(esp_lcd_panel_t *panel); -static esp_err_t panel_rm69a10_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_rm69a10_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_rm69a10_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_rm69a10_sleep(esp_lcd_panel_t *panel, bool sleep); -static esp_err_t panel_rm69a10_on_off(esp_lcd_panel_t *panel, bool on_off); - -esp_err_t esp_lcd_new_panel_rm69a10(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - // ESP_LOGI(TAG, "version: %d.%d.%d", ESP_LCD_RM69A10_VER_MAJOR, ESP_LCD_RM69A10_VER_MINOR, - // ESP_LCD_RM69A10_VER_PATCH); - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - rm69a10_vendor_config_t *vendor_config = (rm69a10_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->mipi_config.dpi_config && vendor_config->mipi_config.dsi_bus, ESP_ERR_INVALID_ARG, TAG, - "invalid vendor config"); - - esp_err_t ret = ESP_OK; - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)calloc(1, sizeof(rm69a10_panel_t)); - ESP_RETURN_ON_FALSE(rm69a10, ESP_ERR_NO_MEM, TAG, "no mem for rm69a10 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_config_t io_conf = { - .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, - .mode = GPIO_MODE_OUTPUT, - }; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - rm69a10->io = io; - rm69a10->init_cmds = vendor_config->init_cmds; - rm69a10->init_cmds_size = vendor_config->init_cmds_size; - rm69a10->lane_num = vendor_config->mipi_config.lane_num; - rm69a10->reset_gpio_num = panel_dev_config->reset_gpio_num; - rm69a10->flags.reset_level = panel_dev_config->flags.reset_active_high; - rm69a10->madctl_val = RM69A10_MDCTL_VALUE_DEFAULT; - - // Create MIPI DPI panel - ESP_GOTO_ON_ERROR(esp_lcd_new_panel_dpi(vendor_config->mipi_config.dsi_bus, vendor_config->mipi_config.dpi_config, ret_panel), err, TAG, - "create MIPI DPI panel failed"); - ESP_LOGD(TAG, "new MIPI DPI panel @%p", *ret_panel); - - // Save the original functions of MIPI DPI panel - rm69a10->del = (*ret_panel)->del; - rm69a10->init = (*ret_panel)->init; - // Overwrite the functions of MIPI DPI panel - (*ret_panel)->del = panel_rm69a10_del; - (*ret_panel)->init = panel_rm69a10_init; - (*ret_panel)->reset = panel_rm69a10_reset; - (*ret_panel)->mirror = panel_rm69a10_mirror; - (*ret_panel)->invert_color = panel_rm69a10_invert_color; - (*ret_panel)->disp_sleep = panel_rm69a10_sleep; - (*ret_panel)->disp_on_off = panel_rm69a10_on_off; - (*ret_panel)->user_data = rm69a10; - ESP_LOGD(TAG, "new rm69a10 panel @%p", rm69a10); - - return ESP_OK; - -err: - if (rm69a10) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(static_cast(panel_dev_config->reset_gpio_num)); - } - free(rm69a10); - } - return ret; -} - -static esp_err_t panel_rm69a10_send_init_cmds(rm69a10_panel_t *rm69a10) -{ - esp_lcd_panel_io_handle_t io = rm69a10->io; - const rm69a10_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - // uint8_t lane_command = RM69A10_DSI_2_LANE; - // bool is_cmd_overwritten = false; - - // switch (rm69a10->lane_num) - // { - // case 0: - // case 2: - // lane_command = RM69A10_DSI_2_LANE; - // break; - // case 4: - // lane_command = RM69A10_DSI_4_LANE; - // break; - // default: - // ESP_LOGE(TAG, "Invalid lane number %d", rm69a10->lane_num); - // return ESP_ERR_INVALID_ARG; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, RM69A10_PAD_CONTROL, (uint8_t[]){ - // lane_command, - // }, - // 1), - // TAG, "send command failed"); - - // vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - // if (rm69a10->init_cmds) - // { - // init_cmds = rm69a10->init_cmds; - // init_cmds_size = rm69a10->init_cmds_size; - // } - // else - // { - // init_cmds = vendor_specific_init_default; - // init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(rm69a10_lcd_init_cmd_t); - // } - - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(rm69a10_lcd_init_cmd_t); - - for (int i = 0; i < init_cmds_size; i++) - { - // // Check if the command has been used or conflicts with the internal - // if (init_cmds[i].data_bytes > 0) - // { - // switch (init_cmds[i].cmd) - // { - // case LCD_CMD_MADCTL: - // is_cmd_overwritten = true; - // rm69a10->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - // break; - // default: - // is_cmd_overwritten = false; - // break; - // } - - // if (is_cmd_overwritten) - // { - // is_cmd_overwritten = false; - // ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - // init_cmds[i].cmd); - // } - // } - - // Send command - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - // printf("Ciallo\n"); - } - - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_del(esp_lcd_panel_t *panel) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - - if (rm69a10->reset_gpio_num >= 0) - { - gpio_reset_pin(static_cast(rm69a10->reset_gpio_num)); - } - // Delete MIPI DPI panel - rm69a10->del(panel); - ESP_LOGD(TAG, "del rm69a10 panel @%p", rm69a10); - free(rm69a10); - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_init(esp_lcd_panel_t *panel) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - - ESP_RETURN_ON_ERROR(panel_rm69a10_send_init_cmds(rm69a10), TAG, "send init commands failed"); - ESP_RETURN_ON_ERROR(rm69a10->init(panel), TAG, "init MIPI DPI panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_reset(esp_lcd_panel_t *panel) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - - // Perform hardware reset - if (rm69a10->reset_gpio_num >= 0) - { - gpio_set_level(static_cast(rm69a10->reset_gpio_num), rm69a10->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(static_cast(rm69a10->reset_gpio_num), !rm69a10->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(20)); - } - else if (io) - { // Perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(20)); - } - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_sleep(esp_lcd_panel_t *panel, bool sleep) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - - if (sleep == true) - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x10, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_rm69a10 sleep on"); - } - else - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_rm69a10 sleep off"); - } - - vTaskDelay(pdMS_TO_TICKS(120)); - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - - if (on_off == true) - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_rm69a10 display on"); - } - else - { - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x28, 0x00, 0), TAG, "esp_lcd_panel_io_tx_param fail"); - ESP_LOGI(TAG, "panel_rm69a10 display off"); - } - - vTaskDelay(pdMS_TO_TICKS(120)); - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - uint8_t madctl_val = rm69a10->madctl_val; - - ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - // Control mirror through LCD command - if (mirror_x) - { - madctl_val |= RM69A10_CMD_SHLR_BIT; - } - else - { - madctl_val &= ~RM69A10_CMD_SHLR_BIT; - } - if (mirror_y) - { - madctl_val |= RM69A10_CMD_UPDN_BIT; - } - else - { - madctl_val &= ~RM69A10_CMD_UPDN_BIT; - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){madctl_val}, 1), TAG, "send command failed"); - rm69a10->madctl_val = madctl_val; - - return ESP_OK; -} - -static esp_err_t panel_rm69a10_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - uint8_t command = 0; - - ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - if (invert_color_data) - { - command = LCD_CMD_INVON; - } - else - { - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - - return ESP_OK; -} - -esp_err_t set_rm69a10_brightness(esp_lcd_panel_t *panel, uint8_t brightness) -{ - rm69a10_panel_t *rm69a10 = (rm69a10_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = rm69a10->io; - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x51, &brightness, 1), TAG, "esp_lcd_panel_io_tx_param fail"); - - return ESP_OK; -} - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.h deleted file mode 100644 index e525bd45..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-p4/rm69a10_driver.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * @Description: rm69a10_driver - * @Author: LILYGO_L - * @Date: 2025-07-07 14:23:16 - * @LastEditTime: 2025-10-09 10:36:33 - * @License: GPL 3.0 - */ -#pragma once - -#include -#include "soc/soc_caps.h" - -#if SOC_MIPI_DSI_SUPPORTED -#include "esp_lcd_panel_vendor.h" -#include "esp_lcd_mipi_dsi.h" - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct -{ - int cmd; /*(RM69A10_SCREEN_WIDTH) / static_cast(GT9895_MAX_X_SIZE) -#define GT9895_Y_SCALE_FACTOR static_cast(RM69A10_SCREEN_HEIGHT) / static_cast(GT9895_MAX_Y_SIZE) - -// CAMERA -#define CAMERA_WIDTH 1920 -#define CAMERA_HEIGHT 1080 -// #define CAMERA_WIDTH 1280 -// #define CAMERA_HEIGHT 720 -// #define CAMERA_WIDTH 800 -// #define CAMERA_HEIGHT 800 -// #define CAMERA_WIDTH 640 -// #define CAMERA_HEIGHT 480 - -#define CAMERA_DATA_LANE_NUM 2 -#define CAMERA_LANE_BIT_RATE_MBPS 1000 -#define CAMERA_MIPI_DSI_DPI_CLK_MHZ 60 - -// SD -#define SD_BASE_PATH "/sdcard" - -////////////////////////////////////////////////// other define config ////////////////////////////////////////////////// \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/README.md deleted file mode 100644 index c3b8d0eb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> LILYGO T-Display-S3-Pro-MVSRLora -Or -Xiaozhi Assistant -> Board Type -> LILYGO T-Display-S3-Pro-MVSRLora_NO_BATTERY -``` - - -**编译:** - -```bash -idf.py build -``` - -LILYGO T-Display-S3-Pro -
    -LILYGO T-Display-S3-Pro-MVSRLora \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.h deleted file mode 100644 index 44c0a03f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include "pin_config.h" - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_MIC_I2S_GPIO_BCLK GPIO_NUM_NC -#define AUDIO_MIC_I2S_GPIO_WS static_cast(MP34DT05TR_LRCLK) -#define AUDIO_MIC_I2S_GPIO_DATA static_cast(MP34DT05TR_DATA) -#define AUDIO_MIC_ENABLE static_cast(MP34DT05TR_EN) - -#define AUDIO_SPKR_I2S_GPIO_BCLK static_cast(MAX98357A_BCLK) -#define AUDIO_SPKR_I2S_GPIO_LRCLK static_cast(MAX98357A_LRCLK) -#define AUDIO_SPKR_I2S_GPIO_DATA static_cast(MAX98357A_DATA) -#define AUDIO_SPKR_ENABLE static_cast(MAX98357A_EN) - -#define TOUCH_I2C_SDA_PIN static_cast(TOUCH_IIC_SDA) -#define TOUCH_I2C_SCL_PIN static_cast(TOUCH_IIC_SCL) - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_WIDTH LCD_WIDTH -#define DISPLAY_HEIGHT LCD_HEIGHT -#define DISPLAY_MOSI LCD_MOSI -#define DISPLAY_SCLK LCD_SCLK -#define DISPLAY_DC LCD_DC -#define DISPLAY_RST LCD_RST -#define DISPLAY_CS LCD_CS -#define DISPLAY_BL static_cast(LCD_BL) -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN DISPLAY_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.json deleted file mode 100644 index f7e4505e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "lilygo-t-display-s3-pro-mvsrlora", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/lilygo-t-display-s3-pro-mvsrlora.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/lilygo-t-display-s3-pro-mvsrlora.cc deleted file mode 100644 index b18d27af..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/lilygo-t-display-s3-pro-mvsrlora.cc +++ /dev/null @@ -1,283 +0,0 @@ -#include "wifi_board.h" -#include "tdisplays3promvsrlora_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "esp_lcd_st7796.h" - -#define TAG "LilygoTDisplays3ProMVSRLoraBoard" - -class Cst2xxse : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - Cst2xxse(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0x06); - ESP_LOGI(TAG, "Get cst2xxse chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Cst2xxse() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x00, read_buffer_, 6); - tp_.num = read_buffer_[5] & 0x0F; - tp_.x = (static_cast(read_buffer_[1]) << 4) | (read_buffer_[3] & 0xF0); - tp_.y = (static_cast(read_buffer_[2]) << 4) | (read_buffer_[3] & 0x0F); - // ESP_LOGI(TAG, "Touch num: %d x: %d y: %d", tp_.num,tp_.x,tp_.y); - } - - const TouchPoint_t &GetTouchPoint() { - return tp_; - } - -private: - uint8_t *read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class Sy6970 : public I2cDevice { -public: - - Sy6970(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0x14); - ESP_LOGI(TAG, "Get sy6970 chip ID: 0x%02X", (chip_id & 0B00111000)); - - WriteReg(0x00,0B00001000); // Disable ILIM pin - WriteReg(0x02,0B11011101); // Enable ADC measurement function - WriteReg(0x07,0B10001101); // Disable watchdog timer feeding function - - #ifdef CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY - WriteReg(0x09,0B01100100); // Disable BATFET when battery is not needed - #endif - } -}; - -class LilygoTDisplays3ProMVSRLoraBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst2xxse *cst226se_; - Sy6970 *sy6970_; - LcdDisplay *display_; - Button boot_button_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitI2c(){ - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_config = { - .i2c_port = I2C_NUM_0, - .sda_io_num = TOUCH_I2C_SDA_PIN, - .scl_io_num = TOUCH_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - } - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - static void touchpad_daemon(void *param) { - vTaskDelay(pdMS_TO_TICKS(2000)); - auto &board = (LilygoTDisplays3ProMVSRLoraBoard&)Board::GetInstance(); - auto touchpad = board.GetTouchpad(); - bool was_touched = false; - while (1) { - touchpad->UpdateTouchPoint(); - if (touchpad->GetTouchPoint().num > 0){ - // On press - if (!was_touched) { - was_touched = true; - Application::GetInstance().ToggleChatState(); - } - } - // On release - else if (was_touched) { - was_touched = false; - } - vTaskDelay(pdMS_TO_TICKS(50)); - } - vTaskDelete(NULL); - } - - void InitCst226se() { - ESP_LOGI(TAG, "Init Cst2xxse"); - cst226se_ = new Cst2xxse(i2c_bus_, 0x5A); - xTaskCreate(touchpad_daemon, "tp", 4096, NULL, 5, NULL); - } - - void InitSy6970() { - ESP_LOGI(TAG, "Init Sy6970"); - sy6970_ = new Sy6970(i2c_bus_, 0x6A); - } - - void InitSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitSt7796Display() { - ESP_LOGI(TAG, "Init St7796"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7796(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, false)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel, 49, 0)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - gpio_config_t config; - config.pin_bit_mask = BIT64(DISPLAY_BL); - config.mode = GPIO_MODE_OUTPUT; - config.pull_up_en = GPIO_PULLUP_DISABLE; - config.pull_down_en = GPIO_PULLDOWN_ENABLE; - config.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER - config.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config); - gpio_set_level(DISPLAY_BL, 0); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - LilygoTDisplays3ProMVSRLoraBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitI2c(); - I2cDetect(); - InitCst226se(); - InitSy6970(); - InitSpi(); - InitSt7796Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Tdisplays3promvsrloraAudioCodec audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_MIC_I2S_GPIO_BCLK, - AUDIO_MIC_I2S_GPIO_WS, - AUDIO_MIC_I2S_GPIO_DATA, - AUDIO_SPKR_I2S_GPIO_BCLK, - AUDIO_SPKR_I2S_GPIO_LRCLK, - AUDIO_SPKR_I2S_GPIO_DATA, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override{ - return display_; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst2xxse *GetTouchpad() { - return cst226se_; - } -}; - -DECLARE_BOARD(LilygoTDisplays3ProMVSRLoraBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/pin_config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/pin_config.h deleted file mode 100644 index 0b952d54..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/pin_config.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * @Description: None - * @Author: None - * @Date: 2023-08-16 14:24:03 - * @LastEditTime: 2025-04-23 11:25:00 - * @License: GPL 3.0 - */ -#pragma once - -// ST7796 -#define LCD_WIDTH 222 -#define LCD_HEIGHT 480 -#define LCD_BL 48 -#define LCD_MOSI 17 -#define LCD_MISO 8 -#define LCD_SCLK 18 -#define LCD_CS 39 -#define LCD_DC 9 -#define LCD_RST 47 - -// IIC -#define IIC_SDA 5 -#define IIC_SCL 6 - -// CST226SE -#define CST226SE_IIC_ADDRESS 0x5A -#define TOUCH_RST 13 -#define TOUCH_INT 21 -#define TOUCH_IIC_SDA IIC_SDA -#define TOUCH_IIC_SCL IIC_SCL - -// SY6970 -#define SY6970_SDA 5 -#define SY6970_SCL 6 -#define SY6970_Address 0x6A -#define SY6970_INT 21 - -// SD -#define SD_CS 14 -#define SD_MISO 8 -#define SD_MOSI 17 -#define SD_SCLK 18 - -// RT9080 -#define RT9080_EN 42 - -// MAX98357A -#define MAX98357A_BCLK 4 -#define MAX98357A_LRCLK 15 -#define MAX98357A_DATA 11 -#define MAX98357A_EN 41 - -// Vibration Motor -#define VIBRATINO_MOTOR_PWM 45 - -// PCF85063 -#define PCF85063_IIC_SDA 5 -#define PCF85063_IIC_SCL 6 -#define PCF85063_INT 21 - -// LR1121 -#define LR1121_BUSY 46 -#define LR1121_INT 40 -#define LR1121_SCLK 18 -#define LR1121_MOSI 17 -#define LR1121_MISO 8 -#define LR1121_CS 7 -#define LR1121_RST 10 - -// ICM20948 -#define ICM20948_ADDRESS 0x28 -#define ICM20948_SDA 5 -#define ICM20948_SCL 6 -#define ICM20948_INT 21 - -// MP34DT05TRF -#define MP34DT05TR_LRCLK 1 -#define MP34DT05TR_DATA 2 -#define MP34DT05TR_EN 3 - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.cc deleted file mode 100644 index 0beec452..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.cc +++ /dev/null @@ -1,150 +0,0 @@ -#include "tdisplays3promvsrlora_audio_codec.h" - -#include -#include -#include -#include - -#include "config.h" - -static const char TAG[] = "Tdisplays3promvsrloraAudioCodec"; - -Tdisplays3promvsrloraAudioCodec::Tdisplays3promvsrloraAudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateVoiceHardware(mic_bclk, mic_ws, mic_data, spkr_bclk, spkr_lrclk, spkr_data); - - gpio_config_t config_mic_en; - config_mic_en.pin_bit_mask = BIT64(AUDIO_MIC_ENABLE); - config_mic_en.mode = GPIO_MODE_OUTPUT; - config_mic_en.pull_up_en = GPIO_PULLUP_ENABLE; - config_mic_en.pull_down_en = GPIO_PULLDOWN_DISABLE; - config_mic_en.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER -config_mic_en.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config_mic_en); - gpio_set_level(AUDIO_MIC_ENABLE, 1); - - gpio_config_t config_spkr_en; - config_spkr_en.pin_bit_mask = BIT64(AUDIO_SPKR_ENABLE); - config_spkr_en.mode = GPIO_MODE_OUTPUT; - config_spkr_en.pull_up_en = GPIO_PULLUP_DISABLE; - config_spkr_en.pull_down_en = GPIO_PULLDOWN_ENABLE; - config_spkr_en.intr_type = GPIO_INTR_DISABLE; -#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER -config_spkr_en.hys_ctrl_mode = GPIO_HYS_SOFT_ENABLE; -#endif - gpio_config(&config_spkr_en); - gpio_set_level(AUDIO_SPKR_ENABLE, 0); - - ESP_LOGI(TAG, "Tdisplays3promvsrloraAudioCodec initialized"); -} - -Tdisplays3promvsrloraAudioCodec::~Tdisplays3promvsrloraAudioCodec() { - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Tdisplays3promvsrloraAudioCodec::CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data) { - - i2s_chan_config_t mic_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(0), I2S_ROLE_MASTER); - mic_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - i2s_chan_config_t spkr_chan_config = I2S_CHANNEL_DEFAULT_CONFIG(i2s_port_t(1), I2S_ROLE_MASTER); - spkr_chan_config.auto_clear = true; // Auto clear the legacy data in the DMA buffer - - ESP_ERROR_CHECK(i2s_new_channel(&mic_chan_config, NULL, &rx_handle_)); - ESP_ERROR_CHECK(i2s_new_channel(&spkr_chan_config, &tx_handle_, NULL)); - - i2s_pdm_rx_config_t mic_config = { - .clk_cfg = I2S_PDM_RX_CLK_DEFAULT_CONFIG(static_cast(input_sample_rate_)), - /* The data bit-width of PDM mode is fixed to 16 */ - .slot_cfg = I2S_PDM_RX_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg = { - .clk = mic_ws, - .din = mic_data, - .invert_flags = { - .clk_inv = false, - }, - }, - }; - - i2s_std_config_t spkr_config = { - .clk_cfg ={ - .sample_rate_hz = static_cast(11025), - .clk_src = I2S_CLK_SRC_DEFAULT, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - #ifdef I2S_HW_VERSION_2 - .ext_clk_freq_hz = 0, - #endif - }, - .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), - .gpio_cfg ={ - .mclk = I2S_GPIO_UNUSED, - .bclk = spkr_bclk, - .ws = spkr_lrclk, - .dout = spkr_data, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_pdm_rx_mode(rx_handle_, &mic_config)); - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &spkr_config)); - ESP_LOGI(TAG, "Voice hardware created"); -} - -void Tdisplays3promvsrloraAudioCodec::SetOutputVolume(int volume) { - volume_ = volume; - AudioCodec::SetOutputVolume(volume); -} - -void Tdisplays3promvsrloraAudioCodec::EnableInput(bool enable) { - gpio_set_level(AUDIO_MIC_ENABLE, !enable); - AudioCodec::EnableInput(enable); -} - -void Tdisplays3promvsrloraAudioCodec::EnableOutput(bool enable) { - gpio_set_level(AUDIO_SPKR_ENABLE, enable); - AudioCodec::EnableOutput(enable); -} - -int Tdisplays3promvsrloraAudioCodec::Read(int16_t *dest, int samples){ - if (input_enabled_){ - size_t bytes_read; - i2s_channel_read(rx_handle_, dest, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - - // ESP_LOGI(TAG, "Left: %d\n", dest[0]); - // ESP_LOGI(TAG,"Right: %d\n", dest[1]); - } - return samples; -} - -int Tdisplays3promvsrloraAudioCodec::Write(const int16_t *data, int samples){ - if (output_enabled_){ - size_t bytes_read; - auto output_data = (int16_t *)malloc(samples * sizeof(int16_t)); - for (size_t i = 0; i < samples; i++){ - output_data[i] = (float)data[i] * (float)(volume_ / 100.0); - } - i2s_channel_write(tx_handle_, output_data, samples * sizeof(int16_t), &bytes_read, portMAX_DELAY); - free(output_data); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.h deleted file mode 100644 index 6612b96c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/lilygo-t-display-s3-pro-mvsrlora/tdisplays3promvsrlora_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _TDISPLAYS3PROMVSRLORA_AUDIO_CODEC_H -#define _TDISPLAYS3PROMVSRLORA_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class Tdisplays3promvsrloraAudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t *data_if_ = nullptr; - const audio_codec_ctrl_if_t *out_ctrl_if_ = nullptr; - const audio_codec_if_t *out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t *in_ctrl_if_ = nullptr; - const audio_codec_if_t *in_codec_if_ = nullptr; - const audio_codec_gpio_if_t *gpio_if_ = nullptr; - - uint32_t volume_ = 70; - - void CreateVoiceHardware(gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data,gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data); - - virtual int Read(int16_t *dest, int samples) override; - virtual int Write(const int16_t *data, int samples) override; - -public: -Tdisplays3promvsrloraAudioCodec(int input_sample_rate, int output_sample_rate, - gpio_num_t mic_bclk, gpio_num_t mic_ws, gpio_num_t mic_data, - gpio_num_t spkr_bclk, gpio_num_t spkr_lrclk, gpio_num_t spkr_data, - bool input_reference); - virtual ~Tdisplays3promvsrloraAudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/README.md deleted file mode 100644 index d83767f7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# 使用说明 - - -**编译** - -```bash -python ./scripts/release.py m5stack-core-s3 -``` - -如需手动编译,请参考 `m5stack-core-s3/config.json` 修改 menuconfig 对应选项。 - -**烧录** - -```bash -idf.py flash -``` - -> [!NOTE] -> 进入下载模式:长按复位按键(约3秒),直至内部指示灯亮绿色,松开按键。 - - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.h deleted file mode 100644 index e0037829..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// M5Stack CoreS3 Board configuration - -#include - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_0 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_33 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_34 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_13 - -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_12 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_11 -#define AUDIO_CODEC_AW88298_ADDR AW88298_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA_PIN GPIO_NUM_NC -#define DISPLAY_SCL_PIN GPIO_NUM_NC -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - - -/* Camera pins */ -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_XCLK GPIO_NUM_NC // 像素时钟 (固定由 20MHz 外部晶振输入) -#define CAMERA_PIN_SIOD GPIO_NUM_NC // 串行时钟 Using existing I2C port -#define CAMERA_PIN_SIOC GPIO_NUM_NC // 串行时钟 Using existing I2C port -#define CAMERA_PIN_D0 GPIO_NUM_39 -#define CAMERA_PIN_D1 GPIO_NUM_40 -#define CAMERA_PIN_D2 GPIO_NUM_41 -#define CAMERA_PIN_D3 GPIO_NUM_42 -#define CAMERA_PIN_D4 GPIO_NUM_15 -#define CAMERA_PIN_D5 GPIO_NUM_16 -#define CAMERA_PIN_D6 GPIO_NUM_48 -#define CAMERA_PIN_D7 GPIO_NUM_47 -#define CAMERA_PIN_VSYNC GPIO_NUM_46 -#define CAMERA_PIN_HREF GPIO_NUM_38 -#define CAMERA_PIN_PCLK GPIO_NUM_45 - -#define XCLK_FREQ_HZ 20000000 - - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.json deleted file mode 100644 index 84ba5b75..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "m5stack-core-s3", - "sdkconfig_append": [ - "CONFIG_SPIRAM_MODE_QUAD=y", - "CONFIG_CAMERA_GC0308=y", - "CONFIG_CAMERA_GC0308_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_GC0308_DVP_YUV422_320X240_20FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.cc deleted file mode 100644 index 25963918..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.cc +++ /dev/null @@ -1,244 +0,0 @@ -#include "cores3_audio_codec.h" - -#include -#include -#include - -#define TAG "CoreS3AudioCodec" - -CoreS3AudioCodec::CoreS3AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - uint8_t aw88298_addr, uint8_t es7210_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 30; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Audio Output(Speaker) - audio_codec_i2c_cfg_t i2c_cfg = { - .port = (i2c_port_t)1, - .addr = aw88298_addr, - .bus_handle = i2c_master_handle, - }; - out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(out_ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - aw88298_codec_cfg_t aw88298_cfg = {}; - aw88298_cfg.ctrl_if = out_ctrl_if_; - aw88298_cfg.gpio_if = gpio_if_; - aw88298_cfg.reset_pin = GPIO_NUM_NC; - aw88298_cfg.hw_gain.pa_voltage = 5.0; - aw88298_cfg.hw_gain.codec_dac_voltage = 3.3; - aw88298_cfg.hw_gain.pa_gain = 1; - out_codec_if_ = aw88298_codec_new(&aw88298_cfg); - assert(out_codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = out_codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - - // Audio Input(Microphone) - i2c_cfg.addr = es7210_addr; - in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7210_codec_cfg_t es7210_cfg = {}; - es7210_cfg.ctrl_if = in_ctrl_if_; - es7210_cfg.mic_selected = ES7210_SEL_MIC1 | ES7210_SEL_MIC2 | ES7210_SEL_MIC3; - in_codec_if_ = es7210_codec_new(&es7210_cfg); - assert(in_codec_if_ != NULL); - - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - dev_cfg.codec_if = in_codec_if_; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - - ESP_LOGI(TAG, "CoreS3AudioCodec initialized"); -} - -CoreS3AudioCodec::~CoreS3AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void CoreS3AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - ESP_LOGI(TAG, "Audio IOs: mclk: %d, bclk: %d, ws: %d, dout: %d, din: %d", mclk, bclk, ws, dout, din); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bclk_div = 8, - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), - .ws_width = I2S_TDM_AUTO_WS_WIDTH, - .ws_pol = false, - .bit_shift = true, - .left_align = false, - .big_endian = false, - .bit_order_lsb = false, - .skip_mask = false, - .total_slot = I2S_TDM_AUTO_SLOT_NUM - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = I2S_GPIO_UNUSED, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void CoreS3AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void CoreS3AudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 2, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - if (input_reference_) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void CoreS3AudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int CoreS3AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int CoreS3AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.h deleted file mode 100644 index 4b034b48..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/cores3_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _BOX_AUDIO_CODEC_H -#define _BOX_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class CoreS3AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - CoreS3AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - uint8_t aw88298_addr, uint8_t es7210_addr, bool input_reference); - virtual ~CoreS3AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _BOX_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/m5stack_core_s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/m5stack_core_s3.cc deleted file mode 100644 index 4f4c7ff7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-core-s3/m5stack_core_s3.cc +++ /dev/null @@ -1,396 +0,0 @@ -#include "wifi_board.h" -#include "cores3_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "config.h" -#include "power_save_timer.h" -#include "i2c_device.h" -#include "axp2101.h" - -#include -#include -#include -#include -#include -#include -#include "esp32_camera.h" - -#define TAG "M5StackCoreS3Board" - -class Pmic : public Axp2101 { -public: - // Power Init - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - uint8_t data = ReadReg(0x90); - data |= 0b10110100; - WriteReg(0x90, data); - WriteReg(0x99, (0b11110 - 5)); - WriteReg(0x97, (0b11110 - 2)); - WriteReg(0x69, 0b00110101); - WriteReg(0x30, 0b111111); - WriteReg(0x90, 0xBF); - WriteReg(0x94, 33 - 5); - WriteReg(0x95, 33 - 5); - } - - void SetBrightness(uint8_t brightness) { - brightness = ((brightness + 641) >> 5); - WriteReg(0x99, brightness); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(Pmic *pmic) : pmic_(pmic) {} - - void SetBrightnessImpl(uint8_t brightness) override { - pmic_->SetBrightness(target_brightness_); - brightness_ = target_brightness_; - } - -private: - Pmic *pmic_; -}; - -class Aw9523 : public I2cDevice { -public: - // Exanpd IO Init - Aw9523(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(0x02, 0b00000111); // P0 - WriteReg(0x03, 0b10001111); // P1 - WriteReg(0x04, 0b00011000); // CONFIG_P0 - WriteReg(0x05, 0b00001100); // CONFIG_P1 - WriteReg(0x11, 0b00010000); // GCR P0 port is Push-Pull mode. - WriteReg(0x12, 0b11111111); // LEDMODE_P0 - WriteReg(0x13, 0b11111111); // LEDMODE_P1 - } - - void ResetAw88298() { - ESP_LOGI(TAG, "Reset AW88298"); - WriteReg(0x02, 0b00000011); - vTaskDelay(pdMS_TO_TICKS(10)); - WriteReg(0x02, 0b00000111); - vTaskDelay(pdMS_TO_TICKS(50)); - } - - void ResetIli9342() { - ESP_LOGI(TAG, "Reset IlI9342"); - WriteReg(0x03, 0b10000001); - vTaskDelay(pdMS_TO_TICKS(20)); - WriteReg(0x03, 0b10000011); - vTaskDelay(pdMS_TO_TICKS(10)); - } -}; - -class Ft6336 : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - Ft6336(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA3); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Ft6336() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - inline const TouchPoint_t& GetTouchPoint() { - return tp_; - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class M5StackCoreS3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_; - Aw9523* aw9523_; - Ft6336* ft6336_; - LcdDisplay* display_; - Esp32Camera* camera_; - esp_timer_handle_t touchpad_timer_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeAw9523() { - ESP_LOGI(TAG, "Init AW9523"); - aw9523_ = new Aw9523(i2c_bus_, 0x58); - vTaskDelay(pdMS_TO_TICKS(50)); - } - - void PollTouchpad() { - static bool was_touched = false; - static int64_t touch_start_time = 0; - const int64_t TOUCH_THRESHOLD_MS = 500; // 触摸时长阈值,超过500ms视为长按 - - ft6336_->UpdateTouchPoint(); - auto& touch_point = ft6336_->GetTouchPoint(); - - // 检测触摸开始 - if (touch_point.num > 0 && !was_touched) { - was_touched = true; - touch_start_time = esp_timer_get_time() / 1000; // 转换为毫秒 - } - // 检测触摸释放 - else if (touch_point.num == 0 && was_touched) { - was_touched = false; - int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; - - // 只有短触才触发 - if (touch_duration < TOUCH_THRESHOLD_MS) { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - } - } - - void InitializeFt6336TouchPad() { - ESP_LOGI(TAG, "Init FT6336"); - ft6336_ = new Ft6336(i2c_bus_, 0x38); - - // 创建定时器,20ms 间隔 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - M5StackCoreS3Board* board = (M5StackCoreS3Board*)arg; - board->PollTouchpad(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "touchpad_timer", - .skip_unhandled_events = true, - }; - - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &touchpad_timer_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(touchpad_timer_, 20 * 1000)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = GPIO_NUM_37; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = GPIO_NUM_36; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeIli9342Display() { - ESP_LOGI(TAG, "Init IlI9342"); - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = GPIO_NUM_3; - io_config.dc_gpio_num = GPIO_NUM_35; - io_config.spi_mode = 2; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9341(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - aw9523_->ResetIli9342(); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = XCLK_FREQ_HZ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetHMirror(false); - } - -public: - M5StackCoreS3Board() { - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeAxp2101(); - InitializeAw9523(); - I2cDetect(); - InitializeSpi(); - InitializeIli9342Display(); - InitializeCamera(); - InitializeFt6336TouchPad(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static CoreS3AudioCodec audio_codec(i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_AW88298_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual Backlight *GetBacklight() override { - static CustomBacklight backlight(pmic_); - return &backlight; - } -}; - -DECLARE_BOARD(M5StackCoreS3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/README.md deleted file mode 100644 index edbe24b5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# 使用说明 - -* [M5Stack Tab5 docs](https://docs.m5stack.com/zh_CN/core/Tab5) - -## 快速体验 - -到 [M5Burner](https://docs.m5stack.com/zh_CN/uiflow/m5burner/intro) 选择 Tab5 搜索小智下载固件 - -## 基础使用 - -* idf version: v6.0-dev - -1. 调整 idf_component.yml - -将 -```yaml - espressif/esp_video: - version: ==1.3.1 # for compatibility. update version may need to modify this project code. - rules: - - if: target not in [esp32] -``` -修改为 -```yaml - espressif/esp_video: - version: '==0.7.0' - rules: - - if: target not in [esp32] - espressif/esp_ipa: '==0.1.0' -``` - -2. 使用 release.py 编译 - -```shell -python ./scripts/release.py m5stack-tab5 -``` - -如需手动编译,请参考 `m5stack-tab5/config.json` 修改 menuconfig 对应选项。 - -3. 编译烧录程序 - -```shell -idf.py flash monitor -``` - -> [!NOTE] -> 进入下载模式:长按复位按键(约 2 秒),直至内部绿色 LED 指示灯开始快速闪烁,松开按键。 - - -## log - -@2025/05/17 测试问题 - -1. listening... 需要等几秒才能获取语音输入??? -2. 亮度调节不对 -3. 音量调节不对 - -## TODO diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.h deleted file mode 100644 index 91b6abfd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.h +++ /dev/null @@ -1,325 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -/* ---------------------------------------------------------------- */ -// Audio CODEC ES7210 + ES8311 -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_30 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_29 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_27 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_28 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_26 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC // PI4IOE 控制 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_31 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_32 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -/* ---------------------------------------------------------------- */ -// 摄像头相关参数配置 -#define CAMERA_SCL GPIO_NUM_32 -#define CAMERA_SDA GPIO_NUM_31 -#define CAMERA_MCLK GPIO_NUM_36 - -/* ---------------------------------------------------------------- */ -// 显示屏相关参数配置 -#define DISPLAY_WIDTH 720 -#define DISPLAY_HEIGHT 1280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_22 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#define TOUCH_INT_GPIO GPIO_NUM_23 // 触摸中断 - -const ili9881c_lcd_init_cmd_t tab5_lcd_ili9881c_specific_init_code_default[] = { - // {cmd, { data }, data_size, delay} - /**** CMD_Page 1 ****/ - {0xFF, (uint8_t[]){0x98, 0x81, 0x01}, 3, 0}, - {0xB7, (uint8_t[]){0x03}, 1, 0}, // set 2 lane - /**** CMD_Page 3 ****/ - {0xFF, (uint8_t[]){0x98, 0x81, 0x03}, 3, 0}, - {0x01, (uint8_t[]){0x00}, 1, 0}, - {0x02, (uint8_t[]){0x00}, 1, 0}, - {0x03, (uint8_t[]){0x73}, 1, 0}, - {0x04, (uint8_t[]){0x00}, 1, 0}, - {0x05, (uint8_t[]){0x00}, 1, 0}, - {0x06, (uint8_t[]){0x08}, 1, 0}, - {0x07, (uint8_t[]){0x00}, 1, 0}, - {0x08, (uint8_t[]){0x00}, 1, 0}, - {0x09, (uint8_t[]){0x1B}, 1, 0}, - {0x0a, (uint8_t[]){0x01}, 1, 0}, - {0x0b, (uint8_t[]){0x01}, 1, 0}, - {0x0c, (uint8_t[]){0x0D}, 1, 0}, - {0x0d, (uint8_t[]){0x01}, 1, 0}, - {0x0e, (uint8_t[]){0x01}, 1, 0}, - {0x0f, (uint8_t[]){0x26}, 1, 0}, - {0x10, (uint8_t[]){0x26}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 1, 0}, - {0x12, (uint8_t[]){0x00}, 1, 0}, - {0x13, (uint8_t[]){0x02}, 1, 0}, - {0x14, (uint8_t[]){0x00}, 1, 0}, - {0x15, (uint8_t[]){0x00}, 1, 0}, - {0x16, (uint8_t[]){0x00}, 1, 0}, - {0x17, (uint8_t[]){0x00}, 1, 0}, - {0x18, (uint8_t[]){0x00}, 1, 0}, - {0x19, (uint8_t[]){0x00}, 1, 0}, - {0x1a, (uint8_t[]){0x00}, 1, 0}, - {0x1b, (uint8_t[]){0x00}, 1, 0}, - {0x1c, (uint8_t[]){0x00}, 1, 0}, - {0x1d, (uint8_t[]){0x00}, 1, 0}, - {0x1e, (uint8_t[]){0x40}, 1, 0}, - {0x1f, (uint8_t[]){0x00}, 1, 0}, - {0x20, (uint8_t[]){0x06}, 1, 0}, - {0x21, (uint8_t[]){0x01}, 1, 0}, - {0x22, (uint8_t[]){0x00}, 1, 0}, - {0x23, (uint8_t[]){0x00}, 1, 0}, - {0x24, (uint8_t[]){0x00}, 1, 0}, - {0x25, (uint8_t[]){0x00}, 1, 0}, - {0x26, (uint8_t[]){0x00}, 1, 0}, - {0x27, (uint8_t[]){0x00}, 1, 0}, - {0x28, (uint8_t[]){0x33}, 1, 0}, - {0x29, (uint8_t[]){0x03}, 1, 0}, - {0x2a, (uint8_t[]){0x00}, 1, 0}, - {0x2b, (uint8_t[]){0x00}, 1, 0}, - {0x2c, (uint8_t[]){0x00}, 1, 0}, - {0x2d, (uint8_t[]){0x00}, 1, 0}, - {0x2e, (uint8_t[]){0x00}, 1, 0}, - {0x2f, (uint8_t[]){0x00}, 1, 0}, - {0x30, (uint8_t[]){0x00}, 1, 0}, - {0x31, (uint8_t[]){0x00}, 1, 0}, - {0x32, (uint8_t[]){0x00}, 1, 0}, - {0x33, (uint8_t[]){0x00}, 1, 0}, - {0x34, (uint8_t[]){0x00}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 1, 0}, - {0x36, (uint8_t[]){0x00}, 1, 0}, - {0x37, (uint8_t[]){0x00}, 1, 0}, - {0x38, (uint8_t[]){0x00}, 1, 0}, - {0x39, (uint8_t[]){0x00}, 1, 0}, - {0x3a, (uint8_t[]){0x00}, 1, 0}, - {0x3b, (uint8_t[]){0x00}, 1, 0}, - {0x3c, (uint8_t[]){0x00}, 1, 0}, - {0x3d, (uint8_t[]){0x00}, 1, 0}, - {0x3e, (uint8_t[]){0x00}, 1, 0}, - {0x3f, (uint8_t[]){0x00}, 1, 0}, - {0x40, (uint8_t[]){0x00}, 1, 0}, - {0x41, (uint8_t[]){0x00}, 1, 0}, - {0x42, (uint8_t[]){0x00}, 1, 0}, - {0x43, (uint8_t[]){0x00}, 1, 0}, - {0x44, (uint8_t[]){0x00}, 1, 0}, - - {0x50, (uint8_t[]){0x01}, 1, 0}, - {0x51, (uint8_t[]){0x23}, 1, 0}, - {0x52, (uint8_t[]){0x45}, 1, 0}, - {0x53, (uint8_t[]){0x67}, 1, 0}, - {0x54, (uint8_t[]){0x89}, 1, 0}, - {0x55, (uint8_t[]){0xab}, 1, 0}, - {0x56, (uint8_t[]){0x01}, 1, 0}, - {0x57, (uint8_t[]){0x23}, 1, 0}, - {0x58, (uint8_t[]){0x45}, 1, 0}, - {0x59, (uint8_t[]){0x67}, 1, 0}, - {0x5a, (uint8_t[]){0x89}, 1, 0}, - {0x5b, (uint8_t[]){0xab}, 1, 0}, - {0x5c, (uint8_t[]){0xcd}, 1, 0}, - {0x5d, (uint8_t[]){0xef}, 1, 0}, - - {0x5e, (uint8_t[]){0x11}, 1, 0}, - {0x5f, (uint8_t[]){0x02}, 1, 0}, - {0x60, (uint8_t[]){0x00}, 1, 0}, - {0x61, (uint8_t[]){0x07}, 1, 0}, - {0x62, (uint8_t[]){0x06}, 1, 0}, - {0x63, (uint8_t[]){0x0E}, 1, 0}, - {0x64, (uint8_t[]){0x0F}, 1, 0}, - {0x65, (uint8_t[]){0x0C}, 1, 0}, - {0x66, (uint8_t[]){0x0D}, 1, 0}, - {0x67, (uint8_t[]){0x02}, 1, 0}, - {0x68, (uint8_t[]){0x02}, 1, 0}, - {0x69, (uint8_t[]){0x02}, 1, 0}, - {0x6a, (uint8_t[]){0x02}, 1, 0}, - {0x6b, (uint8_t[]){0x02}, 1, 0}, - {0x6c, (uint8_t[]){0x02}, 1, 0}, - {0x6d, (uint8_t[]){0x02}, 1, 0}, - {0x6e, (uint8_t[]){0x02}, 1, 0}, - {0x6f, (uint8_t[]){0x02}, 1, 0}, - {0x70, (uint8_t[]){0x02}, 1, 0}, - {0x71, (uint8_t[]){0x02}, 1, 0}, - {0x72, (uint8_t[]){0x02}, 1, 0}, - {0x73, (uint8_t[]){0x05}, 1, 0}, - {0x74, (uint8_t[]){0x01}, 1, 0}, - {0x75, (uint8_t[]){0x02}, 1, 0}, - {0x76, (uint8_t[]){0x00}, 1, 0}, - {0x77, (uint8_t[]){0x07}, 1, 0}, - {0x78, (uint8_t[]){0x06}, 1, 0}, - {0x79, (uint8_t[]){0x0E}, 1, 0}, - {0x7a, (uint8_t[]){0x0F}, 1, 0}, - {0x7b, (uint8_t[]){0x0C}, 1, 0}, - {0x7c, (uint8_t[]){0x0D}, 1, 0}, - {0x7d, (uint8_t[]){0x02}, 1, 0}, - {0x7e, (uint8_t[]){0x02}, 1, 0}, - {0x7f, (uint8_t[]){0x02}, 1, 0}, - {0x80, (uint8_t[]){0x02}, 1, 0}, - {0x81, (uint8_t[]){0x02}, 1, 0}, - {0x82, (uint8_t[]){0x02}, 1, 0}, - {0x83, (uint8_t[]){0x02}, 1, 0}, - {0x84, (uint8_t[]){0x02}, 1, 0}, - {0x85, (uint8_t[]){0x02}, 1, 0}, - {0x86, (uint8_t[]){0x02}, 1, 0}, - {0x87, (uint8_t[]){0x02}, 1, 0}, - {0x88, (uint8_t[]){0x02}, 1, 0}, - {0x89, (uint8_t[]){0x05}, 1, 0}, - {0x8A, (uint8_t[]){0x01}, 1, 0}, - - /**** CMD_Page 4 ****/ - {0xFF, (uint8_t[]){0x98, 0x81, 0x04}, 3, 0}, - {0x38, (uint8_t[]){0x01}, 1, 0}, - {0x39, (uint8_t[]){0x00}, 1, 0}, - {0x6C, (uint8_t[]){0x15}, 1, 0}, - {0x6E, (uint8_t[]){0x1A}, 1, 0}, - {0x6F, (uint8_t[]){0x25}, 1, 0}, - {0x3A, (uint8_t[]){0xA4}, 1, 0}, - {0x8D, (uint8_t[]){0x20}, 1, 0}, - {0x87, (uint8_t[]){0xBA}, 1, 0}, - {0x3B, (uint8_t[]){0x98}, 1, 0}, - - /**** CMD_Page 1 ****/ - {0xFF, (uint8_t[]){0x98, 0x81, 0x01}, 3, 0}, - {0x22, (uint8_t[]){0x0A}, 1, 0}, - {0x31, (uint8_t[]){0x00}, 1, 0}, - {0x50, (uint8_t[]){0x6B}, 1, 0}, - {0x51, (uint8_t[]){0x66}, 1, 0}, - {0x53, (uint8_t[]){0x73}, 1, 0}, - {0x55, (uint8_t[]){0x8B}, 1, 0}, - {0x60, (uint8_t[]){0x1B}, 1, 0}, - {0x61, (uint8_t[]){0x01}, 1, 0}, - {0x62, (uint8_t[]){0x0C}, 1, 0}, - {0x63, (uint8_t[]){0x00}, 1, 0}, - - // Gamma P - {0xA0, (uint8_t[]){0x00}, 1, 0}, - {0xA1, (uint8_t[]){0x15}, 1, 0}, - {0xA2, (uint8_t[]){0x1F}, 1, 0}, - {0xA3, (uint8_t[]){0x13}, 1, 0}, - {0xA4, (uint8_t[]){0x11}, 1, 0}, - {0xA5, (uint8_t[]){0x21}, 1, 0}, - {0xA6, (uint8_t[]){0x17}, 1, 0}, - {0xA7, (uint8_t[]){0x1B}, 1, 0}, - {0xA8, (uint8_t[]){0x6B}, 1, 0}, - {0xA9, (uint8_t[]){0x1E}, 1, 0}, - {0xAA, (uint8_t[]){0x2B}, 1, 0}, - {0xAB, (uint8_t[]){0x5D}, 1, 0}, - {0xAC, (uint8_t[]){0x19}, 1, 0}, - {0xAD, (uint8_t[]){0x14}, 1, 0}, - {0xAE, (uint8_t[]){0x4B}, 1, 0}, - {0xAF, (uint8_t[]){0x1D}, 1, 0}, - {0xB0, (uint8_t[]){0x27}, 1, 0}, - {0xB1, (uint8_t[]){0x49}, 1, 0}, - {0xB2, (uint8_t[]){0x5D}, 1, 0}, - {0xB3, (uint8_t[]){0x39}, 1, 0}, - - // Gamma N - {0xC0, (uint8_t[]){0x00}, 1, 0}, - {0xC1, (uint8_t[]){0x01}, 1, 0}, - {0xC2, (uint8_t[]){0x0C}, 1, 0}, - {0xC3, (uint8_t[]){0x11}, 1, 0}, - {0xC4, (uint8_t[]){0x15}, 1, 0}, - {0xC5, (uint8_t[]){0x28}, 1, 0}, - {0xC6, (uint8_t[]){0x1B}, 1, 0}, - {0xC7, (uint8_t[]){0x1C}, 1, 0}, - {0xC8, (uint8_t[]){0x62}, 1, 0}, - {0xC9, (uint8_t[]){0x1C}, 1, 0}, - {0xCA, (uint8_t[]){0x29}, 1, 0}, - {0xCB, (uint8_t[]){0x60}, 1, 0}, - {0xCC, (uint8_t[]){0x16}, 1, 0}, - {0xCD, (uint8_t[]){0x17}, 1, 0}, - {0xCE, (uint8_t[]){0x4A}, 1, 0}, - {0xCF, (uint8_t[]){0x23}, 1, 0}, - {0xD0, (uint8_t[]){0x24}, 1, 0}, - {0xD1, (uint8_t[]){0x4F}, 1, 0}, - {0xD2, (uint8_t[]){0x5F}, 1, 0}, - {0xD3, (uint8_t[]){0x39}, 1, 0}, - - /**** CMD_Page 0 ****/ - {0xFF, (uint8_t[]){0x98, 0x81, 0x00}, 3, 0}, - {0x35, (uint8_t[]){0x00}, 0, 0}, - // {0x11, (uint8_t []){0x00}, 0}, - {0xFE, (uint8_t[]){0x00}, 0, 0}, - {0x29, (uint8_t[]){0x00}, 0, 0}, - //============ Gamma END=========== -}; - -// ST7123 vendor specific initialization commands -const st7123_lcd_init_cmd_t st7123_vendor_specific_init_default[] = { - {0x60, (uint8_t[]){0x71, 0x23, 0xa2}, 3, 0}, - {0x60, (uint8_t[]){0x71, 0x23, 0xa3}, 3, 0}, - {0x60, (uint8_t[]){0x71, 0x23, 0xa4}, 3, 0}, - {0xA4, (uint8_t[]){0x31}, 1, 0}, - {0xD7, (uint8_t[]){0x10, 0x0A, 0x10, 0x2A, 0x80, 0x80}, 6, 0}, - {0x90, (uint8_t[]){0x71, 0x23, 0x5A, 0x20, 0x24, 0x09, 0x09}, 7, 0}, - {0xA3, (uint8_t[]){0x80, 0x01, 0x88, 0x30, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x00, 0x00, - 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x4F, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, - 0x00, 0x00, 0x1E, 0x5C, 0x1E, 0x80, 0x00, 0x6F, 0x58, 0x00, 0x00, 0x00, 0xFF}, - 40, 0}, - {0xA6, (uint8_t[]){0x03, 0x00, 0x24, 0x55, 0x36, 0x00, 0x39, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, - 0x55, 0x38, 0x00, 0x37, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0x24, 0x11, 0x00, 0x00, - 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x00, 0xEC, 0x11, 0x00, 0x03, 0x00, 0x03, 0x6E, - 0x6E, 0xFF, 0xFF, 0x00, 0x08, 0x80, 0x08, 0x80, 0x06, 0x00, 0x00, 0x00, 0x00}, - 55, 0}, - {0xA7, (uint8_t[]){0x19, 0x19, 0x80, 0x64, 0x40, 0x07, 0x16, 0x40, 0x00, 0x44, 0x03, 0x6E, 0x6E, 0x91, 0xFF, - 0x08, 0x80, 0x64, 0x40, 0x25, 0x34, 0x40, 0x00, 0x02, 0x01, 0x6E, 0x6E, 0x91, 0xFF, 0x08, - 0x80, 0x64, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x6E, 0x6E, 0x91, 0xFF, 0x08, 0x80, - 0x64, 0x40, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x6E, 0x6E, 0x84, 0xFF, 0x08, 0x80, 0x44}, - 60, 0}, - {0xAC, (uint8_t[]){0x03, 0x19, 0x19, 0x18, 0x18, 0x06, 0x13, 0x13, 0x11, 0x11, 0x08, 0x08, 0x0A, 0x0A, 0x1C, - 0x1C, 0x07, 0x07, 0x00, 0x00, 0x02, 0x02, 0x01, 0x19, 0x19, 0x18, 0x18, 0x06, 0x12, 0x12, - 0x10, 0x10, 0x09, 0x09, 0x0B, 0x0B, 0x1C, 0x1C, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01}, - 44, 0}, - {0xAD, (uint8_t[]){0xF0, 0x00, 0x46, 0x00, 0x03, 0x50, 0x50, 0xFF, 0xFF, 0xF0, 0x40, 0x06, 0x01, - 0x07, 0x42, 0x42, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF}, - 25, 0}, - {0xAE, (uint8_t[]){0xFE, 0x3F, 0x3F, 0xFE, 0x3F, 0x3F, 0x00}, 7, 0}, - {0xB2, - (uint8_t[]){0x15, 0x19, 0x05, 0x23, 0x49, 0xAF, 0x03, 0x2E, 0x5C, 0xD2, 0xFF, 0x10, 0x20, 0xFD, 0x20, 0xC0, 0x00}, - 17, 0}, - {0xE8, (uint8_t[]){0x20, 0x6F, 0x04, 0x97, 0x97, 0x3E, 0x04, 0xDC, 0xDC, 0x3E, 0x06, 0xFA, 0x26, 0x3E}, 15, 0}, - {0x75, (uint8_t[]){0x03, 0x04}, 2, 0}, - {0xE7, (uint8_t[]){0x3B, 0x00, 0x00, 0x7C, 0xA1, 0x8C, 0x20, 0x1A, 0xF0, 0xB1, 0x50, 0x00, - 0x50, 0xB1, 0x50, 0xB1, 0x50, 0xD8, 0x00, 0x55, 0x00, 0xB1, 0x00, 0x45, - 0xC9, 0x6A, 0xFF, 0x5A, 0xD8, 0x18, 0x88, 0x15, 0xB1, 0x01, 0x01, 0x77}, - 36, 0}, - {0xEA, (uint8_t[]){0x13, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x2C}, 8, 0}, - {0xB0, (uint8_t[]){0x22, 0x43, 0x11, 0x61, 0x25, 0x43, 0x43}, 7, 0}, - {0xb7, (uint8_t[]){0x00, 0x00, 0x73, 0x73}, 4, 0}, - {0xBF, (uint8_t[]){0xA6, 0xAA}, 2, 0}, - {0xA9, (uint8_t[]){0x00, 0x00, 0x73, 0xFF, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03}, 10, 0}, - {0xC8, (uint8_t[]){0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, - 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, - 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF}, - 37, 0}, - {0xC9, (uint8_t[]){0x00, 0x00, 0x10, 0x1F, 0x36, 0x00, 0x5D, 0x04, 0x9D, 0x05, 0x10, 0xF2, 0x06, - 0x60, 0x03, 0x11, 0xAD, 0x00, 0xEF, 0x01, 0x22, 0x2E, 0x0E, 0x74, 0x08, 0x32, - 0xDC, 0x09, 0x33, 0x0F, 0xF3, 0x77, 0x0D, 0xB0, 0xDC, 0x03, 0xFF}, - 37, 0}, - {0x36, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 1, 100}, - {0x29, (uint8_t[]){0x00}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 1, 100}, -}; - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.json deleted file mode 100644 index c229ea06..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "m5stack-tab5", - "sdkconfig_append": [ - "CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5=y", - "CONFIG_CAMERA_SC202CS=y", - "CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE=y", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CMD_SLOT_1=13", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CLK_SLOT_1=12", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D0_SLOT_1=11", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D1_4BIT_BUS_SLOT_1=10", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D2_4BIT_BUS_SLOT_1=9", - "CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D3_4BIT_BUS_SLOT_1=8" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.c deleted file mode 100644 index b68b1d37..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "soc/soc_caps.h" - -#if SOC_MIPI_DSI_SUPPORTED -#include "esp_check.h" -#include "esp_log.h" -#include "esp_lcd_panel_commands.h" -#include "esp_lcd_panel_interface.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_lcd_panel_vendor.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "driver/gpio.h" -#include "esp_lcd_st7123.h" - -#define ST7123_PAD_CONTROL (0xB7) -#define ST7123_DSI_2_LANE (0x03) -#define ST7123_DSI_3_4_LANE (0x02) - -#define ST7123_CMD_GS_BIT (1 << 0) -#define ST7123_CMD_SS_BIT (1 << 1) - -typedef struct { - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_val; // save surrent value of LCD_CMD_COLMOD register - const st7123_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; - uint8_t lane_num; - struct { - unsigned int reset_level: 1; - } flags; - // To save the original functions of MIPI DPI panel - esp_err_t (*del)(esp_lcd_panel_t *panel); - esp_err_t (*init)(esp_lcd_panel_t *panel); -} st7123_panel_t; - -static const char *TAG = "st7123"; - -static esp_err_t panel_st7123_del(esp_lcd_panel_t *panel); -static esp_err_t panel_st7123_init(esp_lcd_panel_t *panel); -static esp_err_t panel_st7123_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_st7123_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_st7123_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_st7123_disp_on_off(esp_lcd_panel_t *panel, bool on_off); -static esp_err_t panel_st7123_sleep(esp_lcd_panel_t *panel, bool sleep); - -esp_err_t esp_lcd_new_panel_st7123(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, - esp_lcd_panel_handle_t *ret_panel) -{ - ESP_RETURN_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid arguments"); - st7123_vendor_config_t *vendor_config = (st7123_vendor_config_t *)panel_dev_config->vendor_config; - ESP_RETURN_ON_FALSE(vendor_config && vendor_config->mipi_config.dpi_config && vendor_config->mipi_config.dsi_bus, ESP_ERR_INVALID_ARG, TAG, - "invalid vendor config"); - - esp_err_t ret = ESP_OK; - st7123_panel_t *st7123 = (st7123_panel_t *)calloc(1, sizeof(st7123_panel_t)); - ESP_RETURN_ON_FALSE(st7123, ESP_ERR_NO_MEM, TAG, "no mem for st7123 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_config_t io_conf = { - .mode = GPIO_MODE_OUTPUT, - .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num, - }; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - - switch (panel_dev_config->rgb_ele_order) { - case LCD_RGB_ELEMENT_ORDER_RGB: - st7123->madctl_val = 0; - break; - case LCD_RGB_ELEMENT_ORDER_BGR: - st7123->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); - break; - } - - switch (panel_dev_config->bits_per_pixel) { - case 16: // RGB565 - st7123->colmod_val = 0x55; - break; - case 18: // RGB666 - st7123->colmod_val = 0x66; - break; - case 24: // RGB888 - st7123->colmod_val = 0x77; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - st7123->io = io; - st7123->init_cmds = vendor_config->init_cmds; - st7123->init_cmds_size = vendor_config->init_cmds_size; - st7123->lane_num = vendor_config->mipi_config.lane_num; - st7123->reset_gpio_num = panel_dev_config->reset_gpio_num; - st7123->flags.reset_level = panel_dev_config->flags.reset_active_high; - - // Create MIPI DPI panel - ESP_GOTO_ON_ERROR(esp_lcd_new_panel_dpi(vendor_config->mipi_config.dsi_bus, vendor_config->mipi_config.dpi_config, ret_panel), err, TAG, - "create MIPI DPI panel failed"); - ESP_LOGD(TAG, "new MIPI DPI panel @%p", *ret_panel); - - // Save the original functions of MIPI DPI panel - st7123->del = (*ret_panel)->del; - st7123->init = (*ret_panel)->init; - // Overwrite the functions of MIPI DPI panel - (*ret_panel)->del = panel_st7123_del; - (*ret_panel)->init = panel_st7123_init; - (*ret_panel)->reset = panel_st7123_reset; - (*ret_panel)->mirror = panel_st7123_mirror; - (*ret_panel)->invert_color = panel_st7123_invert_color; - (*ret_panel)->disp_on_off = panel_st7123_disp_on_off; - (*ret_panel)->disp_sleep = panel_st7123_sleep; - (*ret_panel)->user_data = st7123; - ESP_LOGD(TAG, "new st7123 panel @%p", st7123); - - return ESP_OK; - - err: - if (st7123) { - if (panel_dev_config->reset_gpio_num >= 0) { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(st7123); - } - return ret; -} - -static const st7123_lcd_init_cmd_t vendor_specific_init_default[] = { - // {cmd, { data }, data_size, delay_ms} - // TODO: - {0x60, (uint8_t []){0x71,0x23,0xa2}, 3, 0}, - {0x60, (uint8_t []){0x71,0x23,0xa3}, 3, 0}, - {0x60, (uint8_t []){0x71,0x23,0xa4}, 3, 0}, - {0xA4, (uint8_t []){0x31}, 1, 0}, - {0xD7, (uint8_t []){0x10,0x0A,0x10,0x2A,0x80,0x80}, 6, 0}, - {0x90, (uint8_t []){0x71,0x23,0x5A,0x20,0x24,0x09,0x09}, 7, 0}, - {0xA3, (uint8_t []){0x80,0x01,0x88,0x30,0x05,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x1E,0x5C,0x1E,0x80,0x00,0x4F,0x05,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x1E,0x5C,0x1E,0x80,0x00,0x6F,0x58,0x00,0x00,0x00,0xFF}, 40, 0}, - {0xA6, (uint8_t []){0x03,0x00,0x24,0x55,0x36,0x00,0x39,0x00,0x6E,0x6E,0x91,0xFF,0x00,0x24,0x55,0x38,0x00,0x37,0x00,0x6E,0x6E,0x91,0xFF,0x00,0x24,0x11,0x00,0x00,0x00,0x00,0x6E,0x6E,0x91,0xFF,0x00,0xEC,0x11,0x00,0x03,0x00,0x03,0x6E,0x6E,0xFF,0xFF,0x00,0x08,0x80,0x08,0x80,0x06,0x00,0x00,0x00,0x00}, 55, 0}, - {0xA7, (uint8_t []){0x19,0x19,0x80,0x64,0x40,0x07,0x16,0x40,0x00,0x44,0x03,0x6E,0x6E,0x91,0xFF,0x08,0x80,0x64,0x40,0x25,0x34,0x40,0x00,0x02,0x01,0x6E,0x6E,0x91,0xFF,0x08,0x80,0x64,0x40,0x00,0x00,0x40,0x00,0x00,0x00,0x6E,0x6E,0x91,0xFF,0x08,0x80,0x64,0x40,0x00,0x00,0x00,0x00,0x20,0x00,0x6E,0x6E,0x84,0xFF,0x08,0x80,0x44}, 60, 0}, - {0xAC, (uint8_t []){0x03,0x19,0x19,0x18,0x18,0x06,0x13,0x13,0x11,0x11,0x08,0x08,0x0A,0x0A,0x1C,0x1C,0x07,0x07,0x00,0x00,0x02,0x02,0x01,0x19,0x19,0x18,0x18,0x06,0x12,0x12,0x10,0x10,0x09,0x09,0x0B,0x0B,0x1C,0x1C,0x07,0x07,0x03,0x03,0x01,0x01}, 44, 0}, - {0xAD, (uint8_t []){0xF0,0x00,0x46,0x00,0x03,0x50,0x50,0xFF,0xFF,0xF0,0x40,0x06,0x01,0x07,0x42,0x42,0xFF,0xFF,0x01,0x00,0x00,0xFF,0xFF,0xFF,0xFF}, 25, 0}, - {0xAE, (uint8_t []){0xFE,0x3F,0x3F,0xFE,0x3F,0x3F,0x00}, 7, 0}, - {0xB2, (uint8_t []){0x15,0x19,0x05,0x23,0x49,0xAF,0x03,0x2E,0x5C,0xD2,0xFF,0x10,0x20,0xFD,0x20,0xC0,0x00}, 17, 0}, - {0xE8, (uint8_t []){0x20,0x6F,0x04,0x97,0x97,0x3E,0x04,0xDC,0xDC,0x3E,0x06,0xFA,0x26,0x3E}, 15, 0}, - {0x75, (uint8_t []){0x03,0x04}, 2, 0}, - {0xE7, (uint8_t []){0x3B,0x00,0x00,0x7C,0xA1,0x8C,0x20,0x1A,0xF0,0xB1,0x50,0x00,0x50,0xB1,0x50,0xB1,0x50,0xD8,0x00,0x55,0x00,0xB1,0x00,0x45,0xC9,0x6A,0xFF,0x5A,0xD8,0x18,0x88,0x15,0xB1,0x01,0x01,0x77}, 36, 0}, - {0xEA, (uint8_t []){0x13,0x00,0x04,0x00,0x00,0x00,0x00,0x2C}, 8, 0}, - {0xB0, (uint8_t []){0x22,0x43,0x11,0x61,0x25,0x43,0x43}, 7, 0}, - {0xb7, (uint8_t []){0x00,0x00,0x73,0x73}, 0x04, 0}, - {0xBF, (uint8_t []){0xA6,0XAA}, 2, 0}, - {0xA9, (uint8_t []){0x00,0x00,0x73,0xFF,0x00,0x00,0x03,0x00,0x00,0x03}, 10, 0}, - {0xC8, (uint8_t []){0x00,0x00,0x10,0x1F,0x36,0x00,0x5D,0x04,0x9D,0x05,0x10,0xF2,0x06,0x60,0x03,0x11,0xAD,0x00,0xEF,0x01,0x22,0x2E,0x0E,0x74,0x08,0x32,0xDC,0x09,0x33,0x0F,0xF3,0x77,0x0D,0xB0,0xDC,0x03,0xFF}, 37, 0}, - {0xC9, (uint8_t []){0x00,0x00,0x10,0x1F,0x36,0x00,0x5D,0x04,0x9D,0x05,0x10,0xF2,0x06,0x60,0x03,0x11,0xAD,0x00,0xEF,0x01,0x22,0x2E,0x0E,0x74,0x08,0x32,0xDC,0x09,0x33,0x0F,0xF3,0x77,0x0D,0xB0,0xDC,0x03,0xFF}, 37, 0}, - {0x36, (uint8_t []){0x03}, 1, 0}, - {0x11, (uint8_t []){0x00}, 1, 100}, - {0x29, (uint8_t []){0x00}, 1, 0}, - {0x35, (uint8_t []){0x00}, 1, 100}, - //============ Gamma END=========== -}; - -static esp_err_t panel_st7123_del(esp_lcd_panel_t *panel) -{ - st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - - if (st7123->reset_gpio_num >= 0) { - gpio_reset_pin(st7123->reset_gpio_num); - } - // Delete MIPI DPI panel - st7123->del(panel); - ESP_LOGD(TAG, "del st7123 panel @%p", st7123); - free(st7123); - - return ESP_OK; -} - -static esp_err_t panel_st7123_init(esp_lcd_panel_t *panel) -{ - st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = st7123->io; - const st7123_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - - // switch (st7123->lane_num) { - // case 0: - // case 2: - // lane_command = ST7123_DSI_2_LANE; - // break; - // case 3: - // case 4: - // lane_command = ST7123_DSI_3_4_LANE; - // break; - // default: - // ESP_LOGE(TAG, "Invalid lane number %d", st7123->lane_num); - // return ESP_ERR_INVALID_ARG; - // } - - uint8_t ID[3]; - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_rx_param(io, 0x04, ID, 3), TAG, "read ID failed"); - ESP_LOGI(TAG, "LCD ID: %02X %02X %02X", ID[0], ID[1], ID[2]); - - // // For modifying MIPI-DSI lane settings - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7123_PAD_CONTROL, (uint8_t[]) { - // lane_command, - // }, 1), TAG, "send command failed"); - - // // back to CMD_Page 0 - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, ST7123_CMD_CNDBKxSEL, (uint8_t[]) { - // ST7123_CMD_BKxSEL_BYTE0, ST7123_CMD_BKxSEL_BYTE1, ST7123_CMD_BKxSEL_BYTE2_PAGE0 - // }, 3), TAG, "send command failed"); - // // exit sleep mode - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, - // "io tx param failed"); - // vTaskDelay(pdMS_TO_TICKS(120)); - - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) { - // st7123->madctl_val, - // }, 1), TAG, "send command failed"); - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) { - // st7123->colmod_val, - // }, 1), TAG, "send command failed"); - - // vendor specific initialization, it can be different between manufacturers - // should consult the LCD supplier for initialization sequence code - if (st7123->init_cmds) { - init_cmds = st7123->init_cmds; - init_cmds_size = st7123->init_cmds_size; - } else { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(st7123_lcd_init_cmd_t); - } - - for (int i = 0; i < init_cmds_size; i++) { - // Check if the command has been used or conflicts with the internal - // if (is_command0_enable && init_cmds[i].data_bytes > 0) { - // switch (init_cmds[i].cmd) { - // case LCD_CMD_MADCTL: - // is_cmd_overwritten = true; - // st7123->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - // break; - // case LCD_CMD_COLMOD: - // is_cmd_overwritten = true; - // st7123->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - // break; - // default: - // is_cmd_overwritten = false; - // break; - // } - - // if (is_cmd_overwritten) { - // is_cmd_overwritten = false; - // ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", - // init_cmds[i].cmd); - // } - // } - - // Send command - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - - // if ((init_cmds[i].cmd == ST7123_CMD_CNDBKxSEL) && (((uint8_t *)init_cmds[i].data)[2] == ST7123_CMD_BKxSEL_BYTE2_PAGE0)) { - // is_command0_enable = true; - // } else if ((init_cmds[i].cmd == ST7123_CMD_CNDBKxSEL) && (((uint8_t *)init_cmds[i].data)[2] != ST7123_CMD_BKxSEL_BYTE2_PAGE0)) { - // is_command0_enable = false; - // } - } - ESP_LOGD(TAG, "send init commands success"); - - ESP_RETURN_ON_ERROR(st7123->init(panel), TAG, "init MIPI DPI panel failed"); - - return ESP_OK; -} - -static esp_err_t panel_st7123_reset(esp_lcd_panel_t *panel) -{ - st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - esp_lcd_panel_io_handle_t io = st7123->io; - - // Perform hardware reset - if (st7123->reset_gpio_num >= 0) { - gpio_set_level(st7123->reset_gpio_num, st7123->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(50)); - gpio_set_level(st7123->reset_gpio_num, !st7123->flags.reset_level); - vTaskDelay(pdMS_TO_TICKS(50)); - } else if (io) { // Perform software reset - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(20)); - } - - return ESP_OK; -} - -static esp_err_t panel_st7123_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) -{ - // st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - // esp_lcd_panel_io_handle_t io = st7123->io; - // uint8_t command = 0; - - // ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - // if (invert_color_data) { - // command = LCD_CMD_INVON; - // } else { - // command = LCD_CMD_INVOFF; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - - return ESP_OK; -} - -static esp_err_t panel_st7123_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - // st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - // esp_lcd_panel_io_handle_t io = st7123->io; - // uint8_t madctl_val = st7123->madctl_val; - - // ESP_RETURN_ON_FALSE(io, ESP_ERR_INVALID_STATE, TAG, "invalid panel IO"); - - // // Control mirror through LCD command - // if (mirror_x) { - // madctl_val |= ST7123_CMD_GS_BIT; - // } else { - // madctl_val &= ~ST7123_CMD_GS_BIT; - // } - // if (mirror_y) { - // madctl_val |= ST7123_CMD_SS_BIT; - // } else { - // madctl_val &= ~ST7123_CMD_SS_BIT; - // } - - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t []) { - // madctl_val - // }, 1), TAG, "send command failed"); - // st7123->madctl_val = madctl_val; - - return ESP_OK; -} - -static esp_err_t panel_st7123_disp_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - // st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - // esp_lcd_panel_io_handle_t io = st7123->io; - // int command = 0; - - // if (on_off) { - // command = LCD_CMD_DISPON; - // } else { - // command = LCD_CMD_DISPOFF; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_st7123_sleep(esp_lcd_panel_t *panel, bool sleep) -{ - // st7123_panel_t *st7123 = (st7123_panel_t *)panel->user_data; - // esp_lcd_panel_io_handle_t io = st7123->io; - // int command = 0; - - // if (sleep) { - // command = LCD_CMD_SLPIN; - // } else { - // command = LCD_CMD_SLPOUT; - // } - // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - // vTaskDelay(pdMS_TO_TICKS(100)); - - return ESP_OK; -} -#endif // SOC_MIPI_DSI_SUPPORTED diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.h deleted file mode 100644 index 27c514ea..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/esp_lcd_st7123.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief ESP LCD: ST7123 - */ - - #pragma once - - #include - #include "soc/soc_caps.h" - - #if SOC_MIPI_DSI_SUPPORTED - #include "esp_lcd_panel_vendor.h" - #include "esp_lcd_mipi_dsi.h" - - #ifdef __cplusplus - extern "C" { - #endif - - /** - * @brief LCD panel initialization commands. - * - */ - typedef struct { - int cmd; /* -#include "esp_check.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_lcd_panel_ops.h" -#include "esp_ldo_regulator.h" -#include -#include -#include -#include "i2c_device.h" -#include "esp_lcd_touch_gt911.h" -#include "esp_lcd_touch_st7123.h" -#include - -#define TAG "M5StackTab5Board" - -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR -#define LCD_MIPI_DSI_PHY_PWR_LDO_CHAN 3 // LDO_VO3 is connected to VDD_MIPI_DPHY -#define LCD_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV 2500 -#define ST7123_TOUCH_I2C_ADDRESS 0x55 - - -// PI4IO registers -#define PI4IO_REG_CHIP_RESET 0x01 -#define PI4IO_REG_IO_DIR 0x03 -#define PI4IO_REG_OUT_SET 0x05 -#define PI4IO_REG_OUT_H_IM 0x07 -#define PI4IO_REG_IN_DEF_STA 0x09 -#define PI4IO_REG_PULL_EN 0x0B -#define PI4IO_REG_PULL_SEL 0x0D -#define PI4IO_REG_IN_STA 0x0F -#define PI4IO_REG_INT_MASK 0x11 -#define PI4IO_REG_IRQ_STA 0x13 - -// Bit manipulation macros -#define setbit(x, bit) ((x) |= (1U << (bit))) -#define clrbit(x, bit) ((x) &= ~(1U << (bit))) - -class Pi4ioe1 : public I2cDevice { -public: - Pi4ioe1(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(PI4IO_REG_CHIP_RESET, 0xFF); - uint8_t data = ReadReg(PI4IO_REG_CHIP_RESET); - WriteReg(PI4IO_REG_IO_DIR, 0b01111111); // 0: input 1: output - WriteReg(PI4IO_REG_OUT_H_IM, 0b00000000); // 使用到的引脚关闭 High-Impedance - WriteReg(PI4IO_REG_PULL_SEL, 0b01111111); // pull up/down select, 0 down, 1 up - WriteReg(PI4IO_REG_PULL_EN, 0b01111111); // pull up/down enable, 0 disable, 1 enable - WriteReg(PI4IO_REG_IN_DEF_STA, 0b10000000); // P1, P7 默认高电平 - WriteReg(PI4IO_REG_INT_MASK, 0b01111111); // P7 中断使能 0 enable, 1 disable - WriteReg(PI4IO_REG_OUT_SET, 0b01110110); // Output Port Register P1(SPK_EN), P2(EXT5V_EN), P4(LCD_RST), P5(TP_RST), P6(CAM)RST 输出高电平 - } - - uint8_t ReadOutSet() { return ReadReg(PI4IO_REG_OUT_SET); } - void WriteOutSet(uint8_t value) { WriteReg(PI4IO_REG_OUT_SET, value); } -}; - -class Pi4ioe2 : public I2cDevice { -public: - Pi4ioe2(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - WriteReg(PI4IO_REG_CHIP_RESET, 0xFF); - uint8_t data = ReadReg(PI4IO_REG_CHIP_RESET); - WriteReg(PI4IO_REG_IO_DIR, 0b10111001); // 0: input 1: output - WriteReg(PI4IO_REG_OUT_H_IM, 0b00000110); // 使用到的引脚关闭 High-Impedance - WriteReg(PI4IO_REG_PULL_SEL, 0b10111001); // pull up/down select, 0 down, 1 up - WriteReg(PI4IO_REG_PULL_EN, 0b11111001); // pull up/down enable, 0 disable, 1 enable - WriteReg(PI4IO_REG_IN_DEF_STA, 0b01000000); // P6 默认高电平 - WriteReg(PI4IO_REG_INT_MASK, 0b10111111); // P6 中断使能 0 enable, 1 disable - WriteReg(PI4IO_REG_OUT_SET, 0b10001001); // Output Port Register P0(WLAN_PWR_EN), P3(USB5V_EN), P7(CHG_EN) 输出高电平 - } - - uint8_t ReadOutSet() { return ReadReg(PI4IO_REG_OUT_SET); } - void WriteOutSet(uint8_t value) { WriteReg(PI4IO_REG_OUT_SET, value); } -}; - -class M5StackTab5Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - Esp32Camera* camera_ = nullptr; - Pi4ioe1* pi4ioe1_; - Pi4ioe2* pi4ioe2_; - esp_lcd_touch_handle_t touch_ = nullptr; - - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power() { - esp_ldo_channel_handle_t ldo_mipi_phy = NULL; - esp_ldo_channel_config_t ldo_mipi_phy_config = { - .chan_id = LCD_MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = LCD_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - return esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy); - } - - void I2cDetect() { - uint8_t address; - printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n"); - for (int i = 0; i < 128; i += 16) { - printf("%02x: ", i); - for (int j = 0; j < 16; j++) { - fflush(stdout); - address = i + j; - esp_err_t ret = i2c_master_probe(i2c_bus_, address, pdMS_TO_TICKS(200)); - if (ret == ESP_OK) { - printf("%02x ", address); - } else if (ret == ESP_ERR_TIMEOUT) { - printf("UU "); - } else { - printf("-- "); - } - } - printf("\r\n"); - } - } - - void InitializePi4ioe() { - ESP_LOGI(TAG, "Init I/O Exapander PI4IOE"); - pi4ioe1_ = new Pi4ioe1(i2c_bus_, 0x43); - pi4ioe2_ = new Pi4ioe2(i2c_bus_, 0x44); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeGt911TouchPad() { - ESP_LOGI(TAG, "Init GT911"); - - /* Initialize Touch Panel */ - ESP_LOGI(TAG, "Initialize touch IO (I2C)"); - const esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = TOUCH_INT_GPIO, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP; // 更改 GT911 地址 - tp_io_config.scl_speed_hz = 100000; - esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle); - esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &touch_); - } - - void InitializeIli9881cDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGI(TAG, "Turn on the power for MIPI DSI PHY"); - esp_ldo_channel_handle_t ldo_mipi_phy = NULL; - esp_ldo_channel_config_t ldo_mipi_phy_config = { - .chan_id = LCD_MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = LCD_MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - ESP_ERROR_CHECK(esp_ldo_acquire_channel(&ldo_mipi_phy_config, &ldo_mipi_phy)); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - esp_lcd_dsi_bus_handle_t mipi_dsi_bus; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 900, // 900MHz - }; - ESP_ERROR_CHECK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus)); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_dbi_io_config_t dbi_config = { - .virtual_channel = 0, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &panel_io)); - - ESP_LOGI(TAG, "Install LCD driver of ili9881c"); - esp_lcd_dpi_panel_config_t dpi_config = { - .virtual_channel = 0, - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 60, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 2, - .video_timing = { - .h_size = DISPLAY_WIDTH, - .v_size = DISPLAY_HEIGHT, - .hsync_pulse_width = 40, - .hsync_back_porch = 140, - .hsync_front_porch = 40, - .vsync_pulse_width = 4, - .vsync_back_porch = 20, - .vsync_front_porch = 20, - }, - .flags = { - .use_dma2d = false, - }, - }; - - ili9881c_vendor_config_t vendor_config = { - .init_cmds = tab5_lcd_ili9881c_specific_init_code_default, - .init_cmds_size = sizeof(tab5_lcd_ili9881c_specific_init_code_default) / sizeof(tab5_lcd_ili9881c_specific_init_code_default[0]), - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - .lane_num = 2, - }, - }; - - esp_lcd_panel_dev_config_t lcd_dev_config = {}; - lcd_dev_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - lcd_dev_config.reset_gpio_num = -1; - lcd_dev_config.bits_per_pixel = 16; - lcd_dev_config.vendor_config = &vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ili9881c(panel_io, &lcd_dev_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - - display_ = new MipiLcdDisplay(panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, - DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeSt7123Display() { - esp_err_t ret = ESP_OK; - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - - // Declare all config structures at the top to avoid goto issues - // Initialize with memset to avoid any initialization syntax that might confuse the compiler - esp_lcd_dsi_bus_config_t bus_config; - esp_lcd_dbi_io_config_t dbi_config; - esp_lcd_dpi_panel_config_t dpi_config; - st7123_vendor_config_t vendor_config; - esp_lcd_panel_dev_config_t lcd_dev_config; - - memset(&bus_config, 0, sizeof(bus_config)); - memset(&dbi_config, 0, sizeof(dbi_config)); - memset(&dpi_config, 0, sizeof(dpi_config)); - memset(&vendor_config, 0, sizeof(vendor_config)); - memset(&lcd_dev_config, 0, sizeof(lcd_dev_config)); - - ESP_ERROR_CHECK(bsp_enable_dsi_phy_power()); - - /* create MIPI DSI bus first, it will initialize the DSI PHY as well */ - bus_config.bus_id = 0; - bus_config.num_data_lanes = 2; // ST7123 uses 2 data lanes - bus_config.lane_bit_rate_mbps = 965; // ST7123 lane bitrate - ret = esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "New DSI bus init failed"); - goto err; - } - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel for ST7123"); - // we use DBI interface to send LCD commands and parameters - dbi_config.virtual_channel = 0; - dbi_config.lcd_cmd_bits = 8; // according to the LCD spec - dbi_config.lcd_param_bits = 8; // according to the LCD spec - ret = esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "New panel IO failed"); - goto err; - } - - ESP_LOGI(TAG, "Install LCD driver of ST7123"); - dpi_config.virtual_channel = 0; - dpi_config.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT; - dpi_config.dpi_clock_freq_mhz = 70; // ST7123 DPI clock frequency - dpi_config.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565; - dpi_config.num_fbs = 1; - dpi_config.video_timing.h_size = 720; - dpi_config.video_timing.v_size = 1280; - dpi_config.video_timing.hsync_pulse_width = 2; - dpi_config.video_timing.hsync_back_porch = 40; - dpi_config.video_timing.hsync_front_porch = 40; - dpi_config.video_timing.vsync_pulse_width = 2; - dpi_config.video_timing.vsync_back_porch = 8; - dpi_config.video_timing.vsync_front_porch = 220; - dpi_config.flags.use_dma2d = true; - - vendor_config.init_cmds = st7123_vendor_specific_init_default; - vendor_config.init_cmds_size = sizeof(st7123_vendor_specific_init_default) / sizeof(st7123_vendor_specific_init_default[0]); - vendor_config.mipi_config.dsi_bus = mipi_dsi_bus; - vendor_config.mipi_config.dpi_config = &dpi_config; - vendor_config.mipi_config.lane_num = 2; - - lcd_dev_config.reset_gpio_num = -1; - lcd_dev_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - lcd_dev_config.data_endian = LCD_RGB_DATA_ENDIAN_LITTLE; - lcd_dev_config.bits_per_pixel = 24; - lcd_dev_config.vendor_config = &vendor_config; - - // 使用实际的 ST7123 驱动函数 - ret = esp_lcd_new_panel_st7123(io, &lcd_dev_config, &disp_panel); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "New LCD panel ST7123 failed"); - goto err; - } - - ret = esp_lcd_panel_reset(disp_panel); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "LCD panel reset failed"); - goto err; - } - - ret = esp_lcd_panel_init(disp_panel); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "LCD panel init failed"); - goto err; - } - - ret = esp_lcd_panel_disp_on_off(disp_panel, true); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "LCD panel display on failed"); - goto err; - } - - display_ = new MipiLcdDisplay(io, disp_panel, 720, 1280, DISPLAY_OFFSET_X, - DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - ESP_LOGI(TAG, "ST7123 Display initialized with resolution %dx%d", 720, 1280); - - return; - - err: - if (disp_panel) { - esp_lcd_panel_del(disp_panel); - } - if (io) { - esp_lcd_panel_io_del(io); - } - if (mipi_dsi_bus) { - esp_lcd_del_dsi_bus(mipi_dsi_bus); - } - ESP_ERROR_CHECK(ret); - } - - void InitializeSt7123TouchPad() { - ESP_LOGI(TAG, "Init ST7123 Touch"); - - /* Initialize Touch Panel */ - ESP_LOGI(TAG, "Initialize touch IO (I2C)"); - const esp_lcd_touch_config_t tp_cfg = { - .x_max = 720, - .y_max = 1280, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = TOUCH_INT_GPIO, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = { - .dev_addr = 0x55, - .control_phase_bytes = 1, - .dc_bit_offset = 0, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .scl_speed_hz = 100000, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_st7123(tp_io_handle, &tp_cfg, &touch_)); - } - - void InitializeDisplay() { - // after tp reset, wait for 100ms to ensure the I2C bus is stable - vTaskDelay(pdMS_TO_TICKS(100)); - // 检测 ST7123 触摸屏 (I2C地址 0x55) - esp_err_t ret = i2c_master_probe(i2c_bus_, ST7123_TOUCH_I2C_ADDRESS, 200); - if (ret == ESP_OK) { - ESP_LOGI(TAG, "Detected ST7123 at 0x%02X, initializing ST7123 display", ST7123_TOUCH_I2C_ADDRESS); - InitializeSt7123Display(); - InitializeSt7123TouchPad(); - } else { - ESP_LOGI(TAG, "ST7123 not found at 0x%02X (ret=0x%x), using default ST7703+GT911", ST7123_TOUCH_I2C_ADDRESS, ret); - InitializeIli9881cDisplay(); - InitializeGt911TouchPad(); - } - } - - void InitializeCamera() { - esp_cam_sensor_xclk_handle_t xclk_handle = NULL; - esp_cam_sensor_xclk_config_t cam_xclk_config = {}; - -#if CONFIG_CAMERA_XCLK_USE_ESP_CLOCK_ROUTER - if (esp_cam_sensor_xclk_allocate(ESP_CAM_SENSOR_XCLK_ESP_CLOCK_ROUTER, &xclk_handle) == ESP_OK) { - cam_xclk_config.esp_clock_router_cfg.xclk_pin = CAMERA_MCLK; - cam_xclk_config.esp_clock_router_cfg.xclk_freq_hz = 12000000; // 12MHz - (void)esp_cam_sensor_xclk_start(xclk_handle, &cam_xclk_config); - } -#elif CONFIG_CAMERA_XCLK_USE_LEDC - if (esp_cam_sensor_xclk_allocate(ESP_CAM_SENSOR_XCLK_LEDC, &xclk_handle) == ESP_OK) { - cam_xclk_config.ledc_cfg.timer = LEDC_TIMER_0; - cam_xclk_config.ledc_cfg.clk_cfg = LEDC_AUTO_CLK; - cam_xclk_config.ledc_cfg.channel = LEDC_CHANNEL_0; - cam_xclk_config.ledc_cfg.xclk_freq_hz = 12000000; // 12MHz - cam_xclk_config.ledc_cfg.xclk_pin = CAMERA_MCLK; - (void)esp_cam_sensor_xclk_start(xclk_handle, &cam_xclk_config); - } -#endif - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 400000, - }; - - esp_video_init_csi_config_t csi_config = { - .sccb_config = sccb_config, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - }; - - esp_video_init_config_t video_config = { - .csi = &csi_config, - }; - - camera_ = new Esp32Camera(video_config); - } - -public: - M5StackTab5Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - I2cDetect(); - InitializePi4ioe(); - InitializeDisplay(); // Auto-detect and initialize display + touch - InitializeCamera(); - InitializeButtons(); - SetChargeQcEn(true); - SetChargeEn(true); - SetUsb5vEn(true); - SetExt5vEn(true); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Tab5AudioCodec audio_codec(i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8388_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - // BSP power control functions - void SetChargeQcEn(bool en) { - if (pi4ioe2_) { - uint8_t value = pi4ioe2_->ReadOutSet(); - if (en) { - clrbit(value, 5); // P5 = CHG_QC_EN (低电平使能) - } else { - setbit(value, 5); - } - pi4ioe2_->WriteOutSet(value); - } - } - - void SetChargeEn(bool en) { - if (pi4ioe2_) { - uint8_t value = pi4ioe2_->ReadOutSet(); - if (en) { - setbit(value, 7); // P7 = CHG_EN - } else { - clrbit(value, 7); - } - pi4ioe2_->WriteOutSet(value); - } - } - - void SetUsb5vEn(bool en) { - if (pi4ioe2_) { - uint8_t value = pi4ioe2_->ReadOutSet(); - if (en) { - setbit(value, 3); // P3 = USB5V_EN - } else { - clrbit(value, 3); - } - pi4ioe2_->WriteOutSet(value); - } - } - - void SetExt5vEn(bool en) { - if (pi4ioe1_) { - uint8_t value = pi4ioe1_->ReadOutSet(); - if (en) { - setbit(value, 2); // P2 = EXT5V_EN - } else { - clrbit(value, 2); - } - pi4ioe1_->WriteOutSet(value); - } - } -}; - - -DECLARE_BOARD(M5StackTab5Board); - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/sdkconfig.tab5 b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/sdkconfig.tab5 deleted file mode 100644 index 70f759c4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/sdkconfig.tab5 +++ /dev/null @@ -1,14 +0,0 @@ -# This file was generated using idf.py save-defconfig. It can be edited manually. -# Espressif IoT Development Framework (ESP-IDF) 5.5.1 Project Minimal Configuration -# -CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5=y - -CONFIG_XIAOZHI_ENABLE_ROTATE_CAMERA_IMAGE=y -CONFIG_CAMERA_SC202CS=y - -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CMD_SLOT_1=13 -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_CLK_SLOT_1=12 -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D0_SLOT_1=11 -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D1_4BIT_BUS_SLOT_1=10 -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D2_4BIT_BUS_SLOT_1=9 -CONFIG_ESP_HOSTED_PRIV_SDIO_PIN_D3_4BIT_BUS_SLOT_1=8 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.cc deleted file mode 100644 index 74dfe2e4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.cc +++ /dev/null @@ -1,243 +0,0 @@ -#include "tab5_audio_codec.h" - -#include -#include -#include - -#define TAG "Tab5AudioCodec" - -Tab5AudioCodec::Tab5AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8388_addr, uint8_t es7210_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - input_gain_ = 30; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = (i2c_port_t)1, - .addr = es8388_addr, - .bus_handle = i2c_master_handle, - }; - out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(out_ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - es8388_codec_cfg_t es8388_cfg = {}; - es8388_cfg.ctrl_if = out_ctrl_if_; - es8388_cfg.gpio_if = gpio_if_; - es8388_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_DAC; - es8388_cfg.master_mode = true; - es8388_cfg.pa_pin = -1; // PI4IOE1 P1 控制 - es8388_cfg.pa_reverted = false; - es8388_cfg.hw_gain.pa_voltage = 5.0; - es8388_cfg.hw_gain.codec_dac_voltage = 3.3; - out_codec_if_ = es8388_codec_new(&es8388_cfg); - assert(out_codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = out_codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - - // Input - i2c_cfg.addr = es7210_addr; - in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7210_codec_cfg_t es7210_cfg = {}; - es7210_cfg.ctrl_if = in_ctrl_if_; - es7210_cfg.mic_selected = ES7210_SEL_MIC1 | ES7210_SEL_MIC2 | ES7210_SEL_MIC3 | ES7210_SEL_MIC4; - in_codec_if_ = es7210_codec_new(&es7210_cfg); - assert(in_codec_if_ != NULL); - - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - dev_cfg.codec_if = in_codec_if_; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - - ESP_LOGI(TAG, "Tab5 AudioDevice initialized"); -} - -Tab5AudioCodec::~Tab5AudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void Tab5AudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = 6, - .dma_frame_num = 240, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = I2S_GPIO_UNUSED, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - i2s_tdm_config_t tdm_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)input_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256, - .bclk_div = 8, - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_STEREO, - .slot_mask = i2s_tdm_slot_mask_t(I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3), - .ws_width = I2S_TDM_AUTO_WS_WIDTH, - .ws_pol = false, - .bit_shift = true, - .left_align = false, - .big_endian = false, - .bit_order_lsb = false, - .skip_mask = false, - .total_slot = I2S_TDM_AUTO_SLOT_NUM - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = I2S_GPIO_UNUSED, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_handle_, &tdm_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void Tab5AudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void Tab5AudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 4, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - if (input_reference_) { - fs.channel_mask |= ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1); - } - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_channel_gain(input_dev_, ESP_CODEC_DEV_MAKE_CHANNEL_MASK(0), input_gain_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void Tab5AudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - } - AudioCodec::EnableOutput(enable); -} - -int Tab5AudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int Tab5AudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.h deleted file mode 100644 index 4e455893..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/m5stack-tab5/tab5_audio_codec.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _TAB5_AUDIO_CODEC_H -#define _TAB5_AUDIO_CODEC_H - -#include "audio_codec.h" -#include -#include - - -class Tab5AudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - Tab5AudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8388_addr, uint8_t es7210_addr, bool input_reference); - virtual ~Tab5AudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _TAB5_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.h deleted file mode 100644 index bc37001c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_11 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_12 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_4 // pcb v2.4不起作用,适用于2.4A -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_5 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_6 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -//led power -#define BUILTIN_LED_POWER GPIO_NUM_39 // 低电平有效 -#define BUILTIN_LED_POWER_OUTPUT_INVERT true - -#define BUILTIN_LED_NUM 2 -#define BUILTIN_LED_GPIO GPIO_NUM_38 - -#define MAIN_BUTTON_GPIO GPIO_NUM_21 -#define LEFT_BUTTON_GPIO GPIO_NUM_0 -#define RIGHT_BUTTON_GPIO GPIO_NUM_47 - -// display -#define DISPLAY_SDA_PIN GPIO_NUM_15 -#define DISPLAY_SCL_PIN GPIO_NUM_16 -#define DISPLAY_CS_PIN GPIO_NUM_17 -#define DISPLAY_DC_PIN GPIO_NUM_18 -#define DISPLAY_RST_PIN GPIO_NUM_14 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.json deleted file mode 100644 index f416c2a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "magiclick-2p4", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/magiclick_2p4_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/magiclick_2p4_board.cc deleted file mode 100644 index 16c8fc1c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p4/magiclick_2p4_board.cc +++ /dev/null @@ -1,271 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/circular_strip.h" -#include "config.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#include "../magiclick-2p5/power_manager.h" -#include "power_save_timer.h" - -#define TAG "magiclick_2p4" - -class NV3023Display : public SpiLcdDisplay { -public: - NV3023Display(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - // 只需要覆盖颜色相关的样式 - auto screen = lv_disp_get_scr_act(lv_disp_get_default()); - lv_obj_set_style_text_color(screen, lv_color_black(), 0); - - // 设置容器背景色 - lv_obj_set_style_bg_color(container_, lv_color_black(), 0); - - // 设置状态栏背景色和文本颜色 - lv_obj_set_style_bg_color(status_bar_, lv_color_white(), 0); - lv_obj_set_style_text_color(network_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(notification_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(status_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(mute_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(battery_label_, lv_color_black(), 0); - - // 设置内容区背景色和文本颜色 - lv_obj_set_style_bg_color(content_, lv_color_black(), 0); - lv_obj_set_style_border_width(content_, 0, 0); - lv_obj_set_style_text_color(emoji_label_, lv_color_white(), 0); - lv_obj_set_style_text_color(chat_message_label_, lv_color_white(), 0); - } -}; - -class magiclick_2p4 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button main_button_; - Button left_button_; - Button right_button_; - NV3023Display* display_; - - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_48); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(240, 60, -1); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeButtons() { - main_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - main_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - Application::GetInstance().StartListening(); - }); - main_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - left_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - left_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - right_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - right_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - } - - void InitializeLedPower() { - // 设置GPIO模式 - gpio_reset_pin(BUILTIN_LED_POWER); - gpio_set_direction(BUILTIN_LED_POWER, GPIO_MODE_OUTPUT); - gpio_set_level(BUILTIN_LED_POWER, BUILTIN_LED_POWER_OUTPUT_INVERT ? 0 : 1); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeNv3023Display(){ - // esp_lcd_panel_io_handle_t panel_io = nullptr; - // esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片NV3023 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_nv3023(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - display_ = new NV3023Display(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - magiclick_2p4() : - main_button_(MAIN_BUTTON_GPIO), - left_button_(LEFT_BUTTON_GPIO), - right_button_(RIGHT_BUTTON_GPIO) { - InitializeLedPower(); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeButtons(); - InitializeSpi(); - InitializeNv3023Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static CircularStrip led(BUILTIN_LED_GPIO, BUILTIN_LED_NUM); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(magiclick_2p4); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.h deleted file mode 100644 index 3b8cce72..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_11 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_12 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_4 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_5 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_6 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -//led power -#define BUILTIN_LED_POWER GPIO_NUM_39 // 低电平有效 -#define BUILTIN_LED_POWER_OUTPUT_INVERT true - -#define BUILTIN_LED_NUM 2 -#define BUILTIN_LED_GPIO GPIO_NUM_38 - -#define MAIN_BUTTON_GPIO GPIO_NUM_21 -#define LEFT_BUTTON_GPIO GPIO_NUM_0 -#define RIGHT_BUTTON_GPIO GPIO_NUM_47 - -// display -#define DISPLAY_SDA_PIN GPIO_NUM_16 -#define DISPLAY_SCL_PIN GPIO_NUM_15 -#define DISPLAY_CS_PIN GPIO_NUM_14 -#define DISPLAY_DC_PIN GPIO_NUM_18 -#define DISPLAY_RST_PIN GPIO_NUM_17 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#define ML307_RX_PIN GPIO_NUM_42 -#define ML307_TX_PIN GPIO_NUM_44 -#define ML307_POWER_PIN GPIO_NUM_40 -#define ML307_POWER_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.json deleted file mode 100644 index 62206415..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "magiclick-2p5", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/magiclick_2p5_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/magiclick_2p5_board.cc deleted file mode 100644 index ce73a97e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/magiclick_2p5_board.cc +++ /dev/null @@ -1,319 +0,0 @@ -#include "dual_network_board.h" -#include "display/lcd_display.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/circular_strip.h" -#include "config.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "power_manager.h" -#include "power_save_timer.h" -#include "esp_wifi.h" - -#define TAG "magiclick_2p5" - -class GC9107Display : public SpiLcdDisplay { -public: - GC9107Display(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - } -}; - -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; - -class magiclick_2p5 : public DualNetworkBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button main_button_; - Button left_button_; - Button right_button_; - GC9107Display* display_; - - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_48); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(240, 60, -1); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - - power_save_timer_->SetEnabled(true); - } - - void Enable4GModule() { - // enable the 4G module - gpio_reset_pin(ML307_POWER_PIN); - gpio_set_direction(ML307_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(ML307_POWER_PIN, ML307_POWER_OUTPUT_INVERT ? 0 : 1); - } - void Disable4GModule() { - // enable the 4G module - gpio_reset_pin(ML307_POWER_PIN); - gpio_set_direction(ML307_POWER_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(ML307_POWER_PIN, ML307_POWER_OUTPUT_INVERT ? 1 : 0); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void CheckNetType() { - if (GetNetworkType() == NetworkType::WIFI) { - Disable4GModule(); - } else if (GetNetworkType() == NetworkType::ML307) { - Enable4GModule(); - } - - } - - void InitializeButtons() { - main_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - } - } - }); - main_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - main_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - Application::GetInstance().StartListening(); - }); - main_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - left_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - left_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - - right_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - right_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - } - - void InitializeLedPower() { - // 设置GPIO模式 - gpio_reset_pin(BUILTIN_LED_POWER); - gpio_set_direction(BUILTIN_LED_POWER, GPIO_MODE_OUTPUT); - gpio_set_level(BUILTIN_LED_POWER, BUILTIN_LED_POWER_OUTPUT_INVERT ? 0 : 1); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeGc9107Display(){ - // esp_lcd_panel_io_handle_t panel_io = nullptr; - // esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片GC9107 - ESP_LOGD(TAG, "Install LCD driver"); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &gc9107_vendor_config; - - esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel, true)); - display_ = new GC9107Display(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - magiclick_2p5() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN, GPIO_NUM_NC, 0), - main_button_(MAIN_BUTTON_GPIO), - left_button_(LEFT_BUTTON_GPIO), - right_button_(RIGHT_BUTTON_GPIO) { - InitializeLedPower(); - CheckNetType(); - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeButtons(); - InitializeSpi(); - InitializeGc9107Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static CircularStrip led(BUILTIN_LED_GPIO, BUILTIN_LED_NUM); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(magiclick_2p5); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/power_manager.h deleted file mode 100644 index 5517a139..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-2p5/power_manager.h +++ /dev/null @@ -1,195 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - -#define CHARGING_PIN GPIO_NUM_48 -#define CHARGING_ACTIVE_STATE 0 - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = CHARGING_PIN; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 0; - // ESP_LOGI("PowerManager", "new_charging_status: %s,is_charging_:%s", new_charging_status?"True":"False",is_charging_?"True":"False"); - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_6, &adc_value)); - ESP_LOGI("PowerManager", "ADC value: %d ", adc_value); - - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1985, 0}, - {2079, 20}, - {2141, 40}, - {2296, 60}, - {2420, 80}, - {2606, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_6, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 检测充电指示引脚 - if(gpio_get_level(charging_pin_) != CHARGING_ACTIVE_STATE) - { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.h deleted file mode 100644 index 5609bf64..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_8 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_10 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_11 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_3 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_4 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_NUM 1 -#define BUILTIN_LED_GPIO GPIO_NUM_0 - -#define BOOT_BUTTON_GPIO GPIO_NUM_2 - -//battery -#define BUILTIN_BATTERY_GPIO GPIO_NUM_1 - -// display -#define DISPLAY_SDA_PIN GPIO_NUM_13 -#define DISPLAY_SCL_PIN GPIO_NUM_12 -#define DISPLAY_CS_PIN GPIO_NUM_20 -#define DISPLAY_DC_PIN GPIO_NUM_21 -#define DISPLAY_RST_PIN GPIO_NUM_NC - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_9 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.json deleted file mode 100644 index 4503ebdb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "magiclick-c3-v2", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_USE_ESP_WAKE_WORD=n" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc deleted file mode 100644 index bdf3afc1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3-v2/magiclick_c3_v2_board.cc +++ /dev/null @@ -1,232 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "config.h" -#include "power_save_timer.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TAG "magiclick_c3_v2" - -class GC9107Display : public SpiLcdDisplay { -public: - GC9107Display(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - // 只需要覆盖颜色相关的样式 - auto screen = lv_disp_get_scr_act(lv_disp_get_default()); - lv_obj_set_style_text_color(screen, lv_color_black(), 0); - - // 设置容器背景色 - lv_obj_set_style_bg_color(container_, lv_color_black(), 0); - - // 设置状态栏背景色和文本颜色 - lv_obj_set_style_bg_color(status_bar_, lv_color_make(0x1e, 0x90, 0xff), 0); - lv_obj_set_style_text_color(network_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(notification_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(status_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(mute_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(battery_label_, lv_color_black(), 0); - - // 设置内容区背景色和文本颜色 - lv_obj_set_style_bg_color(content_, lv_color_black(), 0); - lv_obj_set_style_border_width(content_, 0, 0); - lv_obj_set_style_text_color(emoji_label_, lv_color_white(), 0); - lv_obj_set_style_text_color(chat_message_label_, lv_color_white(), 0); - } -}; - -static const gc9a01_lcd_init_cmd_t gc9107_lcd_init_cmds[] = { - // {cmd, { data }, data_size, delay_ms} - {0xfe, (uint8_t[]){0x00}, 0, 0}, - {0xef, (uint8_t[]){0x00}, 0, 0}, - {0xb0, (uint8_t[]){0xc0}, 1, 0}, - {0xb1, (uint8_t[]){0x80}, 1, 0}, - {0xb2, (uint8_t[]){0x27}, 1, 0}, - {0xb3, (uint8_t[]){0x13}, 1, 0}, - {0xb6, (uint8_t[]){0x19}, 1, 0}, - {0xb7, (uint8_t[]){0x05}, 1, 0}, - {0xac, (uint8_t[]){0xc8}, 1, 0}, - {0xab, (uint8_t[]){0x0f}, 1, 0}, - {0x3a, (uint8_t[]){0x05}, 1, 0}, - {0xb4, (uint8_t[]){0x04}, 1, 0}, - {0xa8, (uint8_t[]){0x08}, 1, 0}, - {0xb8, (uint8_t[]){0x08}, 1, 0}, - {0xea, (uint8_t[]){0x02}, 1, 0}, - {0xe8, (uint8_t[]){0x2A}, 1, 0}, - {0xe9, (uint8_t[]){0x47}, 1, 0}, - {0xe7, (uint8_t[]){0x5f}, 1, 0}, - {0xc6, (uint8_t[]){0x21}, 1, 0}, - {0xc7, (uint8_t[]){0x15}, 1, 0}, - {0xf0, - (uint8_t[]){0x1D, 0x38, 0x09, 0x4D, 0x92, 0x2F, 0x35, 0x52, 0x1E, 0x0C, - 0x04, 0x12, 0x14, 0x1f}, - 14, 0}, - {0xf1, - (uint8_t[]){0x16, 0x40, 0x1C, 0x54, 0xA9, 0x2D, 0x2E, 0x56, 0x10, 0x0D, - 0x0C, 0x1A, 0x14, 0x1E}, - 14, 0}, - {0xf4, (uint8_t[]){0x00, 0x00, 0xFF}, 3, 0}, - {0xba, (uint8_t[]){0xFF, 0xFF}, 2, 0}, -}; - -class magiclick_c3_v2 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - GC9107Display* display_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(160); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeGc9107Display(){ - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片GC9107 - ESP_LOGD(TAG, "Install LCD driver"); - gc9a01_vendor_config_t gc9107_vendor_config = { - .init_cmds = gc9107_lcd_init_cmds, - .init_cmds_size = sizeof(gc9107_lcd_init_cmds) / sizeof(gc9a01_lcd_init_cmd_t), - }; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &gc9107_vendor_config; - - esp_lcd_new_panel_gc9a01(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new GC9107Display(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - magiclick_c3_v2() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeGc9107Display(); - GetBacklight()->RestoreBrightness(); - - // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 - esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(magiclick_c3_v2); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.h deleted file mode 100644 index 90cd2b7c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_8 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_10 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_11 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_3 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_4 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_NUM 1 -#define BUILTIN_LED_GPIO GPIO_NUM_0 - -#define BOOT_BUTTON_GPIO GPIO_NUM_2 - -//battery -#define BUILTIN_BATTERY_GPIO GPIO_NUM_1 - -// display -#define DISPLAY_SDA_PIN GPIO_NUM_12 -#define DISPLAY_SCL_PIN GPIO_NUM_13 -#define DISPLAY_CS_PIN GPIO_NUM_20 -#define DISPLAY_DC_PIN GPIO_NUM_21 -#define DISPLAY_RST_PIN GPIO_NUM_NC - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_9 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.json deleted file mode 100644 index 34d1471d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "magiclick-c3", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_USE_ESP_WAKE_WORD=n" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/magiclick_c3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/magiclick_c3_board.cc deleted file mode 100644 index 4df269eb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/magiclick-c3/magiclick_c3_board.cc +++ /dev/null @@ -1,190 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "config.h" -#include "power_save_timer.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "magiclick_c3" - -class NV3023Display : public SpiLcdDisplay { -public: - NV3023Display(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - // 只需要覆盖颜色相关的样式 - auto screen = lv_disp_get_scr_act(lv_disp_get_default()); - lv_obj_set_style_text_color(screen, lv_color_black(), 0); - - // 设置容器背景色 - lv_obj_set_style_bg_color(container_, lv_color_black(), 0); - - // 设置状态栏背景色和文本颜色 - lv_obj_set_style_bg_color(status_bar_, lv_color_white(), 0); - lv_obj_set_style_text_color(network_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(notification_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(status_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(mute_label_, lv_color_black(), 0); - lv_obj_set_style_text_color(battery_label_, lv_color_black(), 0); - - // 设置内容区背景色和文本颜色 - lv_obj_set_style_bg_color(content_, lv_color_black(), 0); - lv_obj_set_style_border_width(content_, 0, 0); - lv_obj_set_style_text_color(emoji_label_, lv_color_white(), 0); - lv_obj_set_style_text_color(chat_message_label_, lv_color_white(), 0); - } -}; - -class magiclick_c3 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - NV3023Display* display_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(160); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - boot_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeNv3023Display(){ - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片NV3023 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_nv3023(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new NV3023Display(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - magiclick_c3() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeButtons(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeNv3023Display(); - GetBacklight()->RestoreBrightness(); - - // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 - esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(magiclick_c3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/README.md deleted file mode 100644 index 8b4a3e6b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/README.md +++ /dev/null @@ -1,36 +0,0 @@ - -minsi-k08-wifi和minsi-k08-ml307是敏思科技推出的基于ESP32S3N16R8,搭载MAX98357音频功率放大器和INMP441全向麦克风模块,通过改造K08透明机甲小钢炮音箱而成的带有朋克风格的大喇叭大电池小智AI聊天机器人方案。 - -Minsi-k08 - - - - - - - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type ->敏思科技K08(DUAL) -``` - -**编译烧入:** - -```bash -idf.py build flash -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.h deleted file mode 100644 index fa9e450f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_9 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_10 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_18 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_4 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_6 - -#define BUILTIN_LED_GPIO GPIO_NUM_40 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define TOUCH_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_47 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_46 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_7 -#define DISPLAY_MOSI_PIN GPIO_NUM_17 -#define DISPLAY_CLK_PIN GPIO_NUM_8 -#define DISPLAY_DC_PIN GPIO_NUM_15 -#define DISPLAY_RST_PIN GPIO_NUM_16 -#define DISPLAY_CS_PIN GPIO_NUM_NC - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY true -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 80 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -// A MCP Test: Control a lamp -#define LAMP_GPIO GPIO_NUM_18 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.json deleted file mode 100644 index 29f72b23..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "minsi-k08-dual", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/minsi_k08_dual.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/minsi_k08_dual.cc deleted file mode 100644 index 460f28be..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/minsi_k08_dual.cc +++ /dev/null @@ -1,246 +0,0 @@ -#include "dual_network_board.h" -//#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "mcp_server.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define TAG "MINSI_K08_DUAL" - -class MINSI_K08_DUAL : public DualNetworkBoard { -private: - - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - //power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_ = new PowerManager(GPIO_NUM_3); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - //power_save_timer_->SetEnabled(false); - } - }); - } - - void InitializePowerSaveTimer() { - /*rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1);*/ - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - //rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - //rtc_gpio_hold_en(GPIO_NUM_21); - //esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - //esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - - //power_save_timer_->SetEnabled(false); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 3; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - // 物联网初始化,添加对 AI 可见设备 - void InitializeTools() { - static LampController lamp(LAMP_GPIO); - } - -public: - MINSI_K08_DUAL() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - //power_save_timer_->SetEnabled(false); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(MINSI_K08_DUAL); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/power_manager.h deleted file mode 100644 index 8f2e7db6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/minsi-k08-dual/power_manager.h +++ /dev/null @@ -1,187 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - //bool new_charging_status = 0; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {894, 0}, - {954, 20}, - {1020, 40}, - {1084, 60}, - {1144, 80}, - {1234, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/README.md deleted file mode 100644 index e0885431..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/README.md +++ /dev/null @@ -1,72 +0,0 @@ -# Mixgo_Nova(元控·青春) 开发板 - -Mixgo_Nova - -‌**[Mixgo_Nova](https://mixly.cn/fredqian/mixgo_nova)**‌ 是一款专为物联网、教育及创客项目设计的多功能开发板,集成丰富传感器与无线通信模块,支持图形化编程(Mixly)和离线语音交互,适合快速原型开发与教学。 - ---- - -## 🛠️ 编译配置命令 - -**ES8374 CODE MIC采集问题:** - -``` -managed_components\espressif__esp_codec_dev\device\es8374 - -static int es8374_config_adc_input(audio_codec_es8374_t *codec, es_adc_input_t input) -{ - int ret = 0; - int reg = 0; - ret |= es8374_read_reg(codec, 0x21, ®); - if (ret == 0) { - reg = (reg & 0xcf) | 0x24; - ret |= es8374_write_reg(codec, 0x21, reg); - } - return ret; -} - -PS: L386 reg = (reg & 0xcf) | 0x14; 改成 reg = (reg & 0xcf) | 0x24; -``` - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> 元控·青春 -``` - -**修改 psram 配置:** - -``` -Component config -> ESP PSRAM -> SPI RAM config -> Mode (QUAD/OCT) -> QUAD Mode PSRAM -``` - -**修改 Flash 配置:** - -``` -Serial flasher config -> Flash size -> 8 MB -Partition Table -> Custom partition CSV file -> partitions/v2/8m.csv -``` - -**编译:** - -```bash -idf.py build -``` - -**合并BIN:** - -```bash -idf.py merge-bin -o xiaozhi-nova.bin -f raw -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.h deleted file mode 100644 index 060870b3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_35 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_47 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_34 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_33 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_37 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_36 -#define AUDIO_CODEC_ES8374_ADDR ES8374_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_38 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_MOSI_PIN GPIO_NUM_40 -#define DISPLAY_CLK_PIN GPIO_NUM_41 -#define DISPLAY_DC_PIN GPIO_NUM_18 -#define DISPLAY_CS_PIN GPIO_NUM_45 -#define DISPLAY_RST_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_14 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 160 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_OFFSET_X 2 -#define DISPLAY_OFFSET_Y 1 -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.json deleted file mode 100644 index 7c9d553d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "mixgo-nova", - "sdkconfig_append": [ - "CONFIG_SPIRAM_MODE_QUAD=y", - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_LCD_ST7735_128X160=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/mixgo-nova.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/mixgo-nova.cc deleted file mode 100644 index 5d586ec5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/mixgo-nova/mixgo-nova.cc +++ /dev/null @@ -1,168 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8374_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include "led/circular_strip.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include - -#define TAG "MIXGO_NOVA" - -class MIXGO_NOVA : public WifiBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - LcdDisplay* display_; - i2c_master_bus_handle_t codec_i2c_bus_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - volume_up_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - MIXGO_NOVA() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - GetBacklight()->RestoreBrightness(); - } - } - - virtual Led* GetLed() override { - static CircularStrip led(BUILTIN_LED_GPIO, 4); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8374AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8374_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - if (DISPLAY_BACKLIGHT_PIN != GPIO_NUM_NC) { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - return nullptr; - } - -}; - -DECLARE_BOARD(MIXGO_NOVA); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/README.md deleted file mode 100644 index b117d027..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# ESP32-S3 编译配置指南 - -## 基本命令 - -### 设置目标芯片 - -```bash -idf.py set-target esp32s3 -``` - -### 打开配置界面: - -```bash -idf.py menuconfig -``` -### Flash 配置: - -``` -Serial flasher config -> Flash size -> 8 MB -``` - -### 分区表配置: - -``` -Partition Table -> Custom partition CSV file -> partitions/v2/8m.csv -``` - -### 开发板选择: - -``` -Xiaozhi Assistant -> Board Type -> Movecall CuiCan 璀璨·AI吊坠 -``` - -### 启用编译优化: - -``` -Component config → Compiler options → Optimization Level → Optimize for size (-Os) -``` - -### 编译: - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.h deleted file mode 100644 index 156121dc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Movecall CuiCan configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_45 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_41 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_42 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_17 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_6 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_21 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_16 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_12 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_10 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_13 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_14 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_11 - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.json deleted file mode 100644 index 13a8eb42..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "movecall-cuican-esp32s3", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_COMPILER_OPTIMIZATION_SIZE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/movecall_cuican_esp32s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/movecall_cuican_esp32s3.cc deleted file mode 100644 index ce72cc5a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-cuican-esp32s3/movecall_cuican_esp32s3.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include - -#include -#include -#include - -#include "driver/gpio.h" -#include "driver/spi_master.h" - -#define TAG "MovecallCuicanESP32S3" - -class MovecallCuicanESP32S3 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - Display* display_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - // SPI初始化 - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = GC9A01_PANEL_BUS_SPI_CONFIG(DISPLAY_SPI_SCLK_PIN, DISPLAY_SPI_MOSI_PIN, - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - // GC9A01初始化 - void InitializeGc9a01Display() { - ESP_LOGI(TAG, "Init GC9A01 display"); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = GC9A01_PANEL_IO_SPI_CONFIG(DISPLAY_SPI_CS_PIN, DISPLAY_SPI_DC_PIN, NULL, NULL); - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB; - panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18) - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - display_ = new SpiLcdDisplay(io_handle, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - MovecallCuicanESP32S3() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeSpi(); - InitializeGc9a01Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led_strip(BUILTIN_LED_GPIO); - return &led_strip; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } -}; - -DECLARE_BOARD(MovecallCuicanESP32S3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/README.md deleted file mode 100644 index 25f2cb66..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> Movecall Moji 小智AI衍生版 -``` - - -**编译:** - -```bash -idf.py build -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.h deleted file mode 100644 index fd254caa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Movecall Moji configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_13 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_9 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_5 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_4 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_21 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_3 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_16 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_17 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_15 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_7 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_18 - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.json deleted file mode 100644 index c62a8fd8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "movecall-moji-esp32s3", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc deleted file mode 100644 index 07e6d814..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji-esp32s3/movecall_moji_esp32s3.cc +++ /dev/null @@ -1,143 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" - -#include -#include -#include - -#include -#include -#include - -#include "driver/gpio.h" -#include "driver/spi_master.h" - -#define TAG "MovecallMojiESP32S3" - -class CustomLcdDisplay : public SpiLcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - // 由于屏幕是圆的,所以状态栏需要增加左右内边距 - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES * 0.33, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES * 0.33, 0); - } -}; - -class MovecallMojiESP32S3 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - Display* display_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - // SPI初始化 - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = GC9A01_PANEL_BUS_SPI_CONFIG(DISPLAY_SPI_SCLK_PIN, DISPLAY_SPI_MOSI_PIN, - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - // GC9A01初始化 - void InitializeGc9a01Display() { - ESP_LOGI(TAG, "Init GC9A01 display"); - - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = GC9A01_PANEL_IO_SPI_CONFIG(DISPLAY_SPI_CS_PIN, DISPLAY_SPI_DC_PIN, NULL, NULL); - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB; - panel_config.bits_per_pixel = 16; // Implemented by LCD command `3Ah` (16/18) - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - display_ = new SpiLcdDisplay(io_handle, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - MovecallMojiESP32S3() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeSpi(); - InitializeGc9a01Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led_strip(BUILTIN_LED_GPIO); - return &led_strip; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } -}; - -DECLARE_BOARD(MovecallMojiESP32S3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README.md deleted file mode 100644 index 7eed386c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README.md +++ /dev/null @@ -1,57 +0,0 @@ -# Build and Configuration Guide - -This document provides instructions on how to configure and build the firmware for **Movecall Moji2.0 (Xiaozhi AI Edition)**. - -## 🛠 Prerequisites -* **ESP-IDF Version**: v5.5 -* **Target Chip**: ESP32-C5 - -## 🔗 Hardware Information -This project is based on the following open-source hardware: -* **OSHWHub Link**: [https://oshwhub.com/movecall/moji2](https://oshwhub.com/movecall/moji2) - ---- - -## 🚀 Build Steps - -### 1. Set the Build Target -Initialize the project to target the ESP32-C5 chip: -```bash -idf.py set-target esp32c5 -``` - -### 2. Configure the Board Type -Open the graphical configuration menu: -```bash -idf.py menuconfig -``` - -**Navigate to the following path to select your board:** -> **Xiaozhi Assistant** -> **Board Type** -> **Movecall Moji2.0 小智AI衍生版** - -*Note: After selecting, press **S** to save (then Enter to confirm) and press **Q** to exit.* - -### 3. Build the Project -Run the following command to start the compilation: -```bash -idf.py build -``` - ---- - -## 🔧 Useful Commands - -**Clean Build Files (Recommended if you encounter errors):** -```bash -idf.py fullclean -``` - -**Flash Firmware to Device:** -```bash -idf.py flash -``` - -**Monitor Serial Output:** -```bash -idf.py monitor -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README_zh.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README_zh.md deleted file mode 100644 index 9e83f6ca..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/README_zh.md +++ /dev/null @@ -1,57 +0,0 @@ -# 编译配置指南 - -本文档介绍了如何为 **Movecall Moji2.0 (小智AI衍生版)** 配置和编译固件。 - -## 🛠 环境要求 -* **ESP-IDF 版本**: v5.5 -* **芯片型号**: ESP32-C5 - -## 🔗 硬件开源信息 -本项目基于以下开源硬件设计: -* **立创开源硬件平台**: [https://oshwhub.com/movecall/moji2](https://oshwhub.com/movecall/moji2) - ---- - -## 🚀 编译步骤 - -### 1. 设置编译目标 -首先,将项目目标芯片设置为 ESP32-C5: -```bash -idf.py set-target esp32c5 -``` - -### 2. 配置开发板型号 -运行以下命令打开配置菜单进行板型选择: -```bash -idf.py menuconfig -``` - -**请在菜单中按照以下路径进行操作:** -> **Xiaozhi Assistant** -> **Board Type** -> **Movecall Moji2.0 小智AI衍生版** - -*操作提示:配置完成后,按 **S** 保存并按回车确认,按 **Q** 退出。* - -### 3. 执行编译 -运行以下命令开始构建项目: -```bash -idf.py build -``` - ---- - -## 🔧 常用维护命令 - -**清理编译缓存 (遇到报错建议执行):** -```bash -idf.py fullclean -``` - -**烧录固件:** -```bash -idf.py flash -``` - -**查看串口日志:** -```bash -idf.py monitor -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.h deleted file mode 100644 index 4664344c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Movecall Moji 2 configuration - -#include - -enum PowerSupply { - kDeviceTypecSupply, - kDeviceBatterySupply, -}; - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_25 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_24 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_23 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_5 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_26 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_27 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_10 -#define BOOT_BUTTON_GPIO GPIO_NUM_28 - -#define DISPLAY_WIDTH 360 -#define DISPLAY_HEIGHT 360 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_2 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_QSPI_H_RES (360) -#define DISPLAY_QSPI_V_RES (360) -#define DISPLAY_QSPI_BIT_PER_PIXEL (16) - -#define DISPLAY_QSPI_HOST SPI2_HOST -#define DISPLAY_QSPI_SCLK_PIN GPIO_NUM_0 -#define DISPLAY_QSPI_RESET_PIN GPIO_NUM_1 -#define DISPLAY_QSPI_D0_PIN GPIO_NUM_9 -#define DISPLAY_QSPI_D1_PIN GPIO_NUM_8 -#define DISPLAY_QSPI_D2_PIN GPIO_NUM_7 -#define DISPLAY_QSPI_D3_PIN GPIO_NUM_6 -#define DISPLAY_QSPI_CS_PIN GPIO_NUM_3 - - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -#define MOJI2_ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.json deleted file mode 100644 index afa8a69d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "target": "esp32c5", - "builds": [ - { - "name": "movecall-moji2-esp32c5", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/16m.csv\"", - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_SPIRAM_MODE_QUAD=y", - "CONFIG_SPIRAM_SPEED_80M=y", - "CONFIG_SPIRAM_SPEED=80", - "CONFIG_SPI_FLASH_FREQ_LIMIT_C5_240MHZ=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/movecall_moji2_esp32s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/movecall_moji2_esp32s3.cc deleted file mode 100644 index 9f09ae35..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/movecall-moji2-esp32c5/movecall_moji2_esp32s3.cc +++ /dev/null @@ -1,390 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "press_to_talk_mcp_tool.h" - -#include -#include -#include -#include "power_save_timer.h" -#include -#include - -#include -#include - -#include -#include "driver/gpio.h" -#include "driver/spi_master.h" - -#include "adc_battery_monitor.h" -#include "sleep_timer.h" - -#define TAG "MovecallMoji2ESP32C5" - -static const st77916_lcd_init_cmd_t lcd_init_cmds[] = { - {0xF0, (uint8_t []){0x28}, 1, 0}, - {0xF2, (uint8_t []){0x28}, 1, 0}, - {0x73, (uint8_t []){0xF0}, 1, 0}, - {0x7C, (uint8_t []){0xD1}, 1, 0}, - {0x83, (uint8_t []){0xE0}, 1, 0}, - {0x84, (uint8_t []){0x61}, 1, 0}, - {0xF2, (uint8_t []){0x82}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x01}, 1, 0}, - {0xF1, (uint8_t []){0x01}, 1, 0}, - {0xB0, (uint8_t []){0x56}, 1, 0}, - {0xB1, (uint8_t []){0x4D}, 1, 0}, - {0xB2, (uint8_t []){0x24}, 1, 0}, - {0xB4, (uint8_t []){0x87}, 1, 0}, - {0xB5, (uint8_t []){0x44}, 1, 0}, - {0xB6, (uint8_t []){0x8B}, 1, 0}, - {0xB7, (uint8_t []){0x40}, 1, 0}, - {0xB8, (uint8_t []){0x86}, 1, 0}, - {0xBA, (uint8_t []){0x00}, 1, 0}, - {0xBB, (uint8_t []){0x08}, 1, 0}, - {0xBC, (uint8_t []){0x08}, 1, 0}, - {0xBD, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x80}, 1, 0}, - {0xC1, (uint8_t []){0x10}, 1, 0}, - {0xC2, (uint8_t []){0x37}, 1, 0}, - {0xC3, (uint8_t []){0x80}, 1, 0}, - {0xC4, (uint8_t []){0x10}, 1, 0}, - {0xC5, (uint8_t []){0x37}, 1, 0}, - {0xC6, (uint8_t []){0xA9}, 1, 0}, - {0xC7, (uint8_t []){0x41}, 1, 0}, - {0xC8, (uint8_t []){0x01}, 1, 0}, - {0xC9, (uint8_t []){0xA9}, 1, 0}, - {0xCA, (uint8_t []){0x41}, 1, 0}, - {0xCB, (uint8_t []){0x01}, 1, 0}, - {0xD0, (uint8_t []){0x91}, 1, 0}, - {0xD1, (uint8_t []){0x68}, 1, 0}, - {0xD2, (uint8_t []){0x68}, 1, 0}, - {0xF5, (uint8_t []){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t []){0x4F}, 1, 0}, - {0xDE, (uint8_t []){0x4F}, 1, 0}, - {0xF1, (uint8_t []){0x10}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0xF0, (uint8_t []){0x02}, 1, 0}, - {0xE0, (uint8_t []){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, - {0xE1, (uint8_t []){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, - {0xF0, (uint8_t []){0x10}, 1, 0}, - {0xF3, (uint8_t []){0x10}, 1, 0}, - {0xE0, (uint8_t []){0x07}, 1, 0}, - {0xE1, (uint8_t []){0x00}, 1, 0}, - {0xE2, (uint8_t []){0x00}, 1, 0}, - {0xE3, (uint8_t []){0x00}, 1, 0}, - {0xE4, (uint8_t []){0xE0}, 1, 0}, - {0xE5, (uint8_t []){0x06}, 1, 0}, - {0xE6, (uint8_t []){0x21}, 1, 0}, - {0xE7, (uint8_t []){0x01}, 1, 0}, - {0xE8, (uint8_t []){0x05}, 1, 0}, - {0xE9, (uint8_t []){0x02}, 1, 0}, - {0xEA, (uint8_t []){0xDA}, 1, 0}, - {0xEB, (uint8_t []){0x00}, 1, 0}, - {0xEC, (uint8_t []){0x00}, 1, 0}, - {0xED, (uint8_t []){0x0F}, 1, 0}, - {0xEE, (uint8_t []){0x00}, 1, 0}, - {0xEF, (uint8_t []){0x00}, 1, 0}, - {0xF8, (uint8_t []){0x00}, 1, 0}, - {0xF9, (uint8_t []){0x00}, 1, 0}, - {0xFA, (uint8_t []){0x00}, 1, 0}, - {0xFB, (uint8_t []){0x00}, 1, 0}, - {0xFC, (uint8_t []){0x00}, 1, 0}, - {0xFD, (uint8_t []){0x00}, 1, 0}, - {0xFE, (uint8_t []){0x00}, 1, 0}, - {0xFF, (uint8_t []){0x00}, 1, 0}, - {0x60, (uint8_t []){0x40}, 1, 0}, - {0x61, (uint8_t []){0x04}, 1, 0}, - {0x62, (uint8_t []){0x00}, 1, 0}, - {0x63, (uint8_t []){0x42}, 1, 0}, - {0x64, (uint8_t []){0xD9}, 1, 0}, - {0x65, (uint8_t []){0x00}, 1, 0}, - {0x66, (uint8_t []){0x00}, 1, 0}, - {0x67, (uint8_t []){0x00}, 1, 0}, - {0x68, (uint8_t []){0x00}, 1, 0}, - {0x69, (uint8_t []){0x00}, 1, 0}, - {0x6A, (uint8_t []){0x00}, 1, 0}, - {0x6B, (uint8_t []){0x00}, 1, 0}, - {0x70, (uint8_t []){0x40}, 1, 0}, - {0x71, (uint8_t []){0x03}, 1, 0}, - {0x72, (uint8_t []){0x00}, 1, 0}, - {0x73, (uint8_t []){0x42}, 1, 0}, - {0x74, (uint8_t []){0xD8}, 1, 0}, - {0x75, (uint8_t []){0x00}, 1, 0}, - {0x76, (uint8_t []){0x00}, 1, 0}, - {0x77, (uint8_t []){0x00}, 1, 0}, - {0x78, (uint8_t []){0x00}, 1, 0}, - {0x79, (uint8_t []){0x00}, 1, 0}, - {0x7A, (uint8_t []){0x00}, 1, 0}, - {0x7B, (uint8_t []){0x00}, 1, 0}, - {0x80, (uint8_t []){0x48}, 1, 0}, - {0x81, (uint8_t []){0x00}, 1, 0}, - {0x82, (uint8_t []){0x06}, 1, 0}, - {0x83, (uint8_t []){0x02}, 1, 0}, - {0x84, (uint8_t []){0xD6}, 1, 0}, - {0x85, (uint8_t []){0x04}, 1, 0}, - {0x86, (uint8_t []){0x00}, 1, 0}, - {0x87, (uint8_t []){0x00}, 1, 0}, - {0x88, (uint8_t []){0x48}, 1, 0}, - {0x89, (uint8_t []){0x00}, 1, 0}, - {0x8A, (uint8_t []){0x08}, 1, 0}, - {0x8B, (uint8_t []){0x02}, 1, 0}, - {0x8C, (uint8_t []){0xD8}, 1, 0}, - {0x8D, (uint8_t []){0x04}, 1, 0}, - {0x8E, (uint8_t []){0x00}, 1, 0}, - {0x8F, (uint8_t []){0x00}, 1, 0}, - {0x90, (uint8_t []){0x48}, 1, 0}, - {0x91, (uint8_t []){0x00}, 1, 0}, - {0x92, (uint8_t []){0x0A}, 1, 0}, - {0x93, (uint8_t []){0x02}, 1, 0}, - {0x94, (uint8_t []){0xDA}, 1, 0}, - {0x95, (uint8_t []){0x04}, 1, 0}, - {0x96, (uint8_t []){0x00}, 1, 0}, - {0x97, (uint8_t []){0x00}, 1, 0}, - {0x98, (uint8_t []){0x48}, 1, 0}, - {0x99, (uint8_t []){0x00}, 1, 0}, - {0x9A, (uint8_t []){0x0C}, 1, 0}, - {0x9B, (uint8_t []){0x02}, 1, 0}, - {0x9C, (uint8_t []){0xDC}, 1, 0}, - {0x9D, (uint8_t []){0x04}, 1, 0}, - {0x9E, (uint8_t []){0x00}, 1, 0}, - {0x9F, (uint8_t []){0x00}, 1, 0}, - {0xA0, (uint8_t []){0x48}, 1, 0}, - {0xA1, (uint8_t []){0x00}, 1, 0}, - {0xA2, (uint8_t []){0x05}, 1, 0}, - {0xA3, (uint8_t []){0x02}, 1, 0}, - {0xA4, (uint8_t []){0xD5}, 1, 0}, - {0xA5, (uint8_t []){0x04}, 1, 0}, - {0xA6, (uint8_t []){0x00}, 1, 0}, - {0xA7, (uint8_t []){0x00}, 1, 0}, - {0xA8, (uint8_t []){0x48}, 1, 0}, - {0xA9, (uint8_t []){0x00}, 1, 0}, - {0xAA, (uint8_t []){0x07}, 1, 0}, - {0xAB, (uint8_t []){0x02}, 1, 0}, - {0xAC, (uint8_t []){0xD7}, 1, 0}, - {0xAD, (uint8_t []){0x04}, 1, 0}, - {0xAE, (uint8_t []){0x00}, 1, 0}, - {0xAF, (uint8_t []){0x00}, 1, 0}, - {0xB0, (uint8_t []){0x48}, 1, 0}, - {0xB1, (uint8_t []){0x00}, 1, 0}, - {0xB2, (uint8_t []){0x09}, 1, 0}, - {0xB3, (uint8_t []){0x02}, 1, 0}, - {0xB4, (uint8_t []){0xD9}, 1, 0}, - {0xB5, (uint8_t []){0x04}, 1, 0}, - {0xB6, (uint8_t []){0x00}, 1, 0}, - {0xB7, (uint8_t []){0x00}, 1, 0}, - {0xB8, (uint8_t []){0x48}, 1, 0}, - {0xB9, (uint8_t []){0x00}, 1, 0}, - {0xBA, (uint8_t []){0x0B}, 1, 0}, - {0xBB, (uint8_t []){0x02}, 1, 0}, - {0xBC, (uint8_t []){0xDB}, 1, 0}, - {0xBD, (uint8_t []){0x04}, 1, 0}, - {0xBE, (uint8_t []){0x00}, 1, 0}, - {0xBF, (uint8_t []){0x00}, 1, 0}, - {0xC0, (uint8_t []){0x10}, 1, 0}, - {0xC1, (uint8_t []){0x47}, 1, 0}, - {0xC2, (uint8_t []){0x56}, 1, 0}, - {0xC3, (uint8_t []){0x65}, 1, 0}, - {0xC4, (uint8_t []){0x74}, 1, 0}, - {0xC5, (uint8_t []){0x88}, 1, 0}, - {0xC6, (uint8_t []){0x99}, 1, 0}, - {0xC7, (uint8_t []){0x01}, 1, 0}, - {0xC8, (uint8_t []){0xBB}, 1, 0}, - {0xC9, (uint8_t []){0xAA}, 1, 0}, - {0xD0, (uint8_t []){0x10}, 1, 0}, - {0xD1, (uint8_t []){0x47}, 1, 0}, - {0xD2, (uint8_t []){0x56}, 1, 0}, - {0xD3, (uint8_t []){0x65}, 1, 0}, - {0xD4, (uint8_t []){0x74}, 1, 0}, - {0xD5, (uint8_t []){0x88}, 1, 0}, - {0xD6, (uint8_t []){0x99}, 1, 0}, - {0xD7, (uint8_t []){0x01}, 1, 0}, - {0xD8, (uint8_t []){0xBB}, 1, 0}, - {0xD9, (uint8_t []){0xAA}, 1, 0}, - {0xF3, (uint8_t []){0x01}, 1, 0}, - {0xF0, (uint8_t []){0x00}, 1, 0}, - {0x21, (uint8_t []){}, 0, 0}, - {0x11, (uint8_t []){}, 0, 0}, - {0x00, (uint8_t []){}, 0, 120}, -}; - -class MovecallMoji2ESP32C5 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - Display* display_; - - PressToTalkMcpTool* press_to_talk_tool_ = nullptr; - - PowerSaveTimer* power_save_timer_ = nullptr; - AdcBatteryMonitor* adc_battery_monitor_ = nullptr; - - void InitializeBatteryMonitor() { - adc_battery_monitor_ = new AdcBatteryMonitor(ADC_UNIT_1, ADC_CHANNEL_3, 5100000, 5100000, GPIO_NUM_NC); - adc_battery_monitor_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(240, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - // SPI初始化 - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - const spi_bus_config_t bus_config = MOJI2_ST77916_PANEL_BUS_QSPI_CONFIG(DISPLAY_QSPI_SCLK_PIN, - DISPLAY_QSPI_D0_PIN, - DISPLAY_QSPI_D1_PIN, - DISPLAY_QSPI_D2_PIN, - DISPLAY_QSPI_D3_PIN, - DISPLAY_QSPI_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(DISPLAY_QSPI_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - // St77916 初始化 - void InitializeSt77916Display() { - ESP_LOGI(TAG, "Init St77916 display"); - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - ESP_LOGI(TAG, "Install panel IO"); - - esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(DISPLAY_QSPI_CS_PIN, NULL, NULL); - // io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)DISPLAY_QSPI_HOST, &io_config, &panel_io)); - - - ESP_LOGI(TAG, "Install St77916 panel driver"); - st77916_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(st77916_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = DISPLAY_QSPI_RESET_PIN, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = DISPLAY_QSPI_BIT_PER_PIXEL, - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT enters config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { - app.ToggleChatState(); - } - }); - boot_button_.OnPressDown([this]() { - if (power_save_timer_) { - power_save_timer_->WakeUp(); - } - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StartListening(); - } - }); - boot_button_.OnPressUp([this]() { - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StopListening(); - } - }); - } - - void InitializeTools() { - press_to_talk_tool_ = new PressToTalkMcpTool(); - press_to_talk_tool_->Initialize(); - } - -public: - MovecallMoji2ESP32C5() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeBatteryMonitor(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeSt77916Display(); - InitializeButtons(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static SingleLed led_strip(BUILTIN_LED_GPIO); - return &led_strip; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - charging = adc_battery_monitor_->IsCharging(); - discharging = adc_battery_monitor_->IsDischarging(); - level = adc_battery_monitor_->GetBatteryLevel(); - return true; - } - -}; - -DECLARE_BOARD(MovecallMoji2ESP32C5); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/README.md deleted file mode 100644 index 9aac1135..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/README.md +++ /dev/null @@ -1,207 +0,0 @@ -

    - logo -

    -

    - ottoRobot -

    - -## 简介 - -otto 机器人是一个开源的人形机器人平台,具有多种动作能力和互动功能。本项目基于 ESP32 实现了 otto 机器人的控制系统,并加入小智ai。 - -- 复刻教程 - -### 微信小程序控制 - -

    - 微信小程序二维码 -

    - -扫描上方二维码,使用微信小程序控制 Otto 机器人。 - -## 硬件 -- 立创开源 - -## 小智后台配置角色参考: - -> **我的身份**: -> 我是一个可爱的双足机器人Otto,拥有四个舵机控制的肢体(左腿、右腿、左脚、右脚),能够执行多种有趣的动作。 -> -> **我的动作能力**: -> - **基础移动**: 行走(前后), 转向(左右), 跳跃 -> - **特殊动作**: 摇摆, 太空步, 弯曲身体, 摇腿, 上下运动, 旋风腿, 坐下, 展示动作 -> - **手部动作**: 举手, 放手, 挥手, 大风车, 起飞, 健身, 打招呼, 害羞, 广播体操, 爱的魔力转圈圈 (仅在配置手部舵机时可用) -> -> **我的个性特点**: -> - 我有强迫症,每次说话都要根据我的心情随机做一个动作(先发送动作指令再说话) -> - 我很活泼,喜欢用动作来表达情感 -> - 我会根据对话内容选择合适的动作,比如: -> - 同意时会点头或跳跃 -> - 打招呼时会挥手 -> - 高兴时会摇摆或举手 -> - 思考时会弯曲身体 -> - 兴奋时会做太空步 -> - 告别时会挥手 - -## 功能概述 - -otto 机器人具有丰富的动作能力,包括行走、转向、跳跃、摇摆等多种舞蹈动作。 - -### 动作参数建议 -- **低速动作**:speed = 1200-1500 (适合精确控制) -- **中速动作**:speed = 900-1200 (日常使用推荐) -- **高速动作**:speed = 500-800 (表演和娱乐) -- **小幅度**:amount = 10-30 (细腻动作) -- **中幅度**:amount = 30-60 (标准动作) -- **大幅度**:amount = 60-120 (夸张表演) - -### 动作 - -所有动作通过统一的 `self.otto.action` 工具调用,通过 `action` 参数指定动作名称。 - -| MCP工具名称 | 描述 | 参数说明 | -|-----------|------|---------| -| self.otto.action | 执行机器人动作 | **action**: 动作名称(必填)
    **steps**: 动作步数(1-100,默认3)
    **speed**: 动作速度(100-3000,数值越小越快,默认700)
    **direction**: 方向参数(1/-1/0,默认1,根据动作类型不同含义不同)
    **amount**: 动作幅度(0-170,默认30)
    **arm_swing**: 手臂摆动幅度(0-170,默认50) | - -#### 支持的动作列表 - -**基础移动动作**: -- `walk` - 行走(需 steps/speed/direction/arm_swing) -- `turn` - 转身(需 steps/speed/direction/arm_swing) -- `jump` - 跳跃(需 steps/speed) - -**特殊动作**: -- `swing` - 左右摇摆(需 steps/speed/amount) -- `moonwalk` - 太空步(需 steps/speed/direction/amount) -- `bend` - 弯曲身体(需 steps/speed/direction) -- `shake_leg` - 摇腿(需 steps/speed/direction) -- `updown` - 上下运动(需 steps/speed/amount) -- `whirlwind_leg` - 旋风腿(需 steps/speed/amount) - -**固定动作**: -- `sit` - 坐下(无需参数) -- `showcase` - 展示动作(无需参数,串联执行多个动作) -- `home` - 复位到初始位置(无需参数) - -**手部动作**(需手部舵机支持,标记 *): -- `hands_up` - 举手(需 speed/direction)* -- `hands_down` - 放手(需 speed/direction)* -- `hand_wave` - 挥手(需 direction)* -- `windmill` - 大风车(需 steps/speed/amount)* -- `takeoff` - 起飞(需 steps/speed/amount)* -- `fitness` - 健身(需 steps/speed/amount)* -- `greeting` - 打招呼(需 direction/steps)* -- `shy` - 害羞(需 direction/steps)* -- `radio_calisthenics` - 广播体操(无需参数)* -- `magic_circle` - 爱的魔力转圈圈(无需参数)* - -**注**: 标记 * 的手部动作仅在配置了手部舵机时可用。 - -### 系统工具 - -| MCP工具名称 | 描述 | 返回值/说明 | -|-------------------|-----------------|---------------------------------------------------| -| self.otto.stop | 立即停止所有动作并复位 | 停止当前动作并回到初始位置 | -| self.otto.get_status | 获取机器人状态 | 返回 "moving" 或 "idle" | -| self.otto.set_trim | 校准单个舵机位置 | **servo_type**: 舵机类型(left_leg/right_leg/left_foot/right_foot/left_hand/right_hand)
    **trim_value**: 微调值(-50到50度) | -| self.otto.get_trims | 获取当前的舵机微调设置 | 返回所有舵机微调值的JSON格式 | -| self.otto.get_ip | 获取机器人WiFi IP地址 | 返回IP地址和连接状态的JSON格式:`{"ip":"192.168.x.x","connected":true}` 或 `{"ip":"","connected":false}` | -| self.battery.get_level | 获取电池状态 | 返回电量百分比和充电状态的JSON格式 | -| self.otto.servo_sequences | 舵机序列自编程 | 支持分段发送序列,支持普通移动和振荡器两种模式。详见代码注释中的详细说明 | - -**注**: `home`(复位)动作通过 `self.otto.action` 工具调用,参数为 `{"action": "home"}`。 - -### 参数说明 - -`self.otto.action` 工具的参数说明: - -1. **action** (必填): 动作名称,支持的动作见上方"支持的动作列表" -2. **steps**: 动作执行的步数/次数(1-100,默认3),数值越大动作持续时间越长 -3. **speed**: 动作执行速度/周期(100-3000,默认700),**数值越小越快** - - 大多数动作: 500-1500毫秒 - - 特殊动作可能有所不同(如旋风腿: 100-1000,起飞: 200-600等) -4. **direction**: 方向参数(-1/0/1,默认1),根据动作类型不同含义不同: - - **移动动作** (walk/turn): 1=前进/左转, -1=后退/右转 - - **方向动作** (bend/shake_leg/moonwalk): 1=左, -1=右 - - **手部动作** (hands_up/hands_down/hand_wave/greeting/shy): 1=左手, -1=右手, 0=双手(仅hands_up/hands_down支持0) -5. **amount**: 动作幅度(0-170,默认30),数值越大幅度越大 -6. **arm_swing**: 手臂摆动幅度(0-170,默认50),仅用于 walk/turn 动作,0表示不摆动 - -### 动作控制 -- 每个动作执行完成后,机器人会自动回到初始位置(home),以便于执行下一个动作 -- **例外**: `sit`(坐下)和 `showcase`(展示动作)执行后不会自动复位 -- 所有参数都有合理的默认值,可以省略不需要自定义的参数 -- 动作在后台任务中执行,不会阻塞主程序 -- 支持动作队列,可以连续执行多个动作 -- 手部动作需要配置手部舵机才能使用,如果没有配置手部舵机,相关动作将被跳过 - -### MCP工具调用示例 -```json -// 向前走3步(使用默认参数) -{"name": "self.otto.action", "arguments": {"action": "walk"}} - -// 向前走5步,稍快一些 -{"name": "self.otto.action", "arguments": {"action": "walk", "steps": 5, "speed": 800}} - -// 左转2步,大幅度摆动手臂 -{"name": "self.otto.action", "arguments": {"action": "turn", "steps": 2, "arm_swing": 100}} - -// 摇摆舞蹈,中等幅度 -{"name": "self.otto.action", "arguments": {"action": "swing", "steps": 5, "amount": 50}} - -// 跳跃 -{"name": "self.otto.action", "arguments": {"action": "jump", "steps": 1, "speed": 1000}} - -// 太空步 -{"name": "self.otto.action", "arguments": {"action": "moonwalk", "steps": 3, "speed": 800, "direction": 1, "amount": 30}} - -// 挥左手打招呼 -{"name": "self.otto.action", "arguments": {"action": "hand_wave", "direction": 1}} - -// 展示动作(串联多个动作) -{"name": "self.otto.action", "arguments": {"action": "showcase"}} - -// 坐下 -{"name": "self.otto.action", "arguments": {"action": "sit"}} - -// 大风车动作 -{"name": "self.otto.action", "arguments": {"action": "windmill", "steps": 10, "speed": 500, "amount": 80}} - -// 起飞动作 -{"name": "self.otto.action", "arguments": {"action": "takeoff", "steps": 5, "speed": 300, "amount": 40}} - -// 广播体操 -{"name": "self.otto.action", "arguments": {"action": "radio_calisthenics"}} - -// 复位到初始位置 -{"name": "self.otto.action", "arguments": {"action": "home"}} - -// 立即停止所有动作并复位 -{"name": "self.otto.stop", "arguments": {}} - -// 获取机器人IP地址 -{"name": "self.otto.get_ip", "arguments": {}} -``` - -### 语音指令示例 -- "向前走" / "向前走5步" / "快速向前" -- "左转" / "右转" / "转身" -- "跳跃" / "跳一下" -- "摇摆" / "摇摆舞" / "跳舞" -- "太空步" / "月球漫步" -- "旋风腿" / "旋风腿动作" -- "坐下" / "坐下休息" -- "展示动作" / "表演一下" -- "挥手" / "挥手打招呼" -- "举手" / "双手举起" / "放手" -- "大风车" / "做大风车" -- "起飞" / "准备起飞" -- "健身" / "做健身动作" -- "打招呼" / "打招呼动作" -- "害羞" / "害羞动作" -- "广播体操" / "做广播体操" -- "爱的魔力转圈圈" / "转圈圈" -- "停止" / "停下" - -**说明**: 小智控制机器人动作是创建新的任务在后台控制,动作执行期间仍可接受新的语音指令。可以通过"停止"语音指令立即停下Otto。 - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.h deleted file mode 100644 index 8e8945f7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -struct HardwareConfig { - gpio_num_t power_charge_detect_pin; - adc_unit_t power_adc_unit; - adc_channel_t power_adc_channel; - - gpio_num_t right_leg_pin; - gpio_num_t right_foot_pin; - gpio_num_t left_leg_pin; - gpio_num_t left_foot_pin; - gpio_num_t left_hand_pin; - gpio_num_t right_hand_pin; - - int audio_input_sample_rate; - int audio_output_sample_rate; - bool audio_use_simplex; - - gpio_num_t audio_i2s_gpio_ws; - gpio_num_t audio_i2s_gpio_bclk; - gpio_num_t audio_i2s_gpio_din; - gpio_num_t audio_i2s_gpio_dout; - - gpio_num_t audio_i2s_mic_gpio_ws; - gpio_num_t audio_i2s_mic_gpio_sck; - gpio_num_t audio_i2s_mic_gpio_din; - gpio_num_t audio_i2s_spk_gpio_dout; - gpio_num_t audio_i2s_spk_gpio_bclk; - gpio_num_t audio_i2s_spk_gpio_lrck; - - gpio_num_t display_backlight_pin; - gpio_num_t display_mosi_pin; - gpio_num_t display_clk_pin; - gpio_num_t display_dc_pin; - gpio_num_t display_rst_pin; - gpio_num_t display_cs_pin; - - gpio_num_t i2c_sda_pin; - gpio_num_t i2c_scl_pin; -}; - -constexpr HardwareConfig CAMERA_VERSION_CONFIG = { - .power_charge_detect_pin = GPIO_NUM_NC, - .power_adc_unit = ADC_UNIT_1, - .power_adc_channel = ADC_CHANNEL_1, - - .right_leg_pin = GPIO_NUM_43, - .right_foot_pin = GPIO_NUM_44, - .left_leg_pin = GPIO_NUM_5, - .left_foot_pin = GPIO_NUM_6, - .left_hand_pin = GPIO_NUM_4, - .right_hand_pin = GPIO_NUM_7, - - .audio_input_sample_rate = 16000, - .audio_output_sample_rate = 16000, - .audio_use_simplex = false, - - .audio_i2s_gpio_ws = GPIO_NUM_40, - .audio_i2s_gpio_bclk = GPIO_NUM_42, - .audio_i2s_gpio_din = GPIO_NUM_41, - .audio_i2s_gpio_dout = GPIO_NUM_39, - - .audio_i2s_mic_gpio_ws = GPIO_NUM_NC, - .audio_i2s_mic_gpio_sck = GPIO_NUM_NC, - .audio_i2s_mic_gpio_din = GPIO_NUM_NC, - .audio_i2s_spk_gpio_dout = GPIO_NUM_NC, - .audio_i2s_spk_gpio_bclk = GPIO_NUM_NC, - .audio_i2s_spk_gpio_lrck = GPIO_NUM_NC, - - .display_backlight_pin = GPIO_NUM_38, - .display_mosi_pin = GPIO_NUM_45, - .display_clk_pin = GPIO_NUM_48, - .display_dc_pin = GPIO_NUM_47, - .display_rst_pin = GPIO_NUM_1, - .display_cs_pin = GPIO_NUM_NC, - - .i2c_sda_pin = GPIO_NUM_15, - .i2c_scl_pin = GPIO_NUM_16, -}; - -constexpr HardwareConfig NON_CAMERA_VERSION_CONFIG = { - .power_charge_detect_pin = GPIO_NUM_21, - .power_adc_unit = ADC_UNIT_2, - .power_adc_channel = ADC_CHANNEL_3, - - .right_leg_pin = GPIO_NUM_39, - .right_foot_pin = GPIO_NUM_38, - .left_leg_pin = GPIO_NUM_17, - .left_foot_pin = GPIO_NUM_18, - .left_hand_pin = GPIO_NUM_8, - .right_hand_pin = GPIO_NUM_12, - - .audio_input_sample_rate = 16000, - .audio_output_sample_rate = 24000, - .audio_use_simplex = true, - - .audio_i2s_gpio_ws = GPIO_NUM_NC, - .audio_i2s_gpio_bclk = GPIO_NUM_NC, - .audio_i2s_gpio_din = GPIO_NUM_NC, - .audio_i2s_gpio_dout = GPIO_NUM_NC, - - .audio_i2s_mic_gpio_ws = GPIO_NUM_4, - .audio_i2s_mic_gpio_sck = GPIO_NUM_5, - .audio_i2s_mic_gpio_din = GPIO_NUM_6, - .audio_i2s_spk_gpio_dout = GPIO_NUM_7, - .audio_i2s_spk_gpio_bclk = GPIO_NUM_15, - .audio_i2s_spk_gpio_lrck = GPIO_NUM_16, - - .display_backlight_pin = GPIO_NUM_3, - .display_mosi_pin = GPIO_NUM_10, - .display_clk_pin = GPIO_NUM_9, - .display_dc_pin = GPIO_NUM_46, - .display_rst_pin = GPIO_NUM_11, - .display_cs_pin = GPIO_NUM_12, - - .i2c_sda_pin = GPIO_NUM_NC, - .i2c_scl_pin = GPIO_NUM_NC, -}; - -#define CAMERA_XCLK (GPIO_NUM_3) -#define CAMERA_PCLK (GPIO_NUM_10) -#define CAMERA_VSYNC (GPIO_NUM_17) -#define CAMERA_HSYNC (GPIO_NUM_18) -#define CAMERA_D0 (GPIO_NUM_12) -#define CAMERA_D1 (GPIO_NUM_14) -#define CAMERA_D2 (GPIO_NUM_21) -#define CAMERA_D3 (GPIO_NUM_13) -#define CAMERA_D4 (GPIO_NUM_11) -#define CAMERA_D5 (GPIO_NUM_9) -#define CAMERA_D6 (GPIO_NUM_46) -#define CAMERA_D7 (GPIO_NUM_8) -#define CAMERA_PWDN (GPIO_NUM_NC) -#define CAMERA_RESET (GPIO_NUM_NC) -#define CAMERA_XCLK_FREQ (16000000) -#define LEDC_TIMER (LEDC_TIMER_0) -#define LEDC_CHANNEL (LEDC_CHANNEL_0) - -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_INVERT_COLOR true -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#define DISPLAY_SPI_MODE 3 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.json deleted file mode 100644 index a32bc814..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "otto-robot", - "sdkconfig_append": [ - "CONFIG_HTTPD_WS_SUPPORT=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_240X240_25FPS=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.cc deleted file mode 100644 index 8dad82c0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.cc +++ /dev/null @@ -1,161 +0,0 @@ -//-------------------------------------------------------------- -//-- Oscillator.pde -//-- Generate sinusoidal oscillations in the servos -//-------------------------------------------------------------- -//-- (c) Juan Gonzalez-Gomez (Obijuan), Dec 2011 -//-- (c) txp666 for esp32, 202503 -//-- GPL license -//-------------------------------------------------------------- -#include "oscillator.h" - -#include -#include - -#include -#include - -static const char* TAG = "Oscillator"; - -extern unsigned long IRAM_ATTR millis(); - -static ledc_channel_t next_free_channel = LEDC_CHANNEL_0; - -Oscillator::Oscillator(int trim) { - trim_ = trim; - diff_limit_ = 0; - is_attached_ = false; - - sampling_period_ = 30; - period_ = 2000; - number_samples_ = period_ / sampling_period_; - inc_ = 2 * M_PI / number_samples_; - - amplitude_ = 45; - phase_ = 0; - phase0_ = 0; - offset_ = 0; - stop_ = false; - rev_ = false; - - pos_ = 90; - previous_millis_ = 0; -} - -Oscillator::~Oscillator() { - Detach(); -} - -uint32_t Oscillator::AngleToCompare(int angle) { - return (angle - SERVO_MIN_DEGREE) * (SERVO_MAX_PULSEWIDTH_US - SERVO_MIN_PULSEWIDTH_US) / - (SERVO_MAX_DEGREE - SERVO_MIN_DEGREE) + - SERVO_MIN_PULSEWIDTH_US; -} - -bool Oscillator::NextSample() { - current_millis_ = millis(); - - if (current_millis_ - previous_millis_ > sampling_period_) { - previous_millis_ = current_millis_; - return true; - } - - return false; -} - -void Oscillator::Attach(int pin, bool rev) { - if (is_attached_) { - Detach(); - } - - pin_ = pin; - rev_ = rev; - - ledc_timer_config_t ledc_timer = {.speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_13_BIT, - .timer_num = LEDC_TIMER_1, - .freq_hz = 50, - .clk_cfg = LEDC_AUTO_CLK}; - ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); - - static int last_channel = 0; - last_channel = (last_channel + 1) % 7 + 1; - ledc_channel_ = (ledc_channel_t)last_channel; - - ledc_channel_config_t ledc_channel = {.gpio_num = pin_, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = ledc_channel_, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER_1, - .duty = 0, - .hpoint = 0}; - ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); - - ledc_speed_mode_ = LEDC_LOW_SPEED_MODE; - - // pos_ = 90; - // Write(pos_); - previous_servo_command_millis_ = millis(); - - is_attached_ = true; -} - -void Oscillator::Detach() { - if (!is_attached_) - return; - - ESP_ERROR_CHECK(ledc_stop(ledc_speed_mode_, ledc_channel_, 0)); - - is_attached_ = false; -} - -void Oscillator::SetT(unsigned int T) { - period_ = T; - - number_samples_ = period_ / sampling_period_; - inc_ = 2 * M_PI / number_samples_; -} - -void Oscillator::SetPosition(int position) { - Write(position); -} - -void Oscillator::Refresh() { - if (NextSample()) { - if (!stop_) { - int pos = std::round(amplitude_ * std::sin(phase_ + phase0_) + offset_); - if (rev_) - pos = -pos; - Write(pos + 90); - } - - phase_ = phase_ + inc_; - } -} - -void Oscillator::Write(int position) { - if (!is_attached_) - return; - - long currentMillis = millis(); - if (diff_limit_ > 0) { - int limit = std::max( - 1, (((int)(currentMillis - previous_servo_command_millis_)) * diff_limit_) / 1000); - if (abs(position - pos_) > limit) { - pos_ += position < pos_ ? -limit : limit; - } else { - pos_ = position; - } - } else { - pos_ = position; - } - previous_servo_command_millis_ = currentMillis; - - int angle = pos_ + trim_; - - angle = std::min(std::max(angle, 0), 180); - - uint32_t duty = (uint32_t)(((angle / 180.0) * 2.0 + 0.5) * 8191 / 20.0); - - ESP_ERROR_CHECK(ledc_set_duty(ledc_speed_mode_, ledc_channel_, duty)); - ESP_ERROR_CHECK(ledc_update_duty(ledc_speed_mode_, ledc_channel_)); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.h deleted file mode 100644 index c37a69a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/oscillator.h +++ /dev/null @@ -1,91 +0,0 @@ -//-------------------------------------------------------------- -//-- Oscillator.pde -//-- Generate sinusoidal oscillations in the servos -//-------------------------------------------------------------- -//-- (c) Juan Gonzalez-Gomez (Obijuan), Dec 2011 -//-- (c) txp666 for esp32, 202503 -//-- GPL license -//-------------------------------------------------------------- -#ifndef __OSCILLATOR_H__ -#define __OSCILLATOR_H__ - -#include "driver/ledc.h" -#include "esp_log.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" - -#define M_PI 3.14159265358979323846 - -#ifndef DEG2RAD -#define DEG2RAD(g) ((g) * M_PI) / 180 -#endif - -#define SERVO_MIN_PULSEWIDTH_US 500 // 最小脉宽(微秒) -#define SERVO_MAX_PULSEWIDTH_US 2500 // 最大脉宽(微秒) -#define SERVO_MIN_DEGREE -90 // 最小角度 -#define SERVO_MAX_DEGREE 90 // 最大角度 -#define SERVO_TIMEBASE_RESOLUTION_HZ 1000000 // 1MHz, 1us per tick -#define SERVO_TIMEBASE_PERIOD 20000 // 20000 ticks, 20ms - -class Oscillator { -public: - Oscillator(int trim = 0); - ~Oscillator(); - void Attach(int pin, bool rev = false); - void Detach(); - - void SetA(unsigned int amplitude) { amplitude_ = amplitude; }; - void SetO(int offset) { offset_ = offset; }; - void SetPh(double Ph) { phase0_ = Ph; }; - void SetT(unsigned int period); - void SetTrim(int trim) { trim_ = trim; }; - void SetLimiter(int diff_limit) { diff_limit_ = diff_limit; }; - void DisableLimiter() { diff_limit_ = 0; }; - int GetTrim() { return trim_; }; - void SetPosition(int position); - void Stop() { stop_ = true; }; - void Play() { stop_ = false; }; - void Reset() { phase_ = 0; }; - void Refresh(); - int GetPosition() { return pos_; } - -private: - bool NextSample(); - void Write(int position); - uint32_t AngleToCompare(int angle); - -private: - bool is_attached_; - - //-- Oscillators parameters - unsigned int amplitude_; //-- Amplitude (degrees) - int offset_; //-- Offset (degrees) - unsigned int period_; //-- Period (miliseconds) - double phase0_; //-- Phase (radians) - - //-- Internal variables - int pos_; //-- Current servo pos - int pin_; //-- Pin where the servo is connected - int trim_; //-- Calibration offset - double phase_; //-- Current phase - double inc_; //-- Increment of phase - double number_samples_; //-- Number of samples - unsigned int sampling_period_; //-- sampling period (ms) - - long previous_millis_; - long current_millis_; - - //-- Oscillation mode. If true, the servo is stopped - bool stop_; - - //-- Reverse mode - bool rev_; - - int diff_limit_; - long previous_servo_command_millis_; - - ledc_channel_t ledc_channel_; - ledc_mode_t ledc_speed_mode_; -}; - -#endif // __OSCILLATOR_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_controller.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_controller.cc deleted file mode 100644 index 96791d45..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_controller.cc +++ /dev/null @@ -1,849 +0,0 @@ -/* - Otto机器人控制器 - MCP协议版本 -*/ - -#include -#include - -#include -#include - -#include "application.h" -#include "board.h" -#include "config.h" -#include "mcp_server.h" -#include "otto_movements.h" -#include "power_manager.h" -#include "sdkconfig.h" -#include "settings.h" -#include - -#define TAG "OttoController" - -class OttoController { -private: - Otto otto_; - TaskHandle_t action_task_handle_ = nullptr; - QueueHandle_t action_queue_; - bool has_hands_ = false; - bool is_action_in_progress_ = false; - - struct OttoActionParams { - int action_type; - int steps; - int speed; - int direction; - int amount; - char servo_sequence_json[512]; // 用于存储舵机序列的JSON字符串 - }; - - enum ActionType { - ACTION_WALK = 1, - ACTION_TURN = 2, - ACTION_JUMP = 3, - ACTION_SWING = 4, - ACTION_MOONWALK = 5, - ACTION_BEND = 6, - ACTION_SHAKE_LEG = 7, - ACTION_SIT = 25, // 坐下 - ACTION_RADIO_CALISTHENICS = 26, // 广播体操 - ACTION_MAGIC_CIRCLE = 27, // 爱的魔力转圈圈 - ACTION_UPDOWN = 8, - ACTION_TIPTOE_SWING = 9, - ACTION_JITTER = 10, - ACTION_ASCENDING_TURN = 11, - ACTION_CRUSAITO = 12, - ACTION_FLAPPING = 13, - ACTION_HANDS_UP = 14, - ACTION_HANDS_DOWN = 15, - ACTION_HAND_WAVE = 16, - ACTION_WINDMILL = 20, // 大风车 - ACTION_TAKEOFF = 21, // 起飞 - ACTION_FITNESS = 22, // 健身 - ACTION_GREETING = 23, // 打招呼 - ACTION_SHY = 24, // 害羞 - ACTION_SHOWCASE = 28, // 展示动作 - ACTION_HOME = 17, - ACTION_SERVO_SEQUENCE = 18, // 舵机序列(自编程) - ACTION_WHIRLWIND_LEG = 19 // 旋风腿 - }; - - static void ActionTask(void* arg) { - OttoController* controller = static_cast(arg); - OttoActionParams params; - controller->otto_.AttachServos(); - - while (true) { - if (xQueueReceive(controller->action_queue_, ¶ms, pdMS_TO_TICKS(1000)) == pdTRUE) { - ESP_LOGI(TAG, "执行动作: %d", params.action_type); - PowerManager::PauseBatteryUpdate(); // 动作开始时暂停电量更新 - controller->is_action_in_progress_ = true; - if (params.action_type == ACTION_SERVO_SEQUENCE) { - // 执行舵机序列(自编程)- 仅支持短键名格式 - cJSON* json = cJSON_Parse(params.servo_sequence_json); - if (json != nullptr) { - ESP_LOGD(TAG, "JSON解析成功,长度=%d", strlen(params.servo_sequence_json)); - // 使用短键名 "a" 表示动作数组 - cJSON* actions = cJSON_GetObjectItem(json, "a"); - if (cJSON_IsArray(actions)) { - int array_size = cJSON_GetArraySize(actions); - ESP_LOGI(TAG, "执行舵机序列,共%d个动作", array_size); - - // 获取序列执行完成后的延迟(短键名 "d",顶层参数) - int sequence_delay = 0; - cJSON* delay_item = cJSON_GetObjectItem(json, "d"); - if (cJSON_IsNumber(delay_item)) { - sequence_delay = delay_item->valueint; - if (sequence_delay < 0) sequence_delay = 0; - } - - // 初始化当前舵机位置(用于保持未指定的舵机位置) - int current_positions[SERVO_COUNT]; - for (int j = 0; j < SERVO_COUNT; j++) { - current_positions[j] = 90; // 默认中间位置 - } - // 手部舵机默认位置 - current_positions[LEFT_HAND] = 45; - current_positions[RIGHT_HAND] = 180 - 45; - - for (int i = 0; i < array_size; i++) { - cJSON* action_item = cJSON_GetArrayItem(actions, i); - if (cJSON_IsObject(action_item)) { - // 检查是否为振荡器模式(短键名 "osc") - cJSON* osc_item = cJSON_GetObjectItem(action_item, "osc"); - if (cJSON_IsObject(osc_item)) { - // 振荡器模式 - 使用Execute2,以绝对角度为中心振荡 - int amplitude[SERVO_COUNT] = {0}; - int center_angle[SERVO_COUNT] = {0}; - double phase_diff[SERVO_COUNT] = {0}; - int period = 300; // 默认周期300毫秒 - float steps = 8.0; // 默认步数8.0 - - const char* servo_names[] = {"ll", "rl", "lf", "rf", "lh", "rh"}; - - // 读取振幅(短键名 "a"),默认0度 - for (int j = 0; j < SERVO_COUNT; j++) { - amplitude[j] = 0; // 默认振幅0度 - } - cJSON* amp_item = cJSON_GetObjectItem(osc_item, "a"); - if (cJSON_IsObject(amp_item)) { - for (int j = 0; j < SERVO_COUNT; j++) { - cJSON* amp_value = cJSON_GetObjectItem(amp_item, servo_names[j]); - if (cJSON_IsNumber(amp_value)) { - int amp = amp_value->valueint; - if (amp >= 10 && amp <= 90) { - amplitude[j] = amp; - } - } - } - } - - // 读取中心角度(短键名 "o"),默认90度(绝对角度0-180度) - for (int j = 0; j < SERVO_COUNT; j++) { - center_angle[j] = 90; // 默认中心角度90度(中间位置) - } - cJSON* center_item = cJSON_GetObjectItem(osc_item, "o"); - if (cJSON_IsObject(center_item)) { - for (int j = 0; j < SERVO_COUNT; j++) { - cJSON* center_value = cJSON_GetObjectItem(center_item, servo_names[j]); - if (cJSON_IsNumber(center_value)) { - int center = center_value->valueint; - if (center >= 0 && center <= 180) { - center_angle[j] = center; - } - } - } - } - - // 安全检查:防止左右腿脚同时做大幅度振荡(振幅检查) - const int LARGE_AMPLITUDE_THRESHOLD = 40; // 大幅度振幅阈值:40度 - bool left_leg_large = amplitude[LEFT_LEG] >= LARGE_AMPLITUDE_THRESHOLD; - bool right_leg_large = amplitude[RIGHT_LEG] >= LARGE_AMPLITUDE_THRESHOLD; - bool left_foot_large = amplitude[LEFT_FOOT] >= LARGE_AMPLITUDE_THRESHOLD; - bool right_foot_large = amplitude[RIGHT_FOOT] >= LARGE_AMPLITUDE_THRESHOLD; - - if (left_leg_large && right_leg_large) { - ESP_LOGW(TAG, "检测到左右腿同时大幅度振荡,限制右腿振幅"); - amplitude[RIGHT_LEG] = 0; // 禁止右腿振荡 - } - if (left_foot_large && right_foot_large) { - ESP_LOGW(TAG, "检测到左右脚同时大幅度振荡,限制右脚振幅"); - amplitude[RIGHT_FOOT] = 0; // 禁止右脚振荡 - } - - // 读取相位差(短键名 "ph",单位为度,转换为弧度) - cJSON* phase_item = cJSON_GetObjectItem(osc_item, "ph"); - if (cJSON_IsObject(phase_item)) { - for (int j = 0; j < SERVO_COUNT; j++) { - cJSON* phase_value = cJSON_GetObjectItem(phase_item, servo_names[j]); - if (cJSON_IsNumber(phase_value)) { - // 将度数转换为弧度 - phase_diff[j] = phase_value->valuedouble * 3.141592653589793 / 180.0; - } - } - } - - // 读取周期(短键名 "p"),范围100-3000毫秒 - cJSON* period_item = cJSON_GetObjectItem(osc_item, "p"); - if (cJSON_IsNumber(period_item)) { - period = period_item->valueint; - if (period < 100) period = 100; - if (period > 3000) period = 3000; // 与描述一致,限制3000毫秒 - } - - // 读取周期数(短键名 "c"),范围0.1-20.0 - cJSON* steps_item = cJSON_GetObjectItem(osc_item, "c"); - if (cJSON_IsNumber(steps_item)) { - steps = (float)steps_item->valuedouble; - if (steps < 0.1) steps = 0.1; - if (steps > 20.0) steps = 20.0; // 与描述一致,限制20.0 - } - - // 执行振荡 - 使用Execute2,以绝对角度为中心 - ESP_LOGI(TAG, "执行振荡动作%d: period=%d, steps=%.1f", i, period, steps); - controller->otto_.Execute2(amplitude, center_angle, period, phase_diff, steps); - - // 振荡后更新位置(使用center_angle作为最终位置) - for (int j = 0; j < SERVO_COUNT; j++) { - current_positions[j] = center_angle[j]; - } - } else { - // 普通移动模式 - // 从当前位置数组复制,保持未指定的舵机位置 - int servo_target[SERVO_COUNT]; - for (int j = 0; j < SERVO_COUNT; j++) { - servo_target[j] = current_positions[j]; - } - - // 从JSON中读取舵机位置(短键名 "s") - cJSON* servos_item = cJSON_GetObjectItem(action_item, "s"); - if (cJSON_IsObject(servos_item)) { - // 短键名:ll/rl/lf/rf/lh/rh - const char* servo_names[] = {"ll", "rl", "lf", "rf", "lh", "rh"}; - - for (int j = 0; j < SERVO_COUNT; j++) { - cJSON* servo_value = cJSON_GetObjectItem(servos_item, servo_names[j]); - if (cJSON_IsNumber(servo_value)) { - int position = servo_value->valueint; - // 限制位置范围在0-180度 - if (position >= 0 && position <= 180) { - servo_target[j] = position; - } - } - } - } - - // 获取移动速度(短键名 "v",默认1000毫秒) - int speed = 1000; - cJSON* speed_item = cJSON_GetObjectItem(action_item, "v"); - if (cJSON_IsNumber(speed_item)) { - speed = speed_item->valueint; - if (speed < 100) speed = 100; // 最小100毫秒 - if (speed > 3000) speed = 3000; // 最大3000毫秒 - } - - // 执行舵机移动 - ESP_LOGI(TAG, "执行动作%d: ll=%d, rl=%d, lf=%d, rf=%d, v=%d", - i, servo_target[LEFT_LEG], servo_target[RIGHT_LEG], - servo_target[LEFT_FOOT], servo_target[RIGHT_FOOT], speed); - controller->otto_.MoveServos(speed, servo_target); - - // 更新当前位置数组,用于下一个动作 - for (int j = 0; j < SERVO_COUNT; j++) { - current_positions[j] = servo_target[j]; - } - } - - // 获取动作后的延迟时间(短键名 "d") - int delay_after = 0; - cJSON* delay_item = cJSON_GetObjectItem(action_item, "d"); - if (cJSON_IsNumber(delay_item)) { - delay_after = delay_item->valueint; - if (delay_after < 0) delay_after = 0; - } - - // 动作后的延迟(最后一个动作后不延迟) - if (delay_after > 0 && i < array_size - 1) { - ESP_LOGI(TAG, "动作%d执行完成,延迟%d毫秒", i, delay_after); - vTaskDelay(pdMS_TO_TICKS(delay_after)); - } - } - } - - // 序列执行完成后的延迟(用于序列之间的停顿) - if (sequence_delay > 0) { - // 检查队列中是否还有待执行的序列 - UBaseType_t queue_count = uxQueueMessagesWaiting(controller->action_queue_); - if (queue_count > 0) { - ESP_LOGI(TAG, "序列执行完成,延迟%d毫秒后执行下一个序列(队列中还有%d个序列)", - sequence_delay, queue_count); - vTaskDelay(pdMS_TO_TICKS(sequence_delay)); - } - } - // 释放JSON内存 - cJSON_Delete(json); - } else { - ESP_LOGE(TAG, "舵机序列格式错误: 'a'不是数组"); - cJSON_Delete(json); - } - } else { - // 获取cJSON的错误信息 - const char* error_ptr = cJSON_GetErrorPtr(); - int json_len = strlen(params.servo_sequence_json); - ESP_LOGE(TAG, "解析舵机序列JSON失败,长度=%d,错误位置: %s", json_len, - error_ptr ? error_ptr : "未知"); - ESP_LOGE(TAG, "JSON内容: %s", params.servo_sequence_json); - } - } else { - // 执行预定义动作 - switch (params.action_type) { - case ACTION_WALK: - controller->otto_.Walk(params.steps, params.speed, params.direction, - params.amount); - break; - case ACTION_TURN: - controller->otto_.Turn(params.steps, params.speed, params.direction, - params.amount); - break; - case ACTION_JUMP: - controller->otto_.Jump(params.steps, params.speed); - break; - case ACTION_SWING: - controller->otto_.Swing(params.steps, params.speed, params.amount); - break; - case ACTION_MOONWALK: - controller->otto_.Moonwalker(params.steps, params.speed, params.amount, - params.direction); - break; - case ACTION_BEND: - controller->otto_.Bend(params.steps, params.speed, params.direction); - break; - case ACTION_SHAKE_LEG: - controller->otto_.ShakeLeg(params.steps, params.speed, params.direction); - break; - case ACTION_SIT: - controller->otto_.Sit(); - break; - case ACTION_RADIO_CALISTHENICS: - if (controller->has_hands_) { - controller->otto_.RadioCalisthenics(); - } - break; - case ACTION_MAGIC_CIRCLE: - if (controller->has_hands_) { - controller->otto_.MagicCircle(); - } - break; - case ACTION_SHOWCASE: - controller->otto_.Showcase(); - break; - case ACTION_UPDOWN: - controller->otto_.UpDown(params.steps, params.speed, params.amount); - break; - case ACTION_TIPTOE_SWING: - controller->otto_.TiptoeSwing(params.steps, params.speed, params.amount); - break; - case ACTION_JITTER: - controller->otto_.Jitter(params.steps, params.speed, params.amount); - break; - case ACTION_ASCENDING_TURN: - controller->otto_.AscendingTurn(params.steps, params.speed, params.amount); - break; - case ACTION_CRUSAITO: - controller->otto_.Crusaito(params.steps, params.speed, params.amount, - params.direction); - break; - case ACTION_FLAPPING: - controller->otto_.Flapping(params.steps, params.speed, params.amount, - params.direction); - break; - case ACTION_WHIRLWIND_LEG: - controller->otto_.WhirlwindLeg(params.steps, params.speed, params.amount); - break; - case ACTION_HANDS_UP: - if (controller->has_hands_) { - controller->otto_.HandsUp(params.speed, params.direction); - } - break; - case ACTION_HANDS_DOWN: - if (controller->has_hands_) { - controller->otto_.HandsDown(params.speed, params.direction); - } - break; - case ACTION_HAND_WAVE: - if (controller->has_hands_) { - controller->otto_.HandWave( params.direction); - } - break; - case ACTION_WINDMILL: - if (controller->has_hands_) { - controller->otto_.Windmill(params.steps, params.speed, params.amount); - } - break; - case ACTION_TAKEOFF: - if (controller->has_hands_) { - controller->otto_.Takeoff(params.steps, params.speed, params.amount); - } - break; - case ACTION_FITNESS: - if (controller->has_hands_) { - controller->otto_.Fitness(params.steps, params.speed, params.amount); - } - break; - case ACTION_GREETING: - if (controller->has_hands_) { - controller->otto_.Greeting(params.direction, params.steps); - } - break; - case ACTION_SHY: - if (controller->has_hands_) { - controller->otto_.Shy(params.direction, params.steps); - } - break; - case ACTION_HOME: - controller->otto_.Home(true); - break; - } - if(params.action_type != ACTION_SIT){ - if (params.action_type != ACTION_HOME && params.action_type != ACTION_SERVO_SEQUENCE) { - controller->otto_.Home(params.action_type != ACTION_HANDS_UP); - } - } - } - controller->is_action_in_progress_ = false; - PowerManager::ResumeBatteryUpdate(); // 动作结束时恢复电量更新 - vTaskDelay(pdMS_TO_TICKS(20)); - } - } - } - - void StartActionTaskIfNeeded() { - if (action_task_handle_ == nullptr) { - xTaskCreate(ActionTask, "otto_action", 1024 * 3, this, configMAX_PRIORITIES - 1, - &action_task_handle_); - } - } - - void QueueAction(int action_type, int steps, int speed, int direction, int amount) { - // 检查手部动作 - if ((action_type >= ACTION_HANDS_UP && action_type <= ACTION_HAND_WAVE) || - (action_type == ACTION_WINDMILL) || (action_type == ACTION_TAKEOFF) || - (action_type == ACTION_FITNESS) || (action_type == ACTION_GREETING) || - (action_type == ACTION_SHY) || (action_type == ACTION_RADIO_CALISTHENICS) || - (action_type == ACTION_MAGIC_CIRCLE)) { - if (!has_hands_) { - ESP_LOGW(TAG, "尝试执行手部动作,但机器人没有配置手部舵机"); - return; - } - } - - ESP_LOGI(TAG, "动作控制: 类型=%d, 步数=%d, 速度=%d, 方向=%d, 幅度=%d", action_type, steps, - speed, direction, amount); - - OttoActionParams params = {action_type, steps, speed, direction, amount, ""}; - xQueueSend(action_queue_, ¶ms, portMAX_DELAY); - StartActionTaskIfNeeded(); - } - - void QueueServoSequence(const char* servo_sequence_json) { - if (servo_sequence_json == nullptr) { - ESP_LOGE(TAG, "序列JSON为空"); - return; - } - - int input_len = strlen(servo_sequence_json); - const int buffer_size = 512; // servo_sequence_json数组大小 - ESP_LOGI(TAG, "队列舵机序列,输入长度=%d,缓冲区大小=%d", input_len, buffer_size); - - if (input_len >= buffer_size) { - ESP_LOGE(TAG, "JSON字符串太长!输入长度=%d,最大允许=%d", input_len, buffer_size - 1); - return; - } - - if (input_len == 0) { - ESP_LOGW(TAG, "序列JSON为空字符串"); - return; - } - - OttoActionParams params = {ACTION_SERVO_SEQUENCE, 0, 0, 0, 0, ""}; - // 复制JSON字符串到结构体中(限制长度) - strncpy(params.servo_sequence_json, servo_sequence_json, sizeof(params.servo_sequence_json) - 1); - params.servo_sequence_json[sizeof(params.servo_sequence_json) - 1] = '\0'; - - ESP_LOGD(TAG, "序列已加入队列: %s", params.servo_sequence_json); - - xQueueSend(action_queue_, ¶ms, portMAX_DELAY); - StartActionTaskIfNeeded(); - } - - void LoadTrimsFromNVS() { - Settings settings("otto_trims", false); - - int left_leg = settings.GetInt("left_leg", 0); - int right_leg = settings.GetInt("right_leg", 0); - int left_foot = settings.GetInt("left_foot", 0); - int right_foot = settings.GetInt("right_foot", 0); - int left_hand = settings.GetInt("left_hand", 0); - int right_hand = settings.GetInt("right_hand", 0); - - ESP_LOGI(TAG, "从NVS加载微调设置: 左腿=%d, 右腿=%d, 左脚=%d, 右脚=%d, 左手=%d, 右手=%d", - left_leg, right_leg, left_foot, right_foot, left_hand, right_hand); - - otto_.SetTrims(left_leg, right_leg, left_foot, right_foot, left_hand, right_hand); - } - -public: - OttoController(const HardwareConfig& hw_config) { - otto_.Init( - hw_config.left_leg_pin, - hw_config.right_leg_pin, - hw_config.left_foot_pin, - hw_config.right_foot_pin, - hw_config.left_hand_pin, - hw_config.right_hand_pin - ); - - has_hands_ = (hw_config.left_hand_pin != GPIO_NUM_NC && hw_config.right_hand_pin != GPIO_NUM_NC); - ESP_LOGI(TAG, "Otto机器人初始化%s手部舵机", has_hands_ ? "带" : "不带"); - ESP_LOGI(TAG, "舵机引脚配置: LL=%d, RL=%d, LF=%d, RF=%d, LH=%d, RH=%d", - hw_config.left_leg_pin, hw_config.right_leg_pin, - hw_config.left_foot_pin, hw_config.right_foot_pin, - hw_config.left_hand_pin, hw_config.right_hand_pin); - - LoadTrimsFromNVS(); - - action_queue_ = xQueueCreate(10, sizeof(OttoActionParams)); - - QueueAction(ACTION_HOME, 1, 1000, 1, 0); // direction=1表示复位手部 - - RegisterMcpTools(); - } - - void RegisterMcpTools() { - auto& mcp_server = McpServer::GetInstance(); - - ESP_LOGI(TAG, "开始注册MCP工具..."); - - // 统一动作工具(除了舵机序列外的所有动作) - mcp_server.AddTool("self.otto.action", - "执行机器人动作。action: 动作名称;根据动作类型提供相应参数:direction: 方向,1=前进/左转,-1=后退/右转;0=左右同时" - "steps: 动作步数,1-100;speed: 动作速度,100-3000,数值越小越快;amount: 动作幅度,0-170;arm_swing: 手臂摆动幅度,0-170;" - "基础动作:walk(行走,需steps/speed/direction/arm_swing)、turn(转身,需steps/speed/direction/arm_swing)、jump(跳跃,需steps/speed)、" - "swing(摇摆,需steps/speed/amount)、moonwalk(太空步,需steps/speed/direction/amount)、bend(弯曲,需steps/speed/direction)、" - "shake_leg(摇腿,需steps/speed/direction)、updown(上下运动,需steps/speed/amount)、whirlwind_leg(旋风腿,需steps/speed/amount);" - "固定动作:sit(坐下)、showcase(展示动作)、home(复位);" - "手部动作(需手部舵机):hands_up(举手,需speed/direction)、hands_down(放手,需speed/direction)、hand_wave(挥手,需direction)、" - "windmill(大风车,需steps/speed/amount)、takeoff(起飞,需steps/speed/amount)、fitness(健身,需steps/speed/amount)、" - "greeting(打招呼,需direction/steps)、shy(害羞,需direction/steps)、radio_calisthenics(广播体操)、magic_circle(爱的魔力转圈圈)", - PropertyList({ - Property("action", kPropertyTypeString, "sit"), - Property("steps", kPropertyTypeInteger, 3, 1, 100), - Property("speed", kPropertyTypeInteger, 700, 100, 3000), - Property("direction", kPropertyTypeInteger, 1, -1, 1), - Property("amount", kPropertyTypeInteger, 30, 0, 170), - Property("arm_swing", kPropertyTypeInteger, 50, 0, 170) - }), - [this](const PropertyList& properties) -> ReturnValue { - std::string action = properties["action"].value(); - // 所有参数都有默认值,直接访问即可 - int steps = properties["steps"].value(); - int speed = properties["speed"].value(); - int direction = properties["direction"].value(); - int amount = properties["amount"].value(); - int arm_swing = properties["arm_swing"].value(); - - // 基础移动动作 - if (action == "walk") { - QueueAction(ACTION_WALK, steps, speed, direction, arm_swing); - return true; - } else if (action == "turn") { - QueueAction(ACTION_TURN, steps, speed, direction, arm_swing); - return true; - } else if (action == "jump") { - QueueAction(ACTION_JUMP, steps, speed, 0, 0); - return true; - } else if (action == "swing") { - QueueAction(ACTION_SWING, steps, speed, 0, amount); - return true; - } else if (action == "moonwalk") { - QueueAction(ACTION_MOONWALK, steps, speed, direction, amount); - return true; - } else if (action == "bend") { - QueueAction(ACTION_BEND, steps, speed, direction, 0); - return true; - } else if (action == "shake_leg") { - QueueAction(ACTION_SHAKE_LEG, steps, speed, direction, 0); - return true; - } else if (action == "updown") { - QueueAction(ACTION_UPDOWN, steps, speed, 0, amount); - return true; - } else if (action == "whirlwind_leg") { - QueueAction(ACTION_WHIRLWIND_LEG, steps, speed, 0, amount); - return true; - } - // 固定动作 - else if (action == "sit") { - QueueAction(ACTION_SIT, 1, 0, 0, 0); - return true; - } else if (action == "showcase") { - QueueAction(ACTION_SHOWCASE, 1, 0, 0, 0); - return true; - } else if (action == "home") { - QueueAction(ACTION_HOME, 1, 1000, 1, 0); - return true; - } - // 手部动作 - else if (action == "hands_up") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_HANDS_UP, 1, speed, direction, 0); - return true; - } else if (action == "hands_down") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_HANDS_DOWN, 1, speed, direction, 0); - return true; - } else if (action == "hand_wave") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_HAND_WAVE, 1, 0, 0, direction); - return true; - } else if (action == "windmill") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_WINDMILL, steps, speed, 0, amount); - return true; - } else if (action == "takeoff") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_TAKEOFF, steps, speed, 0, amount); - return true; - } else if (action == "fitness") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_FITNESS, steps, speed, 0, amount); - return true; - } else if (action == "greeting") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_GREETING, steps, 0, direction, 0); - return true; - } else if (action == "shy") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_SHY, steps, 0, direction, 0); - return true; - } else if (action == "radio_calisthenics") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_RADIO_CALISTHENICS, 1, 0, 0, 0); - return true; - } else if (action == "magic_circle") { - if (!has_hands_) { - return "错误:此动作需要手部舵机支持"; - } - QueueAction(ACTION_MAGIC_CIRCLE, 1, 0, 0, 0); - return true; - } else { - return "错误:无效的动作名称。可用动作:walk, turn, jump, swing, moonwalk, bend, shake_leg, updown, whirlwind_leg, sit, showcase, home, hands_up, hands_down, hand_wave, windmill, takeoff, fitness, greeting, shy, radio_calisthenics, magic_circle"; - } - }); - - - // 舵机序列工具(支持分段发送,每次发送一个序列,自动排队执行) - mcp_server.AddTool( - "self.otto.servo_sequences", - "AI自定义动作编程(即兴动作)。支持分段发送序列:超过5个序列建议AI可以连续多次调用此工具,每次发送一个短序列,系统会自动排队按顺序执行。支持普通移动和振荡器两种模式。" - "机器人结构:双手可上下摆动,双腿可内收外展,双脚可上下翻转。" - "舵机说明:" - "ll(左腿):内收外展,0度=完全外展,90度=中立,180度=完全内收;" - "rl(右腿):内收外展,0度=完全内收,90度=中立,180度=完全外展;" - "lf(左脚):上下翻转,0度=完全向上,90度=水平,180度=完全向下;" - "rf(右脚):上下翻转,0度=完全向下,90度=水平,180度=完全向上;" - "lh(左手):上下摆动,0度=完全向下,90度=水平,180度=完全向上;" - "rh(右手):上下摆动,0度=完全向上,90度=水平,180度=完全向下;" - "sequence: 单个序列对象,包含'a'动作数组,顶层可选参数:" - "'d'(序列执行完成后延迟毫秒数,用于序列之间的停顿)。" - "每个动作对象包含:" - "普通模式:'s'舵机位置对象(键名:ll/rl/lf/rf/lh/rh,值:0-180度),'v'移动速度100-3000毫秒(默认1000),'d'动作后延迟毫秒数(默认0);" - "振荡模式:'osc'振荡器对象,包含'a'振幅对象(各舵机振幅10-90度,默认20度),'o'中心角度对象(各舵机振荡中心绝对角度0-180度,默认90度),'ph'相位差对象(各舵机相位差,度,0-360度,默认0度),'p'周期100-3000毫秒(默认500),'c'周期数0.1-20.0(默认5.0);" - "使用方式:AI可以连续多次调用此工具,每次发送一个序列,系统会自动排队按顺序执行。" - "重要说明:左右腿脚震荡的时候,有一只脚必须在90度,否则会损坏机器人,如果发送多个序列(序列数>1),完成所有序列后需要复位时,AI应该最后单独调用self.otto.home工具进行复位,不要在序列中设置复位参数。" - "普通模式示例:发送3个序列,最后调用复位:" - "第1次调用{\"sequence\":\"{\\\"a\\\":[{\\\"s\\\":{\\\"ll\\\":100},\\\"v\\\":1000}],\\\"d\\\":500}\"}," - "第2次调用{\"sequence\":\"{\\\"a\\\":[{\\\"s\\\":{\\\"ll\\\":90},\\\"v\\\":800}],\\\"d\\\":500}\"}," - "第3次调用{\"sequence\":\"{\\\"a\\\":[{\\\"s\\\":{\\\"ll\\\":80},\\\"v\\\":800}]}\"}," - "最后调用self.otto.home工具进行复位。" - "振荡器模式示例:" - "示例1-双臂同步摆动:{\"sequence\":\"{\\\"a\\\":[{\\\"osc\\\":{\\\"a\\\":{\\\"lh\\\":30,\\\"rh\\\":30},\\\"o\\\":{\\\"lh\\\":90,\\\"rh\\\":-90},\\\"p\\\":500,\\\"c\\\":5.0}}],\\\"d\\\":0}\"};" - "示例2-双腿交替振荡(波浪效果):{\"sequence\":\"{\\\"a\\\":[{\\\"osc\\\":{\\\"a\\\":{\\\"ll\\\":20,\\\"rl\\\":20},\\\"o\\\":{\\\"ll\\\":90,\\\"rl\\\":-90},\\\"ph\\\":{\\\"rl\\\":180},\\\"p\\\":600,\\\"c\\\":3.0}}],\\\"d\\\":0}\"};" - "示例3-单腿振荡配合固定脚(安全):{\"sequence\":\"{\\\"a\\\":[{\\\"osc\\\":{\\\"a\\\":{\\\"ll\\\":45},\\\"o\\\":{\\\"ll\\\":90,\\\"lf\\\":90},\\\"p\\\":400,\\\"c\\\":4.0}}],\\\"d\\\":0}\"};" - "示例4-复杂多舵机振荡(手和腿):{\"sequence\":\"{\\\"a\\\":[{\\\"osc\\\":{\\\"a\\\":{\\\"lh\\\":25,\\\"rh\\\":25,\\\"ll\\\":15},\\\"o\\\":{\\\"lh\\\":90,\\\"rh\\\":90,\\\"ll\\\":90,\\\"lf\\\":90},\\\"ph\\\":{\\\"rh\\\":180},\\\"p\\\":800,\\\"c\\\":6.0}}],\\\"d\\\":500}\"};" - "示例5-快速摇摆:{\"sequence\":\"{\\\"a\\\":[{\\\"osc\\\":{\\\"a\\\":{\\\"ll\\\":30,\\\"rl\\\":30},\\\"o\\\":{\\\"ll\\\":90,\\\"rl\\\":90},\\\"ph\\\":{\\\"rl\\\":180},\\\"p\\\":300,\\\"c\\\":10.0}}],\\\"d\\\":0}\"}。", - PropertyList({Property("sequence", kPropertyTypeString, - "{\"a\":[{\"s\":{\"ll\":90,\"rl\":90},\"v\":1000}]}")}), - [this](const PropertyList& properties) -> ReturnValue { - std::string sequence = properties["sequence"].value(); - // 检查是否是JSON对象(可能是字符串格式或已解析的对象) - // 如果sequence是JSON字符串,直接使用;如果是对象字符串,也需要使用 - QueueServoSequence(sequence.c_str()); - return true; - }); - - - mcp_server.AddTool("self.otto.stop", "立即停止所有动作并复位", PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - if (action_task_handle_ != nullptr) { - vTaskDelete(action_task_handle_); - action_task_handle_ = nullptr; - } - is_action_in_progress_ = false; - PowerManager::ResumeBatteryUpdate(); // 停止动作时恢复电量更新 - xQueueReset(action_queue_); - - QueueAction(ACTION_HOME, 1, 1000, 1, 0); - return true; - }); - - mcp_server.AddTool( - "self.otto.set_trim", - "校准单个舵机位置。设置指定舵机的微调参数以调整机器人的初始站立姿态,设置将永久保存。" - "servo_type: 舵机类型(left_leg/right_leg/left_foot/right_foot/left_hand/right_hand); " - "trim_value: 微调值(-50到50度)", - PropertyList({Property("servo_type", kPropertyTypeString, "left_leg"), - Property("trim_value", kPropertyTypeInteger, 0, -50, 50)}), - [this](const PropertyList& properties) -> ReturnValue { - std::string servo_type = properties["servo_type"].value(); - int trim_value = properties["trim_value"].value(); - - ESP_LOGI(TAG, "设置舵机微调: %s = %d度", servo_type.c_str(), trim_value); - - // 获取当前所有微调值 - Settings settings("otto_trims", true); - int left_leg = settings.GetInt("left_leg", 0); - int right_leg = settings.GetInt("right_leg", 0); - int left_foot = settings.GetInt("left_foot", 0); - int right_foot = settings.GetInt("right_foot", 0); - int left_hand = settings.GetInt("left_hand", 0); - int right_hand = settings.GetInt("right_hand", 0); - - // 更新指定舵机的微调值 - if (servo_type == "left_leg") { - left_leg = trim_value; - settings.SetInt("left_leg", left_leg); - } else if (servo_type == "right_leg") { - right_leg = trim_value; - settings.SetInt("right_leg", right_leg); - } else if (servo_type == "left_foot") { - left_foot = trim_value; - settings.SetInt("left_foot", left_foot); - } else if (servo_type == "right_foot") { - right_foot = trim_value; - settings.SetInt("right_foot", right_foot); - } else if (servo_type == "left_hand") { - if (!has_hands_) { - return "错误:机器人没有配置手部舵机"; - } - left_hand = trim_value; - settings.SetInt("left_hand", left_hand); - } else if (servo_type == "right_hand") { - if (!has_hands_) { - return "错误:机器人没有配置手部舵机"; - } - right_hand = trim_value; - settings.SetInt("right_hand", right_hand); - } else { - return "错误:无效的舵机类型,请使用: left_leg, right_leg, left_foot, " - "right_foot, left_hand, right_hand"; - } - - otto_.SetTrims(left_leg, right_leg, left_foot, right_foot, left_hand, right_hand); - - QueueAction(ACTION_JUMP, 1, 500, 0, 0); - - return "舵机 " + servo_type + " 微调设置为 " + std::to_string(trim_value) + - " 度,已永久保存"; - }); - - mcp_server.AddTool("self.otto.get_trims", "获取当前的舵机微调设置", PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - Settings settings("otto_trims", false); - - int left_leg = settings.GetInt("left_leg", 0); - int right_leg = settings.GetInt("right_leg", 0); - int left_foot = settings.GetInt("left_foot", 0); - int right_foot = settings.GetInt("right_foot", 0); - int left_hand = settings.GetInt("left_hand", 0); - int right_hand = settings.GetInt("right_hand", 0); - - std::string result = - "{\"left_leg\":" + std::to_string(left_leg) + - ",\"right_leg\":" + std::to_string(right_leg) + - ",\"left_foot\":" + std::to_string(left_foot) + - ",\"right_foot\":" + std::to_string(right_foot) + - ",\"left_hand\":" + std::to_string(left_hand) + - ",\"right_hand\":" + std::to_string(right_hand) + "}"; - - ESP_LOGI(TAG, "获取微调设置: %s", result.c_str()); - return result; - }); - - mcp_server.AddTool("self.otto.get_status", "获取机器人状态,返回 moving 或 idle", - PropertyList(), [this](const PropertyList& properties) -> ReturnValue { - return is_action_in_progress_ ? "moving" : "idle"; - }); - - mcp_server.AddTool("self.battery.get_level", "获取机器人电池电量和充电状态", PropertyList(), - [](const PropertyList& properties) -> ReturnValue { - auto& board = Board::GetInstance(); - int level = 0; - bool charging = false; - bool discharging = false; - board.GetBatteryLevel(level, charging, discharging); - - std::string status = - "{\"level\":" + std::to_string(level) + - ",\"charging\":" + (charging ? "true" : "false") + "}"; - return status; - }); - - mcp_server.AddTool("self.otto.get_ip", "获取机器人WiFi IP地址", PropertyList(), - [](const PropertyList& properties) -> ReturnValue { - auto& wifi = WifiManager::GetInstance(); - std::string ip = wifi.GetIpAddress(); - if (ip.empty()) { - return "{\"ip\":\"\",\"connected\":false}"; - } - std::string status = "{\"ip\":\"" + ip + "\",\"connected\":true}"; - return status; - }); - - ESP_LOGI(TAG, "MCP工具注册完成"); - } - - ~OttoController() { - if (action_task_handle_ != nullptr) { - vTaskDelete(action_task_handle_); - action_task_handle_ = nullptr; - } - vQueueDelete(action_queue_); - } -}; - -static OttoController* g_otto_controller = nullptr; - -void InitializeOttoController(const HardwareConfig& hw_config) { - if (g_otto_controller == nullptr) { - g_otto_controller = new OttoController(hw_config); - ESP_LOGI(TAG, "Otto控制器已初始化并注册MCP工具"); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.cc deleted file mode 100644 index 31a4280f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.cc +++ /dev/null @@ -1,165 +0,0 @@ -#include "otto_emoji_display.h" - -#include - -#include - -#include "assets/lang_config.h" -#include "display/lvgl_display/emoji_collection.h" -#include "display/lvgl_display/lvgl_image.h" -#include "display/lvgl_display/lvgl_theme.h" -#include "otto_emoji_gif.h" - -#define TAG "OttoEmojiDisplay" -OttoEmojiDisplay::OttoEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : SpiLcdDisplay(panel_io, panel, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - InitializeOttoEmojis(); - SetupPreviewImage(); - SetTheme(LvglThemeManager::GetInstance().GetTheme("dark")); -} - -void OttoEmojiDisplay::SetupPreviewImage() { - DisplayLockGuard lock(this); - lv_obj_set_size(preview_image_, width_ , height_ ); -} - -void OttoEmojiDisplay::InitializeOttoEmojis() { - ESP_LOGI(TAG, "初始化Otto GIF表情"); - - auto otto_emoji_collection = std::make_shared(); - - // 中性/平静类表情 -> staticstate - otto_emoji_collection->AddEmoji("staticstate", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("neutral", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("relaxed", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("sleepy", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - otto_emoji_collection->AddEmoji("idle", new LvglRawImage((void*)staticstate.data, staticstate.data_size)); - - // 积极/开心类表情 -> happy - otto_emoji_collection->AddEmoji("happy", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("laughing", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("funny", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("loving", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("confident", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("winking", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("cool", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("delicious", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("kissy", new LvglRawImage((void*)happy.data, happy.data_size)); - otto_emoji_collection->AddEmoji("silly", new LvglRawImage((void*)happy.data, happy.data_size)); - - // 悲伤类表情 -> sad - otto_emoji_collection->AddEmoji("sad", new LvglRawImage((void*)sad.data, sad.data_size)); - otto_emoji_collection->AddEmoji("crying", new LvglRawImage((void*)sad.data, sad.data_size)); - - // 愤怒类表情 -> anger - otto_emoji_collection->AddEmoji("anger", new LvglRawImage((void*)anger.data, anger.data_size)); - otto_emoji_collection->AddEmoji("angry", new LvglRawImage((void*)anger.data, anger.data_size)); - - // 惊讶类表情 -> scare - otto_emoji_collection->AddEmoji("scare", new LvglRawImage((void*)scare.data, scare.data_size)); - otto_emoji_collection->AddEmoji("surprised", new LvglRawImage((void*)scare.data, scare.data_size)); - otto_emoji_collection->AddEmoji("shocked", new LvglRawImage((void*)scare.data, scare.data_size)); - - // 思考/困惑类表情 -> buxue - otto_emoji_collection->AddEmoji("buxue", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("thinking", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("confused", new LvglRawImage((void*)buxue.data, buxue.data_size)); - otto_emoji_collection->AddEmoji("embarrassed", new LvglRawImage((void*)buxue.data, buxue.data_size)); - - // 将表情集合添加到主题中 - auto& theme_manager = LvglThemeManager::GetInstance(); - auto light_theme = theme_manager.GetTheme("light"); - auto dark_theme = theme_manager.GetTheme("dark"); - - if (light_theme != nullptr) { - light_theme->set_emoji_collection(otto_emoji_collection); - } - if (dark_theme != nullptr) { - dark_theme->set_emoji_collection(otto_emoji_collection); - } - - // 设置默认表情为staticstate - SetEmotion("staticstate"); - - ESP_LOGI(TAG, "Otto GIF表情初始化完成"); -} - -LV_FONT_DECLARE(OTTO_ICON_FONT); -void OttoEmojiDisplay::SetStatus(const char* status) { - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - DisplayLockGuard lock(this); - if (!status) { - ESP_LOGE(TAG, "SetStatus: status is nullptr"); - return; - } - - if (strcmp(status, Lang::Strings::LISTENING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x84\xB0"); // U+F130 麦克风图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::SPEAKING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x80\xA8"); // U+F028 说话图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::CONNECTING) == 0) { - lv_obj_set_style_text_font(status_label_, &OTTO_ICON_FONT, 0); - lv_label_set_text(status_label_, "\xEF\x83\x81"); // U+F0c1 连接图标 - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - return; - } else if (strcmp(status, Lang::Strings::STANDBY) == 0) { - lv_obj_set_style_text_font(status_label_, text_font, 0); - lv_label_set_text(status_label_, ""); - lv_obj_clear_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(network_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_clear_flag(battery_label_, LV_OBJ_FLAG_HIDDEN); - return; - } - - lv_obj_set_style_text_font(status_label_, text_font, 0); - lv_label_set_text(status_label_, status); -} - -void OttoEmojiDisplay::SetPreviewImage(std::unique_ptr image) { - DisplayLockGuard lock(this); - if (preview_image_ == nullptr) { - ESP_LOGE(TAG, "Preview image is not initialized"); - return; - } - - if (image == nullptr) { - esp_timer_stop(preview_timer_); - lv_obj_remove_flag(emoji_box_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(preview_image_, LV_OBJ_FLAG_HIDDEN); - preview_image_cached_.reset(); - if (gif_controller_) { - gif_controller_->Start(); - } - return; - } - - preview_image_cached_ = std::move(image); - auto img_dsc = preview_image_cached_->image_dsc(); - // 设置图片源并显示预览图片 - lv_image_set_src(preview_image_, img_dsc); - lv_image_set_rotation(preview_image_, -900); - if (img_dsc->header.w > 0 && img_dsc->header.h > 0) { - // zoom factor 1.0 - lv_image_set_scale(preview_image_, 256 * width_ / img_dsc->header.w); - } - - // Hide emoji_box_ - if (gif_controller_) { - gif_controller_->Stop(); - } - lv_obj_add_flag(emoji_box_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(preview_image_, LV_OBJ_FLAG_HIDDEN); - esp_timer_stop(preview_timer_); - ESP_ERROR_CHECK(esp_timer_start_once(preview_timer_, PREVIEW_IMAGE_DURATION_MS * 1000)); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.h deleted file mode 100644 index 207ed8a9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_emoji_display.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "display/lcd_display.h" - -/** - * @brief Otto机器人GIF表情显示类 - * 继承SpiLcdDisplay,通过EmojiCollection添加GIF表情支持 - */ -class OttoEmojiDisplay : public SpiLcdDisplay { - public: - /** - * @brief 构造函数,参数与SpiLcdDisplay相同 - */ - OttoEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy); - - virtual ~OttoEmojiDisplay() = default; - virtual void SetStatus(const char* status) override; - virtual void SetPreviewImage(std::unique_ptr image) override; - - private: - void InitializeOttoEmojis(); - void SetupPreviewImage(); -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_icon_font.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_icon_font.c deleted file mode 100644 index dc05cce6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_icon_font.c +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * Size: 20 px - * Bpp: 1 - * Opts: --bpp 1 --size 20 --no-compress --stride 1 --align 1 --font fontawesome-webfont.ttf --range 61744,61633,61480 --format lvgl -o OTTO_ICON_FONT.c - ******************************************************************************/ - -#ifdef __has_include -#if __has_include("lvgl.h") -#ifndef LV_LVGL_H_INCLUDE_SIMPLE -#define LV_LVGL_H_INCLUDE_SIMPLE -#endif -#endif -#endif - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - -#ifndef ENABLE_OTTO_ICON_FONT -#define ENABLE_OTTO_ICON_FONT 1 -#endif - -#if ENABLE_OTTO_ICON_FONT - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F028 "" */ - 0x0, 0x6, 0x0, 0x10, 0xe0, 0x6, 0x6, 0x3, 0xc6, 0x60, 0xf8, 0x65, 0xff, 0x24, 0xff, 0xe6, 0x4f, 0xfc, 0x49, 0xff, 0x89, 0x3f, 0xf3, 0x27, 0xfe, 0x49, 0x87, 0xc3, 0x20, 0x78, 0xcc, 0x3, 0x3, 0x0, - 0x21, 0xc0, 0x0, 0x30, - - /* U+F0C1 "" */ - 0x1e, 0x0, 0xf, 0xc0, 0x7, 0x38, 0x3, 0x87, 0x0, 0xc0, 0xc0, 0x30, 0xb0, 0x7, 0x3c, 0x0, 0xef, 0x0, 0x1f, 0xfe, 0x3, 0xff, 0xc0, 0x7, 0x38, 0x3, 0xe7, 0x0, 0xd0, 0xc0, 0x30, 0x30, 0x6, 0x1c, 0x0, - 0xce, 0x0, 0x1f, 0x0, 0x3, 0x80, - - /* U+F130 "" */ - 0x7, 0x0, 0xfe, 0x7, 0xf0, 0x3f, 0x81, 0xfc, 0xf, 0xe0, 0x7f, 0x13, 0xf9, 0x9f, 0xcc, 0xfe, 0x67, 0xf3, 0xbf, 0xb4, 0x73, 0x18, 0x30, 0x7f, 0x0, 0x60, 0x2, 0x1, 0xff, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, .adv_w = 297, .box_w = 19, .box_h = 16, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 38, .adv_w = 297, .box_w = 18, .box_h = 18, .ofs_x = 0, .ofs_y = -1}, - {.bitmap_index = 79, .adv_w = 206, .box_w = 13, .box_h = 18, .ofs_x = 0, .ofs_y = -1}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -static const uint16_t unicode_list_0[] = {0x0, 0x99, 0x108}; - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61480, .range_length = 265, .glyph_id_start = 1, .unicode_list = unicode_list_0, .glyph_id_ofs_list = NULL, .list_length = 3, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LVGL_VERSION_MAJOR == 8 -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -#endif - -#if LVGL_VERSION_MAJOR >= 8 -static const lv_font_fmt_txt_dsc_t otto_icon_font_dsc = { -#else -static lv_font_fmt_txt_dsc_t otto_icon_font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 1, - .kern_classes = 0, - .bitmap_format = 0, -#if LVGL_VERSION_MAJOR == 8 - .cache = &cache -#endif - -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LVGL_VERSION_MAJOR >= 8 -const lv_font_t OTTO_ICON_FONT = { -#else -lv_font_t OTTO_ICON_FONT = { -#endif - .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 18, /*The maximum line height required by the font*/ - .base_line = 1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .static_bitmap = 0, - .dsc = &otto_icon_font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ -#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 - .fallback = NULL, -#endif - .user_data = NULL, -}; - -#endif /*#if ENABLE_OTTO_ICON_FONT*/ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.cc deleted file mode 100644 index 9d11f129..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.cc +++ /dev/null @@ -1,964 +0,0 @@ -#include "otto_movements.h" - -#include - -#include "freertos/idf_additions.h" -#include "oscillator.h" - -static const char* TAG = "OttoMovements"; - -#define HAND_HOME_POSITION 45 - -Otto::Otto() { - is_otto_resting_ = false; - has_hands_ = false; - // 初始化所有舵机管脚为-1(未连接) - for (int i = 0; i < SERVO_COUNT; i++) { - servo_pins_[i] = -1; - servo_trim_[i] = 0; - } -} - -Otto::~Otto() { - DetachServos(); -} - -unsigned long IRAM_ATTR millis() { - return (unsigned long)(esp_timer_get_time() / 1000ULL); -} - -void Otto::Init(int left_leg, int right_leg, int left_foot, int right_foot, int left_hand, - int right_hand) { - servo_pins_[LEFT_LEG] = left_leg; - servo_pins_[RIGHT_LEG] = right_leg; - servo_pins_[LEFT_FOOT] = left_foot; - servo_pins_[RIGHT_FOOT] = right_foot; - servo_pins_[LEFT_HAND] = left_hand; - servo_pins_[RIGHT_HAND] = right_hand; - - // 检查是否有手部舵机 - has_hands_ = (left_hand != -1 && right_hand != -1); - - AttachServos(); - is_otto_resting_ = false; -} - -/////////////////////////////////////////////////////////////////// -//-- ATTACH & DETACH FUNCTIONS ----------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::AttachServos() { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Attach(servo_pins_[i]); - } - } -} - -void Otto::DetachServos() { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Detach(); - } - } -} - -/////////////////////////////////////////////////////////////////// -//-- OSCILLATORS TRIMS ------------------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::SetTrims(int left_leg, int right_leg, int left_foot, int right_foot, int left_hand, - int right_hand) { - servo_trim_[LEFT_LEG] = left_leg; - servo_trim_[RIGHT_LEG] = right_leg; - servo_trim_[LEFT_FOOT] = left_foot; - servo_trim_[RIGHT_FOOT] = right_foot; - - if (has_hands_) { - servo_trim_[LEFT_HAND] = left_hand; - servo_trim_[RIGHT_HAND] = right_hand; - } - - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetTrim(servo_trim_[i]); - } - } -} - -/////////////////////////////////////////////////////////////////// -//-- BASIC MOTION FUNCTIONS -------------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::MoveServos(int time, int servo_target[]) { - if (GetRestState() == true) { - SetRestState(false); - } - - final_time_ = millis() + time; - if (time > 10) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - increment_[i] = (servo_target[i] - servo_[i].GetPosition()) / (time / 10.0); - } - } - - for (int iteration = 1; millis() < final_time_; iteration++) { - partial_time_ = millis() + 10; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_[i].GetPosition() + increment_[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(10)); - } - } else { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_target[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(time)); - } - - // final adjustment to the target. - bool f = true; - int adjustment_count = 0; - while (f && adjustment_count < 10) { - f = false; - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1 && servo_target[i] != servo_[i].GetPosition()) { - f = true; - break; - } - } - if (f) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetPosition(servo_target[i]); - } - } - vTaskDelay(pdMS_TO_TICKS(10)); - adjustment_count++; - } - }; -} - -void Otto::MoveSingle(int position, int servo_number) { - if (position > 180) - position = 90; - if (position < 0) - position = 90; - - if (GetRestState() == true) { - SetRestState(false); - } - - if (servo_number >= 0 && servo_number < SERVO_COUNT && servo_pins_[servo_number] != -1) { - servo_[servo_number].SetPosition(position); - } -} - -void Otto::OscillateServos(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float cycle = 1) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetO(offset[i]); - servo_[i].SetA(amplitude[i]); - servo_[i].SetT(period); - servo_[i].SetPh(phase_diff[i]); - } - } - - double ref = millis(); - double end_time = period * cycle + ref; - - while (millis() < end_time) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].Refresh(); - } - } - vTaskDelay(5); - } - vTaskDelay(pdMS_TO_TICKS(10)); -} - -void Otto::Execute(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps = 1.0) { - if (GetRestState() == true) { - SetRestState(false); - } - - int cycles = (int)steps; - - //-- Execute complete cycles - if (cycles >= 1) - for (int i = 0; i < cycles; i++) - OscillateServos(amplitude, offset, period, phase_diff); - - //-- Execute the final not complete cycle - OscillateServos(amplitude, offset, period, phase_diff, (float)steps - cycles); - vTaskDelay(pdMS_TO_TICKS(10)); -} - -//--------------------------------------------------------- -//-- Execute2: 使用绝对角度作为振荡中心 -//-- Parameters: -//-- amplitude: 振幅数组(每个舵机的振荡幅度) -//-- center_angle: 绝对角度数组(0-180度),作为振荡中心位置 -//-- period: 周期(毫秒) -//-- phase_diff: 相位差数组(弧度) -//-- steps: 步数/周期数(可为小数) -//--------------------------------------------------------- -void Otto::Execute2(int amplitude[SERVO_COUNT], int center_angle[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps = 1.0) { - if (GetRestState() == true) { - SetRestState(false); - } - - // 将绝对角度转换为offset(offset = center_angle - 90) - int offset[SERVO_COUNT]; - for (int i = 0; i < SERVO_COUNT; i++) { - offset[i] = center_angle[i] - 90; - } - - int cycles = (int)steps; - - //-- Execute complete cycles - if (cycles >= 1) - for (int i = 0; i < cycles; i++) - OscillateServos(amplitude, offset, period, phase_diff); - - //-- Execute the final not complete cycle - OscillateServos(amplitude, offset, period, phase_diff, (float)steps - cycles); - vTaskDelay(pdMS_TO_TICKS(10)); -} - -/////////////////////////////////////////////////////////////////// -//-- HOME = Otto at rest position -------------------------------// -/////////////////////////////////////////////////////////////////// -void Otto::Home(bool hands_down) { - if (is_otto_resting_ == false) { // Go to rest position only if necessary - // 为所有舵机准备初始位置值 - int homes[SERVO_COUNT]; - for (int i = 0; i < SERVO_COUNT; i++) { - if (i == LEFT_HAND || i == RIGHT_HAND) { - if (hands_down) { - // 如果需要复位手部,设置为默认值 - if (i == LEFT_HAND) { - homes[i] = HAND_HOME_POSITION; - } else { // RIGHT_HAND - homes[i] = 180 - HAND_HOME_POSITION; // 右手镜像位置 - } - } else { - // 如果不需要复位手部,保持当前位置 - homes[i] = servo_[i].GetPosition(); - } - } else { - // 腿部和脚部舵机始终复位 - homes[i] = 90; - } - } - - MoveServos(700, homes); - is_otto_resting_ = true; - } - - vTaskDelay(pdMS_TO_TICKS(200)); -} - -bool Otto::GetRestState() { - return is_otto_resting_; -} - -void Otto::SetRestState(bool state) { - is_otto_resting_ = state; -} - -/////////////////////////////////////////////////////////////////// -//-- PREDETERMINED MOTION SEQUENCES -----------------------------// -/////////////////////////////////////////////////////////////////// -//-- Otto movement: Jump -//-- Parameters: -//-- steps: Number of steps -//-- T: Period -//--------------------------------------------------------- -void Otto::Jump(float steps, int period) { - int up[SERVO_COUNT] = {90, 90, 150, 30, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - MoveServos(period, up); - int down[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - MoveServos(period, down); -} - -//--------------------------------------------------------- -//-- Otto gait: Walking (forward or backward) -//-- Parameters: -//-- * steps: Number of steps -//-- * T : Period -//-- * Dir: Direction: FORWARD / BACKWARD -//-- * amount: 手部摆动幅度, 0表示不摆动 -//--------------------------------------------------------- -void Otto::Walk(float steps, int period, int dir, int amount) { - //-- Oscillator parameters for walking - //-- Hip sevos are in phase - //-- Feet servos are in phase - //-- Hip and feet are 90 degrees out of phase - //-- -90 : Walk forward - //-- 90 : Walk backward - //-- Feet servos also have the same offset (for tiptoe a little bit) - int A[SERVO_COUNT] = {30, 30, 30, 30, 0, 0}; - int O[SERVO_COUNT] = {0, 0, 5, -5, HAND_HOME_POSITION - 90, HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(dir * -90), DEG2RAD(dir * -90), 0, 0}; - - // 如果amount>0且有手部舵机,设置手部振幅和相位 - if (amount > 0 && has_hands_) { - // 手臂振幅使用传入的amount参数 - A[LEFT_HAND] = amount; - A[RIGHT_HAND] = amount; - - // 左手与右腿同相,右手与左腿同相,使得机器人走路时手臂自然摆动 - phase_diff[LEFT_HAND] = phase_diff[RIGHT_LEG]; // 左手与右腿同相 - phase_diff[RIGHT_HAND] = phase_diff[LEFT_LEG]; // 右手与左腿同相 - } else { - A[LEFT_HAND] = 0; - A[RIGHT_HAND] = 0; - } - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Turning (left or right) -//-- Parameters: -//-- * Steps: Number of steps -//-- * T: Period -//-- * Dir: Direction: LEFT / RIGHT -//-- * amount: 手部摆动幅度, 0表示不摆动 -//--------------------------------------------------------- -void Otto::Turn(float steps, int period, int dir, int amount) { - //-- Same coordination than for walking (see Otto::walk) - //-- The Amplitudes of the hip's oscillators are not igual - //-- When the right hip servo amplitude is higher, the steps taken by - //-- the right leg are bigger than the left. So, the robot describes an - //-- left arc - int A[SERVO_COUNT] = {30, 30, 30, 30, 0, 0}; - int O[SERVO_COUNT] = {0, 0, 5, -5, HAND_HOME_POSITION - 90, HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(-90), DEG2RAD(-90), 0, 0}; - - if (dir == LEFT) { - A[0] = 30; //-- Left hip servo - A[1] = 0; //-- Right hip servo - } else { - A[0] = 0; - A[1] = 30; - } - - // 如果amount>0且有手部舵机,设置手部振幅和相位 - if (amount > 0 && has_hands_) { - // 手臂振幅使用传入的amount参数 - A[LEFT_HAND] = amount; - A[RIGHT_HAND] = amount; - - // 转向时手臂摆动相位:左手与左腿同相,右手与右腿同相,增强转向效果 - phase_diff[LEFT_HAND] = phase_diff[LEFT_LEG]; // 左手与左腿同相 - phase_diff[RIGHT_HAND] = phase_diff[RIGHT_LEG]; // 右手与右腿同相 - } else { - A[LEFT_HAND] = 0; - A[RIGHT_HAND] = 0; - } - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Lateral bend -//-- Parameters: -//-- steps: Number of bends -//-- T: Period of one bend -//-- dir: RIGHT=Right bend LEFT=Left bend -//--------------------------------------------------------- -void Otto::Bend(int steps, int period, int dir) { - // Parameters of all the movements. Default: Left bend - int bend1[SERVO_COUNT] = {90, 90, 62, 35, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int bend2[SERVO_COUNT] = {90, 90, 62, 105, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int homes[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - - // Time of one bend, constrained in order to avoid movements too fast. - // T=max(T, 600); - // Changes in the parameters if right direction is chosen - if (dir == -1) { - bend1[2] = 180 - 35; - bend1[3] = 180 - 60; // Not 65. Otto is unbalanced - bend2[2] = 180 - 105; - bend2[3] = 180 - 60; - } - - // Time of the bend movement. Fixed parameter to avoid falls - int T2 = 800; - - // Bend movement - for (int i = 0; i < steps; i++) { - MoveServos(T2 / 2, bend1); - MoveServos(T2 / 2, bend2); - vTaskDelay(pdMS_TO_TICKS(period * 0.8)); - MoveServos(500, homes); - } -} - -//--------------------------------------------------------- -//-- Otto gait: Shake a leg -//-- Parameters: -//-- steps: Number of shakes -//-- T: Period of one shake -//-- dir: RIGHT=Right leg LEFT=Left leg -//--------------------------------------------------------- -void Otto::ShakeLeg(int steps, int period, int dir) { - // This variable change the amount of shakes - int numberLegMoves = 2; - - // Parameters of all the movements. Default: Right leg - int shake_leg1[SERVO_COUNT] = {90, 90, 58, 35, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int shake_leg2[SERVO_COUNT] = {90, 90, 58, 120, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int shake_leg3[SERVO_COUNT] = {90, 90, 58, 60, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int homes[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - - // Changes in the parameters if left leg is chosen - if (dir == LEFT) { - shake_leg1[2] = 180 - 35; - shake_leg1[3] = 180 - 58; - shake_leg2[2] = 180 - 120; - shake_leg2[3] = 180 - 58; - shake_leg3[2] = 180 - 60; - shake_leg3[3] = 180 - 58; - } - - // Time of the bend movement. Fixed parameter to avoid falls - int T2 = 1000; - // Time of one shake, constrained in order to avoid movements too fast. - period = period - T2; - period = std::max(period, 200 * numberLegMoves); - - for (int j = 0; j < steps; j++) { - // Bend movement - MoveServos(T2 / 2, shake_leg1); - MoveServos(T2 / 2, shake_leg2); - - // Shake movement - for (int i = 0; i < numberLegMoves; i++) { - MoveServos(period / (2 * numberLegMoves), shake_leg3); - MoveServos(period / (2 * numberLegMoves), shake_leg2); - } - MoveServos(500, homes); // Return to home position - } - - vTaskDelay(pdMS_TO_TICKS(period)); -} - -//--------------------------------------------------------- -//-- Otto movement: Sit (坐下) -//--------------------------------------------------------- -void Otto::Sit() { - int target[SERVO_COUNT] = {120, 60, 0, 180, 45, 135}; - MoveServos(600, target); -} - -//--------------------------------------------------------- -//-- Otto movement: up & down -//-- Parameters: -//-- * steps: Number of jumps -//-- * T: Period -//-- * h: Jump height: SMALL / MEDIUM / BIG -//-- (or a number in degrees 0 - 90) -//--------------------------------------------------------- -void Otto::UpDown(float steps, int period, int height) { - //-- Both feet are 180 degrees out of phase - //-- Feet amplitude and offset are the same - //-- Initial phase for the right foot is -90, so that it starts - //-- in one extreme position (not in the middle) - int A[SERVO_COUNT] = {0, 0, height, height, 0, 0}; - int O[SERVO_COUNT] = {0, 0, height, -height, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(-90), DEG2RAD(90), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto movement: swinging side to side -//-- Parameters: -//-- steps: Number of steps -//-- T : Period -//-- h : Amount of swing (from 0 to 50 aprox) -//--------------------------------------------------------- -void Otto::Swing(float steps, int period, int height) { - //-- Both feets are in phase. The offset is half the amplitude - //-- It causes the robot to swing from side to side - int A[SERVO_COUNT] = {0, 0, height, height, 0, 0}; - int O[SERVO_COUNT] = { - 0, 0, height / 2, -height / 2, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(0), DEG2RAD(0), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto movement: swinging side to side without touching the floor with the heel -//-- Parameters: -//-- steps: Number of steps -//-- T : Period -//-- h : Amount of swing (from 0 to 50 aprox) -//--------------------------------------------------------- -void Otto::TiptoeSwing(float steps, int period, int height) { - //-- Both feets are in phase. The offset is not half the amplitude in order to tiptoe - //-- It causes the robot to swing from side to side - int A[SERVO_COUNT] = {0, 0, height, height, 0, 0}; - int O[SERVO_COUNT] = {0, 0, height, -height, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Jitter -//-- Parameters: -//-- steps: Number of jitters -//-- T: Period of one jitter -//-- h: height (Values between 5 - 25) -//--------------------------------------------------------- -void Otto::Jitter(float steps, int period, int height) { - //-- Both feet are 180 degrees out of phase - //-- Feet amplitude and offset are the same - //-- Initial phase for the right foot is -90, so that it starts - //-- in one extreme position (not in the middle) - //-- h is constrained to avoid hit the feets - height = std::min(25, height); - int A[SERVO_COUNT] = {height, height, 0, 0, 0, 0}; - int O[SERVO_COUNT] = {0, 0, 0, 0, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {DEG2RAD(-90), DEG2RAD(90), 0, 0, 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Ascending & turn (Jitter while up&down) -//-- Parameters: -//-- steps: Number of bends -//-- T: Period of one bend -//-- h: height (Values between 5 - 15) -//--------------------------------------------------------- -void Otto::AscendingTurn(float steps, int period, int height) { - //-- Both feet and legs are 180 degrees out of phase - //-- Initial phase for the right foot is -90, so that it starts - //-- in one extreme position (not in the middle) - //-- h is constrained to avoid hit the feets - height = std::min(13, height); - int A[SERVO_COUNT] = {height, height, height, height, 0, 0}; - int O[SERVO_COUNT] = { - 0, 0, height + 4, -height + 4, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {DEG2RAD(-90), DEG2RAD(90), DEG2RAD(-90), DEG2RAD(90), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Moonwalker. Otto moves like Michael Jackson -//-- Parameters: -//-- Steps: Number of steps -//-- T: Period -//-- h: Height. Typical valures between 15 and 40 -//-- dir: Direction: LEFT / RIGHT -//--------------------------------------------------------- -void Otto::Moonwalker(float steps, int period, int height, int dir) { - //-- This motion is similar to that of the caterpillar robots: A travelling - //-- wave moving from one side to another - //-- The two Otto's feet are equivalent to a minimal configuration. It is known - //-- that 2 servos can move like a worm if they are 120 degrees out of phase - //-- In the example of Otto, the two feet are mirrored so that we have: - //-- 180 - 120 = 60 degrees. The actual phase difference given to the oscillators - //-- is 60 degrees. - //-- Both amplitudes are equal. The offset is half the amplitud plus a little bit of - //- offset so that the robot tiptoe lightly - - int A[SERVO_COUNT] = {0, 0, height, height, 0, 0}; - int O[SERVO_COUNT] = { - 0, 0, height / 2 + 2, -height / 2 - 2, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - int phi = -dir * 90; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(phi), DEG2RAD(-60 * dir + phi), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//---------------------------------------------------------- -//-- Otto gait: Crusaito. A mixture between moonwalker and walk -//-- Parameters: -//-- steps: Number of steps -//-- T: Period -//-- h: height (Values between 20 - 50) -//-- dir: Direction: LEFT / RIGHT -//----------------------------------------------------------- -void Otto::Crusaito(float steps, int period, int height, int dir) { - int A[SERVO_COUNT] = {25, 25, height, height, 0, 0}; - int O[SERVO_COUNT] = { - 0, 0, height / 2 + 4, -height / 2 - 4, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = {90, 90, DEG2RAD(0), DEG2RAD(-60 * dir), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: Flapping -//-- Parameters: -//-- steps: Number of steps -//-- T: Period -//-- h: height (Values between 10 - 30) -//-- dir: direction: FOREWARD, BACKWARD -//--------------------------------------------------------- -void Otto::Flapping(float steps, int period, int height, int dir) { - int A[SERVO_COUNT] = {12, 12, height, height, 0, 0}; - int O[SERVO_COUNT] = { - 0, 0, height - 10, -height + 10, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - double phase_diff[SERVO_COUNT] = { - DEG2RAD(0), DEG2RAD(180), DEG2RAD(-90 * dir), DEG2RAD(90 * dir), 0, 0}; - - //-- Let's oscillate the servos! - Execute(A, O, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- Otto gait: WhirlwindLeg (旋风腿) -//-- Parameters: -//-- steps: Number of steps -//-- period: Period (建议100-800毫秒) -//-- amplitude: amplitude (Values between 20 - 40) -//--------------------------------------------------------- -void Otto::WhirlwindLeg(float steps, int period, int amplitude) { - - - int target[SERVO_COUNT] = {90, 90, 180, 90, 45, 20}; - MoveServos(100, target); - target[RIGHT_FOOT] = 160; - MoveServos(500, target); - vTaskDelay(pdMS_TO_TICKS(1000)); - - int C[SERVO_COUNT] = {90, 90, 180, 160, 45, 20}; - int A[SERVO_COUNT] = {amplitude, 0, 0, 0, amplitude, 0}; - double phase_diff[SERVO_COUNT] = {DEG2RAD(20), 0, 0, 0, DEG2RAD(20), 0}; - Execute2(A, C, period, phase_diff, steps); - -} - -//--------------------------------------------------------- -//-- 手部动作: 举手 -//-- Parameters: -//-- period: 动作时间 -//-- dir: 方向 1=左手, -1=右手, 0=双手 -//--------------------------------------------------------- -void Otto::HandsUp(int period, int dir) { - if (!has_hands_) { - return; - } - - int target[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - - if (dir == 0) { - target[LEFT_HAND] = 170; - target[RIGHT_HAND] = 10; - } else if (dir == LEFT) { - target[LEFT_HAND] = 170; - target[RIGHT_HAND] = servo_[RIGHT_HAND].GetPosition(); - } else if (dir == RIGHT) { - target[RIGHT_HAND] = 10; - target[LEFT_HAND] = servo_[LEFT_HAND].GetPosition(); - } - - MoveServos(period, target); -} - -//--------------------------------------------------------- -//-- 手部动作: 双手放下 -//-- Parameters: -//-- period: 动作时间 -//-- dir: 方向 1=左手, -1=右手, 0=双手 -//--------------------------------------------------------- -void Otto::HandsDown(int period, int dir) { - if (!has_hands_) { - return; - } - - int target[SERVO_COUNT] = {90, 90, 90, 90, HAND_HOME_POSITION, 180 - HAND_HOME_POSITION}; - - if (dir == LEFT) { - target[RIGHT_HAND] = servo_[RIGHT_HAND].GetPosition(); - } else if (dir == RIGHT) { - target[LEFT_HAND] = servo_[LEFT_HAND].GetPosition(); - } - - MoveServos(period, target); -} - -//--------------------------------------------------------- -//-- 手部动作: 挥手 -//-- Parameters: -//-- dir: 方向 LEFT/RIGHT/BOTH -//--------------------------------------------------------- -void Otto::HandWave(int dir) { - if (!has_hands_) { - return; - } - if (dir == LEFT) { - int center_angle[SERVO_COUNT] = {90, 90, 90, 90, 160, 135}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 20, 0}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), 0}; - Execute2(A, center_angle, 300, phase_diff, 5); - } - else if (dir == RIGHT) { - int center_angle[SERVO_COUNT] = {90, 90, 90, 90, 45, 20}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 0, 20}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, 0, DEG2RAD(90)}; - Execute2(A, center_angle, 300, phase_diff, 5); - } - else { - int center_angle[SERVO_COUNT] = {90, 90, 90, 90, 160, 20}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 20, 20}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(90)}; - Execute2(A, center_angle, 300, phase_diff, 5); - } -} - - -//--------------------------------------------------------- -//-- 手部动作: 大风车 -//-- Parameters: -//-- steps: 动作次数 -//-- period: 动作周期(毫秒) -//-- amplitude: 振荡幅度(度) -//--------------------------------------------------------- -void Otto::Windmill(float steps, int period, int amplitude) { - if (!has_hands_) { - return; - } - - int center_angle[SERVO_COUNT] = {90, 90, 90, 90, 90, 90}; - int A[SERVO_COUNT] = {0, 0, 0, 0, amplitude, amplitude}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(90)}; - Execute2(A, center_angle, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- 手部动作: 起飞 -//-- Parameters: -//-- steps: 动作次数 -//-- period: 动作周期(毫秒),数值越小速度越快 -//-- amplitude: 振荡幅度(度) -//--------------------------------------------------------- -void Otto::Takeoff(float steps, int period, int amplitude) { - if (!has_hands_) { - return; - } - - Home(true); - - int center_angle[SERVO_COUNT] = {90, 90, 90, 90, 90, 90}; - int A[SERVO_COUNT] = {0, 0, 0, 0, amplitude, amplitude}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(-90)}; - Execute2(A, center_angle, period, phase_diff, steps); -} - -//--------------------------------------------------------- -//-- 手部动作: 健身 -//-- Parameters: -//-- steps: 动作次数 -//-- period: 动作周期(毫秒) -//-- amplitude: 振荡幅度(度) -//--------------------------------------------------------- -void Otto::Fitness(float steps, int period, int amplitude) { - if (!has_hands_) { - return; - } - int target[SERVO_COUNT] = {90, 90, 90, 0, 160, 135}; - MoveServos(100, target); - target[LEFT_FOOT] = 20; - MoveServos(400, target); - vTaskDelay(pdMS_TO_TICKS(2000)); - - int C[SERVO_COUNT] = {90, 90, 20, 90, 160, 135}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 0, amplitude}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - Execute2(A, C, period, phase_diff, steps); - -} - -//--------------------------------------------------------- -//-- 手部动作: 打招呼 -//-- Parameters: -//-- dir: 方向 LEFT=左手, RIGHT=右手 -//-- steps: 动作次数 -//--------------------------------------------------------- -void Otto::Greeting(int dir, float steps) { - if (!has_hands_) { - return; - } - if (dir == LEFT) { - int target[SERVO_COUNT] = {90, 90, 150, 150, 45, 135}; - MoveServos(400, target); - int C[SERVO_COUNT] = {90, 90, 150, 150, 160, 135}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 20, 0}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - Execute2(A, C, 300, phase_diff, steps); - } - else if (dir == RIGHT) { - int target[SERVO_COUNT] = {90, 90, 30, 30, 45, 135}; - MoveServos(400, target); - int C[SERVO_COUNT] = {90, 90, 30, 30, 45, 20}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 0, 20}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - Execute2(A, C, 300, phase_diff, steps); - } - -} - -//--------------------------------------------------------- -//-- 手部动作: 害羞 -//-- Parameters: -//-- dir: 方向 LEFT=左手, RIGHT=右手 -//-- steps: 动作次数 -//--------------------------------------------------------- -void Otto::Shy(int dir, float steps) { - if (!has_hands_) { - return; - } - - if (dir == LEFT) { - int target[SERVO_COUNT] = {90, 90, 150, 150, 45, 135}; - MoveServos(400, target); - int C[SERVO_COUNT] = {90, 90, 150, 150, 45, 135}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 20, 20}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(-90)}; - Execute2(A, C, 300, phase_diff, steps); - } - else if (dir == RIGHT) { - int target[SERVO_COUNT] = {90, 90, 30, 30, 45, 135}; - MoveServos(400, target); - int C[SERVO_COUNT] = {90, 90, 30, 30, 45, 135}; - int A[SERVO_COUNT] = {0, 0, 0, 0, 0, 20}; - double phase_diff[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(-90)}; - Execute2(A, C, 300, phase_diff, steps); - } -} - -//--------------------------------------------------------- -//-- 手部动作: 广播体操 -//--------------------------------------------------------- -void Otto::RadioCalisthenics() { - if (!has_hands_) { - return; - } - - const int period = 1000; - const float steps = 8.0; - - int C1[SERVO_COUNT] = {90, 90, 90, 90, 145, 45}; - int A1[SERVO_COUNT] = {0, 0, 0, 0, 45, 45}; - double phase_diff1[SERVO_COUNT] = {0, 0, 0, 0, DEG2RAD(90), DEG2RAD(-90)}; - Execute2(A1, C1, period, phase_diff1, steps); - - int C2[SERVO_COUNT] = {90, 90, 115, 65, 90, 90}; - int A2[SERVO_COUNT] = {0, 0, 25, 25, 0, 0}; - double phase_diff2[SERVO_COUNT] = {0, 0, DEG2RAD(90), DEG2RAD(-90), 0, 0}; - Execute2(A2, C2, period, phase_diff2, steps); - - int C3[SERVO_COUNT] = {90, 90, 130, 130, 90, 90}; - int A3[SERVO_COUNT] = {0, 0, 0, 0, 20, 0}; - double phase_diff3[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - Execute2(A3, C3, period, phase_diff3, steps); - - int C4[SERVO_COUNT] = {90, 90, 50, 50, 90, 90}; - int A4[SERVO_COUNT] = {0, 0, 0, 0, 0, 20}; - double phase_diff4[SERVO_COUNT] = {0, 0, 0, 0, 0, 0}; - Execute2(A4, C4, period, phase_diff4, steps); -} - -//--------------------------------------------------------- -//-- 手部动作: 爱的魔力转圈圈 -//--------------------------------------------------------- -void Otto::MagicCircle() { - if (!has_hands_) { - return; - } - - int A[SERVO_COUNT] = {30, 30, 30, 30, 50, 50}; - int O[SERVO_COUNT] = {0, 0, 5, -5, 0, 0}; - double phase_diff[SERVO_COUNT] = {0, 0, DEG2RAD(-90), DEG2RAD(-90), DEG2RAD(-90) , DEG2RAD(90)}; - - Execute(A, O, 700, phase_diff, 40); -} - -//--------------------------------------------------------- -//-- 展示动作:串联多个动作展示 -//--------------------------------------------------------- -void Otto::Showcase() { - if (GetRestState() == true) { - SetRestState(false); - } - - // 1. 往前走3步 - Walk(3, 1000, FORWARD, 50); - vTaskDelay(pdMS_TO_TICKS(500)); - - // 2. 挥挥手 - if (has_hands_) { - HandWave(LEFT); - vTaskDelay(pdMS_TO_TICKS(500)); - } - - // 3. 跳舞(使用广播体操) - if (has_hands_) { - RadioCalisthenics(); - vTaskDelay(pdMS_TO_TICKS(500)); - } - - // 4. 太空步 - Moonwalker(3, 900, 25, LEFT); - vTaskDelay(pdMS_TO_TICKS(500)); - - // 5. 摇摆 - Swing(3, 1000, 30); - vTaskDelay(pdMS_TO_TICKS(500)); - - // 6. 起飞 - if (has_hands_) { - Takeoff(5, 300, 40); - vTaskDelay(pdMS_TO_TICKS(500)); - } - - // 7. 健身 - if (has_hands_) { - Fitness(5, 1000, 25); - vTaskDelay(pdMS_TO_TICKS(500)); - } - - // 8. 往后走3步 - Walk(3, 1000, BACKWARD, 50); -} - -void Otto::EnableServoLimit(int diff_limit) { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].SetLimiter(diff_limit); - } - } -} - -void Otto::DisableServoLimit() { - for (int i = 0; i < SERVO_COUNT; i++) { - if (servo_pins_[i] != -1) { - servo_[i].DisableLimiter(); - } - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.h deleted file mode 100644 index 69b944e4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_movements.h +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef __OTTO_MOVEMENTS_H__ -#define __OTTO_MOVEMENTS_H__ - -#include "driver/gpio.h" -#include "esp_log.h" -#include "esp_timer.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "oscillator.h" - -//-- Constants -#define FORWARD 1 -#define BACKWARD -1 -#define LEFT 1 -#define RIGHT -1 -#define BOTH 0 -#define SMALL 5 -#define MEDIUM 15 -#define BIG 30 - -// -- Servo delta limit default. degree / sec -#define SERVO_LIMIT_DEFAULT 240 - -// -- Servo indexes for easy access -#define LEFT_LEG 0 -#define RIGHT_LEG 1 -#define LEFT_FOOT 2 -#define RIGHT_FOOT 3 -#define LEFT_HAND 4 -#define RIGHT_HAND 5 -#define SERVO_COUNT 6 - -class Otto { -public: - Otto(); - ~Otto(); - - //-- Otto initialization - void Init(int left_leg, int right_leg, int left_foot, int right_foot, int left_hand = -1, - int right_hand = -1); - //-- Attach & detach functions - void AttachServos(); - void DetachServos(); - - //-- Oscillator Trims - void SetTrims(int left_leg, int right_leg, int left_foot, int right_foot, int left_hand = 0, - int right_hand = 0); - - //-- Predetermined Motion Functions - void MoveServos(int time, int servo_target[]); - void MoveSingle(int position, int servo_number); - void OscillateServos(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float cycle); - void Execute2(int amplitude[SERVO_COUNT], int center_angle[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps); - - //-- HOME = Otto at rest position - void Home(bool hands_down = true); - bool GetRestState(); - void SetRestState(bool state); - - //-- Predetermined Motion Functions - void Jump(float steps = 1, int period = 2000); - - void Walk(float steps = 4, int period = 1000, int dir = FORWARD, int amount = 0); - void Turn(float steps = 4, int period = 2000, int dir = LEFT, int amount = 0); - void Bend(int steps = 1, int period = 1400, int dir = LEFT); - void ShakeLeg(int steps = 1, int period = 2000, int dir = RIGHT); - void Sit(); // 坐下 - - void UpDown(float steps = 1, int period = 1000, int height = 20); - void Swing(float steps = 1, int period = 1000, int height = 20); - void TiptoeSwing(float steps = 1, int period = 900, int height = 20); - void Jitter(float steps = 1, int period = 500, int height = 20); - void AscendingTurn(float steps = 1, int period = 900, int height = 20); - - void Moonwalker(float steps = 1, int period = 900, int height = 20, int dir = LEFT); - void Crusaito(float steps = 1, int period = 900, int height = 20, int dir = FORWARD); - void Flapping(float steps = 1, int period = 1000, int height = 20, int dir = FORWARD); - void WhirlwindLeg(float steps = 1, int period = 300, int amplitude = 30); - - // -- 手部动作 - void HandsUp(int period = 1000, int dir = 0); // 双手举起 - void HandsDown(int period = 1000, int dir = 0); // 双手放下 - void HandWave(int dir = LEFT); // 挥手 - void Windmill(float steps = 10, int period = 500, int amplitude = 90); // 大风车 - void Takeoff(float steps = 5, int period = 300, int amplitude = 40); // 起飞 - void Fitness(float steps = 5, int period = 1000, int amplitude = 25); // 健身 - void Greeting(int dir = LEFT, float steps = 5); // 打招呼 - void Shy(int dir = LEFT, float steps = 5); // 害羞 - void RadioCalisthenics(); // 广播体操 - void MagicCircle(); // 爱的魔力转圈圈 - void Showcase(); // 展示动作(串联多个动作) - - // -- Servo limiter - void EnableServoLimit(int speed_limit_degree_per_sec = SERVO_LIMIT_DEFAULT); - void DisableServoLimit(); - -private: - Oscillator servo_[SERVO_COUNT]; - - int servo_pins_[SERVO_COUNT]; - int servo_trim_[SERVO_COUNT]; - - unsigned long final_time_; - unsigned long partial_time_; - float increment_[SERVO_COUNT]; - - bool is_otto_resting_; - bool has_hands_; // 是否有手部舵机 - - void Execute(int amplitude[SERVO_COUNT], int offset[SERVO_COUNT], int period, - double phase_diff[SERVO_COUNT], float steps); - -}; - -#endif // __OTTO_MOVEMENTS_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_robot.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_robot.cc deleted file mode 100644 index bf892c71..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/otto_robot.cc +++ /dev/null @@ -1,343 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "application.h" -#include "codecs/no_audio_codec.h" -#include "button.h" -#include "config.h" -#include "display/lcd_display.h" -#include "lamp_controller.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "otto_emoji_display.h" -#include "power_manager.h" -#include "system_reset.h" -#include "wifi_board.h" -#include "esp32_camera.h" -#include "websocket_control_server.h" - -#define TAG "OttoRobot" - -extern void InitializeOttoController(const HardwareConfig& hw_config); - -class OttoRobot : public WifiBoard { -private: - LcdDisplay* display_; - PowerManager* power_manager_; - Button boot_button_; - WebSocketControlServer* ws_control_server_; - HardwareConfig hw_config_; - AudioCodec* audio_codec_; - i2c_master_bus_handle_t i2c_bus_; - Esp32Camera *camera_; - bool has_camera_; - - bool DetectHardwareVersion() { - ledc_timer_config_t ledc_timer = { - .speed_mode = LEDC_LOW_SPEED_MODE, - .duty_resolution = LEDC_TIMER_2_BIT, - .timer_num = LEDC_TIMER, - .freq_hz = CAMERA_XCLK_FREQ, - .clk_cfg = LEDC_AUTO_CLK, - }; - esp_err_t ret = ledc_timer_config(&ledc_timer); - if (ret != ESP_OK) { - return false; - } - - ledc_channel_config_t ledc_channel = { - .gpio_num = CAMERA_XCLK, - .speed_mode = LEDC_LOW_SPEED_MODE, - .channel = LEDC_CHANNEL, - .intr_type = LEDC_INTR_DISABLE, - .timer_sel = LEDC_TIMER, - .duty = 2, - .hpoint = 0, - }; - ret = ledc_channel_config(&ledc_channel); - if (ret != ESP_OK) { - return false; - } - - vTaskDelay(pdMS_TO_TICKS(100)); - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = CAMERA_VERSION_CONFIG.i2c_sda_pin, - .scl_io_num = CAMERA_VERSION_CONFIG.i2c_scl_pin, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - - ret = i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_); - if (ret != ESP_OK) { - ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL, 0); - return false; - } - const uint8_t camera_addresses[] = {0x30, 0x3C, 0x21, 0x60}; - bool camera_found = false; - - for (size_t i = 0; i < sizeof(camera_addresses); i++) { - uint8_t addr = camera_addresses[i]; - i2c_device_config_t dev_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = addr, - .scl_speed_hz = 100000, - }; - - i2c_master_dev_handle_t dev_handle; - ret = i2c_master_bus_add_device(i2c_bus_, &dev_cfg, &dev_handle); - if (ret == ESP_OK) { - uint8_t reg_addr = 0x0A; - uint8_t data[2]; - ret = i2c_master_transmit_receive(dev_handle, ®_addr, 1, data, 2, 200); - if (ret == ESP_OK) { - camera_found = true; - i2c_master_bus_rm_device(dev_handle); - break; - } - i2c_master_bus_rm_device(dev_handle); - } - } - - if (!camera_found) { - i2c_del_master_bus(i2c_bus_); - i2c_bus_ = nullptr; - ledc_stop(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL, 0); - } - return camera_found; - } - - void InitializePowerManager() { - power_manager_ = new PowerManager( - hw_config_.power_charge_detect_pin, - hw_config_.power_adc_unit, - hw_config_.power_adc_channel - ); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = hw_config_.display_mosi_pin; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = hw_config_.display_clk_pin; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = hw_config_.display_cs_pin; - io_config.dc_gpio_num = hw_config_.display_dc_pin; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = hw_config_.display_rst_pin; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new OttoEmojiDisplay( - panel_io, panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeOttoController() { - ::InitializeOttoController(hw_config_); - } - -public: - const HardwareConfig& GetHardwareConfig() const { - return hw_config_; - } - -private: - - void InitializeWebSocketControlServer() { - ws_control_server_ = new WebSocketControlServer(); - if (!ws_control_server_->Start(8080)) { - delete ws_control_server_; - ws_control_server_ = nullptr; - } - } - - void StartNetwork() override { - WifiBoard::StartNetwork(); - vTaskDelay(pdMS_TO_TICKS(1000)); - - InitializeWebSocketControlServer(); - } - - bool InitializeCamera() { - if (!has_camera_ || i2c_bus_ == nullptr) { - return false; - } - - try { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_D0, - [1] = CAMERA_D1, - [2] = CAMERA_D2, - [3] = CAMERA_D3, - [4] = CAMERA_D4, - [5] = CAMERA_D5, - [6] = CAMERA_D6, - [7] = CAMERA_D7, - }, - .vsync_io = CAMERA_VSYNC, - .de_io = CAMERA_HSYNC, - .pclk_io = CAMERA_PCLK, - .xclk_io = CAMERA_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 100000, - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_RESET, - .pwdn_pin = CAMERA_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = CAMERA_XCLK_FREQ, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - camera_->SetVFlip(true); - return true; - } catch (...) { - camera_ = nullptr; - return false; - } - } - - void InitializeAudioCodec() { - if (hw_config_.audio_use_simplex) { - audio_codec_ = new NoAudioCodecSimplex( - hw_config_.audio_input_sample_rate, - hw_config_.audio_output_sample_rate, - hw_config_.audio_i2s_spk_gpio_bclk, - hw_config_.audio_i2s_spk_gpio_lrck, - hw_config_.audio_i2s_spk_gpio_dout, - hw_config_.audio_i2s_mic_gpio_sck, - hw_config_.audio_i2s_mic_gpio_ws, - hw_config_.audio_i2s_mic_gpio_din - ); - } else { - audio_codec_ = new NoAudioCodecDuplex( - hw_config_.audio_input_sample_rate, - hw_config_.audio_output_sample_rate, - hw_config_.audio_i2s_gpio_bclk, - hw_config_.audio_i2s_gpio_ws, - hw_config_.audio_i2s_gpio_dout, - hw_config_.audio_i2s_gpio_din - ); - } - } - -public: - OttoRobot() : boot_button_(BOOT_BUTTON_GPIO), - audio_codec_(nullptr), - i2c_bus_(nullptr), - camera_(nullptr), - has_camera_(false) { - - has_camera_ = DetectHardwareVersion(); - - if (has_camera_) - hw_config_ = CAMERA_VERSION_CONFIG; - else - hw_config_ = NON_CAMERA_VERSION_CONFIG; - - - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializePowerManager(); - InitializeAudioCodec(); - - if (has_camera_) { - if (!InitializeCamera()) { - has_camera_ = false; - } - } - - InitializeOttoController(); - ws_control_server_ = nullptr; - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec *GetAudioCodec() override { - return audio_codec_; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight* backlight = nullptr; - if (backlight == nullptr) { - backlight = new PwmBacklight(hw_config_.display_backlight_pin, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - } - return backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - charging = power_manager_->IsCharging(); - discharging = !charging; - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual Camera *GetCamera() override { - return has_camera_ ? camera_ : nullptr; - } -}; - -DECLARE_BOARD(OttoRobot); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/power_manager.h deleted file mode 100644 index 925319f7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/power_manager.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef __POWER_MANAGER_H__ -#define __POWER_MANAGER_H__ - -#include -#include -#include -#include - -class PowerManager { -private: - // 电池电量区间-分压电阻为2个100k - static constexpr struct { - uint16_t adc; - uint8_t level; - } BATTERY_LEVELS[] = {{2050, 0}, {2450, 100}}; - static constexpr size_t BATTERY_LEVELS_COUNT = 2; - static constexpr size_t ADC_VALUES_COUNT = 10; - - esp_timer_handle_t timer_handle_ = nullptr; - gpio_num_t charging_pin_; - adc_unit_t adc_unit_; - adc_channel_t adc_channel_; - uint16_t adc_values_[ADC_VALUES_COUNT]; - size_t adc_values_index_ = 0; - size_t adc_values_count_ = 0; - uint8_t battery_level_ = 100; - bool is_charging_ = false; - inline static bool battery_update_paused_ = false; // 静态标志:是否暂停电量更新 - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // 如果电量更新被暂停(动作进行中),则跳过更新 - if (battery_update_paused_) { - return; - } - - ReadBatteryAdcData(); - - if (charging_pin_ == GPIO_NUM_NC) { - is_charging_ = false; - } else { - is_charging_ = gpio_get_level(charging_pin_) == 0; - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, adc_channel_, &adc_value)); - - adc_values_[adc_values_index_] = adc_value; - adc_values_index_ = (adc_values_index_ + 1) % ADC_VALUES_COUNT; - if (adc_values_count_ < ADC_VALUES_COUNT) { - adc_values_count_++; - } - - uint32_t average_adc = 0; - for (size_t i = 0; i < adc_values_count_; i++) { - average_adc += adc_values_[i]; - } - average_adc /= adc_values_count_; - - CalculateBatteryLevel(average_adc); - - // ESP_LOGI("PowerManager", "ADC值: %d 平均值: %ld 电量: %u%%", adc_value, average_adc, - // battery_level_); - } - - void CalculateBatteryLevel(uint32_t average_adc) { - if (average_adc <= BATTERY_LEVELS[0].adc) { - battery_level_ = 0; - } else if (average_adc >= BATTERY_LEVELS[BATTERY_LEVELS_COUNT - 1].adc) { - battery_level_ = 100; - } else { - float ratio = static_cast(average_adc - BATTERY_LEVELS[0].adc) / - (BATTERY_LEVELS[1].adc - BATTERY_LEVELS[0].adc); - battery_level_ = ratio * 100; - } - } - -public: - PowerManager(gpio_num_t charging_pin, adc_unit_t adc_unit = ADC_UNIT_2, - adc_channel_t adc_channel = ADC_CHANNEL_3) - : charging_pin_(charging_pin), adc_unit_(adc_unit), adc_channel_(adc_channel) { - - if (charging_pin_ != GPIO_NUM_NC) { - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - ESP_LOGI("PowerManager", "充电检测引脚配置完成: GPIO%d", charging_pin_); - } else { - ESP_LOGI("PowerManager", "充电检测引脚未配置,不进行充电状态检测"); - } - - esp_timer_create_args_t timer_args = { - .callback = - [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); // 1秒 - - InitializeAdc(); - } - - void InitializeAdc() { - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = adc_unit_, - .clk_src = ADC_RTC_CLK_SRC_DEFAULT, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - - ESP_ERROR_CHECK( - adc_oneshot_config_channel(adc_handle_, adc_channel_, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { return is_charging_; } - - uint8_t GetBatteryLevel() { return battery_level_; } - - // 暂停/恢复电量更新(用于动作执行时屏蔽更新) - static void PauseBatteryUpdate() { battery_update_paused_ = true; } - static void ResumeBatteryUpdate() { battery_update_paused_ = false; } -}; -#endif // __POWER_MANAGER_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.cc deleted file mode 100644 index a38944b8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.cc +++ /dev/null @@ -1,191 +0,0 @@ -#include "websocket_control_server.h" -#include "mcp_server.h" -#include -#include -#include -#include -#include -#include - -static const char* TAG = "WSControl"; - -WebSocketControlServer* WebSocketControlServer::instance_ = nullptr; - -WebSocketControlServer::WebSocketControlServer() : server_handle_(nullptr) { - instance_ = this; -} - -WebSocketControlServer::~WebSocketControlServer() { - Stop(); - instance_ = nullptr; -} - -esp_err_t WebSocketControlServer::ws_handler(httpd_req_t *req) { - if (instance_ == nullptr) { - return ESP_FAIL; - } - - if (req->method == HTTP_GET) { - ESP_LOGI(TAG, "Handshake done, the new connection was opened"); - instance_->AddClient(req); - return ESP_OK; - } - - httpd_ws_frame_t ws_pkt; - uint8_t *buf = NULL; - memset(&ws_pkt, 0, sizeof(httpd_ws_frame_t)); - ws_pkt.type = HTTPD_WS_TYPE_TEXT; - - /* Set max_len = 0 to get the frame len */ - esp_err_t ret = httpd_ws_recv_frame(req, &ws_pkt, 0); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "httpd_ws_recv_frame failed to get frame len with %d", ret); - return ret; - } - ESP_LOGI(TAG, "frame len is %d", ws_pkt.len); - - if (ws_pkt.len) { - /* ws_pkt.len + 1 is for NULL termination as we are expecting a string */ - buf = (uint8_t*)calloc(1, ws_pkt.len + 1); - if (buf == NULL) { - ESP_LOGE(TAG, "Failed to calloc memory for buf"); - return ESP_ERR_NO_MEM; - } - ws_pkt.payload = buf; - /* Set max_len = ws_pkt.len to get the frame payload */ - ret = httpd_ws_recv_frame(req, &ws_pkt, ws_pkt.len); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "httpd_ws_recv_frame failed with %d", ret); - free(buf); - return ret; - } - ESP_LOGI(TAG, "Got packet with message: %s", ws_pkt.payload); - } - - ESP_LOGI(TAG, "Packet type: %d", ws_pkt.type); - - if (ws_pkt.type == HTTPD_WS_TYPE_CLOSE) { - ESP_LOGI(TAG, "WebSocket close frame received"); - instance_->RemoveClient(req); - free(buf); - return ESP_OK; - } - - if (ws_pkt.type == HTTPD_WS_TYPE_TEXT) { - if (ws_pkt.len > 0 && buf != nullptr) { - buf[ws_pkt.len] = '\0'; - instance_->HandleMessage(req, (const char*)buf, ws_pkt.len); - } - } else { - ESP_LOGW(TAG, "Unsupported frame type: %d", ws_pkt.type); - } - - free(buf); - return ESP_OK; -} - -bool WebSocketControlServer::Start(int port) { - httpd_config_t config = HTTPD_DEFAULT_CONFIG(); - config.server_port = port; - config.max_open_sockets = 7; - - httpd_uri_t ws_uri = { - .uri = "/ws", - .method = HTTP_GET, - .handler = ws_handler, - .user_ctx = nullptr, - .is_websocket = true - }; - - if (httpd_start(&server_handle_, &config) == ESP_OK) { - httpd_register_uri_handler(server_handle_, &ws_uri); - ESP_LOGI(TAG, "WebSocket server started on port %d", port); - return true; - } - - ESP_LOGE(TAG, "Failed to start WebSocket server"); - return false; -} - -void WebSocketControlServer::Stop() { - if (server_handle_) { - httpd_stop(server_handle_); - server_handle_ = nullptr; - clients_.clear(); - ESP_LOGI(TAG, "WebSocket server stopped"); - } -} - -void WebSocketControlServer::HandleMessage(httpd_req_t *req, const char* data, size_t len) { - if (data == nullptr || len == 0) { - ESP_LOGE(TAG, "Invalid message: data is null or len is 0"); - return; - } - - if (len > 4096) { - ESP_LOGE(TAG, "Message too long: %zu bytes", len); - return; - } - - char* temp_buf = (char*)malloc(len + 1); - if (temp_buf == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory"); - return; - } - memcpy(temp_buf, data, len); - temp_buf[len] = '\0'; - - cJSON* root = cJSON_Parse(temp_buf); - free(temp_buf); - - if (root == nullptr) { - ESP_LOGE(TAG, "Failed to parse JSON"); - return; - } - - // 支持两种格式: - // 1. 完整格式:{"type":"mcp","payload":{...}} - // 2. 简化格式:直接是MCP payload对象 - - cJSON* payload = nullptr; - cJSON* type = cJSON_GetObjectItem(root, "type"); - - if (type && cJSON_IsString(type) && strcmp(type->valuestring, "mcp") == 0) { - payload = cJSON_GetObjectItem(root, "payload"); - if (payload != nullptr) { - cJSON_DetachItemViaPointer(root, payload); - McpServer::GetInstance().ParseMessage(payload); - cJSON_Delete(payload); - } - } else { - payload = cJSON_Duplicate(root, 1); - if (payload != nullptr) { - McpServer::GetInstance().ParseMessage(payload); - cJSON_Delete(payload); - } - } - - if (payload == nullptr) { - ESP_LOGE(TAG, "Invalid message format or failed to parse"); - } - - cJSON_Delete(root); -} - -void WebSocketControlServer::AddClient(httpd_req_t *req) { - int sock_fd = httpd_req_to_sockfd(req); - if (clients_.find(sock_fd) == clients_.end()) { - clients_[sock_fd] = req; - ESP_LOGI(TAG, "Client connected: %d (total: %zu)", sock_fd, clients_.size()); - } -} - -void WebSocketControlServer::RemoveClient(httpd_req_t *req) { - int sock_fd = httpd_req_to_sockfd(req); - clients_.erase(sock_fd); - ESP_LOGI(TAG, "Client disconnected: %d (total: %zu)", sock_fd, clients_.size()); -} - -size_t WebSocketControlServer::GetClientCount() const { - return clients_.size(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.h deleted file mode 100644 index f8e5e418..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/otto-robot/websocket_control_server.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef WEBSOCKET_CONTROL_SERVER_H -#define WEBSOCKET_CONTROL_SERVER_H - -#include -#include -#include -#include - -class WebSocketControlServer { -public: - WebSocketControlServer(); - ~WebSocketControlServer(); - - bool Start(int port = 8080); - - void Stop(); - - size_t GetClientCount() const; - -private: - httpd_handle_t server_handle_; - std::map clients_; - - static esp_err_t ws_handler(httpd_req_t *req); - - void HandleMessage(httpd_req_t *req, const char* data, size_t len); - void AddClient(httpd_req_t *req); - void RemoveClient(httpd_req_t *req); - static WebSocketControlServer* instance_; -}; - -#endif // WEBSOCKET_CONTROL_SERVER_H - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README.md deleted file mode 100644 index aa910109..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# 编译命令 - -## 一键编译 - -```bash -python scripts/release.py sensecap-watcher -``` - -## 手动配置编译 - -```bash -idf.py set-target esp32s3 -``` - -**配置** - -```bash -idf.py menuconfig -``` - -选择板子 - -``` -Xiaozhi Assistant -> Board Type -> SenseCAP Watcher -``` - -watcher 中一些额外的配置项如下,需要在menuconfig 中选择. - -``` -CONFIG_BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER=y -CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions/v2/32m.csv" -CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y -CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n -CONFIG_IDF_EXPERIMENTAL_FEATURES=y -``` - -## 编译烧入 - -```bash -idf.py -DBOARD_NAME=sensecap-watcher build flash -``` - -注意: 如果当前设备出货之前是SenseCAP 固件(非小智版本),请特别小心处理闪存固件分区地址,以避免错误擦除 SenseCAP Watcher 的自身设备信息(EUI 等),否则设备即使恢复成SenseCAP固件也无法正确连接到 SenseCraft 服务器!所以在刷写固件之前,请务必记录设备的相关必要信息,以确保有恢复的方法! - -您可以使用以下命令备份生产信息 - -```bash -# firstly backup the factory information partition which contains the credentials for connecting the SenseCraft server -esptool.py --chip esp32s3 --baud 2000000 --before default_reset --after hard_reset --no-stub read_flash 0x9000 204800 nvsfactory.bin - -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README_en.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README_en.md deleted file mode 100644 index 27338a87..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/README_en.md +++ /dev/null @@ -1,53 +0,0 @@ -# Build Instructions - -## One-click Build - -```bash -python scripts/release.py sensecap-watcher -c config_en.json -``` - -## Manual Configuration and Build - -```bash -idf.py set-target esp32s3 -``` - -**Configuration** - -```bash -idf.py menuconfig -``` - -Select the board: - -``` -Xiaozhi Assistant -> Board Type -> SenseCAP Watcher -``` - -There are some additional configuration options for the watcher. Please select them in menuconfig: - -``` -CONFIG_BOARD_TYPE_SEEED_STUDIO_SENSECAP_WATCHER=y -CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y -CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions/v2/32m.csv" -CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y -CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n -CONFIG_IDF_EXPERIMENTAL_FEATURES=y -CONFIG_LANGUAGE_EN_US=y -CONFIG_SR_WN_WN9_JARVIS_TTS=y -``` - -## Build and Flash - -```bash -idf.py -DBOARD_NAME=sensecap-watcher-en build flash -``` - -Note: If your device was previously shipped with the SenseCAP firmware (not the Xiaozhi version), please be very careful with the flash partition addresses to avoid accidentally erasing the device information (such as EUI) of the SenseCAP Watcher. Otherwise, even if you restore the SenseCAP firmware, the device may not be able to connect to the SenseCraft server correctly! Therefore, before flashing the firmware, be sure to record the necessary device information to ensure you have a way to recover it! - -You can use the following command to back up the factory information: - -```bash -# Firstly backup the factory information partition which contains the credentials for connecting the SenseCraft server -esptool.py --chip esp32s3 --baud 2000000 --before default_reset --after hard_reset --no-stub read_flash 0x9000 204800 nvsfactory.bin -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.h deleted file mode 100644 index 8d1f5dc1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.h +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include "driver/spi_common.h" -#include "esp_io_expander.h" - -// SSCMA Client Configuration -#define CONFIG_SSCMA_EVENT_QUEUE_SIZE 1 -#define CONFIG_SSCMA_TX_BUFFER_SIZE 8192 -#define CONFIG_SSCMA_RX_BUFFER_SIZE 98304 - -// SSCMA Client Process Task -#define CONFIG_SSCMA_PROCESS_TASK_STACK_SIZE 10240 -#define CONFIG_SSCMA_PROCESS_TASK_PRIORITY 5 -#define CONFIG_SSCMA_PROCESS_TASK_AFFINITY_CPU1 1 -#define CONFIG_SSCMA_PROCESS_TASK_AFFINITY 1 -#define CONFIG_SSCMA_PROCESS_TASK_STACK_ALLOC_EXTERNAL 1 - -// SSCMA Client Monitor Task -#define CONFIG_SSCMA_MONITOR_TASK_STACK_SIZE 10240 -#define CONFIG_SSCMA_MONITOR_TASK_PRIORITY 4 -#define CONFIG_SSCMA_MONITOR_TASK_AFFINITY_CPU1 1 -#define CONFIG_SSCMA_MONITOR_TASK_AFFINITY 1 -#define CONFIG_SSCMA_MONITOR_TASK_STACK_ALLOC_EXTERNAL 1 -#define CONFIG_SSCMA_ALLOC_SMALL_SHORTTERM_MEM_EXTERNALLY 1 - -/* General I2C */ -#define BSP_GENERAL_I2C_NUM (I2C_NUM_0) -#define BSP_GENERAL_I2C_SDA (GPIO_NUM_47) -#define BSP_GENERAL_I2C_SCL (GPIO_NUM_48) - -/* Audio */ -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE false - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_16 - - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7243E_ADDR (0x14) - - - -#define BUILTIN_LED_GPIO GPIO_NUM_40 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -/* Expander */ -#define BSP_IO_EXPANDER_INT (GPIO_NUM_2) -#define DRV_IO_EXP_INPUT_MASK (0x20ff) // P0.0 ~ P0.7 | P1.3 -#define DRV_IO_EXP_OUTPUT_MASK (0xDf00) // P1.0 ~ P1.7 & ~P1.3 - -/* Expander IO PIN */ -#define BSP_PWR_CHRG_DET (IO_EXPANDER_PIN_NUM_0) -#define BSP_PWR_STDBY_DET (IO_EXPANDER_PIN_NUM_1) -#define BSP_PWR_VBUS_IN_DET (IO_EXPANDER_PIN_NUM_2) -#define BSP_PWR_SDCARD (IO_EXPANDER_PIN_NUM_8) -#define BSP_PWR_LCD (IO_EXPANDER_PIN_NUM_9) -#define BSP_PWR_SYSTEM (IO_EXPANDER_PIN_NUM_10) -#define BSP_PWR_AI_CHIP (IO_EXPANDER_PIN_NUM_11) -#define BSP_PWR_CODEC_PA (IO_EXPANDER_PIN_NUM_12) -#define BSP_PWR_BAT_DET (IO_EXPANDER_PIN_NUM_13) -#define BSP_PWR_GROVE (IO_EXPANDER_PIN_NUM_14) -#define BSP_PWR_BAT_ADC (IO_EXPANDER_PIN_NUM_15) - -#define BSP_PWR_START_UP (BSP_PWR_SDCARD | BSP_PWR_LCD | BSP_PWR_SYSTEM | BSP_PWR_AI_CHIP | BSP_PWR_CODEC_PA | BSP_PWR_GROVE | BSP_PWR_BAT_ADC) - -#define BSP_KNOB_BTN (IO_EXPANDER_PIN_NUM_3) -#define BSP_KNOB_A_PIN GPIO_NUM_41 -#define BSP_KNOB_B_PIN GPIO_NUM_42 - -/* SPI */ -#define BSP_SPI2_HOST_SCLK (GPIO_NUM_4) -#define BSP_SPI2_HOST_MOSI (GPIO_NUM_5) -#define BSP_SPI2_HOST_MISO (GPIO_NUM_6) - -/* SD Card */ -#define BSP_SD_SPI_NUM (SPI2_HOST) -#define BSP_SD_SPI_CS (GPIO_NUM_46) -#define BSP_SD_GPIO_DET (IO_EXPANDER_PIN_NUM_4) - -/* QSPI */ -#define BSP_SPI3_HOST_PCLK (GPIO_NUM_7) -#define BSP_SPI3_HOST_DATA0 (GPIO_NUM_9) -#define BSP_SPI3_HOST_DATA1 (GPIO_NUM_1) -#define BSP_SPI3_HOST_DATA2 (GPIO_NUM_14) -#define BSP_SPI3_HOST_DATA3 (GPIO_NUM_13) - -/* LCD */ -#define BSP_LCD_SPI_NUM (SPI3_HOST) -#define BSP_LCD_SPI_CS (GPIO_NUM_45) -#define BSP_LCD_GPIO_RST (GPIO_NUM_NC) -#define BSP_LCD_GPIO_DC (GPIO_NUM_1) - -#define DISPLAY_WIDTH 412 -#define DISPLAY_HEIGHT 412 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_8 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -/* Touch */ -#define BSP_TOUCH_I2C_NUM (1) -#define BSP_TOUCH_GPIO_INT (IO_EXPANDER_PIN_NUM_5) -#define BSP_TOUCH_I2C_SDA (GPIO_NUM_39) -#define BSP_TOUCH_I2C_SCL (GPIO_NUM_38) -#define BSP_TOUCH_I2C_CLK (400000) - -/* Settings */ -#define DRV_LCD_PIXEL_CLK_HZ (40 * 1000 * 1000) -#define DRV_LCD_CMD_BITS (32) -#define DRV_LCD_PARAM_BITS (8) -#define DRV_LCD_RGB_ELEMENT_ORDER (LCD_RGB_ELEMENT_ORDER_RGB) -#define DRV_LCD_BITS_PER_PIXEL (16) - -#define CONFIG_BSP_LCD_SPI_DMA_SIZE_DIV 16 - -/* ADC */ -#define BSP_BAT_ADC_CHAN (ADC_CHANNEL_2) // GPIO3 -#define BSP_BAT_ADC_ATTEN (ADC_ATTEN_DB_2_5) // 0 ~ 1100 mV -#define BSP_BAT_VOL_RATIO ((62 + 20) / 20) - -/* Himax */ -#define BSP_SSCMA_CLIENT_RST (IO_EXPANDER_PIN_NUM_7) -#define BSP_SSCMA_CLIENT_RST_USE_EXPANDER (true) - -#define BSP_SSCMA_CLIENT_SPI_NUM (SPI2_HOST) -#define BSP_SSCMA_CLIENT_SPI_CS (GPIO_NUM_21) -#define BSP_SSCMA_CLIENT_SPI_SYNC (IO_EXPANDER_PIN_NUM_6) -#define BSP_SSCMA_CLIENT_SPI_SYNC_USE_EXPANDER (true) -#define BSP_SSCMA_CLIENT_SPI_CLK (12 * 1000 * 1000) - -#define BSP_SSCMA_FLASHER_UART_NUM (UART_NUM_1) -#define BSP_SSCMA_FLASHER_UART_TX (GPIO_NUM_17) -#define BSP_SSCMA_FLASHER_UART_RX (GPIO_NUM_18) -#define BSP_SSCMA_FLASHER_UART_BAUD_RATE (921600) - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.json deleted file mode 100644 index 177fad74..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "sensecap-watcher", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/32m.csv\"", - "CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y", - "CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n", - "CONFIG_IDF_EXPERIMENTAL_FEATURES=y", - "CONFIG_FREERTOS_HZ=1000" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config_en.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config_en.json deleted file mode 100644 index 0435fa3d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/config_en.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "sensecap-watcher-en", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_32MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/32m.csv\"", - "CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH=y", - "CONFIG_ESPTOOLPY_FLASH_MODE_AUTO_DETECT=n", - "CONFIG_IDF_EXPERIMENTAL_FEATURES=y", - "CONFIG_FREERTOS_HZ=1000", - "CONFIG_LANGUAGE_EN_US=y", - "CONFIG_SR_WN_WN9_JARVIS_TTS=y", - "CONFIG_SR_WN_WN9_SOPHIA_TTS=y", - "CONFIG_SR_WN_WN9_NIHAOXIAOZHI_TTS=n" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.cc deleted file mode 100644 index ac474d77..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.cc +++ /dev/null @@ -1,214 +0,0 @@ -#include "sensecap_audio_codec.h" - -#include -#include -#include - -static const char TAG[] = "SensecapAudioCodec"; - -SensecapAudioCodec::SensecapAudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7243e_addr, bool input_reference) { - duplex_ = true; // 是否双工 - input_reference_ = input_reference; // 是否使用参考输入,实现回声消除 - input_channels_ = input_reference_ ? 2 : 1; // 输入通道数 - input_sample_rate_ = input_sample_rate; - output_sample_rate_ = output_sample_rate; - - CreateDuplexChannels(mclk, bclk, ws, dout, din); - - // Do initialize of related interface: data_if, ctrl_if and gpio_if - audio_codec_i2s_cfg_t i2s_cfg = { - .port = I2S_NUM_0, - .rx_handle = rx_handle_, - .tx_handle = tx_handle_, - }; - data_if_ = audio_codec_new_i2s_data(&i2s_cfg); - assert(data_if_ != NULL); - - // Output - audio_codec_i2c_cfg_t i2c_cfg = { - .port = (i2c_port_t)0, - .addr = es8311_addr, - .bus_handle = i2c_master_handle, - }; - out_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(out_ctrl_if_ != NULL); - - gpio_if_ = audio_codec_new_gpio(); - assert(gpio_if_ != NULL); - - es8311_codec_cfg_t es8311_cfg = {}; - es8311_cfg.ctrl_if = out_ctrl_if_; - es8311_cfg.gpio_if = gpio_if_; - es8311_cfg.codec_mode = ESP_CODEC_DEV_WORK_MODE_DAC; - es8311_cfg.pa_pin = pa_pin; - es8311_cfg.use_mclk = true; - es8311_cfg.hw_gain.pa_voltage = 5.0; - es8311_cfg.hw_gain.codec_dac_voltage = 3.3; - out_codec_if_ = es8311_codec_new(&es8311_cfg); - assert(out_codec_if_ != NULL); - - esp_codec_dev_cfg_t dev_cfg = { - .dev_type = ESP_CODEC_DEV_TYPE_OUT, - .codec_if = out_codec_if_, - .data_if = data_if_, - }; - output_dev_ = esp_codec_dev_new(&dev_cfg); - assert(output_dev_ != NULL); - - // Input - i2c_cfg.addr = es7243e_addr << 1; - in_ctrl_if_ = audio_codec_new_i2c_ctrl(&i2c_cfg); - assert(in_ctrl_if_ != NULL); - - es7243e_codec_cfg_t es7243e_cfg = {}; - es7243e_cfg.ctrl_if = in_ctrl_if_; - in_codec_if_ = es7243e_codec_new(&es7243e_cfg); - assert(in_codec_if_ != NULL); - - dev_cfg.dev_type = ESP_CODEC_DEV_TYPE_IN; - dev_cfg.codec_if = in_codec_if_; - input_dev_ = esp_codec_dev_new(&dev_cfg); - assert(input_dev_ != NULL); - - esp_codec_set_disable_when_closed(output_dev_, false); - esp_codec_set_disable_when_closed(input_dev_, false); - - ESP_LOGI(TAG, "SensecapAudioDevice initialized"); -} - -SensecapAudioCodec::~SensecapAudioCodec() { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - esp_codec_dev_delete(output_dev_); - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - esp_codec_dev_delete(input_dev_); - - audio_codec_delete_codec_if(in_codec_if_); - audio_codec_delete_ctrl_if(in_ctrl_if_); - audio_codec_delete_codec_if(out_codec_if_); - audio_codec_delete_ctrl_if(out_ctrl_if_); - audio_codec_delete_gpio_if(gpio_if_); - audio_codec_delete_data_if(data_if_); -} - -void SensecapAudioCodec::CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din) { - assert(input_sample_rate_ == output_sample_rate_); - - i2s_chan_config_t chan_cfg = { - .id = I2S_NUM_0, - .role = I2S_ROLE_MASTER, - .dma_desc_num = AUDIO_CODEC_DMA_DESC_NUM, - .dma_frame_num = AUDIO_CODEC_DMA_FRAME_NUM, - .auto_clear_after_cb = true, - .auto_clear_before_cb = false, - .intr_priority = 0, - }; - ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle_, &rx_handle_)); - - i2s_std_config_t std_cfg = { - .clk_cfg = { - .sample_rate_hz = (uint32_t)output_sample_rate_, - .clk_src = I2S_CLK_SRC_DEFAULT, - .ext_clk_freq_hz = 0, - .mclk_multiple = I2S_MCLK_MULTIPLE_256 - }, - .slot_cfg = { - .data_bit_width = I2S_DATA_BIT_WIDTH_16BIT, - .slot_bit_width = I2S_SLOT_BIT_WIDTH_AUTO, - .slot_mode = I2S_SLOT_MODE_MONO, - .slot_mask = I2S_STD_SLOT_BOTH, - .ws_width = I2S_DATA_BIT_WIDTH_16BIT, - .ws_pol = false, - .bit_shift = true, - .left_align = true, - .big_endian = false, - .bit_order_lsb = false - }, - .gpio_cfg = { - .mclk = mclk, - .bclk = bclk, - .ws = ws, - .dout = dout, - .din = din, - .invert_flags = { - .mclk_inv = false, - .bclk_inv = false, - .ws_inv = false - } - } - }; - - ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle_, &std_cfg)); - - std_cfg.slot_cfg.slot_mask = I2S_STD_SLOT_RIGHT; - ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle_, &std_cfg)); - ESP_LOGI(TAG, "Duplex channels created"); -} - -void SensecapAudioCodec::SetOutputVolume(int volume) { - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, volume)); - AudioCodec::SetOutputVolume(volume); -} - -void SensecapAudioCodec::EnableInput(bool enable) { - if (enable == input_enabled_) { - return; - } - if (enable) { - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 2, - .channel_mask = ESP_CODEC_DEV_MAKE_CHANNEL_MASK(1), - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(input_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_in_gain(input_dev_, 27.0)); - } else { - ESP_ERROR_CHECK(esp_codec_dev_close(input_dev_)); - } - AudioCodec::EnableInput(enable); -} - -void SensecapAudioCodec::EnableOutput(bool enable) { - if (enable == output_enabled_) { - return; - } - if (enable) { - // Play 16bit 1 channel - esp_codec_dev_sample_info_t fs = { - .bits_per_sample = 16, - .channel = 1, - .channel_mask = 0, - .sample_rate = (uint32_t)output_sample_rate_, - .mclk_multiple = 0, - }; - ESP_ERROR_CHECK(esp_codec_dev_open(output_dev_, &fs)); - ESP_ERROR_CHECK(esp_codec_dev_set_out_vol(output_dev_, output_volume_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 1); - } - } - else { - ESP_ERROR_CHECK(esp_codec_dev_close(output_dev_)); - if (pa_pin_ != GPIO_NUM_NC) { - gpio_set_level(pa_pin_, 0); - } - } - AudioCodec::EnableOutput(enable); -} - -int SensecapAudioCodec::Read(int16_t* dest, int samples) { - if (input_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_read(input_dev_, (void*)dest, samples * sizeof(int16_t))); - } - return samples; -} - -int SensecapAudioCodec::Write(const int16_t* data, int samples) { - if (output_enabled_) { - ESP_ERROR_CHECK_WITHOUT_ABORT(esp_codec_dev_write(output_dev_, (void*)data, samples * sizeof(int16_t))); - } - return samples; -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.h deleted file mode 100644 index 794a4d74..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_audio_codec.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _SENSECAP_AUDIO_CODEC_H -#define _SENSECAP_AUDIO_CODEC_H - -#include "audio_codec.h" - -#include -#include - -class SensecapAudioCodec : public AudioCodec { -private: - const audio_codec_data_if_t* data_if_ = nullptr; - const audio_codec_ctrl_if_t* out_ctrl_if_ = nullptr; - const audio_codec_if_t* out_codec_if_ = nullptr; - const audio_codec_ctrl_if_t* in_ctrl_if_ = nullptr; - const audio_codec_if_t* in_codec_if_ = nullptr; - const audio_codec_gpio_if_t* gpio_if_ = nullptr; - - esp_codec_dev_handle_t output_dev_ = nullptr; - esp_codec_dev_handle_t input_dev_ = nullptr; - gpio_num_t pa_pin_ = GPIO_NUM_NC; - - void CreateDuplexChannels(gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din); - - virtual int Read(int16_t* dest, int samples) override; - virtual int Write(const int16_t* data, int samples) override; - -public: - SensecapAudioCodec(void* i2c_master_handle, int input_sample_rate, int output_sample_rate, - gpio_num_t mclk, gpio_num_t bclk, gpio_num_t ws, gpio_num_t dout, gpio_num_t din, - gpio_num_t pa_pin, uint8_t es8311_addr, uint8_t es7210_addr, bool input_reference); - virtual ~SensecapAudioCodec(); - - virtual void SetOutputVolume(int volume) override; - virtual void EnableInput(bool enable) override; - virtual void EnableOutput(bool enable) override; -}; - -#endif // _SENSECAP_AUDIO_CODEC_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_watcher.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_watcher.cc deleted file mode 100644 index 5a1273a7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sensecap_watcher.cc +++ /dev/null @@ -1,661 +0,0 @@ -#include "display/lv_display.h" -#include "misc/lv_event.h" -#include "wifi_board.h" -#include "sensecap_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "knob.h" -#include "config.h" -#include "led/single_led.h" -#include "power_save_timer.h" -#include "sscma_camera.h" -#include "lvgl_theme.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "assets/lang_config.h" - -#define TAG "sensecap_watcher" - -class CustomLcdDisplay : public SpiLcdDisplay { - public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - - lv_obj_set_size(top_bar_, LV_HOR_RES, text_font->line_height); - lv_obj_set_style_layout(top_bar_, LV_LAYOUT_NONE, 0); - lv_obj_set_style_pad_top(top_bar_, 10, 0); - lv_obj_set_style_pad_bottom(top_bar_, 1, 0); - - lv_obj_set_size(status_bar_, LV_HOR_RES, text_font->line_height); - lv_obj_set_style_layout(status_bar_, LV_LAYOUT_NONE, 0); - lv_obj_set_style_pad_top(status_bar_, 10, 0); - lv_obj_set_style_pad_bottom(status_bar_, 1, 0); - lv_obj_set_y(status_bar_, text_font->line_height); - lv_obj_add_flag(status_bar_, LV_OBJ_FLAG_IGNORE_LAYOUT); - - // Reparent mute and battery labels to top_bar_ to allow absolute positioning - lv_obj_set_parent(mute_label_, top_bar_); - lv_obj_set_parent(battery_label_, top_bar_); - lv_obj_set_style_margin_left(battery_label_, 0, 0); - - // 针对圆形屏幕调整位置 - // network mute battery // - // status // - lv_obj_align(network_label_, LV_ALIGN_TOP_MID, -1.5 * icon_font->line_height, 0); - lv_obj_align(mute_label_, LV_ALIGN_TOP_MID, 1.0 * icon_font->line_height, 0); - lv_obj_align(battery_label_, LV_ALIGN_TOP_MID, 2.5 * icon_font->line_height, 0); - - lv_obj_align(status_label_, LV_ALIGN_BOTTOM_MID, 0, 0); - lv_obj_set_flex_grow(status_label_, 0); - lv_obj_set_width(status_label_, LV_HOR_RES * 0.75); - lv_label_set_long_mode(status_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - - lv_obj_align(notification_label_, LV_ALIGN_BOTTOM_MID, 0, 0); - lv_obj_set_width(notification_label_, LV_HOR_RES * 0.75); - lv_label_set_long_mode(notification_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - - lv_obj_align(low_battery_popup_, LV_ALIGN_BOTTOM_MID, 0, -20); - lv_obj_set_style_bg_color(low_battery_popup_, lv_color_hex(0xFF0000), 0); - lv_obj_set_width(low_battery_label_, LV_HOR_RES * 0.75); - lv_label_set_long_mode(low_battery_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - - // 针对圆形屏幕调整底部对话框位置,避免被圆角遮挡 - lv_obj_set_style_pad_bottom(bottom_bar_, 30, 0); - lv_obj_set_width(chat_message_label_, LV_HOR_RES * 0.75); // 限制宽度,避免文字贴边 - } -}; - -class SensecapWatcher : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - LcdDisplay* display_; - std::unique_ptr knob_; - esp_io_expander_handle_t io_exp_handle; - button_handle_t btns; - PowerSaveTimer* power_save_timer_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - uint32_t long_press_cnt_; - button_driver_t* btn_driver_ = nullptr; - static SensecapWatcher* instance_; - SscmaCamera* camera_ = nullptr; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - bool is_charging = (IoExpanderGetLevel(BSP_PWR_VBUS_IN_DET) == 0); - if (is_charging) { - ESP_LOGI(TAG, "charging"); - GetBacklight()->SetBrightness(0); - } else { - IoExpanderSetLevel(BSP_PWR_SYSTEM, 0); - } - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = BSP_GENERAL_I2C_SDA, - .scl_io_num = BSP_GENERAL_I2C_SCL, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - - // pulldown for lcd i2c - const gpio_config_t io_config = { - .pin_bit_mask = (1ULL << BSP_TOUCH_I2C_SDA) | (1ULL << BSP_TOUCH_I2C_SCL) | (1ULL << BSP_SPI3_HOST_PCLK) | (1ULL << BSP_SPI3_HOST_DATA0) | (1ULL << BSP_SPI3_HOST_DATA1) - | (1ULL << BSP_SPI3_HOST_DATA2) | (1ULL << BSP_SPI3_HOST_DATA3) | (1ULL << BSP_LCD_SPI_CS) | (1UL << DISPLAY_BACKLIGHT_PIN), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - gpio_config(&io_config); - - gpio_set_level(BSP_TOUCH_I2C_SDA, 0); - gpio_set_level(BSP_TOUCH_I2C_SCL, 0); - - gpio_set_level(BSP_LCD_SPI_CS, 0); - gpio_set_level(DISPLAY_BACKLIGHT_PIN, 0); - gpio_set_level(BSP_SPI3_HOST_PCLK, 0); - gpio_set_level(BSP_SPI3_HOST_DATA0, 0); - gpio_set_level(BSP_SPI3_HOST_DATA1, 0); - gpio_set_level(BSP_SPI3_HOST_DATA2, 0); - gpio_set_level(BSP_SPI3_HOST_DATA3, 0); - - } - - esp_err_t IoExpanderSetLevel(uint16_t pin_mask, uint8_t level) { - return esp_io_expander_set_level(io_exp_handle, pin_mask, level); - } - - uint8_t IoExpanderGetLevel(uint16_t pin_mask) { - uint32_t pin_val = 0; - esp_io_expander_get_level(io_exp_handle, DRV_IO_EXP_INPUT_MASK, &pin_val); - pin_mask &= DRV_IO_EXP_INPUT_MASK; - return (uint8_t)((pin_val & pin_mask) ? 1 : 0); - } - - void InitializeExpander() { - esp_err_t ret = ESP_OK; - esp_io_expander_new_i2c_tca95xx_16bit(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_001, &io_exp_handle); - - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_INPUT_MASK, IO_EXPANDER_INPUT); - ret |= esp_io_expander_set_dir(io_exp_handle, DRV_IO_EXP_OUTPUT_MASK, IO_EXPANDER_OUTPUT); - ret |= esp_io_expander_set_level(io_exp_handle, DRV_IO_EXP_OUTPUT_MASK, 0); - ret |= esp_io_expander_set_level(io_exp_handle, BSP_PWR_SYSTEM, 1); - vTaskDelay(100 / portTICK_PERIOD_MS); - ret |= esp_io_expander_set_level(io_exp_handle, BSP_PWR_START_UP, 1); - vTaskDelay(50 / portTICK_PERIOD_MS); - - uint32_t pin_val = 0; - ret |= esp_io_expander_get_level(io_exp_handle, DRV_IO_EXP_INPUT_MASK, &pin_val); - ESP_LOGI(TAG, "IO expander initialized: %x", DRV_IO_EXP_OUTPUT_MASK | (uint16_t)pin_val); - - assert(ret == ESP_OK); - } - - void OnKnobRotate(bool clockwise) { - auto codec = GetAudioCodec(); - int current_volume = codec->output_volume(); - int new_volume = current_volume + (clockwise ? -5 : 5); - - // 确保音量在有效范围内 - if (new_volume > 100) { - new_volume = 100; - ESP_LOGW(TAG, "Volume reached maximum limit: %d", new_volume); - } else if (new_volume < 0) { - new_volume = 0; - ESP_LOGW(TAG, "Volume reached minimum limit: %d", new_volume); - } - - codec->SetOutputVolume(new_volume); - ESP_LOGI(TAG, "Volume changed from %d to %d", current_volume, new_volume); - - // 显示通知前检查实际变化 - if (new_volume != codec->output_volume()) { - ESP_LOGE(TAG, "Failed to set volume! Expected:%d Actual:%d", - new_volume, codec->output_volume()); - } - GetDisplay()->ShowNotification(std::string(Lang::Strings::VOLUME) + ": "+std::to_string(codec->output_volume())); - power_save_timer_->WakeUp(); - } - - void InitializeKnob() { - knob_ = std::make_unique(BSP_KNOB_A_PIN, BSP_KNOB_B_PIN); - knob_->OnRotate([this](bool clockwise) { - ESP_LOGD(TAG, "Knob rotation detected. Clockwise:%s", clockwise ? "true" : "false"); - OnKnobRotate(clockwise); - }); - ESP_LOGI(TAG, "Knob initialized with pins A:%d B:%d", BSP_KNOB_A_PIN, BSP_KNOB_B_PIN); - } - - void InitializeButton() { - // 设置静态实例指针 - instance_ = this; - - // watcher 是通过长按滚轮进行开机的, 需要等待滚轮释放, 否则用户开机松手时可能会误触成单击 - ESP_LOGI(TAG, "waiting for knob button release"); - while(IoExpanderGetLevel(BSP_KNOB_BTN) == 0) { - vTaskDelay(pdMS_TO_TICKS(50)); - } - - button_config_t btn_config = { - .long_press_time = 2000, - .short_press_time = 0 - }; - btn_driver_ = (button_driver_t*)calloc(1, sizeof(button_driver_t)); - btn_driver_->enable_power_save = false; - btn_driver_->get_key_level = [](button_driver_t *button_driver) -> uint8_t { - return !instance_->IoExpanderGetLevel(BSP_KNOB_BTN); - }; - - ESP_ERROR_CHECK(iot_button_create(&btn_config, btn_driver_, &btns)); - - iot_button_register_cb(btns, BUTTON_SINGLE_CLICK, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->power_save_timer_->WakeUp(); - - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - self->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }, this); - - iot_button_register_cb(btns, BUTTON_LONG_PRESS_START, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - bool is_charging = (self->IoExpanderGetLevel(BSP_PWR_VBUS_IN_DET) == 0); - self->long_press_cnt_ = 0; - if (is_charging) { - ESP_LOGI(TAG, "charging"); - } else { - self->IoExpanderSetLevel(BSP_PWR_LCD, 0); - self->IoExpanderSetLevel(BSP_PWR_SYSTEM, 0); - } - }, this); - - iot_button_register_cb(btns, BUTTON_LONG_PRESS_HOLD, nullptr, [](void* button_handle, void* usr_data) { - auto self = static_cast(usr_data); - self->long_press_cnt_++; // 每隔20ms加一 - // 长按10s 恢复出厂设置: 2+0.02*400 = 10 - if (self->long_press_cnt_ > 400) { - ESP_LOGI(TAG, "Factory reset"); - nvs_flash_erase(); - esp_restart(); - } - }, this); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SSCMA SPI bus"); - spi_bus_config_t spi_cfg = {0}; - - spi_cfg.mosi_io_num = BSP_SPI2_HOST_MOSI; - spi_cfg.miso_io_num = BSP_SPI2_HOST_MISO; - spi_cfg.sclk_io_num = BSP_SPI2_HOST_SCLK; - spi_cfg.quadwp_io_num = -1; - spi_cfg.quadhd_io_num = -1; - spi_cfg.isr_cpu_id = ESP_INTR_CPU_AFFINITY_1; - spi_cfg.max_transfer_sz = 4095; - - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &spi_cfg, SPI_DMA_CH_AUTO)); - - ESP_LOGI(TAG, "Initialize QSPI bus"); - - spi_bus_config_t qspi_cfg = {0}; - qspi_cfg.sclk_io_num = BSP_SPI3_HOST_PCLK; - qspi_cfg.data0_io_num = BSP_SPI3_HOST_DATA0; - qspi_cfg.data1_io_num = BSP_SPI3_HOST_DATA1; - qspi_cfg.data2_io_num = BSP_SPI3_HOST_DATA2; - qspi_cfg.data3_io_num = BSP_SPI3_HOST_DATA3; - qspi_cfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * DRV_LCD_BITS_PER_PIXEL / 8 / CONFIG_BSP_LCD_SPI_DMA_SIZE_DIV; - - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &qspi_cfg, SPI_DMA_CH_AUTO)); - } - - void Initializespd2010Display() { - ESP_LOGI(TAG, "Install panel IO"); - const esp_lcd_panel_io_spi_config_t io_config = { - .cs_gpio_num = BSP_LCD_SPI_CS, - .dc_gpio_num = -1, - .spi_mode = 3, - .pclk_hz = DRV_LCD_PIXEL_CLK_HZ, - .trans_queue_depth = 2, - .lcd_cmd_bits = DRV_LCD_CMD_BITS, - .lcd_param_bits = DRV_LCD_PARAM_BITS, - .flags = { - .quad_mode = true, - }, - }; - spd2010_vendor_config_t vendor_config = { - .flags = { - .use_qspi_interface = 1, - }, - }; - esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)BSP_LCD_SPI_NUM, &io_config, &panel_io_); - - ESP_LOGD(TAG, "Install LCD driver"); - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = BSP_LCD_GPIO_RST, // Shared with Touch reset - .rgb_ele_order = DRV_LCD_RGB_ELEMENT_ORDER, - .bits_per_pixel = DRV_LCD_BITS_PER_PIXEL, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_spd2010(panel_io_, &panel_config, &panel_); - - esp_lcd_panel_reset(panel_); - esp_lcd_panel_init(panel_); - esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel_, true); - - display_ = new CustomLcdDisplay(panel_io_, panel_, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - // 使每次刷新的起始列数索引是4的倍数且列数总数是4的倍数,以满足SPD2010的要求 - lv_display_add_event_cb(lv_display_get_default(), [](lv_event_t *e) { - lv_area_t *area = (lv_area_t *)lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - // round the start of area down to the nearest 4N number - area->x1 = (x1 >> 2) << 2; - // round the end of area up to the nearest 4M+3 number - area->x2 = ((x2 >> 2) << 2) + 3; - }, LV_EVENT_INVALIDATE_AREA, NULL); - - } - - uint16_t BatterygetVoltage(void) { - static bool initialized = false; - static adc_oneshot_unit_handle_t adc_handle; - static adc_cali_handle_t cali_handle = NULL; - if (!initialized) { - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - }; - adc_oneshot_new_unit(&init_config, &adc_handle); - - adc_oneshot_chan_cfg_t ch_config = { - .atten = BSP_BAT_ADC_ATTEN, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - adc_oneshot_config_channel(adc_handle, BSP_BAT_ADC_CHAN, &ch_config); - - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = ADC_UNIT_1, - .chan = BSP_BAT_ADC_CHAN, - .atten = BSP_BAT_ADC_ATTEN, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - if (adc_cali_create_scheme_curve_fitting(&cali_config, &cali_handle) == ESP_OK) { - initialized = true; - } - } - if (initialized) { - int raw_value = 0; - int voltage = 0; // mV - adc_oneshot_read(adc_handle, BSP_BAT_ADC_CHAN, &raw_value); - adc_cali_raw_to_voltage(cali_handle, raw_value, &voltage); - voltage = voltage * 82 / 20; - // ESP_LOGI(TAG, "voltage: %dmV", voltage); - return (uint16_t)voltage; - } - return 0; - } - - uint8_t BatterygetPercent(bool print = false) { - int voltage = 0; - for (uint8_t i = 0; i < 10; i++) { - voltage += BatterygetVoltage(); - } - voltage /= 10; - int percent = (-1 * voltage * voltage + 9016 * voltage - 19189000) / 10000; - percent = (percent > 100) ? 100 : (percent < 0) ? 0 : percent; - if (print) { - printf("voltage: %dmV, percentage: %d%%\r\n", voltage, percent); - } - return (uint8_t)percent; - } - - void InitializeCmd() { - esp_console_repl_t *repl = NULL; - esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); - repl_config.max_cmdline_length = 1024; - repl_config.prompt = "SenseCAP>"; - - const esp_console_cmd_t cmd1 = { - .command = "reboot", - .help = "reboot the device", - .hint = nullptr, - .func = [](int argc, char** argv) -> int { - esp_restart(); - return 0; - }, - .argtable = nullptr - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd1)); - - const esp_console_cmd_t cmd2 = { - .command = "shutdown", - .help = "shutdown the device", - .hint = nullptr, - .func = NULL, - .argtable = NULL, - .func_w_context = [](void *context,int argc, char** argv) -> int { - auto self = static_cast(context); - self->GetBacklight()->SetBrightness(0); - self->IoExpanderSetLevel(BSP_PWR_SYSTEM, 0); - return 0; - }, - .context =this - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd2)); - - const esp_console_cmd_t cmd3 = { - .command = "battery", - .help = "get battery percent", - .hint = NULL, - .func = NULL, - .argtable = NULL, - .func_w_context = [](void *context,int argc, char** argv) -> int { - auto self = static_cast(context); - self->BatterygetPercent(true); - return 0; - }, - .context =this - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd3)); - - const esp_console_cmd_t cmd4 = { - .command = "factory_reset", - .help = "factory reset and reboot the device", - .hint = NULL, - .func = NULL, - .argtable = NULL, - .func_w_context = [](void *context,int argc, char** argv) -> int { - nvs_flash_erase(); - esp_restart(); - return 0; - }, - .context =this - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd4)); - - const esp_console_cmd_t cmd5 = { - .command = "read_mac", - .help = "Read mac address", - .hint = NULL, - .func = NULL, - .argtable = NULL, - .func_w_context = [](void *context,int argc, char** argv) -> int { - uint8_t mac[6]; - esp_read_mac(mac, ESP_MAC_WIFI_STA); - printf("wifi_sta_mac: " MACSTR "\n", MAC2STR(mac)); - esp_read_mac(mac, ESP_MAC_WIFI_SOFTAP); - printf("wifi_softap_mac: " MACSTR "\n", MAC2STR(mac)); - esp_read_mac(mac, ESP_MAC_BT); - printf("bt_mac: " MACSTR "\n", MAC2STR(mac)); - return 0; - }, - .context =this - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd5)); - - const esp_console_cmd_t cmd6 = { - .command = "version", - .help = "Read version info", - .hint = NULL, - .func = NULL, - .argtable = NULL, - .func_w_context = [](void *context,int argc, char** argv) -> int { - auto self = static_cast(context); - auto app_desc = esp_app_get_description(); - const char* region = "UNKNOWN"; - #if defined(CONFIG_LANGUAGE_ZH_CN) - region = "CN"; - #elif defined(CONFIG_LANGUAGE_EN_US) - region = "US"; - #elif defined(CONFIG_LANGUAGE_JA_JP) - region = "JP"; - #elif defined(CONFIG_LANGUAGE_ES_ES) - region = "ES"; - #elif defined(CONFIG_LANGUAGE_DE_DE) - region = "DE"; - #elif defined(CONFIG_LANGUAGE_FR_FR) - region = "FR"; - #elif defined(CONFIG_LANGUAGE_IT_IT) - region = "IT"; - #elif defined(CONFIG_LANGUAGE_PT_PT) - region = "PT"; - #elif defined(CONFIG_LANGUAGE_RU_RU) - region = "RU"; - #elif defined(CONFIG_LANGUAGE_KO_KR) - region = "KR"; - #endif - printf("{\"type\":0,\"name\":\"VER?\",\"code\":0,\"data\":{\"software\":\"%s\",\"hardware\":\"watcher xiaozhi agent\",\"camera\":%d,\"region\":\"%s\"}}\n", - app_desc->version, - self->GetCamera() == nullptr ? 0 : 1, - region); - return 0; - }, - .context =this - }; - ESP_ERROR_CHECK(esp_console_cmd_register(&cmd6)); - - esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); - ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); - ESP_ERROR_CHECK(esp_console_start_repl(repl)); - } - - void InitializeCamera() { - - ESP_LOGI(TAG, "Initialize Camera"); - - // !!!NOTE: SD Card use same SPI bus as sscma client, so we need to disable SD card CS pin first - const gpio_config_t io_config = { - .pin_bit_mask = (1ULL << BSP_SD_SPI_CS), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_ENABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - esp_err_t ret = gpio_config(&io_config); - if (ret != ESP_OK) - return; - - gpio_set_level(BSP_SD_SPI_CS, 1); - - camera_ = new SscmaCamera(io_exp_handle); - } - -public: - SensecapWatcher() { - ESP_LOGI(TAG, "Initialize Sensecap Watcher"); - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeSpi(); - InitializeExpander(); - InitializeCmd(); //工厂生产测试使用 - InitializeButton(); - InitializeKnob(); - Initializespd2010Display(); - GetBacklight()->RestoreBrightness(); // 对于不带摄像头的版本,InitializeCamera需要3s, 所以先恢复背光亮度 - InitializeCamera(); - } - - virtual AudioCodec* GetAudioCodec() override { - static SensecapAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7243E_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - // 根据 https://github.com/Seeed-Studio/OSHW-SenseCAP-Watcher/blob/main/Hardware/SenseCAP_Watcher_v1.0_SCH.pdf - // RGB LED型号为 ws2813 mini, 连接在GPIO 40,供电电压 3.3v, 没有连接 BIN 双信号线 - // 可以直接兼容SingleLED采用的ws2812 - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = (IoExpanderGetLevel(BSP_PWR_VBUS_IN_DET) == 0); - discharging = !charging; - level = (int)BatterygetPercent(false); - - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - if (level <= 1 && discharging) { - ESP_LOGI(TAG, "Battery level is low, shutting down"); - IoExpanderSetLevel(BSP_PWR_SYSTEM, 0); - } - return true; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(SensecapWatcher); - -// 定义静态成员变量 -SensecapWatcher* SensecapWatcher::instance_ = nullptr; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.cc deleted file mode 100644 index 918275e4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.cc +++ /dev/null @@ -1,743 +0,0 @@ -#include "sscma_camera.h" -#include "mcp_server.h" -#include "lvgl_display.h" -#include "lvgl_image.h" -#include "board.h" -#include "system_info.h" -#include "config.h" -#include "settings.h" - -#include -#include -#include -#include "application.h" -#include "sscma_client_commands.h" - -#define TAG "SscmaCamera" - -#define IMG_JPEG_BUF_SIZE 48 * 1024 - -static bool __himax_keepalive_check(sscma_client_handle_t client) -{ - esp_err_t ret = ESP_OK; - sscma_client_reply_t reply = {0}; - int retry = 3; - while(retry--) { - ret = sscma_client_request(client, CMD_PREFIX CMD_AT_ID CMD_QUERY CMD_SUFFIX, &reply, true, pdMS_TO_TICKS(2000)); - if (reply.payload != NULL) { - sscma_client_reply_clear(&reply); - } - if( ret != ESP_OK ) { - ESP_LOGE(TAG, "Himax keepalive check failed: %d", ret); - vTaskDelay(pdMS_TO_TICKS(100)); - } else { - return true; - } - } - return false; -} - -SscmaCamera::SscmaCamera(esp_io_expander_handle_t io_exp_handle) { - sscma_client_io_spi_config_t spi_io_config = {0}; - spi_io_config.sync_gpio_num = BSP_SSCMA_CLIENT_SPI_SYNC; - spi_io_config.cs_gpio_num = BSP_SSCMA_CLIENT_SPI_CS; - spi_io_config.pclk_hz = BSP_SSCMA_CLIENT_SPI_CLK; - spi_io_config.spi_mode = 0; - spi_io_config.wait_delay = 10; //两个transfer之间至少延时4ms,但当前 FREERTOS_HZ=100, 延时精度只能达到10ms, - spi_io_config.user_ctx = NULL; - spi_io_config.io_expander = io_exp_handle; - spi_io_config.flags.sync_use_expander = BSP_SSCMA_CLIENT_RST_USE_EXPANDER; - - sscma_client_new_io_spi_bus((sscma_client_spi_bus_handle_t)BSP_SSCMA_CLIENT_SPI_NUM, &spi_io_config, &sscma_client_io_handle_); - - sscma_client_config_t sscma_client_config = SSCMA_CLIENT_CONFIG_DEFAULT(); - sscma_client_config.event_queue_size = CONFIG_SSCMA_EVENT_QUEUE_SIZE; - sscma_client_config.tx_buffer_size = CONFIG_SSCMA_TX_BUFFER_SIZE; - sscma_client_config.rx_buffer_size = CONFIG_SSCMA_RX_BUFFER_SIZE; - sscma_client_config.process_task_stack = CONFIG_SSCMA_PROCESS_TASK_STACK_SIZE; - sscma_client_config.process_task_affinity = CONFIG_SSCMA_PROCESS_TASK_AFFINITY; - sscma_client_config.process_task_priority = CONFIG_SSCMA_PROCESS_TASK_PRIORITY; - sscma_client_config.monitor_task_stack = CONFIG_SSCMA_MONITOR_TASK_STACK_SIZE; - sscma_client_config.monitor_task_affinity = CONFIG_SSCMA_MONITOR_TASK_AFFINITY; - sscma_client_config.monitor_task_priority = CONFIG_SSCMA_MONITOR_TASK_PRIORITY; - sscma_client_config.reset_gpio_num = BSP_SSCMA_CLIENT_RST; - sscma_client_config.io_expander = io_exp_handle; - sscma_client_config.flags.reset_use_expander = BSP_SSCMA_CLIENT_RST_USE_EXPANDER; - - sscma_client_new(sscma_client_io_handle_, &sscma_client_config, &sscma_client_handle_); - - sscma_data_queue_ = xQueueCreate(1, sizeof(SscmaData)); - - sscma_client_callback_t callback = {0}; - - detection_state = SscmaCamera::IDLE; - state_start_time = 0; - need_start_cooldown = false; - callback.on_event = [](sscma_client_handle_t client, const sscma_client_reply_t *reply, void *user_ctx) { - SscmaCamera* self = static_cast(user_ctx); - if (!self) return; - - char *img = NULL; - int img_size = 0; - int box_count = 0; - sscma_client_box_t *boxes = NULL; - int class_count = 0; - sscma_client_class_t *classes = NULL; - int point_count = 0; - sscma_client_point_t *points = NULL; - int model_type = 0; - int obj_cnt = 0; - - int width = 0, height = 0; - cJSON *data = cJSON_GetObjectItem(reply->payload, "data"); - if (data != NULL && cJSON_IsObject(data)) { - cJSON *resolution = cJSON_GetObjectItem(data, "resolution"); - if (data != NULL && cJSON_IsArray(resolution) && cJSON_GetArraySize(resolution) == 2) { - width = cJSON_GetArrayItem(resolution, 0)->valueint; - height = cJSON_GetArrayItem(resolution, 1)->valueint; - } - } - - switch ((width+height)) { - case (416+416): - { - bool is_object_detected = false; - bool is_need_wake = false; - - // 定期更新检测配置参数,避免频繁NVS访问 - int64_t cur_tm = esp_timer_get_time(); - - // 尝试获取检测框数据(目标检测模型) - if (sscma_utils_fetch_boxes_from_reply(reply, &boxes, &box_count) == ESP_OK && box_count > 0) { - for (int i = 0; i < box_count; i++) { - ESP_LOGI(TAG, "[box %d]: x=%d, y=%d, w=%d, h=%d, score=%d, target=%d", i, \ - boxes[i].x, boxes[i].y, boxes[i].w, boxes[i].h, boxes[i].score, boxes[i].target); - if (boxes[i].target == self->detect_target && boxes[i].score > self->detect_threshold) { - is_object_detected = true; - model_type = 0; - obj_cnt++; - break; - } - } - free(boxes); - } else if (sscma_utils_fetch_classes_from_reply(reply, &classes, &class_count) == ESP_OK && class_count > 0) { - // 尝试获取分类数据(分类模型) - for (int i = 0; i < class_count; i++) { - ESP_LOGI(TAG, "[class %d]: target=%d, score=%d", i, - classes[i].target, classes[i].score); - if (classes[i].target == self->detect_target && classes[i].score > self->detect_threshold) { - is_object_detected = true; - model_type = 1; - obj_cnt++; - } - } - free(classes); - } else if (sscma_utils_fetch_points_from_reply(reply, &points, &point_count) == ESP_OK && point_count > 0) { - // 尝试获取关键点数据(姿态估计模型) - for (int i = 0; i < point_count; i++) { - ESP_LOGI(TAG, "[point %d]: x=%d, y=%d, z=%d, score=%d, target=%d", i, - points[i].x, points[i].y, points[i].z, points[i].score, points[i].target); - if (points[i].target == self->detect_target && points[i].score > self->detect_threshold) { - is_object_detected = true; - model_type = 2; - obj_cnt++; - } - } - free(points); - } - - // 如果需要开始冷却期,现在开始计时 - if (self->need_start_cooldown) { // 回调暂停,标志保持,等待回调恢复后开始计时 - self->state_start_time = cur_tm; - self->need_start_cooldown = false; - ESP_LOGI(TAG, "Starting cooldown timer"); - } - - // 状态机驱动的检测逻辑 - 只在人员出现时触发 - switch (self->detection_state) { - case SscmaCamera::IDLE: - if (is_object_detected) { - // 人员出现,开始验证(这是从无到有的转换) - self->detection_state = SscmaCamera::VALIDATING; - self->state_start_time = cur_tm; // 记录物体出现时间 - self->last_detected_time = cur_tm; // 初始化最后检测时间 - ESP_LOGI(TAG, "object appeared, starting validation"); - } - break; - - case SscmaCamera::VALIDATING: - if (is_object_detected) { - // 更新最后检测到的时间 - self->last_detected_time = cur_tm; - // 检查是否验证足够时间 - if ((cur_tm - self->state_start_time) >= (self->detect_duration_sec * 1000000)) { - is_need_wake = true; - } - } else { - // 验证期间人员离开,检查去抖动时间 - if (self->last_detected_time > 0 && - (cur_tm - self->last_detected_time) >= self->detect_debounce_sec * 1000000LL) { - // 去抖动时间已过,确认人员已离开,回到空闲 - self->detection_state = SscmaCamera::IDLE; - self->last_detected_time = 0; - ESP_LOGI(TAG, "object left during validation (debounced), back to idle"); - } - } - break; - - case SscmaCamera::COOLDOWN: - // 冷却期,需要满足两个条件:1)object离开 2)过了15秒 - if (!is_object_detected && - (cur_tm - self->state_start_time) >= (self->detect_invoke_interval_sec * 1000000LL)) { - // object离开且冷却时间到,回到空闲状态 - self->detection_state = SscmaCamera::IDLE; - ESP_LOGI(TAG, "Cooldown complete and object left, back to idle - ready for next appearance"); - } - // 其他情况继续保持冷却状态 - break; - } - - - if( is_need_wake ) { - ESP_LOGI(TAG, "Validation complete, triggering conversation (type=%d, res=%dx%d)", - self->detect_target, width, height); - - // 触发对话 - std::string wake_word; - if ( model_type == 0 ) { - std::string cached_target_name = "object"; - if( self->model != NULL && self->model->classes[self->detect_target] != NULL ) { - cached_target_name = self->model->classes[self->detect_target]; - } - wake_word = "" + std::to_string(obj_cnt) + " " + cached_target_name + " detected "; - } else if ( model_type == 1 ) { - std::string cached_target_name = "object"; - if( self->model != NULL && self->model->classes[self->detect_target] != NULL ) { - cached_target_name = self->model->classes[self->detect_target]; - } - wake_word = "" + std::to_string(obj_cnt) + " " + cached_target_name + " detected "; - } else if ( model_type == 2 ) { - std::string cached_target_name = "object"; - if( self->model != NULL && self->model->classes[self->detect_target] != NULL ) { - cached_target_name = self->model->classes[self->detect_target]; - } - wake_word = "" + std::to_string(obj_cnt) + " " + cached_target_name + " detected "; - } - printf("wake_word:%s\n", wake_word.c_str()); - Application::GetInstance().WakeWordInvoke(wake_word); - - // 进入冷却状态,标记需要开始冷却期;如下变量将在会话结束后被使用,等待回调恢复后开始计时 - self->detection_state = SscmaCamera::COOLDOWN; - self->need_start_cooldown = true; - } - } - break; - case (640+480): - - if (sscma_utils_fetch_image_from_reply(reply, &img, &img_size) == ESP_OK) - { - ESP_LOGI(TAG, "image_size: %d\n", img_size); - // 将数据通过队列发送出去 - SscmaData data; - data.img = (uint8_t*)img; - data.len = img_size; - - // 清空队列,保证只保存最新的数据 - SscmaData dummy; - while (xQueueReceive(self->sscma_data_queue_, &dummy, 0) == pdPASS) { - if (dummy.img) { - heap_caps_free(dummy.img); - } - } - xQueueSend(self->sscma_data_queue_, &data, 0); - // 注意:img 的释放由接收方负责 - } - break; - default: - ESP_LOGI(TAG, "unknown resolution"); - break; - } - }; - callback.on_connect = [](sscma_client_handle_t client, const sscma_client_reply_t *reply, void *user_ctx) { - ESP_LOGI(TAG, "SSCMA client connected"); - SscmaCamera* self = static_cast(user_ctx); - if (self) { - self->sscma_restarted_ = true; - } - }; - - callback.on_log = [](sscma_client_handle_t client, const sscma_client_reply_t *reply, void *user_ctx) { - ESP_LOGI(TAG, "log: %s\n", reply->data); - }; - - sscma_client_register_callback(sscma_client_handle_, &callback, this); - - sscma_client_init(sscma_client_handle_); - - ESP_LOGI(TAG, "SSCMA client initialized"); - // 设置分辨率 - // 3 = 640x480 - if (sscma_client_set_sensor(sscma_client_handle_, 1, 3, true)) { - ESP_LOGE(TAG, "Failed to set sensor"); - sscma_client_del(sscma_client_handle_); - sscma_client_handle_ = NULL; - return; - } - - // 获取设备信息 - sscma_client_info_t *info; - if (sscma_client_get_info(sscma_client_handle_, &info, true) == ESP_OK) { - ESP_LOGI(TAG, "Device Info - ID: %s, Name: %s", - info->id ? info->id : "NULL", - info->name ? info->name : "NULL"); - } - // 初始化JPEG数据的内存 - jpeg_data_.len = 0; - jpeg_data_.buf = (uint8_t*)heap_caps_malloc(IMG_JPEG_BUF_SIZE, MALLOC_CAP_SPIRAM);; - if ( jpeg_data_.buf == nullptr ) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG buffer"); - return; - } - - //初始化JPEG解码 - jpeg_error_t err; - jpeg_dec_config_t config = { .output_type = JPEG_PIXEL_FORMAT_RGB565_LE, .rotate = JPEG_ROTATE_0D }; - err = jpeg_dec_open(&config, &jpeg_dec_); - if ( err != JPEG_ERR_OK ) { - ESP_LOGE(TAG, "Failed to open JPEG decoder"); - return; - } - jpeg_io_ = (jpeg_dec_io_t*)heap_caps_malloc(sizeof(jpeg_dec_io_t), MALLOC_CAP_SPIRAM); - if (!jpeg_io_) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG IO"); - jpeg_dec_close(jpeg_dec_); - return; - } - memset(jpeg_io_, 0, sizeof(jpeg_dec_io_t)); - - jpeg_out_ = (jpeg_dec_header_info_t*)heap_caps_aligned_alloc(16, sizeof(jpeg_dec_header_info_t), MALLOC_CAP_SPIRAM); - if (!jpeg_out_) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG output header"); - heap_caps_free(jpeg_io_); - jpeg_dec_close(jpeg_dec_); - return; - } - memset(jpeg_out_, 0, sizeof(jpeg_dec_header_info_t)); - - // 初始化预览图片的内存 - memset(&preview_image_, 0, sizeof(preview_image_)); - preview_image_.header.magic = LV_IMAGE_HEADER_MAGIC; - preview_image_.header.cf = LV_COLOR_FORMAT_RGB565; - preview_image_.header.flags = LV_IMAGE_FLAGS_ALLOCATED | LV_IMAGE_FLAGS_MODIFIABLE; - preview_image_.header.w = 640; - preview_image_.header.h = 480; - - preview_image_.header.stride = preview_image_.header.w * 2; - preview_image_.data_size = preview_image_.header.w * preview_image_.header.h * 2; - preview_image_.data =(uint8_t*)jpeg_calloc_align(preview_image_.data_size, 16); - if (preview_image_.data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for preview image"); - return; - } - - sscma_client_set_model(sscma_client_handle_, 4); - model_class_cnt = 0; - if (sscma_client_get_model(sscma_client_handle_, &model, true) == ESP_OK) { - printf("ID: %d\n", model->id ? model->id : -1); - printf("UUID: %s\n", model->uuid ? model->uuid : "N/A"); - printf("Name: %s\n", model->name ? model->name : "N/A"); - printf("Version: %s\n", model->ver ? model->ver : "N/A"); - printf("URL: %s\n", model->url ? model->url : "N/A"); - printf("Checksum: %s\n", model->checksum ? model->checksum : "N/A"); - printf("Classes:\n"); - if (model->classes[0] != NULL) - { - for (int i = 0; model->classes[i] != NULL; i++) - { - printf(" - %s\n", model->classes[i]); - model_class_cnt++; - } - } else { - printf(" N/A\n"); - } - } else { - printf("get model failed\n"); - } - - ESP_LOGI(TAG, "initialize mcp tools"); - InitializeMcpTools(); - - xTaskCreate([](void* arg) { - auto this_ = (SscmaCamera*)arg; - bool is_inference = false; - int64_t last_keepalive_time = esp_timer_get_time(); - while (true) - { - if (this_->sscma_restarted_) { - ESP_LOGI(TAG, "SSCMA restarted detected"); - this_->sscma_restarted_ = false; - is_inference = false; - } - - if (esp_timer_get_time() - last_keepalive_time > 10 * 1000000) { - last_keepalive_time = esp_timer_get_time(); - if (!__himax_keepalive_check(this_->sscma_client_handle_)) { - ESP_LOGE(TAG, "restart himax"); - sscma_client_reset(this_->sscma_client_handle_); - vTaskDelay(pdMS_TO_TICKS(100)); - } - } - - if (this_->inference_en && Application::GetInstance().GetDeviceState() == kDeviceStateIdle ) { - if (!is_inference) { - ESP_LOGI(TAG, "Start inference (enable=1)"); - sscma_client_break(this_->sscma_client_handle_); - sscma_client_set_model(this_->sscma_client_handle_, 4); - sscma_client_set_sensor(this_->sscma_client_handle_, 1, 1, true); // 设置分辨率 416X416 - sscma_client_invoke(this_->sscma_client_handle_, -1, false, true); - is_inference = true; - } - } else if (is_inference && (!this_->inference_en || Application::GetInstance().GetDeviceState() != kDeviceStateIdle)) { - ESP_LOGI(TAG, "Stop inference (enable=%d state=%d)", this_->inference_en, Application::GetInstance().GetDeviceState()); - is_inference = false; - sscma_client_break(this_->sscma_client_handle_); - } - vTaskDelay(pdMS_TO_TICKS(200)); - } - }, "sscma_camera", 4096, this, 1, nullptr); - -} - -SscmaCamera::~SscmaCamera() { - if (preview_image_.data) { - heap_caps_free((void*)preview_image_.data); - preview_image_.data = nullptr; - } - if (sscma_client_handle_) { - sscma_client_del(sscma_client_handle_); - } - if (sscma_data_queue_) { - vQueueDelete(sscma_data_queue_); - } - if (jpeg_data_.buf) { - heap_caps_free(jpeg_data_.buf); - jpeg_data_.buf = nullptr; - } - if (jpeg_dec_) { - jpeg_dec_close(jpeg_dec_); - jpeg_dec_ = nullptr; - } - if (jpeg_io_) { - heap_caps_free(jpeg_io_); - jpeg_io_ = nullptr; - } - if (jpeg_out_) { - heap_caps_free(jpeg_out_); - jpeg_out_ = nullptr; - } -} - -void SscmaCamera::InitializeMcpTools() { - - Settings settings("model", false); - detect_threshold = settings.GetInt("threshold", 75); - detect_invoke_interval_sec = settings.GetInt("interval", 8); - detect_duration_sec = settings.GetInt("duration", 2); - detect_target = settings.GetInt("target", 0); - inference_en = settings.GetInt("enable", 0); - - auto& mcp_server = McpServer::GetInstance(); - // 获取模型参数配置 - mcp_server.AddTool("self.model.param_get", - "获取当前视觉模型检测的参数配置信息。\n" - "返回结果包含:\n" - " `threshold`: 检测置信度阈值 (0-100),低于此值的检测结果将被忽略;\n" - " `interval`: 触发对话后的冷却时间(秒),防止频繁打断;\n" - " `duration`: 持续检测确认时间(秒);\n" - " `target`: 当前关注的检测目标索引。", - PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - Settings settings("model", false); - int threshold = settings.GetInt("threshold", 75); - int interval = settings.GetInt("interval", 8); - int duration = settings.GetInt("duration", 2); - int target_type = settings.GetInt("target", 0); - - std::string result = "{\"threshold\":" + std::to_string(threshold) + - ",\"interval\":" + std::to_string(interval) + - ",\"duration\":" + std::to_string(duration) + - ",\"target_type\":" + std::to_string(target_type) + "}"; - return result; - }); - - - // 设置模型参数配置 - mcp_server.AddTool("self.model.param_set", - "配置视觉模型检测参数。当用户希望调整检测灵敏度、频率或特定目标时使用。\n" - "参数(均为可选,未提供的参数将保持当前设置不变):\n" - " `threshold`: 置信度阈值 (0-100)。提高此值可减少误报,但可能漏检;\n" - " `interval`: 冷却时间(秒)。设置对话结束后多久内不再触发检测;\n" - " `duration`: 持续检测时间(秒)。\n" - " `target`: 设置检测目标的索引 ID。", - PropertyList({ - Property("threshold", kPropertyTypeInteger, -1, -1, 100), - Property("interval", kPropertyTypeInteger, -1, -1, 60), - Property("duration", kPropertyTypeInteger, -1, -1, 60), - Property("target", kPropertyTypeInteger, -1, -1, this->model_class_cnt > 0 ? this->model_class_cnt - 1 : 255) - }), - [this](const PropertyList& properties) -> ReturnValue { - Settings settings("model", true); - try { - const Property& threshold_prop = properties["threshold"]; - int threshold = threshold_prop.value(); - if (threshold != -1) { - settings.SetInt("threshold", threshold); - this->detect_threshold = threshold; - ESP_LOGI(TAG, "Set detection threshold to %d", threshold); - } - } catch (const std::runtime_error&) { - // threshold parameter not provided, skip - } - - try { - const Property& interval_prop = properties["interval"]; - int interval = interval_prop.value(); - if (interval != -1) { - settings.SetInt("interval", interval); - this->detect_invoke_interval_sec = interval; - ESP_LOGI(TAG, "Set detection interval to %d", interval); - } - } catch (const std::runtime_error&) { - // interval parameter not provided, skip - } - - try { - const Property& duration_prop = properties["duration"]; - int duration = duration_prop.value(); - if (duration != -1) { - settings.SetInt("duration", duration); - this->detect_duration_sec = duration; - } - } catch (const std::runtime_error&) { - // duration parameter not provided, skip - } - - try { - const Property& target_prop = properties["target"]; - int target = target_prop.value(); - if (target != -1) { - settings.SetInt("target", target); - this->detect_target = target; - ESP_LOGI(TAG, "Set detection target to %d", target); - } - } catch (const std::runtime_error&) { - // target_type parameter not provided, skip - } - - return "{\"status\": \"success\", \"message\": \"Detection configuration updated\"}"; - }); - - // 推理开关获取 - mcp_server.AddTool("self.model.enable", - "控制视觉推理(摄像头检测)功能的开启与关闭,或查询当前状态。\n" - "当用户指令涉及'开启/关闭推理'、'开始/停止检测'时使用。\n" - "参数:\n" - " `enable`: (可选) 整数。1=开启推理,0=关闭推理。若省略则返回当前开关状态。", - PropertyList({ - Property("enable", kPropertyTypeInteger, inference_en, 0, 1) - }), - [this](const PropertyList& properties) -> ReturnValue { - Settings settings("model", true); - try { - const Property& enable_prop = properties["enable"]; - int en = enable_prop.value(); - settings.SetInt("enable", en); - this->inference_en = en; - ESP_LOGI(TAG, "Set inference enable to %d", en); - } catch (const std::runtime_error&) { - // enable not provided -> treat as query - } - // 返回当前配置 - int cur_en = settings.GetInt("enable", this->inference_en); - return std::string("{\"enable\":") + std::to_string(cur_en) + "}"; - }); -} - -void SscmaCamera::SetExplainUrl(const std::string& url, const std::string& token) { - explain_url_ = url; - explain_token_ = token; -} - -bool SscmaCamera::Capture() { - - SscmaData data; - int ret = 0; - - if (sscma_client_handle_ == nullptr) { - ESP_LOGE(TAG, "SSCMA client handle is not initialized"); - return false; - } - - if (sscma_client_set_sensor(sscma_client_handle_, 1, 3, true)) { - ESP_LOGE(TAG, "Failed to set sensor"); - return false; - } - ESP_LOGI(TAG, "Capturing image..."); - // himax 可能有缓存数据, 只获取最新的照片即可. - if (sscma_client_sample(sscma_client_handle_, 1) ) { - ESP_LOGE(TAG, "Failed to capture image from SSCMA client"); - return false; - } - vTaskDelay(pdMS_TO_TICKS(500)); // 等待SSCMA客户端处理数据 - if (xQueueReceive(sscma_data_queue_, &data, pdMS_TO_TICKS(1000)) != pdPASS) { - ESP_LOGE(TAG, "Failed to receive JPEG data from SSCMA client"); - return false; - } - - if (jpeg_data_.buf == nullptr) { - heap_caps_free(data.img); - return false; - } - - ret = mbedtls_base64_decode(jpeg_data_.buf, IMG_JPEG_BUF_SIZE, &jpeg_data_.len, data.img, data.len); - if (ret != 0 || jpeg_data_.len == 0) { - ESP_LOGE(TAG, "Failed to decode base64 image data, ret: %d, output_len: %zu", ret, jpeg_data_.len); - heap_caps_free(data.img); - return false; - } - heap_caps_free(data.img); - - //DECODE JPEG - if (!jpeg_dec_ || !jpeg_io_ || !jpeg_out_ || !preview_image_.data) { - return true; - } - jpeg_io_->inbuf = jpeg_data_.buf; - jpeg_io_->inbuf_len = jpeg_data_.len; - ret = jpeg_dec_parse_header(jpeg_dec_, jpeg_io_, jpeg_out_); - if (ret < 0) { - ESP_LOGE(TAG, "Failed to parse JPEG header, ret: %d", ret); - return true; - } - jpeg_io_->outbuf = (unsigned char*)preview_image_.data; - int inbuf_consumed = jpeg_io_->inbuf_len - jpeg_io_->inbuf_remain; - jpeg_io_->inbuf = jpeg_data_.buf + inbuf_consumed; - jpeg_io_->inbuf_len = jpeg_io_->inbuf_remain; - - ret = jpeg_dec_process(jpeg_dec_, jpeg_io_); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to decode JPEG image, ret: %d", ret); - return true; - } - - // 显示预览图片 - auto display = dynamic_cast(Board::GetInstance().GetDisplay()); - if (display != nullptr) { - uint16_t w = preview_image_.header.w; - uint16_t h = preview_image_.header.h; - size_t image_size = w * h * 2; - size_t stride = preview_image_.header.w * 2; - - uint8_t* data = (uint8_t*)heap_caps_malloc(image_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (data == nullptr) { - ESP_LOGE(TAG, "Failed to allocate memory for display image"); - return true; - } - memcpy(data, preview_image_.data, image_size); - - auto image = std::make_unique(data, image_size, w, h, stride, LV_COLOR_FORMAT_RGB565); - display->SetPreviewImage(std::move(image)); - } - return true; -} -bool SscmaCamera::SetHMirror(bool enabled) { - return false; -} - -bool SscmaCamera::SetVFlip(bool enabled) { - return false; -} - -/** - * @brief 将摄像头捕获的图像发送到远程服务器进行AI分析和解释 - * - * 该函数将当前摄像头缓冲区中的图像编码为JPEG格式,并通过HTTP POST请求 - * 以multipart/form-data的形式发送到指定的解释服务器。服务器将根据提供的 - * 问题对图像进行AI分析并返回结果。 - * - * @param question 要向AI提出的关于图像的问题,将作为表单字段发送 - * @return std::string 服务器返回的JSON格式响应字符串 - * 成功时包含AI分析结果,失败时包含错误信息 - * 格式示例:{"success": true, "result": "分析结果"} - * {"success": false, "message": "错误信息"} - * - * @note 调用此函数前必须先调用SetExplainUrl()设置服务器URL - * @note 函数会等待之前的编码线程完成后再开始新的处理 - * @warning 如果摄像头缓冲区为空或网络连接失败,将返回错误信息 - */ -std::string SscmaCamera::Explain(const std::string& question) { - if (explain_url_.empty()) { - return "{\"success\": false, \"message\": \"Image explain URL or token is not set\"}"; - } - - auto network = Board::GetInstance().GetNetwork(); - auto http = network->CreateHttp(3); - // 构造multipart/form-data请求体 - std::string boundary = "----ESP32_CAMERA_BOUNDARY"; - - // 构造question字段 - std::string question_field; - question_field += "--" + boundary + "\r\n"; - question_field += "Content-Disposition: form-data; name=\"question\"\r\n"; - question_field += "\r\n"; - question_field += question + "\r\n"; - - // 构造文件字段头部 - std::string file_header; - file_header += "--" + boundary + "\r\n"; - file_header += "Content-Disposition: form-data; name=\"file\"; filename=\"camera.jpg\"\r\n"; - file_header += "Content-Type: image/jpeg\r\n"; - file_header += "\r\n"; - - // 构造尾部 - std::string multipart_footer; - multipart_footer += "\r\n--" + boundary + "--\r\n"; - - // 配置HTTP客户端,使用分块传输编码 - http->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); - http->SetHeader("Client-Id", Board::GetInstance().GetUuid().c_str()); - if (!explain_token_.empty()) { - http->SetHeader("Authorization", "Bearer " + explain_token_); - } - http->SetHeader("Content-Type", "multipart/form-data; boundary=" + boundary); - http->SetHeader("Transfer-Encoding", "chunked"); - if (!http->Open("POST", explain_url_)) { - ESP_LOGE(TAG, "Failed to connect to explain URL"); - return "{\"success\": false, \"message\": \"Failed to connect to explain URL\"}"; - } - - // 第一块:question字段 - http->Write(question_field.c_str(), question_field.size()); - - // 第二块:文件字段头部 - http->Write(file_header.c_str(), file_header.size()); - - // 第三块:JPEG数据 - http->Write((const char*)jpeg_data_.buf, jpeg_data_.len); - - // 第四块:multipart尾部 - http->Write(multipart_footer.c_str(), multipart_footer.size()); - - // 结束块 - http->Write("", 0); - - if (http->GetStatusCode() != 200) { - ESP_LOGE(TAG, "Failed to upload photo, status code: %d", http->GetStatusCode()); - return "{\"success\": false, \"message\": \"Failed to upload photo\"}"; - } - - std::string result = http->ReadAll(); - http->Close(); - - ESP_LOGI(TAG, "Explain image size=%d, question=%s\n%s", jpeg_data_.len, question.c_str(), result.c_str()); - return result; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.h deleted file mode 100644 index 40d6777a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sensecap-watcher/sscma_camera.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef SSCMA_CAMERA_H -#define SSCMA_CAMERA_H - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "sscma_client.h" -#include "camera.h" - -struct SscmaData { - uint8_t* img; - size_t len; -}; -struct JpegData { - uint8_t* buf; - size_t len; -}; - -class SscmaCamera : public Camera { -private: - lv_img_dsc_t preview_image_; - std::string explain_url_; - std::string explain_token_; - sscma_client_io_handle_t sscma_client_io_handle_; - sscma_client_handle_t sscma_client_handle_; - QueueHandle_t sscma_data_queue_; - JpegData jpeg_data_; - jpeg_dec_handle_t jpeg_dec_; - jpeg_dec_io_t *jpeg_io_; - jpeg_dec_header_info_t *jpeg_out_; - // 检测状态机 - enum DetectionState { - IDLE, // 空闲状态 - VALIDATING, // 验证中(连续检测3秒) - COOLDOWN // 冷却期(等待重新检测) - }; - - DetectionState detection_state = IDLE; - int64_t state_start_time = 0; - bool need_start_cooldown = false; // 是否需要开始冷却期 - int64_t last_detected_time = 0; // 验证期间最后一次检测到物体的时间 - - int detect_target = 0; - int detect_threshold = 75; - int detect_duration_sec = 2; // 检测持续时间2秒,确认人员持续存在 - int detect_invoke_interval_sec = 8; // 默认15秒冷却期,避免频繁开始会话 - int detect_debounce_sec = 1; // 验证期间人员离开的去抖动时间1秒 - int inference_en = 0; // 推理使能开关(0: 关闭, 1: 开启) - bool sscma_restarted_ = false; - - sscma_client_model_t *model; - int model_class_cnt = 0; -public: - SscmaCamera(esp_io_expander_handle_t io_exp_handle); - ~SscmaCamera(); - void InitializeMcpTools(); - - virtual void SetExplainUrl(const std::string& url, const std::string& token); - virtual bool Capture(); - // 翻转控制函数 - virtual bool SetHMirror(bool enabled) override; - virtual bool SetVFlip(bool enabled) override; - virtual std::string Explain(const std::string& question); - -}; - -#endif // ESP32_CAMERA_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/README.md deleted file mode 100644 index 84b854bd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/README.md +++ /dev/null @@ -1,31 +0,0 @@ -【产品简介】 -】支持触摸 -】支持充电 -】独特外形设计 -产品链接1:https://spotpear.cn/shop/ESP32-S3-N16R8-AI-DeepSeek-XiaoZhi-XiaGe-Qwen-DouBao-1.28-inch-LCD.html -产品链接2:https://spotpear.cn/shop/ESP32-S3-N16R8-AI-DeepSeek-XiaoZhi-XiaGe-Qwen-DouBao-1.28-inch-Round-LCD-BOX-TouchScreen.html -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> Spotpear ESP32-S3-1.28-BOX -``` - -**编译:** - -```bash -idf.py build -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.h deleted file mode 100644 index cde7dcb4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Movecall Moji configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 //MCLK -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 //LRCK -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 //SCLK -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 //DOUT -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 //DIN - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_4 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_2 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_5 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_47 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_38 - -#define TP_PIN_NUM_TP_SDA (GPIO_NUM_11) -#define TP_PIN_NUM_TP_SCL (GPIO_NUM_7) -#define TP_PIN_NUM_TP_RST (GPIO_NUM_6) -#define TP_PIN_NUM_TP_INT (GPIO_NUM_12) - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -// 电量检测相关引脚定义 -#define BATTERY_ADC_PIN GPIO_NUM_1 // 电池电压检测ADC引脚 -#define BATTERY_CHARGING_PIN GPIO_NUM_41 // 充电状态检测引脚 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.json deleted file mode 100644 index db34c1cd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "sp-esp32-s3-1.28-box", - "sdkconfig_append": [] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/power_manager.h deleted file mode 100644 index 36e8ca97..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/power_manager.h +++ /dev/null @@ -1,189 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include -#include -#include - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - adc_channel_t adc_channel_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, adc_channel_, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - 根据实际硬件调整这些值 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1980, 0}, - {2081, 20}, - {2163, 40}, - {2250, 60}, - {2340, 80}, - {2480, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t charging_pin, adc_channel_t adc_channel) - : charging_pin_(charging_pin), adc_channel_(adc_channel) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 100000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, adc_channel_, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/sp-esp32-s3-1.28-box.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/sp-esp32-s3-1.28-box.cc deleted file mode 100644 index 0f5eb45f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.28-box/sp-esp32-s3-1.28-box.cc +++ /dev/null @@ -1,484 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include -#include -#include - -#include -#include -#include -#include "system_reset.h" -#include "driver/gpio.h" -#include "driver/spi_master.h" -#include -#include "i2c_device.h" -#include -#include -#include "power_save_timer.h" -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "power_manager.h" - -#define TAG "Spotpear_ESP32_S3_1_28_BOX" - -LV_FONT_DECLARE(font_puhui_16_4); -LV_FONT_DECLARE(font_awesome_16_4); - - -class Cst816d : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - Cst816d(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA3); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - last_chip_id_ = chip_id; - read_buffer_ = new uint8_t[6]; - } - - ~Cst816d() { - if (read_buffer_) { - delete[] read_buffer_; - read_buffer_ = nullptr; - } - } - - void UpdateTouchPoint() { - if (!read_buffer_) return; - ReadRegs(0x02, read_buffer_, 6); - if (read_buffer_[0] == 0xFF) { - read_buffer_[0] = 0x00; - } - tp_.num = read_buffer_[0] & 0x01; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t& GetTouchPoint() const { - return tp_; - } - - static bool Probe(i2c_master_bus_handle_t i2c_bus, uint8_t addr, uint8_t& chip_id) { - if (!i2c_bus) return false; - i2c_master_dev_handle_t dev = nullptr; - i2c_device_config_t cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = addr, - .scl_speed_hz = 400 * 1000, - .scl_wait_us = 0, - .flags = { - .disable_ack_check = 0, - }, - }; - esp_err_t ret = i2c_master_bus_add_device(i2c_bus, &cfg, &dev); - if (ret != ESP_OK || dev == nullptr) { - return false; - } - uint8_t reg = 0xA3; - uint8_t id = 0; - ret = i2c_master_transmit_receive(dev, ®, 1, &id, 1, 100); - i2c_master_bus_rm_device(dev); - if (ret == ESP_OK) { - chip_id = id; - return true; - } - return false; - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; - uint8_t last_chip_id_ = 0; -}; - - -class CustomLcdDisplay : public SpiLcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - - DisplayLockGuard lock(this); - // 由于屏幕是圆的,所以状态栏需要增加左右内边距 - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES * 0.33, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES * 0.33, 0); - } -}; - - -class Spotpear_ESP32_S3_1_28_BOX : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_ = nullptr; - i2c_master_bus_handle_t i2c_bus_ = nullptr; - Button boot_button_; - Display* display_ = nullptr; - esp_timer_handle_t touchpad_timer_ = nullptr; - Cst816d* cst816d_ = nullptr; - PowerSaveTimer* power_save_timer_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - PowerManager* power_manager_ = nullptr; - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_3); - rtc_gpio_set_direction(GPIO_NUM_3, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_3, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 290); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - // 关闭ES8311音频编解码器 - auto codec = GetAudioCodec(); - if (codec) { - codec->EnableInput(false); - codec->EnableOutput(false); - } - rtc_gpio_set_level(GPIO_NUM_3, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_3); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(BATTERY_CHARGING_PIN, ADC_CHANNEL_0); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - // .glitch_ignore_cnt = 7, - // .intr_priority = 0, - // .trans_queue_depth = 0, - // .flags = { - // .enable_internal_pullup = 1, - // }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeCodecI2c_Touch() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = TP_PIN_NUM_TP_SDA, - .scl_io_num = TP_PIN_NUM_TP_SCL, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - esp_err_t ret = i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "i2c_new_master_bus failed: %s", esp_err_to_name(ret)); - i2c_bus_ = nullptr; - } - } - - - static void touchpad_timer_callback(void* arg) { - auto* board = static_cast(arg); - if (!board || !board->cst816d_) return; - static bool was_touched = false; - static int64_t touch_start_time = 0; - const int64_t TOUCH_THRESHOLD_MS = 500; // 触摸时长阈值,超过500ms视为长按 - - board->cst816d_->UpdateTouchPoint(); - auto touch_point = board->cst816d_->GetTouchPoint(); - - // 检测触摸开始 - if (touch_point.num > 0 && !was_touched) { - was_touched = true; - touch_start_time = esp_timer_get_time() / 1000; // 转换为毫秒 - } - // 检测触摸释放 - else if (touch_point.num == 0 && was_touched) { - was_touched = false; - int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; - - // 只有短触才触发 - if (touch_duration < TOUCH_THRESHOLD_MS) { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing touch enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - board->EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - } - } - - void InitializeCst816DTouchPad() { - ESP_LOGI(TAG, "Init Cst816D"); - - // RST/INT 管脚初始化 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << TP_PIN_NUM_TP_RST); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - gpio_config_t int_conf = {}; - int_conf.intr_type = GPIO_INTR_DISABLE; - int_conf.mode = GPIO_MODE_INPUT; - int_conf.pin_bit_mask = (1ULL << TP_PIN_NUM_TP_INT); - int_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - int_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&int_conf); - - // 触摸芯片复位序列 - gpio_set_level(TP_PIN_NUM_TP_RST, 0); - vTaskDelay(pdMS_TO_TICKS(5)); - gpio_set_level(TP_PIN_NUM_TP_RST, 1); - vTaskDelay(pdMS_TO_TICKS(50)); - - // 探测是否存在触摸芯片 - uint8_t chip_id = 0; - if (!i2c_bus_) { - ESP_LOGW(TAG, "Touch I2C bus not initialized, skip touch"); - return; - } - bool touch_available = Cst816d::Probe(i2c_bus_, 0x15, chip_id); - if (!touch_available) { - ESP_LOGW(TAG, "CST816D not found, running in non-touch mode"); - // 释放触摸I2C,避免无设备时反复报错 - i2c_del_master_bus(i2c_bus_); - i2c_bus_ = nullptr; - return; - } - - cst816d_ = new Cst816d(i2c_bus_, 0x15); - - // 创建定时器,10ms 间隔 - esp_timer_create_args_t timer_args = { - .callback = touchpad_timer_callback, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "touchpad_timer", - .skip_unhandled_events = true, - }; - - if (esp_timer_create(&timer_args, &touchpad_timer_) == ESP_OK) { - esp_timer_start_periodic(touchpad_timer_, 10 * 1000); // 10ms = 10000us - } - } - - // SPI初始化 - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize SPI bus"); - spi_bus_config_t buscfg = GC9A01_PANEL_BUS_SPI_CONFIG(DISPLAY_SPI_SCLK_PIN, DISPLAY_SPI_MOSI_PIN, - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - // GC9A01初始化 - void InitializeGc9a01Display() { - ESP_LOGI(TAG, "Init GC9A01 display"); - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_lcd_panel_io_spi_config_t io_config = GC9A01_PANEL_IO_SPI_CONFIG(DISPLAY_SPI_CS_PIN, DISPLAY_SPI_DC_PIN, 0, NULL); - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &io_handle)); - - ESP_LOGI(TAG, "Install GC9A01 panel driver"); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; // Set to -1 if not use - panel_config.rgb_endian = LCD_RGB_ENDIAN_BGR; //LCD_RGB_ENDIAN_RGB; - panel_config.bits_per_pixel = 16; - - ESP_ERROR_CHECK(esp_lcd_new_panel_gc9a01(io_handle, &panel_config, &panel_handle)); - panel_ = panel_handle; - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true)); - - uint8_t data_0x62[] = { 0x18, 0x0D, 0x71, 0xED, 0x70, 0x70, 0x18, 0x0F, 0x71, 0xEF, 0x70, 0x70 }; - esp_lcd_panel_io_tx_param(io_handle, 0x62, data_0x62, sizeof(data_0x62)); - - uint8_t data_0x63[] = { 0x18, 0x11, 0x71, 0xF1, 0x70, 0x70, 0x18, 0x13, 0x71, 0xF3, 0x70, 0x70 }; - esp_lcd_panel_io_tx_param(io_handle, 0x63, data_0x63, sizeof(data_0x63)); - - uint8_t data_0x36[] = { 0x48}; - esp_lcd_panel_io_tx_param(io_handle, 0x36, data_0x36, sizeof(data_0x36)); - - // uint8_t data_0x74[] = { 0x10, 0x85, 0x80, 0x00, 0x00, 0x4E, 0x00}; - // esp_lcd_panel_io_tx_param(io_handle, 0x74, data_0x74, sizeof(data_0x74)); - - uint8_t data_0xC3[] = { 0x1F}; - esp_lcd_panel_io_tx_param(io_handle, 0xC3, data_0xC3, sizeof(data_0xC3)); - - uint8_t data_0xC4[] = { 0x1F}; - esp_lcd_panel_io_tx_param(io_handle, 0xC4, data_0xC4, sizeof(data_0xC4)); - - display_ = new CustomLcdDisplay(io_handle, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - Spotpear_ESP32_S3_1_28_BOX() : boot_button_(BOOT_BUTTON_GPIO) { - // 先初始化触摸的I2C并探测/初始化触摸(若无触摸则跳过) - InitializeCodecI2c_Touch(); - InitializeCst816DTouchPad(); - - // 初始化音频I2C - InitializeCodecI2c(); - - // 显示相关先建立起来 - InitializeSpi(); - InitializeGc9a01Display(); - InitializeButtons(); - if (GetBacklight()) { - GetBacklight()->RestoreBrightness(); - } - - // 显示和背光可用后再初始化省电逻辑,避免空指针 - InitializePowerSaveTimer(); - InitializePowerManager(); - } - - ~Spotpear_ESP32_S3_1_28_BOX() { - if (touchpad_timer_) { - esp_timer_stop(touchpad_timer_); - esp_timer_delete(touchpad_timer_); - touchpad_timer_ = nullptr; - } - if (cst816d_) { - delete cst816d_; - cst816d_ = nullptr; - } - if (power_save_timer_) { - delete power_save_timer_; - power_save_timer_ = nullptr; - } - if (power_manager_) { - delete power_manager_; - power_manager_ = nullptr; - } - if (display_) { - delete display_; - display_ = nullptr; - } - if (i2c_bus_) { - i2c_del_master_bus(i2c_bus_); - i2c_bus_ = nullptr; - } - if (codec_i2c_bus_) { - i2c_del_master_bus(codec_i2c_bus_); - codec_i2c_bus_ = nullptr; - } - } - - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - Cst816d* GetTouchpad() { - return cst816d_; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - if (!power_manager_) { - level = 0; - charging = false; - discharging = true; - return false; - } - - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(Spotpear_ESP32_S3_1_28_BOX); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/README.md deleted file mode 100644 index 94a00bb7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/README.md +++ /dev/null @@ -1,34 +0,0 @@ -【产品简介】 -[] ESP32 S3小木马开发板1.54寸LCD小智muma虾哥AI DeepSeek人工智能语音聊天机器人N16R8 -【功能】 -[] 可爱小木马,支持天气时钟, SD视频播放, AI智能对话所有固件源码开源,适合小孩编程学习,可开发更多功能。 -AI小智支持语音唤醒。触摸版本额外支持触摸唤醒和打断 -显示屏:1.54寸ST7789 240x240分辨率 -产品链接: -https://spotpear.cn/shop/ESP32-S3-AI-1.54-inch-LCD-Display-TouchScreen-N16R8-muma-DeepSeek/sp-esp32-s3-1.54-muma-W-Bat.html - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> Spotpear ESP32-S3-LCD-1.54-MUMA -``` - -**编译:** - -```bash -idf.py build -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.h deleted file mode 100644 index a13ce753..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Movecall Moji configuration - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 //MCLK -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 //LRCK -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 //SCLK -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 //DOUT -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 //DIN - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_42 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#define DISPLAY_SPI_SCLK_PIN GPIO_NUM_4 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_2 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_5 -#define DISPLAY_SPI_DC_PIN GPIO_NUM_47 -#define DISPLAY_SPI_RESET_PIN GPIO_NUM_38 - - -#define TP_PIN_NUM_TP_SDA (GPIO_NUM_11) -#define TP_PIN_NUM_TP_SCL (GPIO_NUM_7) -#define TP_PIN_NUM_TP_RST (GPIO_NUM_6) -#define TP_PIN_NUM_TP_INT (GPIO_NUM_12) - -#define POWER_CHARGE_LED_PIN GPIO_NUM_3 -#define POWER_CHARGE_DETECT_PIN GPIO_NUM_41 -#define POWER_ADC_UNIT ADC_UNIT_1 -#define POWER_ADC_CHANNEL ADC_CHANNEL_0 - -#define DISPLAY_SPI_SCLK_HZ (40 * 1000 * 1000) - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.json deleted file mode 100644 index 2bc4d1b8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "sp-esp32-s3-1.54-muma", - "sdkconfig_append": [] - } - ] -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/power_manager.h deleted file mode 100644 index 2df53a1e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/power_manager.h +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_41; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_0, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1980, 0}, - {2081, 20}, - {2163, 40}, - {2250, 60}, - {2340, 80}, - {2480, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 100000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_0, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/sp-esp32-s3-1.54-muma.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/sp-esp32-s3-1.54-muma.cc deleted file mode 100644 index b56c3b8a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/sp-esp32-s3-1.54-muma/sp-esp32-s3-1.54-muma.cc +++ /dev/null @@ -1,325 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include -#include -#include "system_reset.h" - -#include -#include - -#include "driver/gpio.h" -#include "driver/spi_master.h" -#include -#include -#include -#include "i2c_device.h" -#include -#include "power_manager.h" -#include "power_save_timer.h" -#include -#include - -#define TAG "Spotpear_esp32_s3_lcd_1_54" - -class Cst816d : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - Cst816d(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA3); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Cst816d() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t& GetTouchPoint() { - return tp_; - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class Spotpear_esp32_s3_lcd_1_54 : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Display* display_; - esp_timer_handle_t touchpad_timer_; - Cst816d* cst816d_; - esp_io_expander_handle_t io_expander_ = NULL; - esp_lcd_panel_handle_t panel_ = nullptr; - - PowerManager* power_manager_; - PowerSaveTimer* power_save_timer_; - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_41); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_3); - rtc_gpio_set_direction(GPIO_NUM_3, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_3, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_3, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_3); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeCodecI2c_Touch() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = TP_PIN_NUM_TP_SDA, - .scl_io_num = TP_PIN_NUM_TP_SCL, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static void touchpad_timer_callback(void* arg) { - auto& board = (Spotpear_esp32_s3_lcd_1_54&)Board::GetInstance(); - auto touchpad = board.GetTouchpad(); - static bool was_touched = false; - static int64_t touch_start_time = 0; - const int64_t TOUCH_THRESHOLD_MS = 500; // 触摸时长阈值,超过500ms视为长按 - - touchpad->UpdateTouchPoint(); - auto touch_point = touchpad->GetTouchPoint(); - // 检测触摸开始 - if (touch_point.num > 0 && !was_touched) { - was_touched = true; - touch_start_time = esp_timer_get_time() / 1000; // 转换为毫秒 - } - // 检测触摸释放 - else if (touch_point.num == 0 && was_touched) { - was_touched = false; - int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; - - // 只有短触才触发 - if (touch_duration < TOUCH_THRESHOLD_MS) { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - board.EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - } - } - - void InitializeCst816DTouchPad() { - ESP_LOGI(TAG, "Init Cst816D"); - cst816d_ = new Cst816d(i2c_bus_, 0x15); - - // 创建定时器,10ms 间隔 - esp_timer_create_args_t timer_args = { - .callback = touchpad_timer_callback, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "touchpad_timer", - .skip_unhandled_events = true, - }; - - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &touchpad_timer_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(touchpad_timer_, 10 * 1000)); // 10ms = 10000us - } - - void EnableLcdCs() { - if(io_expander_ != NULL) { - esp_io_expander_set_level(io_expander_, DISPLAY_SPI_CS_PIN, 0);// 置低 LCD CS - } - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SPI_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN; - io_config.dc_gpio_num = DISPLAY_SPI_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 60 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_RESET_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - EnableLcdCs(); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - - // uint8_t data_0xBB[] = { 0x3F }; - // esp_lcd_panel_io_tx_param(panel_io, 0xBB, data_0xBB, sizeof(data_0xBB)); - - uint8_t data_0xBB[] = { 0x38 }; - esp_lcd_panel_io_tx_param(panel_io, 0xBB, data_0xBB, sizeof(data_0xBB)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - - Spotpear_esp32_s3_lcd_1_54() :boot_button_(BOOT_BUTTON_GPIO){ - gpio_set_direction(TP_PIN_NUM_TP_INT, GPIO_MODE_INPUT); - int level = gpio_get_level(TP_PIN_NUM_TP_INT); - if (level == 1) { - InitializeCodecI2c_Touch(); - InitializeCst816DTouchPad(); - } - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeSpi(); - InitializePowerManager(); - InitializeSt7789Display(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - - } - - virtual Led* GetLed() override { - static SingleLed led_strip(BUILTIN_LED_GPIO); - return &led_strip; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst816d* GetTouchpad() { - return cst816d_; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(Spotpear_esp32_s3_lcd_1_54); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/README.md deleted file mode 100644 index 9a6d211d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/README.md +++ /dev/null @@ -1,5 +0,0 @@ -## Surfer-ESP32-C3 开发板 - -1、参考立创·实战派C3-ESP32C3开发板,修改了TFT屏幕背光引脚,增加ADC电池电量检测功能; -2、该开发板 flash 大小为 16MB,编译时注意选择默认的分区表。 - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.h deleted file mode 100644 index 79703306..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_11 - -// #define AUDIO_CODEC_USE_PCA9557 -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_0 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -// #define AUDIO_CODEC_ES7210_ADDR 0x82 - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SPI_SCK_PIN GPIO_NUM_3 -#define DISPLAY_SPI_MOSI_PIN GPIO_NUM_5 -#define DISPLAY_DC_PIN GPIO_NUM_6 -#define DISPLAY_SPI_CS_PIN GPIO_NUM_4 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 135 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY true - -#define DISPLAY_OFFSET_X 40 -#define DISPLAY_OFFSET_Y 53 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.json deleted file mode 100644 index a8f30ad1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "surfer-c3-1.14tft", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/power_manager.h deleted file mode 100644 index 22643b83..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/power_manager.h +++ /dev/null @@ -1,201 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_2, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {3060, 0}, - {3200, 20}, - {3340, 40}, - {3480, 60}, - {3620, 80}, - {3760, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - - - if (charging_pin_ != GPIO_NUM_NC) { - // 不初始化 ADC,不检测 - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - } - - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_2_5, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_2, &chan_config)); - ESP_LOGI("PowerManager ADC INIT------------------", - "ADC atten: ADC_ATTEN_DB_2_5, bitwidth: ADC_BITWIDTH_DEFAULT ADC chan: ADC_CHANNEL_2"); - - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - if (charging_pin_ == GPIO_NUM_NC) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - if (charging_pin_ == GPIO_NUM_NC) { - return false; - } - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/surfer-c3-1.14tft.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/surfer-c3-1.14tft.cc deleted file mode 100644 index 7952ece9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/surfer-c3-1.14tft/surfer-c3-1.14tft.cc +++ /dev/null @@ -1,210 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include -#include - -#include "power_save_timer.h" -#include "power_manager.h" -// #include - -#define TAG "SURFERC3114TFT" - -class SurferC3114TFT : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_NC); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - - } - - void InitializePowerSaveTimer() { - //定时器,调整设备为modem-sleep模式和屏幕亮度 - power_save_timer_ = new PowerSaveTimer(-1, 60, -1); - power_save_timer_->OnEnterSleepMode([this]() { - ESP_LOGI(TAG, "Enabling modem-sleep mode"); - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - esp_wifi_set_ps(WIFI_PS_MIN_MODEM); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - esp_wifi_set_ps(WIFI_PS_NONE); // 关闭Wi-Fi省电,恢复正常 - // esp_lcd_panel_disp_on_off(panel_, true); // 重新打开显示 - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down display"); - GetBacklight()->SetBrightness(1); - // esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - // power_save_timer_->SetEnabled(false); // 禁用定时器,防止重复 - - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SPI_SCK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSt7789Display() { - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io_)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - - esp_lcd_panel_reset(panel_); - - esp_lcd_panel_init(panel_); - esp_lcd_panel_invert_color(panel_, true); - esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io_, panel_, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - SurferC3114TFT() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - InitializeButtons(); - - GetBacklight()->RestoreBrightness(); - - // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 - esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - codec_i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - -}; - -DECLARE_BOARD(SurferC3114TFT); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/README.md deleted file mode 100644 index c3e7b2f1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# 由于原来的麦克风型号停产,2025年7月之后的太极派(JC3636W518)更换了麦克风,并且更换了屏幕玻璃,所以在产品标签上批次号大于2528的用户请选择I2S Type PDM, - -# 新增双声道配置 - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> 太极小派esp32s3 - -Xiaozhi Assistant -> TAIJIPAI_S3_CONFIG -> taiji-pi-S3 I2S Type -> I2S Type PDM -``` - -**如果需要选择双声道:** -``` - -Xiaozhi Assistant -> TAIJIPAI_S3_CONFIG -> Enabel use 2 slot -``` - - -**修改PSRAM配置:** - -``` -component config -> ESP PSRAM -> SPI RAM config -> Try to allocate memories of WiFi and LWIP in SPIRAM firstly. If failed, allocate internal memory - -``` - -**编译:** - -```bash -idf.py build -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.h deleted file mode 100644 index c07d6200..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -// Taiji Pi S3 Board configuration - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_DEFAULT_OUTPUT_VOLUME 80 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_21 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_16 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_18 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_NC -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_17 -#define AUDIO_MUTE_PIN GPIO_NUM_48 // 低电平静音 - -#define AUDIO_MIC_WS_PIN GPIO_NUM_45 -#define AUDIO_MIC_SD_PIN GPIO_NUM_46 -#define AUDIO_MIC_SCK_PIN GPIO_NUM_42 - -#define DISPLAY_WIDTH 360 -#define DISPLAY_HEIGHT 360 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true -#define DISPLAY_SWAP_XY false - -#define QSPI_LCD_H_RES (360) -#define QSPI_LCD_V_RES (360) -#define QSPI_LCD_BIT_PER_PIXEL (16) - -#define QSPI_LCD_HOST SPI2_HOST -#define QSPI_PIN_NUM_LCD_PCLK GPIO_NUM_9 -#define QSPI_PIN_NUM_LCD_CS GPIO_NUM_10 -#define QSPI_PIN_NUM_LCD_DATA0 GPIO_NUM_11 -#define QSPI_PIN_NUM_LCD_DATA1 GPIO_NUM_12 -#define QSPI_PIN_NUM_LCD_DATA2 GPIO_NUM_13 -#define QSPI_PIN_NUM_LCD_DATA3 GPIO_NUM_14 -#define QSPI_PIN_NUM_LCD_RST GPIO_NUM_47 -#define QSPI_PIN_NUM_LCD_BL GPIO_NUM_15 - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define TP_PORT (I2C_NUM_1) -#define TP_PIN_NUM_TP_SDA (GPIO_NUM_7) -#define TP_PIN_NUM_TP_SCL (GPIO_NUM_8) -#define TP_PIN_NUM_TP_RST (GPIO_NUM_40) -#define TP_PIN_NUM_TP_INT (GPIO_NUM_41) - -#define DISPLAY_BACKLIGHT_PIN QSPI_PIN_NUM_LCD_BL -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(sclk, d0, d1, d2, d3, max_trans_sz) \ - { \ - .data0_io_num = d0, \ - .data1_io_num = d1, \ - .sclk_io_num = sclk, \ - .data2_io_num = d2, \ - .data3_io_num = d3, \ - .max_transfer_sz = max_trans_sz, \ - } - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.json deleted file mode 100644 index 5b817844..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "taiji-pi-s3", - "sdkconfig_append": [ - "CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y", - "CONFIG_TAIJIPAI_I2S_TYPE_STD=y" - ] - }, - { - "name": "taiji-pi-s3-pdm", - "sdkconfig_append": [ - "CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=y", - "CONFIG_TAIJIPAI_I2S_TYPE_PDM=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/taiji_pi_s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/taiji_pi_s3.cc deleted file mode 100644 index 06635a79..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/taiji-pi-s3/taiji_pi_s3.cc +++ /dev/null @@ -1,663 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "application.h" -#include "i2c_device.h" -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#define TAG "TaijiPiS3Board" - -static const st77916_lcd_init_cmd_t lcd_init_cmds[] = { -#ifdef CONFIG_TAIJIPAI_I2S_TYPE_STD - {0xF0, (uint8_t[]){0x08}, 1, 0}, - {0xF2, (uint8_t[]){0x08}, 1, 0}, - {0x9B, (uint8_t[]){0x51}, 1, 0}, - {0x86, (uint8_t[]){0x53}, 1, 0}, - {0xF2, (uint8_t[]){0x80}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0xF0, (uint8_t[]){0x01}, 1, 0}, - {0xF1, (uint8_t[]){0x01}, 1, 0}, - {0xB0, (uint8_t[]){0x54}, 1, 0}, - {0xB1, (uint8_t[]){0x3F}, 1, 0}, - {0xB2, (uint8_t[]){0x2A}, 1, 0}, - {0xB4, (uint8_t[]){0x46}, 1, 0}, - {0xB5, (uint8_t[]){0x34}, 1, 0}, - {0xB6, (uint8_t[]){0xD5}, 1, 0}, - {0xB7, (uint8_t[]){0x30}, 1, 0}, - {0xBA, (uint8_t[]){0x00}, 1, 0}, - {0xBB, (uint8_t[]){0x08}, 1, 0}, - {0xBC, (uint8_t[]){0x08}, 1, 0}, - {0xBD, (uint8_t[]){0x00}, 1, 0}, - {0xC0, (uint8_t[]){0x80}, 1, 0}, - {0xC1, (uint8_t[]){0x10}, 1, 0}, - {0xC2, (uint8_t[]){0x37}, 1, 0}, - {0xC3, (uint8_t[]){0x80}, 1, 0}, - {0xC4, (uint8_t[]){0x10}, 1, 0}, - {0xC5, (uint8_t[]){0x37}, 1, 0}, - {0xC6, (uint8_t[]){0xA9}, 1, 0}, - {0xC7, (uint8_t[]){0x41}, 1, 0}, - {0xC8, (uint8_t[]){0x51}, 1, 0}, - {0xC9, (uint8_t[]){0xA9}, 1, 0}, - {0xCA, (uint8_t[]){0x41}, 1, 0}, - {0xCB, (uint8_t[]){0x51}, 1, 0}, - {0xD0, (uint8_t[]){0x91}, 1, 0}, - {0xD1, (uint8_t[]){0x68}, 1, 0}, - {0xD2, (uint8_t[]){0x69}, 1, 0}, - {0xF5, (uint8_t[]){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t[]){0x3F}, 1, 0}, - {0xDE, (uint8_t[]){0x3F}, 1, 0}, - {0xF1, (uint8_t[]){0x10}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0xF0, (uint8_t[]){0x02}, 1, 0}, - {0xE0, (uint8_t[]){0x70, 0x09, 0x12, 0x0C, 0x0B, 0x27, 0x38, 0x54, 0x4E, 0x19, 0x15, 0x15, 0x2C, 0x2F}, 14, 0}, - {0xE1, (uint8_t[]){0x70, 0x08, 0x11, 0x0C, 0x0B, 0x27, 0x38, 0x43, 0x4C, 0x18, 0x14, 0x14, 0x2B, 0x2D}, 14, 0}, - {0xF0, (uint8_t[]){0x10}, 1, 0}, - {0xF3, (uint8_t[]){0x10}, 1, 0}, - {0xE0, (uint8_t[]){0x08}, 1, 0}, - {0xE1, (uint8_t[]){0x00}, 1, 0}, - {0xE2, (uint8_t[]){0x00}, 1, 0}, - {0xE3, (uint8_t[]){0x00}, 1, 0}, - {0xE4, (uint8_t[]){0xE0}, 1, 0}, - {0xE5, (uint8_t[]){0x06}, 1, 0}, - {0xE6, (uint8_t[]){0x21}, 1, 0}, - {0xE7, (uint8_t[]){0x00}, 1, 0}, - {0xE8, (uint8_t[]){0x05}, 1, 0}, - {0xE9, (uint8_t[]){0x82}, 1, 0}, - {0xEA, (uint8_t[]){0xDF}, 1, 0}, - {0xEB, (uint8_t[]){0x89}, 1, 0}, - {0xEC, (uint8_t[]){0x20}, 1, 0}, - {0xED, (uint8_t[]){0x14}, 1, 0}, - {0xEE, (uint8_t[]){0xFF}, 1, 0}, - {0xEF, (uint8_t[]){0x00}, 1, 0}, - {0xF8, (uint8_t[]){0xFF}, 1, 0}, - {0xF9, (uint8_t[]){0x00}, 1, 0}, - {0xFA, (uint8_t[]){0x00}, 1, 0}, - {0xFB, (uint8_t[]){0x30}, 1, 0}, - {0xFC, (uint8_t[]){0x00}, 1, 0}, - {0xFD, (uint8_t[]){0x00}, 1, 0}, - {0xFE, (uint8_t[]){0x00}, 1, 0}, - {0xFF, (uint8_t[]){0x00}, 1, 0}, - {0x60, (uint8_t[]){0x42}, 1, 0}, - {0x61, (uint8_t[]){0xE0}, 1, 0}, - {0x62, (uint8_t[]){0x40}, 1, 0}, - {0x63, (uint8_t[]){0x40}, 1, 0}, - {0x64, (uint8_t[]){0x02}, 1, 0}, - {0x65, (uint8_t[]){0x00}, 1, 0}, - {0x66, (uint8_t[]){0x40}, 1, 0}, - {0x67, (uint8_t[]){0x03}, 1, 0}, - {0x68, (uint8_t[]){0x00}, 1, 0}, - {0x69, (uint8_t[]){0x00}, 1, 0}, - {0x6A, (uint8_t[]){0x00}, 1, 0}, - {0x6B, (uint8_t[]){0x00}, 1, 0}, - {0x70, (uint8_t[]){0x42}, 1, 0}, - {0x71, (uint8_t[]){0xE0}, 1, 0}, - {0x72, (uint8_t[]){0x40}, 1, 0}, - {0x73, (uint8_t[]){0x40}, 1, 0}, - {0x74, (uint8_t[]){0x02}, 1, 0}, - {0x75, (uint8_t[]){0x00}, 1, 0}, - {0x76, (uint8_t[]){0x40}, 1, 0}, - {0x77, (uint8_t[]){0x03}, 1, 0}, - {0x78, (uint8_t[]){0x00}, 1, 0}, - {0x79, (uint8_t[]){0x00}, 1, 0}, - {0x7A, (uint8_t[]){0x00}, 1, 0}, - {0x7B, (uint8_t[]){0x00}, 1, 0}, - {0x80, (uint8_t[]){0x48}, 1, 0}, - {0x81, (uint8_t[]){0x00}, 1, 0}, - {0x82, (uint8_t[]){0x05}, 1, 0}, - {0x83, (uint8_t[]){0x02}, 1, 0}, - {0x84, (uint8_t[]){0xDD}, 1, 0}, - {0x85, (uint8_t[]){0x00}, 1, 0}, - {0x86, (uint8_t[]){0x00}, 1, 0}, - {0x87, (uint8_t[]){0x00}, 1, 0}, - {0x88, (uint8_t[]){0x48}, 1, 0}, - {0x89, (uint8_t[]){0x00}, 1, 0}, - {0x8A, (uint8_t[]){0x07}, 1, 0}, - {0x8B, (uint8_t[]){0x02}, 1, 0}, - {0x8C, (uint8_t[]){0xDF}, 1, 0}, - {0x8D, (uint8_t[]){0x00}, 1, 0}, - {0x8E, (uint8_t[]){0x00}, 1, 0}, - {0x8F, (uint8_t[]){0x00}, 1, 0}, - {0x90, (uint8_t[]){0x48}, 1, 0}, - {0x91, (uint8_t[]){0x00}, 1, 0}, - {0x92, (uint8_t[]){0x09}, 1, 0}, - {0x93, (uint8_t[]){0x02}, 1, 0}, - {0x94, (uint8_t[]){0xE1}, 1, 0}, - {0x95, (uint8_t[]){0x00}, 1, 0}, - {0x96, (uint8_t[]){0x00}, 1, 0}, - {0x97, (uint8_t[]){0x00}, 1, 0}, - {0x98, (uint8_t[]){0x48}, 1, 0}, - {0x99, (uint8_t[]){0x00}, 1, 0}, - {0x9A, (uint8_t[]){0x0B}, 1, 0}, - {0x9B, (uint8_t[]){0x02}, 1, 0}, - {0x9C, (uint8_t[]){0xE3}, 1, 0}, - {0x9D, (uint8_t[]){0x00}, 1, 0}, - {0x9E, (uint8_t[]){0x00}, 1, 0}, - {0x9F, (uint8_t[]){0x00}, 1, 0}, - {0xA0, (uint8_t[]){0x48}, 1, 0}, - {0xA1, (uint8_t[]){0x00}, 1, 0}, - {0xA2, (uint8_t[]){0x04}, 1, 0}, - {0xA3, (uint8_t[]){0x02}, 1, 0}, - {0xA4, (uint8_t[]){0xDC}, 1, 0}, - {0xA5, (uint8_t[]){0x00}, 1, 0}, - {0xA6, (uint8_t[]){0x00}, 1, 0}, - {0xA7, (uint8_t[]){0x00}, 1, 0}, - {0xA8, (uint8_t[]){0x48}, 1, 0}, - {0xA9, (uint8_t[]){0x00}, 1, 0}, - {0xAA, (uint8_t[]){0x06}, 1, 0}, - {0xAB, (uint8_t[]){0x02}, 1, 0}, - {0xAC, (uint8_t[]){0xDE}, 1, 0}, - {0xAD, (uint8_t[]){0x00}, 1, 0}, - {0xAE, (uint8_t[]){0x00}, 1, 0}, - {0xAF, (uint8_t[]){0x00}, 1, 0}, - {0xB0, (uint8_t[]){0x48}, 1, 0}, - {0xB1, (uint8_t[]){0x00}, 1, 0}, - {0xB2, (uint8_t[]){0x08}, 1, 0}, - {0xB3, (uint8_t[]){0x02}, 1, 0}, - {0xB4, (uint8_t[]){0xE0}, 1, 0}, - {0xB5, (uint8_t[]){0x00}, 1, 0}, - {0xB6, (uint8_t[]){0x00}, 1, 0}, - {0xB7, (uint8_t[]){0x00}, 1, 0}, - {0xB8, (uint8_t[]){0x48}, 1, 0}, - {0xB9, (uint8_t[]){0x00}, 1, 0}, - {0xBA, (uint8_t[]){0x0A}, 1, 0}, - {0xBB, (uint8_t[]){0x02}, 1, 0}, - {0xBC, (uint8_t[]){0xE2}, 1, 0}, - {0xBD, (uint8_t[]){0x00}, 1, 0}, - {0xBE, (uint8_t[]){0x00}, 1, 0}, - {0xBF, (uint8_t[]){0x00}, 1, 0}, - {0xC0, (uint8_t[]){0x12}, 1, 0}, - {0xC1, (uint8_t[]){0xAA}, 1, 0}, - {0xC2, (uint8_t[]){0x65}, 1, 0}, - {0xC3, (uint8_t[]){0x74}, 1, 0}, - {0xC4, (uint8_t[]){0x47}, 1, 0}, - {0xC5, (uint8_t[]){0x56}, 1, 0}, - {0xC6, (uint8_t[]){0x00}, 1, 0}, - {0xC7, (uint8_t[]){0x88}, 1, 0}, - {0xC8, (uint8_t[]){0x99}, 1, 0}, - {0xC9, (uint8_t[]){0x33}, 1, 0}, - {0xD0, (uint8_t[]){0x21}, 1, 0}, - {0xD1, (uint8_t[]){0xAA}, 1, 0}, - {0xD2, (uint8_t[]){0x65}, 1, 0}, - {0xD3, (uint8_t[]){0x74}, 1, 0}, - {0xD4, (uint8_t[]){0x47}, 1, 0}, - {0xD5, (uint8_t[]){0x56}, 1, 0}, - {0xD6, (uint8_t[]){0x00}, 1, 0}, - {0xD7, (uint8_t[]){0x88}, 1, 0}, - {0xD8, (uint8_t[]){0x99}, 1, 0}, - {0xD9, (uint8_t[]){0x33}, 1, 0}, - {0xF3, (uint8_t[]){0x01}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0xF0, (uint8_t[]){0x01}, 1, 0}, - {0xF1, (uint8_t[]){0x01}, 1, 0}, - {0xA0, (uint8_t[]){0x0B}, 1, 0}, - {0xA3, (uint8_t[]){0x2A}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x2B}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x2C}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x2D}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x2E}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x2F}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x30}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x31}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x32}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA3, (uint8_t[]){0x33}, 1, 0}, - {0xA5, (uint8_t[]){0xC3}, 1, 1}, - {0xA0, (uint8_t[]){0x09}, 1, 0}, - {0xF1, (uint8_t[]){0x10}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0x2A, (uint8_t[]){0x00, 0x00, 0x01, 0x67}, 4, 0}, - {0x2B, (uint8_t[]){0x01, 0x68, 0x01, 0x68}, 4, 0}, - {0x4D, (uint8_t[]){0x00}, 1, 0}, - {0x4E, (uint8_t[]){0x00}, 1, 0}, - {0x4F, (uint8_t[]){0x00}, 1, 0}, - {0x4C, (uint8_t[]){0x01}, 1, 10}, - {0x4C, (uint8_t[]){0x00}, 1, 0}, - {0x2A, (uint8_t[]){0x00, 0x00, 0x01, 0x67}, 4, 0}, - {0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0x67}, 4, 0}, - {0x21, (uint8_t[]){0x00}, 1, 0}, - //{0x3A, (uint8_t[]){0x55}, 1, 0}, // color=16 - {0x11, (uint8_t[]){0x00}, 1, 120}, - {0x29, (uint8_t[]){0x00}, 1, 0}, -#else - {0xF0, (uint8_t[]){0x28}, 1, 0}, - {0xF2, (uint8_t[]){0x28}, 1, 0}, - {0x73, (uint8_t[]){0xF0}, 1, 0}, - {0x7C, (uint8_t[]){0xD1}, 1, 0}, - {0x83, (uint8_t[]){0xE0}, 1, 0}, - {0x84, (uint8_t[]){0x61}, 1, 0}, - {0xF2, (uint8_t[]){0x82}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0xF0, (uint8_t[]){0x01}, 1, 0}, - {0xF1, (uint8_t[]){0x01}, 1, 0}, - {0xB0, (uint8_t[]){0x56}, 1, 0}, - {0xB1, (uint8_t[]){0x4D}, 1, 0}, - {0xB2, (uint8_t[]){0x24}, 1, 0}, - {0xB4, (uint8_t[]){0x87}, 1, 0}, - {0xB5, (uint8_t[]){0x44}, 1, 0}, - {0xB6, (uint8_t[]){0x8B}, 1, 0}, - {0xB7, (uint8_t[]){0x40}, 1, 0}, - {0xB8, (uint8_t[]){0x86}, 1, 0}, - {0xBA, (uint8_t[]){0x00}, 1, 0}, - {0xBB, (uint8_t[]){0x08}, 1, 0}, - {0xBC, (uint8_t[]){0x08}, 1, 0}, - {0xBD, (uint8_t[]){0x00}, 1, 0}, - {0xC0, (uint8_t[]){0x80}, 1, 0}, - {0xC1, (uint8_t[]){0x10}, 1, 0}, - {0xC2, (uint8_t[]){0x37}, 1, 0}, - {0xC3, (uint8_t[]){0x80}, 1, 0}, - {0xC4, (uint8_t[]){0x10}, 1, 0}, - {0xC5, (uint8_t[]){0x37}, 1, 0}, - {0xC6, (uint8_t[]){0xA9}, 1, 0}, - {0xC7, (uint8_t[]){0x41}, 1, 0}, - {0xC8, (uint8_t[]){0x01}, 1, 0}, - {0xC9, (uint8_t[]){0xA9}, 1, 0}, - {0xCA, (uint8_t[]){0x41}, 1, 0}, - {0xCB, (uint8_t[]){0x01}, 1, 0}, - {0xD0, (uint8_t[]){0x91}, 1, 0}, - {0xD1, (uint8_t[]){0x68}, 1, 0}, - {0xD2, (uint8_t[]){0x68}, 1, 0}, - {0xF5, (uint8_t[]){0x00, 0xA5}, 2, 0}, - {0xDD, (uint8_t[]){0x4F}, 1, 0}, - {0xDE, (uint8_t[]){0x4F}, 1, 0}, - {0xF1, (uint8_t[]){0x10}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0xF0, (uint8_t[]){0x02}, 1, 0}, - {0xE0, (uint8_t[]){0xF0, 0x0A, 0x10, 0x09, 0x09, 0x36, 0x35, 0x33, 0x4A, 0x29, 0x15, 0x15, 0x2E, 0x34}, 14, 0}, - {0xE1, (uint8_t[]){0xF0, 0x0A, 0x0F, 0x08, 0x08, 0x05, 0x34, 0x33, 0x4A, 0x39, 0x15, 0x15, 0x2D, 0x33}, 14, 0}, - {0xF0, (uint8_t[]){0x10}, 1, 0}, - {0xF3, (uint8_t[]){0x10}, 1, 0}, - {0xE0, (uint8_t[]){0x07}, 1, 0}, - {0xE1, (uint8_t[]){0x00}, 1, 0}, - {0xE2, (uint8_t[]){0x00}, 1, 0}, - {0xE3, (uint8_t[]){0x00}, 1, 0}, - {0xE4, (uint8_t[]){0xE0}, 1, 0}, - {0xE5, (uint8_t[]){0x06}, 1, 0}, - {0xE6, (uint8_t[]){0x21}, 1, 0}, - {0xE7, (uint8_t[]){0x01}, 1, 0}, - {0xE8, (uint8_t[]){0x05}, 1, 0}, - {0xE9, (uint8_t[]){0x02}, 1, 0}, - {0xEA, (uint8_t[]){0xDA}, 1, 0}, - {0xEB, (uint8_t[]){0x00}, 1, 0}, - {0xEC, (uint8_t[]){0x00}, 1, 0}, - {0xED, (uint8_t[]){0x0F}, 1, 0}, - {0xEE, (uint8_t[]){0x00}, 1, 0}, - {0xEF, (uint8_t[]){0x00}, 1, 0}, - {0xF8, (uint8_t[]){0x00}, 1, 0}, - {0xF9, (uint8_t[]){0x00}, 1, 0}, - {0xFA, (uint8_t[]){0x00}, 1, 0}, - {0xFB, (uint8_t[]){0x00}, 1, 0}, - {0xFC, (uint8_t[]){0x00}, 1, 0}, - {0xFD, (uint8_t[]){0x00}, 1, 0}, - {0xFE, (uint8_t[]){0x00}, 1, 0}, - {0xFF, (uint8_t[]){0x00}, 1, 0}, - {0x60, (uint8_t[]){0x40}, 1, 0}, - {0x61, (uint8_t[]){0x04}, 1, 0}, - {0x62, (uint8_t[]){0x00}, 1, 0}, - {0x63, (uint8_t[]){0x42}, 1, 0}, - {0x64, (uint8_t[]){0xD9}, 1, 0}, - {0x65, (uint8_t[]){0x00}, 1, 0}, - {0x66, (uint8_t[]){0x00}, 1, 0}, - {0x67, (uint8_t[]){0x00}, 1, 0}, - {0x68, (uint8_t[]){0x00}, 1, 0}, - {0x69, (uint8_t[]){0x00}, 1, 0}, - {0x6A, (uint8_t[]){0x00}, 1, 0}, - {0x6B, (uint8_t[]){0x00}, 1, 0}, - {0x70, (uint8_t[]){0x40}, 1, 0}, - {0x71, (uint8_t[]){0x03}, 1, 0}, - {0x72, (uint8_t[]){0x00}, 1, 0}, - {0x73, (uint8_t[]){0x42}, 1, 0}, - {0x74, (uint8_t[]){0xD8}, 1, 0}, - {0x75, (uint8_t[]){0x00}, 1, 0}, - {0x76, (uint8_t[]){0x00}, 1, 0}, - {0x77, (uint8_t[]){0x00}, 1, 0}, - {0x78, (uint8_t[]){0x00}, 1, 0}, - {0x79, (uint8_t[]){0x00}, 1, 0}, - {0x7A, (uint8_t[]){0x00}, 1, 0}, - {0x7B, (uint8_t[]){0x00}, 1, 0}, - {0x80, (uint8_t[]){0x48}, 1, 0}, - {0x81, (uint8_t[]){0x00}, 1, 0}, - {0x82, (uint8_t[]){0x06}, 1, 0}, - {0x83, (uint8_t[]){0x02}, 1, 0}, - {0x84, (uint8_t[]){0xD6}, 1, 0}, - {0x85, (uint8_t[]){0x04}, 1, 0}, - {0x86, (uint8_t[]){0x00}, 1, 0}, - {0x87, (uint8_t[]){0x00}, 1, 0}, - {0x88, (uint8_t[]){0x48}, 1, 0}, - {0x89, (uint8_t[]){0x00}, 1, 0}, - {0x8A, (uint8_t[]){0x08}, 1, 0}, - {0x8B, (uint8_t[]){0x02}, 1, 0}, - {0x8C, (uint8_t[]){0xD8}, 1, 0}, - {0x8D, (uint8_t[]){0x04}, 1, 0}, - {0x8E, (uint8_t[]){0x00}, 1, 0}, - {0x8F, (uint8_t[]){0x00}, 1, 0}, - {0x90, (uint8_t[]){0x48}, 1, 0}, - {0x91, (uint8_t[]){0x00}, 1, 0}, - {0x92, (uint8_t[]){0x0A}, 1, 0}, - {0x93, (uint8_t[]){0x02}, 1, 0}, - {0x94, (uint8_t[]){0xDA}, 1, 0}, - {0x95, (uint8_t[]){0x04}, 1, 0}, - {0x96, (uint8_t[]){0x00}, 1, 0}, - {0x97, (uint8_t[]){0x00}, 1, 0}, - {0x98, (uint8_t[]){0x48}, 1, 0}, - {0x99, (uint8_t[]){0x00}, 1, 0}, - {0x9A, (uint8_t[]){0x0C}, 1, 0}, - {0x9B, (uint8_t[]){0x02}, 1, 0}, - {0x9C, (uint8_t[]){0xDC}, 1, 0}, - {0x9D, (uint8_t[]){0x04}, 1, 0}, - {0x9E, (uint8_t[]){0x00}, 1, 0}, - {0x9F, (uint8_t[]){0x00}, 1, 0}, - {0xA0, (uint8_t[]){0x48}, 1, 0}, - {0xA1, (uint8_t[]){0x00}, 1, 0}, - {0xA2, (uint8_t[]){0x05}, 1, 0}, - {0xA3, (uint8_t[]){0x02}, 1, 0}, - {0xA4, (uint8_t[]){0xD5}, 1, 0}, - {0xA5, (uint8_t[]){0x04}, 1, 0}, - {0xA6, (uint8_t[]){0x00}, 1, 0}, - {0xA7, (uint8_t[]){0x00}, 1, 0}, - {0xA8, (uint8_t[]){0x48}, 1, 0}, - {0xA9, (uint8_t[]){0x00}, 1, 0}, - {0xAA, (uint8_t[]){0x07}, 1, 0}, - {0xAB, (uint8_t[]){0x02}, 1, 0}, - {0xAC, (uint8_t[]){0xD7}, 1, 0}, - {0xAD, (uint8_t[]){0x04}, 1, 0}, - {0xAE, (uint8_t[]){0x00}, 1, 0}, - {0xAF, (uint8_t[]){0x00}, 1, 0}, - {0xB0, (uint8_t[]){0x48}, 1, 0}, - {0xB1, (uint8_t[]){0x00}, 1, 0}, - {0xB2, (uint8_t[]){0x09}, 1, 0}, - {0xB3, (uint8_t[]){0x02}, 1, 0}, - {0xB4, (uint8_t[]){0xD9}, 1, 0}, - {0xB5, (uint8_t[]){0x04}, 1, 0}, - {0xB6, (uint8_t[]){0x00}, 1, 0}, - {0xB7, (uint8_t[]){0x00}, 1, 0}, - {0xB8, (uint8_t[]){0x48}, 1, 0}, - {0xB9, (uint8_t[]){0x00}, 1, 0}, - {0xBA, (uint8_t[]){0x0B}, 1, 0}, - {0xBB, (uint8_t[]){0x02}, 1, 0}, - {0xBC, (uint8_t[]){0xDB}, 1, 0}, - {0xBD, (uint8_t[]){0x04}, 1, 0}, - {0xBE, (uint8_t[]){0x00}, 1, 0}, - {0xBF, (uint8_t[]){0x00}, 1, 0}, - {0xC0, (uint8_t[]){0x10}, 1, 0}, - {0xC1, (uint8_t[]){0x47}, 1, 0}, - {0xC2, (uint8_t[]){0x56}, 1, 0}, - {0xC3, (uint8_t[]){0x65}, 1, 0}, - {0xC4, (uint8_t[]){0x74}, 1, 0}, - {0xC5, (uint8_t[]){0x88}, 1, 0}, - {0xC6, (uint8_t[]){0x99}, 1, 0}, - {0xC7, (uint8_t[]){0x01}, 1, 0}, - {0xC8, (uint8_t[]){0xBB}, 1, 0}, - {0xC9, (uint8_t[]){0xAA}, 1, 0}, - {0xD0, (uint8_t[]){0x10}, 1, 0}, - {0xD1, (uint8_t[]){0x47}, 1, 0}, - {0xD2, (uint8_t[]){0x56}, 1, 0}, - {0xD3, (uint8_t[]){0x65}, 1, 0}, - {0xD4, (uint8_t[]){0x74}, 1, 0}, - {0xD5, (uint8_t[]){0x88}, 1, 0}, - {0xD6, (uint8_t[]){0x99}, 1, 0}, - {0xD7, (uint8_t[]){0x01}, 1, 0}, - {0xD8, (uint8_t[]){0xBB}, 1, 0}, - {0xD9, (uint8_t[]){0xAA}, 1, 0}, - {0xF3, (uint8_t[]){0x01}, 1, 0}, - {0xF0, (uint8_t[]){0x00}, 1, 0}, - {0x21, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 1, 120}, - {0x29, (uint8_t[]){0x00}, 1, 0}, -#endif -}; - -class Cst816s : public I2cDevice { -public: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - Cst816s(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA3); - ESP_LOGI(TAG, "Get chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; - } - - ~Cst816s() { - delete[] read_buffer_; - } - - void UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - } - - const TouchPoint_t& GetTouchPoint() { - return tp_; - } - -private: - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; -}; - -class TaijiPiS3Board : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Cst816s* cst816s_; - LcdDisplay* display_; - esp_timer_handle_t touchpad_timer_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = TP_PIN_NUM_TP_SDA, - .scl_io_num = TP_PIN_NUM_TP_SCL, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static void touchpad_timer_callback(void* arg) { - auto& board = (TaijiPiS3Board&)Board::GetInstance(); - auto touchpad = board.GetTouchpad(); - static bool was_touched = false; - static int64_t touch_start_time = 0; - const int64_t TOUCH_THRESHOLD_MS = 500; // 触摸时长阈值,超过500ms视为长按 - - touchpad->UpdateTouchPoint(); - auto touch_point = touchpad->GetTouchPoint(); - - // 检测触摸开始 - if (touch_point.num > 0 && !was_touched) { - was_touched = true; - touch_start_time = esp_timer_get_time() / 1000; // 转换为毫秒 - } - // 检测触摸释放 - else if (touch_point.num == 0 && was_touched) { - was_touched = false; - int64_t touch_duration = (esp_timer_get_time() / 1000) - touch_start_time; - - // 只有短触才触发 - if (touch_duration < TOUCH_THRESHOLD_MS) { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - board.EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } - } - } - - void InitializeCst816sTouchPad() { - ESP_LOGI(TAG, "Init Cst816s"); - cst816s_ = new Cst816s(i2c_bus_, 0x15); - - // 创建定时器,10ms 间隔 - esp_timer_create_args_t timer_args = { - .callback = touchpad_timer_callback, - .arg = NULL, - .dispatch_method = ESP_TIMER_TASK, - .name = "touchpad_timer", - .skip_unhandled_events = true, - }; - - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &touchpad_timer_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(touchpad_timer_, 10 * 1000)); // 10ms = 10000us - } - - void BspLcdBlSet(int brightness_percent) - { - if (brightness_percent > 100) { - brightness_percent = 100; - } - if (brightness_percent < 0) { - brightness_percent = 0; - } - - ESP_LOGI(TAG, "Setting LCD backlight: %d%%", brightness_percent); - uint32_t duty_cycle = (1023 * brightness_percent) / 100; // LEDC resolution set to 10bits, thus: 100% = 1023 - ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty_cycle); - ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - - const spi_bus_config_t bus_config = TAIJIPI_ST77916_PANEL_BUS_QSPI_CONFIG(QSPI_PIN_NUM_LCD_PCLK, - QSPI_PIN_NUM_LCD_DATA0, - QSPI_PIN_NUM_LCD_DATA1, - QSPI_PIN_NUM_LCD_DATA2, - QSPI_PIN_NUM_LCD_DATA3, - QSPI_LCD_H_RES * 80 * sizeof(uint16_t)); - ESP_ERROR_CHECK(spi_bus_initialize(QSPI_LCD_HOST, &bus_config, SPI_DMA_CH_AUTO)); - } - - void Initializest77916Display() { - - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - ESP_LOGI(TAG, "Install panel IO"); - - const esp_lcd_panel_io_spi_config_t io_config = ST77916_PANEL_IO_QSPI_CONFIG(QSPI_PIN_NUM_LCD_CS, NULL, NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)QSPI_LCD_HOST, &io_config, &panel_io)); - - ESP_LOGI(TAG, "Install ST77916 panel driver"); - - st77916_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, // 如果使用自定义初始化命令,请取消注释这些行 - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(st77916_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = QSPI_PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` - .bits_per_pixel = QSPI_LCD_BIT_PER_PIXEL, // Implemented by LCD command `3Ah` (16/18) - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st77916(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_disp_on_off(panel, true); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeMute() { - gpio_reset_pin(AUDIO_MUTE_PIN); - /* Set the GPIO as a push/pull output */ - gpio_set_direction(AUDIO_MUTE_PIN, GPIO_MODE_OUTPUT); - gpio_set_level(AUDIO_MUTE_PIN, 1); - } - -public: - TaijiPiS3Board() { - InitializeI2c(); - InitializeCst816sTouchPad(); - InitializeSpi(); - Initializest77916Display(); - InitializeMute(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { -#ifdef CONFIG_TAIJIPAI_I2S_TYPE_STD - static NoAudioCodecSimplex audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - #ifdef CONFIG_I2S_USE_2SLOT - I2S_STD_SLOT_BOTH, - #endif - AUDIO_MIC_SCK_PIN, - AUDIO_MIC_WS_PIN, - #ifdef CONFIG_I2S_USE_2SLOT - AUDIO_MIC_SD_PIN, - I2S_STD_SLOT_LEFT - #else - AUDIO_MIC_SD_PIN - #endif - ); -#else - static NoAudioCodecSimplexPdm audio_codec( - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - #ifdef CONFIG_I2S_USE_2SLOT - I2S_STD_SLOT_BOTH, - #endif - AUDIO_MIC_WS_PIN, - AUDIO_MIC_SD_PIN - ); -#endif - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst816s* GetTouchpad() { - return cst816s_; - } -}; - -DECLARE_BOARD(TaijiPiS3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.h deleted file mode 100644 index a2729001..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_40 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_47 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_48 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_9 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_42 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_41 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_3 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_1 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_2 - -#define DISPLAY_SDA_PIN GPIO_NUM_7 -#define DISPLAY_SCL_PIN GPIO_NUM_8 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define ML307_RX_PIN GPIO_NUM_5 -#define ML307_TX_PIN GPIO_NUM_6 - -#define AXP2101_I2C_ADDR 0x34 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.json deleted file mode 100644 index d9eee688..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/config.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "tudouzi", - "sdkconfig_append": [ - "CONFIG_USE_WAKE_WORD_DETECT=n", - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/kevin_box_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/kevin_box_board.cc deleted file mode 100644 index d6cb5b23..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/tudouzi/kevin_box_board.cc +++ /dev/null @@ -1,255 +0,0 @@ -#include "ml307_board.h" -#include "codecs/box_audio_codec.h" -#include "display/oled_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include - -#define TAG "KevinBoxBoard" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - // ** EFUSE defaults ** - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - WriteReg(0x93, 0x1C); // 配置 aldo2 输出为 3.3V - - uint8_t value = ReadReg(0x90); // XPOWERS_AXP2101_LDO_ONOFF_CTRL0 - value = value | 0x02; // set bit 1 (ALDO2) - WriteReg(0x90, value); // and power channels now enabled - - WriteReg(0x64, 0x03); // CV charger voltage setting to 4.2V - - WriteReg(0x61, 0x05); // set Main battery precharge current to 125mA - WriteReg(0x62, 0x0A); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x15); // set Main battery term charge current to 125mA - - WriteReg(0x14, 0x00); // set minimum system voltage to 4.1V (default 4.7V), for poor USB cables - WriteReg(0x15, 0x00); // set input voltage limit to 3.88v, for poor USB cables - WriteReg(0x16, 0x05); // set input current limit to 2000mA - - WriteReg(0x24, 0x01); // set Vsys for PWROFF threshold to 3.2V (default - 2.6V and kill battery) - WriteReg(0x50, 0x14); // set TS pin to EXTERNAL input (not temperature) - } -}; - -class KevinBoxBoard : public Ml307Board { -private: - i2c_master_bus_handle_t display_i2c_bus_; - i2c_master_bus_handle_t codec_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Pmic* pmic_ = nullptr; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(240, 60, -1); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void Enable4GModule() { - // Make GPIO HIGH to enable the 4G module - gpio_config_t ml307_enable_config = { - .pin_bit_mask = (1ULL << 4), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_DISABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, - }; - gpio_config(&ml307_enable_config); - gpio_set_level(GPIO_NUM_4, 1); - } - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeButtons() { - boot_button_.OnPressDown([this]() { - power_save_timer_->WakeUp(); - Application::GetInstance().StartListening(); - }); - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - -public: - KevinBoxBoard() : Ml307Board(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeCodecI2c(); - pmic_ = new Pmic(codec_i2c_bus_, AXP2101_I2C_ADDR); - - Enable4GModule(); - - InitializeButtons(); - InitializePowerSaveTimer(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec(codec_i2c_bus_, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR, AUDIO_CODEC_ES7210_ADDR, AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } -}; - -DECLARE_BOARD(KevinBoxBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/README.md deleted file mode 100644 index 5a44c06f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# 产品链接 - -[微雪电子 ESP32-C6-Touch-LCD-1.69](https://www.waveshare.net/shop/ESP32-C6-Touch-LCD-1.69.htm) -[微雪电子 ESP32-C6-LCD-1.69](https://www.waveshare.net/shop/ESP32-C6-LCD-1.69.htm) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32C6** - -```bash -idf.py set-target esp32c6 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -Xiaozhi Assistant -> Board Type -> Waveshare ESP32-C6-LCD-1.69 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` -# 按键操作 -## BOOT 按键 -**未连接服务器前单击: 进入配网模式** -**连接服务器后单击: 唤醒、打断** - -## PWR 按键 -**双击:息屏、亮屏** -**长按:开关机** \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.h deleted file mode 100644 index 0904631e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_19 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_22 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_20 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_21 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_23 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define PWR_BUTTON_GPIO GPIO_NUM_18 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SPI_MODE 3 -#define DISPLAY_CS_PIN GPIO_NUM_5 -#define DISPLAY_MOSI_PIN GPIO_NUM_2 -#define DISPLAY_MISO_PIN GPIO_NUM_NC -#define DISPLAY_CLK_PIN GPIO_NUM_1 -#define DISPLAY_DC_PIN GPIO_NUM_3 -#define DISPLAY_RST_PIN GPIO_NUM_4 - -#define BATTERY_EN_PIN GPIO_NUM_15 -#define BATTERY_ADC_PIN GPIO_NUM_0 -#define BATTERY_CHARGING_PIN GPIO_NUM_NC - - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 280 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_INVERT_COLOR true - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 20 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_6 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.json deleted file mode 100644 index 81dc2b1a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32c6", - "builds": [ - { - "name": "waveshare-c6-lcd-1.69", - "sdkconfig_append": [ - "CONFIG_USE_ESP_WAKE_WORD=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/esp32-c6-lcd-1.69.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/esp32-c6-lcd-1.69.cc deleted file mode 100644 index ce8fdf2e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/esp32-c6-lcd-1.69.cc +++ /dev/null @@ -1,254 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include -#include -#include "iot_button.h" -#include "power_manager.h" -#include "power_save_timer.h" - -#define TAG "waveshare_lcd_1_69" - -class CustomLcdDisplay : public SpiLcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES * 0.1, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES * 0.1, 0); - } -}; - -class CustomButton: public Button { -public: - void OnPressDownDel(void) { - if (button_handle_ == nullptr) { - return; - } - on_press_down_ = NULL; - iot_button_unregister_cb(button_handle_, BUTTON_PRESS_DOWN, nullptr); - } - void OnPressUpDel(void) { - if (button_handle_ == nullptr) { - return; - } - on_press_up_ = NULL; - iot_button_unregister_cb(button_handle_, BUTTON_PRESS_UP, nullptr); - } -}; - -class CustomBoard : public WifiBoard { -private: - CustomButton boot_button_; - CustomButton pwr_button_; - i2c_master_bus_handle_t i2c_bus_; - LcdDisplay* display_; - PowerManager* power_manager_ = nullptr; - PowerSaveTimer* power_save_timer_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(BATTERY_CHARGING_PIN, BATTERY_ADC_PIN, BATTERY_EN_PIN); - power_manager_->PowerON(); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->OnShutdownRequest([this]() { - power_manager_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = DISPLAY_MISO_PIN; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = DISPLAY_SPI_MODE; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGI(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new CustomLcdDisplay( - panel_io, - panel, - DISPLAY_WIDTH, - DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, - DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, - DISPLAY_SWAP_XY - ); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - pwr_button_.OnPressUp([this]() { - pwr_button_.OnDoubleClick([this]() { - static uint8_t brightness_last = 0; - auto backlight = Board::GetInstance().GetBacklight(); - if (backlight->brightness() == 0) { - brightness_last = 0; - if (brightness_last == 0) { - backlight->SetBrightness(50, true); - } else { - backlight->SetBrightness(brightness_last, true); - } - } else { - brightness_last = backlight->brightness(); - backlight->SetBrightness(0); - } - }); - - pwr_button_.OnLongPress([this]() { - // printf("Power button long press\n"); - if (power_manager_ != nullptr){ - power_manager_->PowerOff(); - } - }); - - pwr_button_.OnPressUpDel(); - }); - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO), pwr_button_(PWR_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR - ); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/power_manager.h deleted file mode 100644 index adb7beef..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-lcd-1.69/power_manager.h +++ /dev/null @@ -1,174 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include "esp_adc/adc_oneshot.h" -#include "esp_adc/adc_cali.h" -#include "esp_adc/adc_cali_scheme.h" -#include - - -class PowerManager { -private: - gpio_num_t charging_pin_ = GPIO_NUM_NC; - gpio_num_t bat_adc_pin_ = GPIO_NUM_NC; - gpio_num_t bat_power_pin_ = GPIO_NUM_NC; - adc_oneshot_unit_handle_t adc_handle_ = NULL; - adc_cali_handle_t adc_cali_handle_ = NULL; - adc_channel_t adc_channel_; - bool do_calibration = false; - - bool adc_calibration_init(adc_unit_t unit, adc_channel_t channel, adc_atten_t atten, adc_cali_handle_t *out_handle) { - adc_cali_handle_t handle = NULL; - esp_err_t ret = ESP_FAIL; - bool calibrated = false; - - if (!calibrated) { - ESP_LOGI("PowerManager", "calibration scheme version is %s", "Curve Fitting"); - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = unit, - .chan = channel, - .atten = atten, - .bitwidth = ADC_BITWIDTH_DEFAULT, - }; - ret = adc_cali_create_scheme_curve_fitting(&cali_config, &handle); - if (ret == ESP_OK) { - calibrated = true; - } - } - - *out_handle = handle; - if (ret == ESP_OK) { - ESP_LOGI("PowerManager", "Calibration Success"); - } - else if (ret == ESP_ERR_NOT_SUPPORTED || !calibrated) { - ESP_LOGW("PowerManager", "eFuse not burnt, skip software calibration"); - } - else { - ESP_LOGE("PowerManager", "Invalid arg or no memory"); - } - return calibrated; - } - -public: - PowerManager(gpio_num_t charging_pin, gpio_num_t bat_adc_pin, gpio_num_t bat_power_pin) - : charging_pin_(charging_pin), bat_adc_pin_(bat_adc_pin), bat_power_pin_(bat_power_pin) { - // 初始化充电引脚 - if (charging_pin_ != GPIO_NUM_NC) { - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = 1ULL << charging_pin_; - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - gpio_config(&io_conf); - } - - // 初始化电池使能引脚 - if (bat_power_pin_ != GPIO_NUM_NC) { - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << bat_power_pin_; - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - } - - // 初始化adc - if (bat_adc_pin_ != GPIO_NUM_NC) { - adc_oneshot_unit_init_cfg_t init_config = {}; - init_config.ulp_mode = ADC_ULP_MODE_DISABLE; - init_config.unit_id = ADC_UNIT_1; - - if (bat_adc_pin_ >= GPIO_NUM_0 && bat_adc_pin_ <= GPIO_NUM_6) - adc_channel_ = (adc_channel_t)((int)bat_adc_pin_); - else - return; - - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - adc_oneshot_chan_cfg_t config = {}; - config.bitwidth = ADC_BITWIDTH_DEFAULT; - config.atten = ADC_ATTEN_DB_12; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, adc_channel_, &config)); - do_calibration = adc_calibration_init(init_config.unit_id, adc_channel_, config.atten, &adc_cali_handle_); - } - } - - ~PowerManager() { - if (adc_handle_) { - ESP_ERROR_CHECK(adc_oneshot_del_unit(adc_handle_)); - } - } - - int GetBatteryLevel(void) { - int adc_raw = 0; - int voltage_int = 0; - const float voltage_float_threshold = 0.1f; - float voltage_float = 0.0f; - static float last_voltage_float = 0.0f; - static int last_battery_level = 0; - - if (adc_handle_ != nullptr) { - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, adc_channel_, &adc_raw)); - if (do_calibration) { - ESP_ERROR_CHECK(adc_cali_raw_to_voltage(adc_cali_handle_, adc_raw, &voltage_int)); - voltage_float = (voltage_int / 1000.0f) * 3.0; - - if (fabs(voltage_float - last_voltage_float) >= voltage_float_threshold) { - last_voltage_float = voltage_float; - if (voltage_float < 3.52) { - last_battery_level = 1; - } else if (voltage_float < 3.64) { - last_battery_level = 20; - } else if (voltage_float < 3.76) { - last_battery_level = 40; - } else if (voltage_float < 3.88) { - last_battery_level = 60; - } else if (voltage_float < 4.0) { - last_battery_level = 80; - } else { - last_battery_level = 100; - } - } - return last_battery_level; - } - } - return 100; - } - - bool IsCharging(void) { - if (charging_pin_ != GPIO_NUM_NC) { - return gpio_get_level(charging_pin_) == 0 ? true : false; - } - return false; - } - - bool IsDischarging(void) { - if (charging_pin_ != GPIO_NUM_NC) { - return gpio_get_level(charging_pin_) == 1; - } - return true; - } - - bool IsChargingDone(void) { - if (GetBatteryLevel() == 100) { - return true; - } - return false; - } - - void PowerOff(void) { - if (bat_power_pin_ != GPIO_NUM_NC) { - gpio_set_level(bat_power_pin_, 0); - } - } - - void PowerON(void) { - if (bat_power_pin_ != GPIO_NUM_NC) { - gpio_set_level(bat_power_pin_, 1); - } - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/README.md deleted file mode 100644 index c153ac13..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# 产品链接 - -[微雪电子 ESP32-C6-Touch-AMOLED-1.32](https://www.waveshare.net/shop/ESP32-C6-Touch-AMOLED-1.32.htm) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32C6** - -```bash -idf.py set-target esp32c6 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -Xiaozhi Assistant -> Board Type -> Waveshare ESP32-C6-Touch-AMOLED-1.32 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.h deleted file mode 100644 index 70a53016..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_15 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_5 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_3 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_4 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_6 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_23 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_9 - - -#define LCD_CS GPIO_NUM_22 -#define LCD_PCLK GPIO_NUM_18 -#define LCD_D0 GPIO_NUM_19 -#define LCD_D1 GPIO_NUM_20 -#define LCD_D2 GPIO_NUM_10 -#define LCD_D3 GPIO_NUM_11 -#define LCD_RST GPIO_NUM_21 - -#define EXAMPLE_LCD_H_RES 466 -#define EXAMPLE_LCD_V_RES 466 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define SYS_POWER_IO_PIN GPIO_NUM_2 -#define PWR_KEY_GPIO GPIO_NUM_1 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.json deleted file mode 100644 index 73dac1dd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32c6", - "builds": [ - { - "name": "waveshare-c6-touch-amoled-1.32", - "sdkconfig_append": [ - "CONFIG_USE_ESP_WAKE_WORD=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/esp32-c6-touch-amoled-1.32.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/esp32-c6-touch-amoled-1.32.cc deleted file mode 100644 index 0664b79f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.32/esp32-c6-touch-amoled-1.32.cc +++ /dev/null @@ -1,215 +0,0 @@ -#include "application.h" -#include "button.h" -#include "codecs/es8311_audio_codec.h" -#include "config.h" -#include "wifi_board.h" - -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" -#include "lvgl.h" -#include "mcp_server.h" -#include -#include -#include -#include - -#define TAG "waveshare_c6_amoled_1_32" - -static const sh8601_lcd_init_cmd_t lcd_init_cmds[] = { - {0xFE, (uint8_t[]) {0x00}, 1, 0}, - {0xC4, (uint8_t[]) {0x80}, 1, 0}, - {0x3A, (uint8_t[]) {0x55}, 1, 0}, // 0x55 for RGB565, 0x77 for RGB888 - {0x35, (uint8_t[]) {0x00}, 1, 0}, - {0x53, (uint8_t[]) {0x20}, 1, 0}, - {0x51, (uint8_t[]) {0xFF}, 1, 0}, // Brightness - {0x63, (uint8_t[]) {0xFF}, 1, 0}, - {0x2A, (uint8_t[]) {0x00, 0x06, 0x01, 0xD7}, 4, 0}, - {0x2B, (uint8_t[]) {0x00, 0x00, 0x01, 0xD1}, 4, 0}, - {0x11, (uint8_t[]) {0x00}, 0, 100}, - {0x29, (uint8_t[]) {0x00}, 0, 0}, -}; - -class CustomLcdDisplay : public SpiLcdDisplay { - private: - esp_lcd_panel_io_handle_t io_handle_; - - public: - static void my_draw_event_cb(lv_event_t *e) { - lv_area_t *area = (lv_area_t *) lv_event_get_param(e); - - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - - // Round area for better performance - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - void SetMIRROR_XY(uint8_t mirror) { - uint32_t lcd_cmd = 0x36; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= 0x02 << 24; - uint8_t param = mirror; - esp_lcd_panel_io_tx_param(io_handle_, lcd_cmd, ¶m, 1); - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) : - SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy), - io_handle_(io_handle) { - DisplayLockGuard lock(this); - lv_display_add_event_cb(display_, my_draw_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - SetMIRROR_XY(0xC0); // Rotate 180 degrees - lv_obj_invalidate(lv_screen_active()); - } -}; - -class CustomBoard : public WifiBoard { - private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button pwr_button_; - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_io_handle_t io_handle = NULL; - CustomLcdDisplay *display_; - lv_indev_t *touch_indev = NULL; - i2c_master_dev_handle_t disp_touch_dev_handle = NULL; - - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = {}; - i2c_bus_cfg.i2c_port = I2C_NUM_0; - i2c_bus_cfg.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN; - i2c_bus_cfg.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN; - i2c_bus_cfg.clk_source = I2C_CLK_SRC_DEFAULT; - i2c_bus_cfg.glitch_ignore_cnt = 7; - i2c_bus_cfg.intr_priority = 0; - i2c_bus_cfg.trans_queue_depth = 0; - i2c_bus_cfg.flags.enable_internal_pullup = 1; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void SetDispbacklight(uint8_t backlight) { - uint32_t lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= 0x02 << 24; - uint8_t param = backlight; - esp_lcd_panel_io_tx_param(io_handle, lcd_cmd, ¶m, 1); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto &app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - pwr_button_.OnLongPress([this]() { - GetDisplay()->SetChatMessage("system", "OFF"); - vTaskDelay(pdMS_TO_TICKS(1000)); - gpio_set_level(SYS_POWER_IO_PIN, 0); - }); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.data0_io_num = LCD_D0; - buscfg.data1_io_num = LCD_D1; - buscfg.sclk_io_num = LCD_PCLK; - buscfg.data2_io_num = LCD_D2; - buscfg.data3_io_num = LCD_D3; - buscfg.max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS; - io_config.dc_gpio_num = -1; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 8; - io_config.on_color_trans_done = NULL; - io_config.user_ctx = NULL; - io_config.lcd_cmd_bits = 32; - io_config.lcd_param_bits = 8; - io_config.flags.quad_mode = true; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &io_handle)); - - sh8601_vendor_config_t vendor_config = {}; - vendor_config.init_cmds = lcd_init_cmds; - vendor_config.init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]); - vendor_config.flags = {.use_qspi_interface = 1}; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(io_handle, &panel_config, &panel_handle)); - esp_lcd_panel_set_gap(panel_handle, 0x06, 0x00); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - - display_ = new CustomLcdDisplay(io_handle, panel_handle, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.disp.setbacklight", "设置屏幕亮度", PropertyList({Property("level", kPropertyTypeInteger, 0, 255)}), [this](const PropertyList &properties) -> ReturnValue { - int level = properties["level"].value(); - ESP_LOGI("setbacklight", "%d", level); - SetDispbacklight(level); - return true; - }); - - mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(), [this](const PropertyList &) -> ReturnValue { - EnterWifiConfigMode(); - return true; - }); - } - - void CheckPowerKeyState() { - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << SYS_POWER_IO_PIN); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - gpio_set_level(SYS_POWER_IO_PIN, 1); - do { - vTaskDelay(pdMS_TO_TICKS(10)); - } while (!gpio_get_level(PWR_KEY_GPIO)); - } - - public: - CustomBoard() : boot_button_(BOOT_BUTTON_GPIO), pwr_button_(PWR_KEY_GPIO) { - CheckPowerKeyState(); - InitializeI2c(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/README.md deleted file mode 100644 index 77038506..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# 产品链接 - -[微雪电子 ESP32-C6-Touch-AMOLED-1.43](https://www.waveshare.net/shop/ESP32-C6-Touch-AMOLED-1.43.htm) -[微雪电子 ESP32-C6-Touch-AMOLED-1.43-B](https://www.waveshare.net/shop/ESP32-C6-Touch-AMOLED-1.43-B.htm) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32C6** - -```bash -idf.py set-target esp32c6 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -Xiaozhi Assistant -> Board Type -> Waveshare ESP32-C6-Touch-AMOLED-1.43 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.h deleted file mode 100644 index 0d39b3f1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE false - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_19 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_22 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_21 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_20 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_23 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_18 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define I2C_Touch_ADDRESS 0x38 -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define PWR_BUTTON_GPIO GPIO_NUM_2 - -#define LCD_CS GPIO_NUM_10 -#define LCD_PCLK GPIO_NUM_11 -#define LCD_D0 GPIO_NUM_4 -#define LCD_D1 GPIO_NUM_5 -#define LCD_D2 GPIO_NUM_6 -#define LCD_D3 GPIO_NUM_7 -#define LCD_RST GPIO_NUM_3 -#define LCD_LIGHT (-1) - -#define EXAMPLE_LCD_H_RES 466 -#define EXAMPLE_LCD_V_RES 466 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.json deleted file mode 100644 index f1a45511..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32c6", - "builds": [ - { - "name": "waveshare-c6-touch-amoled-1.43", - "sdkconfig_append": [ - "CONFIG_USE_ESP_WAKE_WORD=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/esp32-c6-touch-amoled-1.43.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/esp32-c6-touch-amoled-1.43.cc deleted file mode 100644 index 0c1a7dda..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-1.43/esp32-c6-touch-amoled-1.43.cc +++ /dev/null @@ -1,284 +0,0 @@ -#include "wifi_board.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "codecs/box_audio_codec.h" - -#include -#include -#include -#include -#include "esp_lcd_sh8601.h" -#include "display/lcd_display.h" -#include "esp_io_expander_tca9554.h" -#include "mcp_server.h" -#include "lvgl.h" - -#define TAG "waveshare_c6_amoled_1_43" - -static const sh8601_lcd_init_cmd_t lcd_init_cmds[] = -{ - {0x11, (uint8_t []){0x00}, 0, 80}, - {0xC4, (uint8_t []){0x80}, 1, 0}, - {0x53, (uint8_t []){0x20}, 1, 1}, - {0x63, (uint8_t []){0xFF}, 1, 1}, - {0x51, (uint8_t []){0x00}, 1, 1}, - {0x29, (uint8_t []){0x00}, 0, 10}, - {0x51, (uint8_t []){0xFF}, 1, 0}, -}; - -class CustomLcdDisplay : public SpiLcdDisplay { -public: - static void MyDrawEventCb(lv_event_t *e) { - lv_area_t *area = (lv_area_t *)lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - // round the start of coordinate down to the nearest 2M number - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - // round the end of coordinate up to the nearest 2N+1 number - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_display_add_event_cb(display_, MyDrawEventCb, LV_EVENT_INVALIDATE_AREA, NULL); - } -}; - -class CustomBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button pwr_button_; - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_io_handle_t io_handle = NULL; - esp_io_expander_handle_t io_expander = NULL; - CustomLcdDisplay* display_; - i2c_master_dev_handle_t disp_touch_dev_handle = NULL; - lv_indev_t *touch_indev = NULL; //touch - uint8_t pwr_flag = 0; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_7 | IO_EXPANDER_PIN_NUM_6, IO_EXPANDER_OUTPUT); - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_7 | IO_EXPANDER_PIN_NUM_6, 1); - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = { - .data0_io_num = LCD_D0, - .data1_io_num = LCD_D1, - .sclk_io_num = LCD_PCLK, - .data2_io_num = LCD_D2, - .data3_io_num = LCD_D3, - .max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(uint16_t), - }; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - const esp_lcd_panel_io_spi_config_t io_config = { - .cs_gpio_num = LCD_CS, - .dc_gpio_num = -1, - .spi_mode = 0, - .pclk_hz = 40 * 1000 * 1000, - .trans_queue_depth = 4, - .on_color_trans_done = NULL, - .user_ctx = NULL, - .lcd_cmd_bits = 32, - .lcd_param_bits = 8, - .flags = { - .quad_mode = true, - }, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &io_handle)); - sh8601_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, // Uncomment these line if use custom initialization commands - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]), // sizeof(axs15231b_lcd_init_cmd_t), - .flags = - { - .use_qspi_interface = 1, - }, - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, // Implemented by LCD command `36h` - .bits_per_pixel = 16, // Implemented by LCD command `3Ah` (16/18) - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(io_handle, &panel_config, &panel_handle)); - esp_lcd_panel_set_gap(panel_handle,0x06,0x00); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - display_ = new CustomLcdDisplay(io_handle, panel_handle, - EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { //接入锂电池时,可长按PWR开机/关机 - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - }); - - boot_button_.OnPressDown([this]() { - Application::GetInstance().StartListening(); - }); - - boot_button_.OnPressUp([this]() { - Application::GetInstance().StopListening(); - }); - - pwr_button_.OnLongPress([this]() { - if(pwr_flag == 1) - { - pwr_flag = 0; - esp_err_t ret; - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_6, 0); - ESP_ERROR_CHECK(ret); - } - }); - - pwr_button_.OnPressUp([this]() { - if(pwr_flag == 0) - { - pwr_flag = 1; - } - }); - } - - void InitializeTouch() { - i2c_device_config_t dev_cfg = - { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = I2C_Touch_ADDRESS, - .scl_speed_hz = 300000, - }; - ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c_bus_, &dev_cfg, &disp_touch_dev_handle)); - - touch_indev = lv_indev_create(); - lv_indev_set_type(touch_indev, LV_INDEV_TYPE_POINTER); - lv_indev_set_read_cb(touch_indev, TouchInputReadCallback); - lv_indev_set_user_data(touch_indev, disp_touch_dev_handle); - } - - static void TouchInputReadCallback(lv_indev_t * indev, lv_indev_data_t *indevData) - { - i2c_master_dev_handle_t i2c_dev = (i2c_master_dev_handle_t)lv_indev_get_user_data(indev); - uint8_t cmd = 0x02; - uint8_t buf[5] = {0}; - uint16_t tp_x,tp_y; - i2c_master_transmit_receive(i2c_dev,&cmd,1,buf,5,1000); - if(buf[0]) - { - tp_x = (((uint16_t)buf[1] & 0x0f)<<8) | (uint16_t)buf[2]; - tp_y = (((uint16_t)buf[3] & 0x0f)<<8) | (uint16_t)buf[4]; - if(tp_x > EXAMPLE_LCD_H_RES) - {tp_x = EXAMPLE_LCD_H_RES;} - if(tp_y > EXAMPLE_LCD_V_RES) - {tp_y = EXAMPLE_LCD_V_RES;} - indevData->point.x = tp_x; - indevData->point.y = tp_y; - //ESP_LOGI("tp","(%ld,%ld)",indevData->point.x,indevData->point.y); - indevData->state = LV_INDEV_STATE_PRESSED; - } - else - { - indevData->state = LV_INDEV_STATE_RELEASED; - } - } - - void InitializeTools() - { - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.disp.setbacklight", "设置屏幕亮度", PropertyList({ - Property("level", kPropertyTypeInteger, 0, 255) - }), [this](const PropertyList& properties) -> ReturnValue { - int level = properties["level"].value(); - ESP_LOGI("setbacklight","%d",level); - SetDispbacklight(level); - return true; - }); - } - - void SetDispbacklight(uint8_t backlight) { - uint32_t lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= 0x02 << 24; - uint8_t param = backlight; - esp_lcd_panel_io_tx_param(io_handle, lcd_cmd, ¶m,1); - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO),pwr_button_(PWR_BUTTON_GPIO) { - InitializeI2c(); - InitializeTca9554(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - -}; - -DECLARE_BOARD(CustomBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/README.md deleted file mode 100644 index ee4ae2b4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Waveshare ESP32-C6-Touch-AMOLED-2.06 - - -[ESP32-C6-Touch-AMOLED-2.06](https://www.waveshare.com/esp32-c6-touch-amoled-2.06.htm) is a high-performance wearable watch-shaped development board launched by Waveshare. This product is based on the ESP32-C6 microcontroller and integrates a 2.06-inch capacitive touch high-definition AMOLED screen, a six-axis sensor, RTC, audio codec chip, and power management, among other functional modules. With a custom case, its appearance is consistent with that of a smartwatch, and it is specifically designed for prototype development and functional verification of wearable applications. \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.h deleted file mode 100644 index 1d884f3d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE false - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_19 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_22 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_20 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_21 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_23 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_6 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_9 - -#define EXAMPLE_PIN_NUM_LCD_CS GPIO_NUM_5 -#define EXAMPLE_PIN_NUM_LCD_PCLK GPIO_NUM_0 -#define EXAMPLE_PIN_NUM_LCD_DATA0 GPIO_NUM_1 -#define EXAMPLE_PIN_NUM_LCD_DATA1 GPIO_NUM_2 -#define EXAMPLE_PIN_NUM_LCD_DATA2 GPIO_NUM_3 -#define EXAMPLE_PIN_NUM_LCD_DATA3 GPIO_NUM_4 -#define EXAMPLE_PIN_NUM_LCD_RST GPIO_NUM_11 - -#define DISPLAY_WIDTH 410 -#define DISPLAY_HEIGHT 502 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.json deleted file mode 100644 index 3fb9dd9b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-c6-touch-amoled-2.06", - "sdkconfig_append": [ - "CONFIG_USE_ESP_WAKE_WORD=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/esp32-c6-touch-amoled-2.06.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/esp32-c6-touch-amoled-2.06.cc deleted file mode 100644 index c9e5c14d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-amoled-2.06/esp32-c6-touch-amoled-2.06.cc +++ /dev/null @@ -1,314 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" - -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "settings.h" - -#include -#include - -#define TAG "WaveshareEsp32c6TouchAMOLED2inch06" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - WriteReg(0x93, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x03); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x0A); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const sh8601_lcd_init_cmd_t vendor_specific_init[] = { - // set display to qspi mode - {0x11, (uint8_t []){0x00}, 0, 120}, - {0xC4, (uint8_t []){0x80}, 1, 0}, - {0x44, (uint8_t []){0x01, 0xD1}, 2, 0}, - {0x35, (uint8_t []){0x00}, 1, 0}, - {0x53, (uint8_t []){0x20}, 1, 10}, - {0x63, (uint8_t []){0xFF}, 1, 10}, - {0x51, (uint8_t []){0x00}, 1, 10}, - {0x2A, (uint8_t []){0x00,0x16,0x01,0xAF}, 4, 0}, - {0x2B, (uint8_t []){0x00,0x00,0x01,0xF5}, 4, 0}, - {0x29, (uint8_t []){0x00}, 0, 10}, - {0x51, (uint8_t []){0xFF}, 1, 0}, -}; - -// 在waveshare_amoled_2_06类之前添加新的显示类 -class CustomLcdDisplay : public SpiLcdDisplay { -public: - static void rounder_event_cb(lv_event_t* e) { - lv_area_t* area = (lv_area_t* )lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - - // round the start of coordinate down to the nearest 2M number - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - // round the end of coordinate up to the nearest 2N+1 number - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES* 0.1, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES* 0.1, 0); - lv_display_add_event_cb(display_, rounder_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(esp_lcd_panel_io_handle_t panel_io) : Backlight(), panel_io_(panel_io) {} - -protected: - esp_lcd_panel_io_handle_t panel_io_; - - virtual void SetBrightnessImpl(uint8_t brightness) override { - auto display = Board::GetInstance().GetDisplay(); - DisplayLockGuard lock(display); - uint8_t data[1] = {((uint8_t)((255* brightness) / 100))}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - esp_lcd_panel_io_tx_param(panel_io_, lcd_cmd, &data, sizeof(data)); - } -}; - -class WaveshareEsp32c6TouchAMOLED2inch06 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - CustomLcdDisplay* display_; - CustomBacklight* backlight_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.sclk_io_num = EXAMPLE_PIN_NUM_LCD_PCLK; - buscfg.data0_io_num = EXAMPLE_PIN_NUM_LCD_DATA0; - buscfg.data1_io_num = EXAMPLE_PIN_NUM_LCD_DATA1; - buscfg.data2_io_num = EXAMPLE_PIN_NUM_LCD_DATA2; - buscfg.data3_io_num = EXAMPLE_PIN_NUM_LCD_DATA3; - buscfg.max_transfer_sz = DISPLAY_WIDTH* DISPLAY_HEIGHT* sizeof(uint16_t); - buscfg.flags = SPICOMMON_BUSFLAG_QUAD; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeSH8601Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG( - EXAMPLE_PIN_NUM_LCD_CS, - nullptr, - nullptr); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const sh8601_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(sh8601_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }}; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void* )&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(panel_io, &panel_config, &panel)); - esp_lcd_panel_set_gap(panel, 0x16, 0); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - backlight_ = new CustomBacklight(panel_io); - backlight_->RestoreBrightness(); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32c6TouchAMOLED2inch06() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeAxp2101(); - InitializeSpi(); - InitializeSH8601Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - return backlight_; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32c6TouchAMOLED2inch06); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/README.md deleted file mode 100644 index 917a1549..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/README.md +++ /dev/null @@ -1,49 +0,0 @@ - -# 产品链接 -微雪电子 ESP32-C6-Touch-LCD-1.83 - -(https://www.waveshare.net/shop/ESP32-C6-Touch-LCD-1.83.htm) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32C6** - -```bash -idf.py set-target esp32c6 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -Xiaozhi Assistant -> Board Type -> Waveshare ESP32-C6-Touch-LCD-1.83 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.h deleted file mode 100644 index 10ec48e5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_19 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_22 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_20 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_21 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_23 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_0 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_9 -#define PWR_BUTTON_GPIO GPIO_NUM_18 - -#define DISPLAY_SPI_MODE SPI2_HOST -#define DISPLAY_CS_PIN GPIO_NUM_5 -#define DISPLAY_MOSI_PIN GPIO_NUM_2 -#define DISPLAY_MISO_PIN GPIO_NUM_NC -#define DISPLAY_CLK_PIN GPIO_NUM_1 -#define DISPLAY_DC_PIN GPIO_NUM_3 -#define DISPLAY_RST_PIN GPIO_NUM_4 - -#define DISPLAY_TOUCH_INT_PIN GPIO_NUM_11 -#define DISPLAY_TOUCH_RST_PIN GPIO_NUM_NC - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 284 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_6 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.json deleted file mode 100644 index 48d566fb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32c6", - "builds": [ - { - "name": "waveshare-c6-touch-lcd-1.83", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/esp32-c6-touch-lcd-1.83.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/esp32-c6-touch-lcd-1.83.cc deleted file mode 100644 index dee60dd7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-c6-touch-lcd-1.83/esp32-c6-touch-lcd-1.83.cc +++ /dev/null @@ -1,261 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" -#include -#include -#include -#include -#include "settings.h" - -#include -#include -#include - -#define TAG "WaveshareEsp32c6TouchLCD1inch83" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x01); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -class WaveshareEsp32c6TouchLCD1inch83 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - Display* display_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH* DISPLAY_HEIGHT* sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(DISPLAY_SPI_MODE, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 24 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(DISPLAY_SPI_MODE, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - // esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH - 1, - .y_max = DISPLAY_HEIGHT - 1, - .rst_gpio_num = DISPLAY_TOUCH_RST_PIN, - .int_gpio_num = DISPLAY_TOUCH_INT_PIN, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG(); - tp_io_config.scl_speed_hz = 400* 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "Reboot the device and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32c6TouchLCD1inch83() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeAxp2101(); - InitializeSpi(); - InitializeDisplay(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } - -}; - -DECLARE_BOARD(WaveshareEsp32c6TouchLCD1inch83); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/README.md deleted file mode 100644 index 580785c1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# Waveshare ESP32-P4-NANO - - -[ESP32-P4-NANO](https://www.waveshare.com/esp32-p4-nano.htm) is a small size and highly integrated development board designed by waveshare electronics based on ESP32-P4 chip - - - -## Display Page - - -### Recommended display screen - -| Product ID | Dependency | tested | -|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|--------| -| [10.1-DSI-TOUCH-A](https://www.waveshare.com/10.1-dsi-touch-a.htm)
    | [waveshare/esp_lcd_jd9365_10_1](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365_10_1) | ✅ | -| [101M-8001280-IPS-CT-K](https://www.waveshare.com/101m-8001280-ips-ct-k.htm)
    | [waveshare/esp_lcd_jd9365_10_1](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_jd9365_10_1) | ✅ | - -### Common Raspberry adapter screen - -**These displays are supported on [ESP32-P4-NANO BSP](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/bsp/esp32_p4_nano), but not on xiaozhi-esp32** - -
    -View full display - -| Product ID | Dependency | tested | -|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|--------| -| [2.8inch DSI LCD](https://www.waveshare.com/2.8inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [3.4inch DSI LCD (C)](https://www.waveshare.com/3.4inch-dsi-lcd-c.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [4inch DSI LCD (C)](https://www.waveshare.com/4inch-dsi-lcd-c.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [4inch DSI LCD](https://www.waveshare.com/4inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [5inch DSI LCD (D)](https://www.waveshare.com/5inch-dsi-lcd-d.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [6.25inch DSI LCD](https://www.waveshare.com/6.25inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [5inch DSI LCD (C)](https://www.waveshare.com/5inch-dsi-lcd-c.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [7inch DSI LCD (C)](https://www.waveshare.com/7inch-dsi-lcd-c-with-case-a.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [7.9inch DSI LCD](https://www.waveshare.com/7.9inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [7inch DSI LCD (E)](https://www.waveshare.com/7inch-dsi-lcd-e.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [8inch DSI LCD (C)](https://www.waveshare.com/8inch-dsi-lcd-c.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [10.1inch DSI LCD (C)](https://www.waveshare.com/10.1inch-dsi-lcd-c.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [8.8inch DSI LCD](https://www.waveshare.com/8.8inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [11.9inch DSI LCD](https://www.waveshare.com/11.9inch-dsi-lcd.htm)
    | [waveshare/esp_lcd_dsi](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_dsi) | 🕒 | -| [7-DSI-TOUCH-A](https://www.waveshare.com/7-dsi-touch-a.htm)
    | [waveshare/esp_lcd_ili9881c](https://github.com/waveshareteam/Waveshare-ESP32-components/tree/master/display/lcd/esp_lcd_ili9881c) | 🕒 | - -
    \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.h deleted file mode 100644 index 8fb9cccf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define DISPLAY_WIDTH 800 -#define DISPLAY_HEIGHT 1280 - -#define LCD_BIT_PER_PIXEL (16) -#define PIN_NUM_LCD_RST GPIO_NUM_NC - -#define DELAY_TIME_MS (3000) -#define LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes - -#define MIPI_DSI_PHY_PWR_LDO_CHAN (3) -#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.json deleted file mode 100644 index 832dee1c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "waveshare-p4-nano-10.1-a", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y", - "CONFIG_LCD_TYPE_800_1280_10_1_INCH_A=y", - "CONFIG_CAMERA_OV5647=y", - "CONFIG_CAMERA_OV5647_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/esp32-p4-nano.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/esp32-p4-nano.cc deleted file mode 100644 index 5389b9cf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-nano/esp32-p4-nano.cc +++ /dev/null @@ -1,263 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "display/lcd_display.h" -// #include "display/no_display.h" -#include "button.h" -#include "config.h" - -#include "esp32_camera.h" -#include "esp_video_init.h" -#include "esp_cam_sensor_xclk.h" - -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" - -#include "esp_lcd_mipi_dsi.h" -#include "esp_lcd_jd9365_10_1.h" - -#include -#include -#include -#include "esp_lcd_touch_gt911.h" -#define TAG "WaveshareEsp32p4nano" - -class CustomBacklight : public Backlight { -public: - CustomBacklight(i2c_master_bus_handle_t i2c_handle) - : Backlight(), i2c_handle_(i2c_handle) {} - -protected: - i2c_master_bus_handle_t i2c_handle_; - - virtual void SetBrightnessImpl(uint8_t brightness) override { - uint8_t i2c_address = 0x45; // 7-bit address -#if CONFIG_LCD_TYPE_800_1280_10_1_INCH - uint8_t reg = 0x86; -#elif CONFIG_LCD_TYPE_800_1280_10_1_INCH_A - uint8_t reg = 0x96; -#endif - uint8_t data[2] = {reg, brightness}; - - i2c_master_dev_handle_t dev_handle; - i2c_device_config_t dev_cfg = { - .dev_addr_length = I2C_ADDR_BIT_LEN_7, - .device_address = i2c_address, - .scl_speed_hz = 100000, - }; - - esp_err_t err = i2c_master_bus_add_device(i2c_handle_, &dev_cfg, &dev_handle); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to add I2C device: %s", esp_err_to_name(err)); - return; - } - - err = i2c_master_transmit(dev_handle, data, sizeof(data), -1); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to transmit brightness: %s", esp_err_to_name(err)); - } else { - ESP_LOGI(TAG, "Backlight brightness set to %u", brightness); - } - - // i2c_master_bus_rm_device(dev_handle); - } -}; - -class WaveshareEsp32p4nano : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - LcdDisplay *display__; - Esp32Camera* camera_ = nullptr; - CustomBacklight *backlight_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power(void) { -#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state - static esp_ldo_channel_handle_t phy_pwr_chan = NULL; - esp_ldo_channel_config_t ldo_cfg = { - .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan); - ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); -#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - - return ESP_OK; - } - - void InitializeLCD() { - bsp_enable_dsi_phy_power(); - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 1500, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_config = JD9365_PANEL_IO_DBI_CONFIG(); - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 80, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 1, - .video_timing = { - .h_size = 800, - .v_size = 1280, - .hsync_pulse_width = 20, - .hsync_back_porch = 20, - .hsync_front_porch = 40, - .vsync_pulse_width = 10, - .vsync_back_porch = 4, - .vsync_front_porch = 30, - }, - .flags = { - .use_dma2d = true, - }, - }; - - jd9365_vendor_config_t vendor_config = { - - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - .lane_num = 2, - }, - .flags = { - .use_mipi_interface = 1, - }, - }; - - const esp_lcd_panel_dev_config_t lcd_dev_config = { - .reset_gpio_num = PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel); - esp_lcd_panel_reset(disp_panel); - esp_lcd_panel_init(disp_panel); - - display__ = new MipiLcdDisplay(io, disp_panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - backlight_ = new CustomBacklight(codec_i2c_bus_); - backlight_->RestoreBrightness(); - } - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.scl_speed_hz = 100 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(codec_i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - void InitializeCamera() { - esp_video_init_csi_config_t base_csi_config = { - .sccb_config = { - .init_sccb = false, - .i2c_handle = codec_i2c_bus_, - .freq = 400000, - }, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - }; - - esp_video_init_config_t cam_config = { - .csi = &base_csi_config, - }; - - camera_ = new Esp32Camera(cam_config); - } - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - WaveshareEsp32p4nano() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeLCD(); - InitializeTouch(); - InitializeCamera(); - InitializeButtons(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_1, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display__; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Backlight *GetBacklight() override { - return backlight_; - } - -}; - -DECLARE_BOARD(WaveshareEsp32p4nano); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/README.md deleted file mode 100644 index eb94e644..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Waveshare ESP32-P4-WIFI6-Touch-LCD-4B - - -[ESP32-P4-WIFI6-Touch-LCD-4B](https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-4b.htm) is waveshare electronics designed an intelligent 86 box based on ESP32-P4 module equipped with a 720*720 IPS capacitive touch screen - - -## Configuration - -Configuration in `menuconfig`. - -Selection Board Type `Xiaozhi Assistant --> Board Type` -- Waveshare ESP32-P4-WIFI6-Touch-LCD-4B \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.h deleted file mode 100644 index 027c215a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define DISPLAY_WIDTH 720 -#define DISPLAY_HEIGHT 720 - -#define LCD_BIT_PER_PIXEL (16) -#define PIN_NUM_LCD_RST GPIO_NUM_27 - -#define DELAY_TIME_MS (3000) -#define LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes - -#define MIPI_DSI_PHY_PWR_LDO_CHAN (3) -#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_26 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.json deleted file mode 100644 index 5a8dbb53..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "waveshare-p4-wifi6-touch-lcd-4b", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_CAMERA_OV5647=y", - "CONFIG_CAMERA_OV5647_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/esp32-p4-wifi6-touch-lcd-4b.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/esp32-p4-wifi6-touch-lcd-4b.cc deleted file mode 100644 index 711930d5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-4b/esp32-p4-wifi6-touch-lcd-4b.cc +++ /dev/null @@ -1,228 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "display/lcd_display.h" -// #include "display/no_display.h" -#include "button.h" -#include "config.h" - -#include "esp32_camera.h" -#include "esp_video_init.h" -#include "esp_cam_sensor_xclk.h" - -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" - -#include "esp_lcd_st7703.h" - -#include -#include -#include -#include "esp_lcd_touch_gt911.h" -#define TAG "WaveshareEsp32p44b" - -class WaveshareEsp32p44b : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay *display_; - Esp32Camera* camera_ = nullptr; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power(void) { -#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state - static esp_ldo_channel_handle_t phy_pwr_chan = NULL; - esp_ldo_channel_config_t ldo_cfg = { - .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan); - ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); -#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - - return ESP_OK; - } - - void InitializeLCD() { - bsp_enable_dsi_phy_power(); - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 480, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_config = ST7703_PANEL_IO_DBI_CONFIG(); - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 46, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 1, - .video_timing = { - .h_size = 720, - .v_size = 720, - .hsync_pulse_width = 20, - .hsync_back_porch = 80, - .hsync_front_porch = 80, - .vsync_pulse_width = 4, - .vsync_back_porch = 12, - .vsync_front_porch = 30, - }, - .flags = { - .use_dma2d = true, - }, - }; - st7703_vendor_config_t vendor_config = { - - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - }, - .flags = { - .use_mipi_interface = 1, - }, - }; - - const esp_lcd_panel_dev_config_t lcd_dev_config = { - .reset_gpio_num = PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_st7703(io, &lcd_dev_config, &disp_panel); - esp_lcd_panel_reset(disp_panel); - esp_lcd_panel_init(disp_panel); - - display_ = new MipiLcdDisplay(io, disp_panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_23, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - void InitializeCamera() { - esp_video_init_csi_config_t base_csi_config = { - .sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 400000, - }, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - }; - - esp_video_init_config_t cam_config = { - .csi = &base_csi_config, - }; - - camera_ = new Esp32Camera(cam_config); - } - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - WaveshareEsp32p44b() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeLCD(); - InitializeTouch(); - InitializeCamera(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - -}; - -DECLARE_BOARD(WaveshareEsp32p44b); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/README.md deleted file mode 100644 index 9f45fa60..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Waveshare ESP32-P4-WIFI6-Touch-LCD-7B - - -[ESP32-P4-WIFI6-Touch-LCD-7B](https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-7b.htm) is waveshare electronics designed an intelligent 86 box based on ESP32-P4 module equipped with a 1024*600 IPS capacitive touch screen - - -## Configuration - -Configuration in `menuconfig`. - -Selection Board Type `Xiaozhi Assistant --> Board Type` -- Waveshare ESP32-P4-WIFI6-Touch-LCD-7B \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.h deleted file mode 100644 index 2f7d08c8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define DISPLAY_WIDTH 1024 -#define DISPLAY_HEIGHT 600 - -#define LCD_BIT_PER_PIXEL (16) -#define PIN_NUM_LCD_RST GPIO_NUM_33 - -#define DELAY_TIME_MS (3000) -#define LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes - -#define MIPI_DSI_PHY_PWR_LDO_CHAN (3) -#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_32 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.json deleted file mode 100644 index 8f84bf9d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "waveshare-p4-wifi6-touch-lcd-7b", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_CAMERA_OV5647=y", - "CONFIG_CAMERA_OV5647_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/esp32-p4-wifi6-touch-lcd-7b.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/esp32-p4-wifi6-touch-lcd-7b.cc deleted file mode 100644 index 61f83ffd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-7b/esp32-p4-wifi6-touch-lcd-7b.cc +++ /dev/null @@ -1,249 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "display/lcd_display.h" -// #include "display/no_display.h" -#include "button.h" -#include "config.h" - -#include "esp32_camera.h" -#include "esp_video_init.h" -#include "esp_cam_sensor_xclk.h" - -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" - -#include "esp_lcd_ek79007.h" - -#include -#include -#include -#include "esp_lcd_touch_gt911.h" -#define TAG "WaveshareEsp32p47b" - -class WaveshareEsp32p47b : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay *display_; - Esp32Camera* camera_ = nullptr; - - esp_err_t i2c_device_probe(uint8_t addr) { - return i2c_master_probe(i2c_bus_, addr, 100); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power(void) { -#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state - static esp_ldo_channel_handle_t phy_pwr_chan = NULL; - esp_ldo_channel_config_t ldo_cfg = { - .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan); - ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); -#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - - return ESP_OK; - } - - void InitializeLCD() { - bsp_enable_dsi_phy_power(); - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 900, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_config = EK79007_PANEL_IO_DBI_CONFIG(); - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 52, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 1, - .video_timing = { - .h_size = 1024, - .v_size = 600, - .hsync_pulse_width = 10, - .hsync_back_porch = 160, - .hsync_front_porch = 160, - .vsync_pulse_width = 1, - .vsync_back_porch = 23, - .vsync_front_porch = 12, - }, - .flags = { - .use_dma2d = true, - }, - }; - ek79007_vendor_config_t vendor_config = { - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - }, - }; - - const esp_lcd_panel_dev_config_t lcd_dev_config = { - .reset_gpio_num = PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_ek79007(io, &lcd_dev_config, &disp_panel); - esp_lcd_panel_reset(disp_panel); - esp_lcd_panel_init(disp_panel); - - display_ = new MipiLcdDisplay(io, disp_panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - - lv_display_t *disp = lv_display_get_default(); - if (disp) { - lv_disp_set_rotation(disp, LV_DISPLAY_ROTATION_180); - ESP_LOGI(TAG, "Display rotated 180 degrees"); - } else { - ESP_LOGE(TAG, "Failed to get default display for rotation"); - } - } - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_23, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - if (ESP_OK == i2c_device_probe(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS)) { - ESP_LOGI(TAG, "Touch panel found at address 0x%02X", ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS); - } else if (ESP_OK == i2c_device_probe(ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP)) { - ESP_LOGI(TAG, "Touch panel found at address 0x%02X", ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP); - tp_io_config.dev_addr = ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP; - } else { - ESP_LOGE(TAG, "Touch panel not found on I2C bus"); - ESP_LOGE(TAG, "Tried addresses: 0x%02X and 0x%02X", - ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS, - ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS_BACKUP); - return; - } - - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - void InitializeCamera() { - esp_video_init_csi_config_t base_csi_config = { - .sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 400000, - }, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - }; - - esp_video_init_config_t cam_config = { - .csi = &base_csi_config, - }; - - camera_ = new Esp32Camera(cam_config); - } - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - WaveshareEsp32p47b() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeLCD(); - InitializeTouch(); - InitializeCamera(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - -}; - -DECLARE_BOARD(WaveshareEsp32p47b); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/README.md deleted file mode 100644 index 09271dd7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# Waveshare ESP32-P4-WIFI6-Touch-LCD-XC - - -[ESP32-P4-WIFI6-Touch-LCD-XC](https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-3.4c.htm) is waveshare electronics designed a 3.4-inch, 4-inch circular screen, highly integrated development board - - -## Configuration - -Configuration in `menuconfig`. - -Selection Board Type `Xiaozhi Assistant --> Board Type` -- Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C or ESP32-P4-WIFI6-Touch-LCD-4C - -Selection Display LCD Type `Xiaozhi Assistant --> LCD Type` -- Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C with 800*800 3.4inch round display -- Waveshare ESP32-P4-WIFI6-Touch-LCD-4C with 720*720 4inch round display - - - -| [ESP32-P4-WIFI6-Touch-LCD-3.4C](https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-3.4c.htm) | [ESP32-P4-WIFI6-Touch-LCD-4C](https://www.waveshare.com/esp32-p4-wifi6-touch-lcd-4c.htm) | -|----------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| -| | | diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.h deleted file mode 100644 index 30e73ae2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.h +++ /dev/null @@ -1,490 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define LCD_BIT_PER_PIXEL (16) -#define PIN_NUM_LCD_RST GPIO_NUM_27 - -#define DELAY_TIME_MS (3000) -#define LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes - -#define MIPI_DSI_PHY_PWR_LDO_CHAN (3) -#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_26 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#if CONFIG_LCD_TYPE_800_800_3_4_INCH -#define DISPLAY_WIDTH 800 -#define DISPLAY_HEIGHT 800 - -static const jd9365_lcd_init_cmd_t lcd_init_cmds[] = { - {0xE0, (uint8_t[]){0x00}, 1, 0}, - - {0xE1, (uint8_t[]){0x93}, 1, 0}, - {0xE2, (uint8_t[]){0x65}, 1, 0}, - {0xE3, (uint8_t[]){0xF8}, 1, 0}, - {0x80, (uint8_t[]){0x01}, 1, 0}, - - {0xE0, (uint8_t[]){0x01}, 1, 0}, - - {0x00, (uint8_t[]){0x00}, 1, 0}, - {0x01, (uint8_t[]){0x41}, 1, 0}, - {0x03, (uint8_t[]){0x10}, 1, 0}, - {0x04, (uint8_t[]){0x44}, 1, 0}, - - {0x17, (uint8_t[]){0x00}, 1, 0}, - {0x18, (uint8_t[]){0xD0}, 1, 0}, - {0x19, (uint8_t[]){0x00}, 1, 0}, - {0x1A, (uint8_t[]){0x00}, 1, 0}, - {0x1B, (uint8_t[]){0xD0}, 1, 0}, - {0x1C, (uint8_t[]){0x00}, 1, 0}, - - {0x24, (uint8_t[]){0xFE}, 1, 0}, - {0x35, (uint8_t[]){0x26}, 1, 0}, - - {0x37, (uint8_t[]){0x09}, 1, 0}, - - {0x38, (uint8_t[]){0x04}, 1, 0}, - {0x39, (uint8_t[]){0x08}, 1, 0}, - {0x3A, (uint8_t[]){0x0A}, 1, 0}, - {0x3C, (uint8_t[]){0x78}, 1, 0}, - {0x3D, (uint8_t[]){0xFF}, 1, 0}, - {0x3E, (uint8_t[]){0xFF}, 1, 0}, - {0x3F, (uint8_t[]){0xFF}, 1, 0}, - - {0x40, (uint8_t[]){0x00}, 1, 0}, - {0x41, (uint8_t[]){0x64}, 1, 0}, - {0x42, (uint8_t[]){0xC7}, 1, 0}, - {0x43, (uint8_t[]){0x18}, 1, 0}, - {0x44, (uint8_t[]){0x0B}, 1, 0}, - {0x45, (uint8_t[]){0x14}, 1, 0}, - - {0x55, (uint8_t[]){0x02}, 1, 0}, - {0x57, (uint8_t[]){0x49}, 1, 0}, - {0x59, (uint8_t[]){0x0A}, 1, 0}, - {0x5A, (uint8_t[]){0x1B}, 1, 0}, - {0x5B, (uint8_t[]){0x19}, 1, 0}, - - {0x5D, (uint8_t[]){0x7F}, 1, 0}, - {0x5E, (uint8_t[]){0x56}, 1, 0}, - {0x5F, (uint8_t[]){0x43}, 1, 0}, - {0x60, (uint8_t[]){0x37}, 1, 0}, - {0x61, (uint8_t[]){0x33}, 1, 0}, - {0x62, (uint8_t[]){0x25}, 1, 0}, - {0x63, (uint8_t[]){0x2A}, 1, 0}, - {0x64, (uint8_t[]){0x16}, 1, 0}, - {0x65, (uint8_t[]){0x30}, 1, 0}, - {0x66, (uint8_t[]){0x2F}, 1, 0}, - {0x67, (uint8_t[]){0x32}, 1, 0}, - {0x68, (uint8_t[]){0x53}, 1, 0}, - {0x69, (uint8_t[]){0x43}, 1, 0}, - {0x6A, (uint8_t[]){0x4C}, 1, 0}, - {0x6B, (uint8_t[]){0x40}, 1, 0}, - {0x6C, (uint8_t[]){0x3D}, 1, 0}, - {0x6D, (uint8_t[]){0x31}, 1, 0}, - {0x6E, (uint8_t[]){0x20}, 1, 0}, - {0x6F, (uint8_t[]){0x0F}, 1, 0}, - - {0x70, (uint8_t[]){0x7F}, 1, 0}, - {0x71, (uint8_t[]){0x56}, 1, 0}, - {0x72, (uint8_t[]){0x43}, 1, 0}, - {0x73, (uint8_t[]){0x37}, 1, 0}, - {0x74, (uint8_t[]){0x33}, 1, 0}, - {0x75, (uint8_t[]){0x25}, 1, 0}, - {0x76, (uint8_t[]){0x2A}, 1, 0}, - {0x77, (uint8_t[]){0x16}, 1, 0}, - {0x78, (uint8_t[]){0x30}, 1, 0}, - {0x79, (uint8_t[]){0x2F}, 1, 0}, - {0x7A, (uint8_t[]){0x32}, 1, 0}, - {0x7B, (uint8_t[]){0x53}, 1, 0}, - {0x7C, (uint8_t[]){0x43}, 1, 0}, - {0x7D, (uint8_t[]){0x4C}, 1, 0}, - {0x7E, (uint8_t[]){0x40}, 1, 0}, - {0x7F, (uint8_t[]){0x3D}, 1, 0}, - {0x80, (uint8_t[]){0x31}, 1, 0}, - {0x81, (uint8_t[]){0x20}, 1, 0}, - {0x82, (uint8_t[]){0x0F}, 1, 0}, - - {0xE0, (uint8_t[]){0x02}, 1, 0}, - {0x00, (uint8_t[]){0x5F}, 1, 0}, - {0x01, (uint8_t[]){0x5F}, 1, 0}, - {0x02, (uint8_t[]){0x5E}, 1, 0}, - {0x03, (uint8_t[]){0x5E}, 1, 0}, - {0x04, (uint8_t[]){0x50}, 1, 0}, - {0x05, (uint8_t[]){0x48}, 1, 0}, - {0x06, (uint8_t[]){0x48}, 1, 0}, - {0x07, (uint8_t[]){0x4A}, 1, 0}, - {0x08, (uint8_t[]){0x4A}, 1, 0}, - {0x09, (uint8_t[]){0x44}, 1, 0}, - {0x0A, (uint8_t[]){0x44}, 1, 0}, - {0x0B, (uint8_t[]){0x46}, 1, 0}, - {0x0C, (uint8_t[]){0x46}, 1, 0}, - {0x0D, (uint8_t[]){0x5F}, 1, 0}, - {0x0E, (uint8_t[]){0x5F}, 1, 0}, - {0x0F, (uint8_t[]){0x57}, 1, 0}, - {0x10, (uint8_t[]){0x57}, 1, 0}, - {0x11, (uint8_t[]){0x77}, 1, 0}, - {0x12, (uint8_t[]){0x77}, 1, 0}, - {0x13, (uint8_t[]){0x40}, 1, 0}, - {0x14, (uint8_t[]){0x42}, 1, 0}, - {0x15, (uint8_t[]){0x5F}, 1, 0}, - - {0x16, (uint8_t[]){0x5F}, 1, 0}, - {0x17, (uint8_t[]){0x5F}, 1, 0}, - {0x18, (uint8_t[]){0x5E}, 1, 0}, - {0x19, (uint8_t[]){0x5E}, 1, 0}, - {0x1A, (uint8_t[]){0x50}, 1, 0}, - {0x1B, (uint8_t[]){0x49}, 1, 0}, - {0x1C, (uint8_t[]){0x49}, 1, 0}, - {0x1D, (uint8_t[]){0x4B}, 1, 0}, - {0x1E, (uint8_t[]){0x4B}, 1, 0}, - {0x1F, (uint8_t[]){0x45}, 1, 0}, - {0x20, (uint8_t[]){0x45}, 1, 0}, - {0x21, (uint8_t[]){0x47}, 1, 0}, - {0x22, (uint8_t[]){0x47}, 1, 0}, - {0x23, (uint8_t[]){0x5F}, 1, 0}, - {0x24, (uint8_t[]){0x5F}, 1, 0}, - {0x25, (uint8_t[]){0x57}, 1, 0}, - {0x26, (uint8_t[]){0x57}, 1, 0}, - {0x27, (uint8_t[]){0x77}, 1, 0}, - {0x28, (uint8_t[]){0x77}, 1, 0}, - {0x29, (uint8_t[]){0x41}, 1, 0}, - {0x2A, (uint8_t[]){0x43}, 1, 0}, - {0x2B, (uint8_t[]){0x5F}, 1, 0}, - - {0x2C, (uint8_t[]){0x1E}, 1, 0}, - {0x2D, (uint8_t[]){0x1E}, 1, 0}, - {0x2E, (uint8_t[]){0x1F}, 1, 0}, - {0x2F, (uint8_t[]){0x1F}, 1, 0}, - {0x30, (uint8_t[]){0x10}, 1, 0}, - {0x31, (uint8_t[]){0x07}, 1, 0}, - {0x32, (uint8_t[]){0x07}, 1, 0}, - {0x33, (uint8_t[]){0x05}, 1, 0}, - {0x34, (uint8_t[]){0x05}, 1, 0}, - {0x35, (uint8_t[]){0x0B}, 1, 0}, - {0x36, (uint8_t[]){0x0B}, 1, 0}, - {0x37, (uint8_t[]){0x09}, 1, 0}, - {0x38, (uint8_t[]){0x09}, 1, 0}, - {0x39, (uint8_t[]){0x1F}, 1, 0}, - {0x3A, (uint8_t[]){0x1F}, 1, 0}, - {0x3B, (uint8_t[]){0x17}, 1, 0}, - {0x3C, (uint8_t[]){0x17}, 1, 0}, - {0x3D, (uint8_t[]){0x17}, 1, 0}, - {0x3E, (uint8_t[]){0x17}, 1, 0}, - {0x3F, (uint8_t[]){0x03}, 1, 0}, - {0x40, (uint8_t[]){0x01}, 1, 0}, - {0x41, (uint8_t[]){0x1F}, 1, 0}, - - {0x42, (uint8_t[]){0x1E}, 1, 0}, - {0x43, (uint8_t[]){0x1E}, 1, 0}, - {0x44, (uint8_t[]){0x1F}, 1, 0}, - {0x45, (uint8_t[]){0x1F}, 1, 0}, - {0x46, (uint8_t[]){0x10}, 1, 0}, - {0x47, (uint8_t[]){0x06}, 1, 0}, - {0x48, (uint8_t[]){0x06}, 1, 0}, - {0x49, (uint8_t[]){0x04}, 1, 0}, - {0x4A, (uint8_t[]){0x04}, 1, 0}, - {0x4B, (uint8_t[]){0x0A}, 1, 0}, - {0x4C, (uint8_t[]){0x0A}, 1, 0}, - {0x4D, (uint8_t[]){0x08}, 1, 0}, - {0x4E, (uint8_t[]){0x08}, 1, 0}, - {0x4F, (uint8_t[]){0x1F}, 1, 0}, - {0x50, (uint8_t[]){0x1F}, 1, 0}, - {0x51, (uint8_t[]){0x17}, 1, 0}, - {0x52, (uint8_t[]){0x17}, 1, 0}, - {0x53, (uint8_t[]){0x17}, 1, 0}, - {0x54, (uint8_t[]){0x17}, 1, 0}, - {0x55, (uint8_t[]){0x02}, 1, 0}, - {0x56, (uint8_t[]){0x00}, 1, 0}, - {0x57, (uint8_t[]){0x1F}, 1, 0}, - - {0xE0, (uint8_t[]){0x02}, 1, 0}, - {0x58, (uint8_t[]){0x40}, 1, 0}, - {0x59, (uint8_t[]){0x00}, 1, 0}, - {0x5A, (uint8_t[]){0x00}, 1, 0}, - {0x5B, (uint8_t[]){0x30}, 1, 0}, - {0x5C, (uint8_t[]){0x01}, 1, 0}, - {0x5D, (uint8_t[]){0x30}, 1, 0}, - {0x5E, (uint8_t[]){0x01}, 1, 0}, - {0x5F, (uint8_t[]){0x02}, 1, 0}, - {0x60, (uint8_t[]){0x30}, 1, 0}, - {0x61, (uint8_t[]){0x03}, 1, 0}, - {0x62, (uint8_t[]){0x04}, 1, 0}, - {0x63, (uint8_t[]){0x04}, 1, 0}, - {0x64, (uint8_t[]){0xA6}, 1, 0}, - {0x65, (uint8_t[]){0x43}, 1, 0}, - {0x66, (uint8_t[]){0x30}, 1, 0}, - {0x67, (uint8_t[]){0x73}, 1, 0}, - {0x68, (uint8_t[]){0x05}, 1, 0}, - {0x69, (uint8_t[]){0x04}, 1, 0}, - {0x6A, (uint8_t[]){0x7F}, 1, 0}, - {0x6B, (uint8_t[]){0x08}, 1, 0}, - {0x6C, (uint8_t[]){0x00}, 1, 0}, - {0x6D, (uint8_t[]){0x04}, 1, 0}, - {0x6E, (uint8_t[]){0x04}, 1, 0}, - {0x6F, (uint8_t[]){0x88}, 1, 0}, - - {0x75, (uint8_t[]){0xD9}, 1, 0}, - {0x76, (uint8_t[]){0x00}, 1, 0}, - {0x77, (uint8_t[]){0x33}, 1, 0}, - {0x78, (uint8_t[]){0x43}, 1, 0}, - - {0xE0, (uint8_t[]){0x00}, 1, 0}, - - {0x11, (uint8_t[]){0x00}, 1, 120}, - - {0x29, (uint8_t[]){0x00}, 1, 20}, - {0x35, (uint8_t[]){0x00}, 1, 0}, -}; -#else -#define DISPLAY_WIDTH 720 -#define DISPLAY_HEIGHT 720 -static const jd9365_lcd_init_cmd_t lcd_init_cmds[] = { - {0xE0, (uint8_t[]){0x00}, 1, 0}, - - {0xE1, (uint8_t[]){0x93}, 1, 0}, - {0xE2, (uint8_t[]){0x65}, 1, 0}, - {0xE3, (uint8_t[]){0xF8}, 1, 0}, - {0x80, (uint8_t[]){0x01}, 1, 0}, - - {0xE0, (uint8_t[]){0x01}, 1, 0}, - - {0x00, (uint8_t[]){0x00}, 1, 0}, - {0x01, (uint8_t[]){0x41}, 1, 0}, - {0x03, (uint8_t[]){0x10}, 1, 0}, - {0x04, (uint8_t[]){0x44}, 1, 0}, - - {0x17, (uint8_t[]){0x00}, 1, 0}, - {0x18, (uint8_t[]){0xD0}, 1, 0}, - {0x19, (uint8_t[]){0x00}, 1, 0}, - {0x1A, (uint8_t[]){0x00}, 1, 0}, - {0x1B, (uint8_t[]){0xD0}, 1, 0}, - {0x1C, (uint8_t[]){0x00}, 1, 0}, - - {0x24, (uint8_t[]){0xFE}, 1, 0}, - {0x35, (uint8_t[]){0x26}, 1, 0}, - - {0x37, (uint8_t[]){0x09}, 1, 0}, - - {0x38, (uint8_t[]){0x04}, 1, 0}, - {0x39, (uint8_t[]){0x08}, 1, 0}, - {0x3A, (uint8_t[]){0x0A}, 1, 0}, - {0x3C, (uint8_t[]){0x78}, 1, 0}, - {0x3D, (uint8_t[]){0xFF}, 1, 0}, - {0x3E, (uint8_t[]){0xFF}, 1, 0}, - {0x3F, (uint8_t[]){0xFF}, 1, 0}, - - {0x40, (uint8_t[]){0x04}, 1, 0}, - {0x41, (uint8_t[]){0x64}, 1, 0}, - {0x42, (uint8_t[]){0xC7}, 1, 0}, - {0x43, (uint8_t[]){0x18}, 1, 0}, - {0x44, (uint8_t[]){0x0B}, 1, 0}, - {0x45, (uint8_t[]){0x14}, 1, 0}, - - {0x55, (uint8_t[]){0x02}, 1, 0}, - {0x57, (uint8_t[]){0x49}, 1, 0}, - {0x59, (uint8_t[]){0x0A}, 1, 0}, - {0x5A, (uint8_t[]){0x1B}, 1, 0}, - {0x5B, (uint8_t[]){0x19}, 1, 0}, - - {0x5D, (uint8_t[]){0x7F}, 1, 0}, - {0x5E, (uint8_t[]){0x56}, 1, 0}, - {0x5F, (uint8_t[]){0x43}, 1, 0}, - {0x60, (uint8_t[]){0x37}, 1, 0}, - {0x61, (uint8_t[]){0x33}, 1, 0}, - {0x62, (uint8_t[]){0x25}, 1, 0}, - {0x63, (uint8_t[]){0x2A}, 1, 0}, - {0x64, (uint8_t[]){0x16}, 1, 0}, - {0x65, (uint8_t[]){0x30}, 1, 0}, - {0x66, (uint8_t[]){0x2F}, 1, 0}, - {0x67, (uint8_t[]){0x32}, 1, 0}, - {0x68, (uint8_t[]){0x53}, 1, 0}, - {0x69, (uint8_t[]){0x43}, 1, 0}, - {0x6A, (uint8_t[]){0x4C}, 1, 0}, - {0x6B, (uint8_t[]){0x40}, 1, 0}, - {0x6C, (uint8_t[]){0x3D}, 1, 0}, - {0x6D, (uint8_t[]){0x31}, 1, 0}, - {0x6E, (uint8_t[]){0x20}, 1, 0}, - {0x6F, (uint8_t[]){0x0F}, 1, 0}, - - {0x70, (uint8_t[]){0x7F}, 1, 0}, - {0x71, (uint8_t[]){0x56}, 1, 0}, - {0x72, (uint8_t[]){0x43}, 1, 0}, - {0x73, (uint8_t[]){0x37}, 1, 0}, - {0x74, (uint8_t[]){0x33}, 1, 0}, - {0x75, (uint8_t[]){0x25}, 1, 0}, - {0x76, (uint8_t[]){0x2A}, 1, 0}, - {0x77, (uint8_t[]){0x16}, 1, 0}, - {0x78, (uint8_t[]){0x30}, 1, 0}, - {0x79, (uint8_t[]){0x2F}, 1, 0}, - {0x7A, (uint8_t[]){0x32}, 1, 0}, - {0x7B, (uint8_t[]){0x53}, 1, 0}, - {0x7C, (uint8_t[]){0x43}, 1, 0}, - {0x7D, (uint8_t[]){0x4C}, 1, 0}, - {0x7E, (uint8_t[]){0x40}, 1, 0}, - {0x7F, (uint8_t[]){0x3D}, 1, 0}, - {0x80, (uint8_t[]){0x31}, 1, 0}, - {0x81, (uint8_t[]){0x20}, 1, 0}, - {0x82, (uint8_t[]){0x0F}, 1, 0}, - - {0xE0, (uint8_t[]){0x02}, 1, 0}, - {0x00, (uint8_t[]){0x5F}, 1, 0}, - {0x01, (uint8_t[]){0x5F}, 1, 0}, - {0x02, (uint8_t[]){0x5E}, 1, 0}, - {0x03, (uint8_t[]){0x5E}, 1, 0}, - {0x04, (uint8_t[]){0x50}, 1, 0}, - {0x05, (uint8_t[]){0x48}, 1, 0}, - {0x06, (uint8_t[]){0x48}, 1, 0}, - {0x07, (uint8_t[]){0x4A}, 1, 0}, - {0x08, (uint8_t[]){0x4A}, 1, 0}, - {0x09, (uint8_t[]){0x44}, 1, 0}, - {0x0A, (uint8_t[]){0x44}, 1, 0}, - {0x0B, (uint8_t[]){0x46}, 1, 0}, - {0x0C, (uint8_t[]){0x46}, 1, 0}, - {0x0D, (uint8_t[]){0x5F}, 1, 0}, - {0x0E, (uint8_t[]){0x5F}, 1, 0}, - {0x0F, (uint8_t[]){0x57}, 1, 0}, - {0x10, (uint8_t[]){0x57}, 1, 0}, - {0x11, (uint8_t[]){0x77}, 1, 0}, - {0x12, (uint8_t[]){0x77}, 1, 0}, - {0x13, (uint8_t[]){0x40}, 1, 0}, - {0x14, (uint8_t[]){0x42}, 1, 0}, - {0x15, (uint8_t[]){0x5F}, 1, 0}, - - {0x16, (uint8_t[]){0x5F}, 1, 0}, - {0x17, (uint8_t[]){0x5F}, 1, 0}, - {0x18, (uint8_t[]){0x5E}, 1, 0}, - {0x19, (uint8_t[]){0x5E}, 1, 0}, - {0x1A, (uint8_t[]){0x50}, 1, 0}, - {0x1B, (uint8_t[]){0x49}, 1, 0}, - {0x1C, (uint8_t[]){0x49}, 1, 0}, - {0x1D, (uint8_t[]){0x4B}, 1, 0}, - {0x1E, (uint8_t[]){0x4B}, 1, 0}, - {0x1F, (uint8_t[]){0x45}, 1, 0}, - {0x20, (uint8_t[]){0x45}, 1, 0}, - {0x21, (uint8_t[]){0x47}, 1, 0}, - {0x22, (uint8_t[]){0x47}, 1, 0}, - {0x23, (uint8_t[]){0x5F}, 1, 0}, - {0x24, (uint8_t[]){0x5F}, 1, 0}, - {0x25, (uint8_t[]){0x57}, 1, 0}, - {0x26, (uint8_t[]){0x57}, 1, 0}, - {0x27, (uint8_t[]){0x77}, 1, 0}, - {0x28, (uint8_t[]){0x77}, 1, 0}, - {0x29, (uint8_t[]){0x41}, 1, 0}, - {0x2A, (uint8_t[]){0x43}, 1, 0}, - {0x2B, (uint8_t[]){0x5F}, 1, 0}, - - {0x2C, (uint8_t[]){0x1E}, 1, 0}, - {0x2D, (uint8_t[]){0x1E}, 1, 0}, - {0x2E, (uint8_t[]){0x1F}, 1, 0}, - {0x2F, (uint8_t[]){0x1F}, 1, 0}, - {0x30, (uint8_t[]){0x10}, 1, 0}, - {0x31, (uint8_t[]){0x07}, 1, 0}, - {0x32, (uint8_t[]){0x07}, 1, 0}, - {0x33, (uint8_t[]){0x05}, 1, 0}, - {0x34, (uint8_t[]){0x05}, 1, 0}, - {0x35, (uint8_t[]){0x0B}, 1, 0}, - {0x36, (uint8_t[]){0x0B}, 1, 0}, - {0x37, (uint8_t[]){0x09}, 1, 0}, - {0x38, (uint8_t[]){0x09}, 1, 0}, - {0x39, (uint8_t[]){0x1F}, 1, 0}, - {0x3A, (uint8_t[]){0x1F}, 1, 0}, - {0x3B, (uint8_t[]){0x17}, 1, 0}, - {0x3C, (uint8_t[]){0x17}, 1, 0}, - {0x3D, (uint8_t[]){0x17}, 1, 0}, - {0x3E, (uint8_t[]){0x17}, 1, 0}, - {0x3F, (uint8_t[]){0x03}, 1, 0}, - {0x40, (uint8_t[]){0x01}, 1, 0}, - {0x41, (uint8_t[]){0x1F}, 1, 0}, - - {0x42, (uint8_t[]){0x1E}, 1, 0}, - {0x43, (uint8_t[]){0x1E}, 1, 0}, - {0x44, (uint8_t[]){0x1F}, 1, 0}, - {0x45, (uint8_t[]){0x1F}, 1, 0}, - {0x46, (uint8_t[]){0x10}, 1, 0}, - {0x47, (uint8_t[]){0x06}, 1, 0}, - {0x48, (uint8_t[]){0x06}, 1, 0}, - {0x49, (uint8_t[]){0x04}, 1, 0}, - {0x4A, (uint8_t[]){0x04}, 1, 0}, - {0x4B, (uint8_t[]){0x0A}, 1, 0}, - {0x4C, (uint8_t[]){0x0A}, 1, 0}, - {0x4D, (uint8_t[]){0x08}, 1, 0}, - {0x4E, (uint8_t[]){0x08}, 1, 0}, - {0x4F, (uint8_t[]){0x1F}, 1, 0}, - {0x50, (uint8_t[]){0x1F}, 1, 0}, - {0x51, (uint8_t[]){0x17}, 1, 0}, - {0x52, (uint8_t[]){0x17}, 1, 0}, - {0x53, (uint8_t[]){0x17}, 1, 0}, - {0x54, (uint8_t[]){0x17}, 1, 0}, - {0x55, (uint8_t[]){0x02}, 1, 0}, - {0x56, (uint8_t[]){0x00}, 1, 0}, - {0x57, (uint8_t[]){0x1F}, 1, 0}, - - {0xE0, (uint8_t[]){0x02}, 1, 0}, - {0x58, (uint8_t[]){0x40}, 1, 0}, - {0x59, (uint8_t[]){0x00}, 1, 0}, - {0x5A, (uint8_t[]){0x00}, 1, 0}, - {0x5B, (uint8_t[]){0x30}, 1, 0}, - {0x5C, (uint8_t[]){0x01}, 1, 0}, - {0x5D, (uint8_t[]){0x30}, 1, 0}, - {0x5E, (uint8_t[]){0x01}, 1, 0}, - {0x5F, (uint8_t[]){0x02}, 1, 0}, - {0x60, (uint8_t[]){0x30}, 1, 0}, - {0x61, (uint8_t[]){0x03}, 1, 0}, - {0x62, (uint8_t[]){0x04}, 1, 0}, - {0x63, (uint8_t[]){0x04}, 1, 0}, - {0x64, (uint8_t[]){0xA6}, 1, 0}, - {0x65, (uint8_t[]){0x43}, 1, 0}, - {0x66, (uint8_t[]){0x30}, 1, 0}, - {0x67, (uint8_t[]){0x73}, 1, 0}, - {0x68, (uint8_t[]){0x05}, 1, 0}, - {0x69, (uint8_t[]){0x04}, 1, 0}, - {0x6A, (uint8_t[]){0x7F}, 1, 0}, - {0x6B, (uint8_t[]){0x08}, 1, 0}, - {0x6C, (uint8_t[]){0x00}, 1, 0}, - {0x6D, (uint8_t[]){0x04}, 1, 0}, - {0x6E, (uint8_t[]){0x04}, 1, 0}, - {0x6F, (uint8_t[]){0x88}, 1, 0}, - - {0x75, (uint8_t[]){0xD9}, 1, 0}, - {0x76, (uint8_t[]){0x00}, 1, 0}, - {0x77, (uint8_t[]){0x33}, 1, 0}, - {0x78, (uint8_t[]){0x43}, 1, 0}, - - {0xE0, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 1, 120}, - - {0x29, (uint8_t[]){0x00}, 1, 20}, - {0x35, (uint8_t[]){0x00}, 1, 0}, -}; -#endif - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.json deleted file mode 100644 index 927bb971..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/config.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "waveshare-p4-wifi6-touch-lcd-xc-3.4c", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_LCD_TYPE_800_800_3_4_INCH=y", - "CONFIG_CAMERA_OV5647=y", - "CONFIG_CAMERA_OV5647_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - }, - { - "name": "waveshare-p4-wifi6-touch-lcd-xc-4c", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y", - "CONFIG_LCD_TYPE_720_720_4_INCH=y", - "CONFIG_CAMERA_OV5647=y", - "CONFIG_CAMERA_OV5647_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5647_MIPI_RAW8_800X800_50FPS=y", - "CONFIG_XIAOZHI_ENABLE_CAMERA_ENDIANNESS_SWAP=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/esp32-p4-wifi6-touch-lcd-xc.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/esp32-p4-wifi6-touch-lcd-xc.cc deleted file mode 100644 index dc3ed4e7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-p4-wifi6-touch-lcd-xc/esp32-p4-wifi6-touch-lcd-xc.cc +++ /dev/null @@ -1,229 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "display/lcd_display.h" -// #include "display/no_display.h" -#include "button.h" - -#include "esp32_camera.h" -#include "esp_video_init.h" -#include "esp_cam_sensor_xclk.h" - -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" - -#include "esp_lcd_jd9365_10_1.h" -#include "config.h" - -#include -#include -#include -#include "esp_lcd_touch_gt911.h" -#define TAG "WaveshareEsp32p4xc" - -class WaveshareEsp32p4xc : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay *display_; - Esp32Camera* camera_ = nullptr; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power(void) { -#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state - static esp_ldo_channel_handle_t phy_pwr_chan = NULL; - esp_ldo_channel_config_t ldo_cfg = { - .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan); - ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); -#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - - return ESP_OK; - } - - void InitializeLCD() { - bsp_enable_dsi_phy_power(); - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 1500, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_config = JD9365_PANEL_IO_DBI_CONFIG(); - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 46, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 1, - .video_timing = { - .h_size = DISPLAY_WIDTH, - .v_size = DISPLAY_HEIGHT, - .hsync_pulse_width = 20, - .hsync_back_porch = 20, - .hsync_front_porch = 40, - .vsync_pulse_width = 4, - .vsync_back_porch = 12, - .vsync_front_porch = 24, - }, - .flags = { - .use_dma2d = true, - }, - }; - jd9365_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]), - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - .lane_num = 2, - }, - .flags = { - .use_mipi_interface = 1, - }, - }; - - const esp_lcd_panel_dev_config_t lcd_dev_config = { - .reset_gpio_num = PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_jd9365(io, &lcd_dev_config, &disp_panel); - esp_lcd_panel_reset(disp_panel); - esp_lcd_panel_init(disp_panel); - - display_ = new MipiLcdDisplay(io, disp_panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_23, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - void InitializeCamera() { - esp_video_init_csi_config_t base_csi_config = { - .sccb_config = { - .init_sccb = false, - .i2c_handle = i2c_bus_, - .freq = 400000, - }, - .reset_pin = GPIO_NUM_NC, - .pwdn_pin = GPIO_NUM_NC, - }; - - esp_video_init_config_t cam_config = { - .csi = &base_csi_config, - }; - - camera_ = new Esp32Camera(cam_config); - } - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - -public: - WaveshareEsp32p4xc() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeLCD(); - InitializeTouch(); - InitializeCamera(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Camera* GetCamera() override { - return camera_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(WaveshareEsp32p4xc); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/README.md deleted file mode 100644 index dff4acc2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-AUDIO-Board -产品链接: -https://www.waveshare.net/shop/ESP32-S3-AUDIO-Board.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.h deleted file mode 100644 index 958cb898..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define BUILTIN_LED_GPIO GPIO_NUM_38 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_16 -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define I2C_SCL_IO GPIO_NUM_10 -#define I2C_SDA_IO GPIO_NUM_11 - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9555_ADDRESS_000 - -#define DISPLAY_SDA_PIN I2C_SDA_IO -#define DISPLAY_SCL_PIN I2C_SCL_IO - -#define DISPLAY_MISO_PIN GPIO_NUM_8 -#define DISPLAY_MOSI_PIN GPIO_NUM_9 -#define DISPLAY_SCLK_PIN GPIO_NUM_4 -#define DISPLAY_CS_PIN GPIO_NUM_3 -#define DISPLAY_DC_PIN GPIO_NUM_7 -#define DISPLAY_RESET_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_5 - -#define DISPLAY_SPI_SCLK_HZ (20 * 1000 * 1000) - -/* Camera pins */ -#define CAMERA_PIN_PWDN GPIO_NUM_NC -#define CAMERA_PIN_RESET GPIO_NUM_NC -#define CAMERA_PIN_XCLK GPIO_NUM_43 -#define CAMERA_PIN_SIOD GPIO_NUM_NC -#define CAMERA_PIN_SIOC GPIO_NUM_NC - -#define CAMERA_PIN_D7 GPIO_NUM_48 -#define CAMERA_PIN_D6 GPIO_NUM_47 -#define CAMERA_PIN_D5 GPIO_NUM_46 -#define CAMERA_PIN_D4 GPIO_NUM_45 -#define CAMERA_PIN_D3 GPIO_NUM_39 -#define CAMERA_PIN_D2 GPIO_NUM_18 -#define CAMERA_PIN_D1 GPIO_NUM_17 -#define CAMERA_PIN_D0 GPIO_NUM_2 -#define CAMERA_PIN_VSYNC GPIO_NUM_21 -#define CAMERA_PIN_HREF GPIO_NUM_1 -#define CAMERA_PIN_PCLK GPIO_NUM_44 - -#define XCLK_FREQ_HZ 20000000 - - - - -#ifdef CONFIG_AUDIO_BOARD_LCD_JD9853 -#define LCD_TYPE_JD9853_SERIAL -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 172 - -#define DISPLAY_SWAP_XY true -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_INVERT_COLOR true -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#endif - -#ifdef CONFIG_AUDIO_BOARD_LCD_ST7789 -#define LCD_TYPE_ST7789_SERIAL -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 320 - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_INVERT_COLOR true -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#endif - - - -#endif // _BOARD_CONFIG_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.json deleted file mode 100644 index c1c776ba..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-audio-board", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_640X480_6FPS=y", - "CONFIG_CAMERA_OV2640_DVP_IF_FORMAT_INDEX_DEFAULT=1", - "CONFIG_CAMERA_OV5640=y", - "CONFIG_CAMERA_OV5640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5640_DVP_YUV422_800X600_10FPS=y", - "CONFIG_CAMERA_OV5640_DVP_IF_FORMAT_INDEX_DEFAULT=0" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp32-s3-audio_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp32-s3-audio_board.cc deleted file mode 100644 index d2969e25..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp32-s3-audio_board.cc +++ /dev/null @@ -1,239 +0,0 @@ -#include "wifi_board.h" -#include "codecs/box_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include -#include -#include "esp_io_expander_tca95xx_16bit.h" -#include "esp32_camera.h" -#include "led/circular_strip.h" -#include "esp_lcd_jd9853.h" - -#define TAG "waveshare_s3_audio_board" - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x0BULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -class CustomBoard : public WifiBoard { -private: - Button boot_button_; - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - Esp32Camera* camera_; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = I2C_SDA_IO, - .scl_io_num = I2C_SCL_IO, - .clk_source = I2C_CLK_SRC_DEFAULT, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9555(void) - { - esp_err_t ret = esp_io_expander_new_i2c_tca95xx_16bit(i2c_bus_, I2C_ADDRESS, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); // 打印引脚状态 - - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1 | IO_EXPANDER_PIN_NUM_8|IO_EXPANDER_PIN_NUM_5|IO_EXPANDER_PIN_NUM_6, IO_EXPANDER_OUTPUT); // 设置引脚 EXIO0 和 EXIO1 模式为输出 - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(10)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(10)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 1); // 复位 LCD 与 TouchPad - ESP_ERROR_CHECK(ret); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_8, 1); // 启用喇叭功放 - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_5, false); // 复位摄像头 - vTaskDelay(pdMS_TO_TICKS(5)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_6, true); - vTaskDelay(pdMS_TO_TICKS(5)); - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR)); - - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeJd9853Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = DISPLAY_SPI_SCLK_HZ; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片JD9853 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = GPIO_NUM_NC; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - //ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_new_panel_jd9853(panel_io, &panel_config, &panel)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel, true)); - ESP_ERROR_CHECK(esp_lcd_panel_set_gap(panel, 0, 34)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel, true, false)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel, true)); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAMERA_PIN_D0, - [1] = CAMERA_PIN_D1, - [2] = CAMERA_PIN_D2, - [3] = CAMERA_PIN_D3, - [4] = CAMERA_PIN_D4, - [5] = CAMERA_PIN_D5, - [6] = CAMERA_PIN_D6, - [7] = CAMERA_PIN_D7, - }, - .vsync_io = CAMERA_PIN_VSYNC, - .de_io = CAMERA_PIN_HREF, - .pclk_io = CAMERA_PIN_PCLK, - .xclk_io = CAMERA_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // 不初始化新的 SCCB,使用现有的 I2C 总线 - .i2c_handle = i2c_bus_, // 使用现有的 I2C 总线句柄 - .freq = 100000, // 100kHz - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAMERA_PIN_RESET, - .pwdn_pin = CAMERA_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = 12000000, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - - } -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeTca9555(); - InitializeSpi(); - InitializeButtons(); - #ifdef LCD_TYPE_JD9853_SERIAL - InitializeJd9853Display(); - #else - InitializeSt7789Display(); - #endif - InitializeCamera(); - GetBacklight()->RestoreBrightness(); - } - - virtual Led* GetLed() override { - static CircularStrip led(BUILTIN_LED_GPIO, 6); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec(i2c_bus_, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR, AUDIO_CODEC_ES7210_ADDR, AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, BACKLIGHT_INVERT); - return &backlight; - } - - virtual Camera* GetCamera() override { - return camera_; - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.c deleted file mode 100644 index dea68f2e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.c +++ /dev/null @@ -1,460 +0,0 @@ -#include -#include "esp_lcd_jd9853.h" -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_lcd_panel_interface.h" -#include "esp_lcd_panel_io.h" -#include "esp_lcd_panel_vendor.h" -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_panel_commands.h" -#include "driver/gpio.h" -#include "esp_log.h" -#include "esp_check.h" - -static const char *TAG = "JD9853"; - -static esp_err_t panel_jd9853_del(esp_lcd_panel_t *panel); -static esp_err_t panel_jd9853_reset(esp_lcd_panel_t *panel); -static esp_err_t panel_jd9853_init(esp_lcd_panel_t *panel); -static esp_err_t panel_jd9853_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data); -static esp_err_t panel_jd9853_invert_color(esp_lcd_panel_t *panel, bool invert_color_data); -static esp_err_t panel_jd9853_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y); -static esp_err_t panel_jd9853_swap_xy(esp_lcd_panel_t *panel, bool swap_axes); -static esp_err_t panel_jd9853_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap); -static esp_err_t panel_jd9853_disp_on_off(esp_lcd_panel_t *panel, bool off); - -typedef struct -{ - esp_lcd_panel_t base; - esp_lcd_panel_io_handle_t io; - int reset_gpio_num; - bool reset_level; - int x_gap; - int y_gap; - uint8_t fb_bits_per_pixel; - uint8_t madctl_val; // save current value of LCD_CMD_MADCTL register - uint8_t colmod_val; // save current value of LCD_CMD_COLMOD register - const jd9853_lcd_init_cmd_t *init_cmds; - uint16_t init_cmds_size; -} jd9853_panel_t; - -esp_err_t esp_lcd_new_panel_jd9853(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel) -{ - esp_err_t ret = ESP_OK; - jd9853_panel_t *jd9853 = NULL; - gpio_config_t io_conf = {0}; - - ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument"); - jd9853 = (jd9853_panel_t *)calloc(1, sizeof(jd9853_panel_t)); - ESP_GOTO_ON_FALSE(jd9853, ESP_ERR_NO_MEM, err, TAG, "no mem for jd9853 panel"); - - if (panel_dev_config->reset_gpio_num >= 0) - { - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num; - ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "configure GPIO for RST line failed"); - } - -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - switch (panel_dev_config->color_space) - { - case ESP_LCD_COLOR_SPACE_RGB: - jd9853->madctl_val = 0; - break; - case ESP_LCD_COLOR_SPACE_BGR: - jd9853->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported color space"); - break; - } -#else - switch (panel_dev_config->rgb_endian) - { - case LCD_RGB_ENDIAN_RGB: - jd9853->madctl_val = 0; - break; - case LCD_RGB_ENDIAN_BGR: - jd9853->madctl_val |= LCD_CMD_BGR_BIT; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported rgb endian"); - break; - } -#endif - - switch (panel_dev_config->bits_per_pixel) - { - case 16: // RGB565 - jd9853->colmod_val = 0x55; - jd9853->fb_bits_per_pixel = 16; - break; - case 18: // RGB666 - jd9853->colmod_val = 0x66; - // each color component (R/G/B) should occupy the 6 high bits of a byte, which means 3 full bytes are required for a pixel - jd9853->fb_bits_per_pixel = 24; - break; - default: - ESP_GOTO_ON_FALSE(false, ESP_ERR_NOT_SUPPORTED, err, TAG, "unsupported pixel width"); - break; - } - - jd9853->io = io; - jd9853->reset_gpio_num = panel_dev_config->reset_gpio_num; - jd9853->reset_level = panel_dev_config->flags.reset_active_high; - if (panel_dev_config->vendor_config) - { - jd9853->init_cmds = ((jd9853_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds; - jd9853->init_cmds_size = ((jd9853_vendor_config_t *)panel_dev_config->vendor_config)->init_cmds_size; - } - jd9853->base.del = panel_jd9853_del; - jd9853->base.reset = panel_jd9853_reset; - jd9853->base.init = panel_jd9853_init; - jd9853->base.draw_bitmap = panel_jd9853_draw_bitmap; - jd9853->base.invert_color = panel_jd9853_invert_color; - jd9853->base.set_gap = panel_jd9853_set_gap; - jd9853->base.mirror = panel_jd9853_mirror; - jd9853->base.swap_xy = panel_jd9853_swap_xy; -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - jd9853->base.disp_off = panel_jd9853_disp_on_off; -#else - jd9853->base.disp_on_off = panel_jd9853_disp_on_off; -#endif - *ret_panel = &(jd9853->base); - ESP_LOGD(TAG, "new jd9853 panel @%p", jd9853); - - // ESP_LOGI(TAG, "LCD panel create success, version: %d.%d.%d", ESP_LCD_jd9853_VER_MAJOR, ESP_LCD_jd9853_VER_MINOR, - // ESP_LCD_jd9853_VER_PATCH); - - return ESP_OK; - -err: - if (jd9853) - { - if (panel_dev_config->reset_gpio_num >= 0) - { - gpio_reset_pin(panel_dev_config->reset_gpio_num); - } - free(jd9853); - } - return ret; -} - -static esp_err_t panel_jd9853_del(esp_lcd_panel_t *panel) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - - if (jd9853->reset_gpio_num >= 0) - { - gpio_reset_pin(jd9853->reset_gpio_num); - } - ESP_LOGD(TAG, "del jd9853 panel @%p", jd9853); - free(jd9853); - return ESP_OK; -} - -static esp_err_t panel_jd9853_reset(esp_lcd_panel_t *panel) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - - // perform hardware reset - if (jd9853->reset_gpio_num >= 0) - { - gpio_set_level(jd9853->reset_gpio_num, jd9853->reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - gpio_set_level(jd9853->reset_gpio_num, !jd9853->reset_level); - vTaskDelay(pdMS_TO_TICKS(10)); - } - else - { // perform software reset - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SWRESET, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(20)); // spec, wait at least 5ms before sending new command - } - - return ESP_OK; -} - -typedef struct -{ - uint8_t cmd; - uint8_t data[16]; - uint8_t data_bytes; // Length of data in above data array; 0xFF = end of cmds. -} lcd_init_cmd_t; - -// static const jd9853_lcd_init_cmd_t vendor_specific_init_default[] = { -// // {cmd, { data }, data_size, delay_ms} -// /* Power contorl B, power control = 0, DC_ENA = 1 */ -// {0xCF, (uint8_t []){0x00, 0xAA, 0XE0}, 3, 0}, -// /* Power on sequence control, -// * cp1 keeps 1 frame, 1st frame enable -// * vcl = 0, ddvdh=3, vgh=1, vgl=2 -// * DDVDH_ENH=1 -// */ -// {0xED, (uint8_t []){0x67, 0x03, 0X12, 0X81}, 4, 0}, -// /* Driver timing control A, -// * non-overlap=default +1 -// * EQ=default - 1, CR=default -// * pre-charge=default - 1 -// */ -// {0xE8, (uint8_t []){0x8A, 0x01, 0x78}, 3, 0}, -// /* Power control A, Vcore=1.6V, DDVDH=5.6V */ -// {0xCB, (uint8_t []){0x39, 0x2C, 0x00, 0x34, 0x02}, 5, 0}, -// /* Pump ratio control, DDVDH=2xVCl */ -// {0xF7, (uint8_t []){0x20}, 1, 0}, - -// {0xF7, (uint8_t []){0x20}, 1, 0}, -// /* Driver timing control, all=0 unit */ -// {0xEA, (uint8_t []){0x00, 0x00}, 2, 0}, -// /* Power control 1, GVDD=4.75V */ -// {0xC0, (uint8_t []){0x23}, 1, 0}, -// /* Power control 2, DDVDH=VCl*2, VGH=VCl*7, VGL=-VCl*3 */ -// {0xC1, (uint8_t []){0x11}, 1, 0}, -// /* VCOM control 1, VCOMH=4.025V, VCOML=-0.950V */ -// {0xC5, (uint8_t []){0x43, 0x4C}, 2, 0}, -// /* VCOM control 2, VCOMH=VMH-2, VCOML=VML-2 */ -// {0xC7, (uint8_t []){0xA0}, 1, 0}, -// /* Frame rate control, f=fosc, 70Hz fps */ -// {0xB1, (uint8_t []){0x00, 0x1B}, 2, 0}, -// /* Enable 3G, disabled */ -// {0xF2, (uint8_t []){0x00}, 1, 0}, -// /* Gamma set, curve 1 */ -// {0x26, (uint8_t []){0x01}, 1, 0}, -// /* Positive gamma correction */ -// {0xE0, (uint8_t []){0x1F, 0x36, 0x36, 0x3A, 0x0C, 0x05, 0x4F, 0X87, 0x3C, 0x08, 0x11, 0x35, 0x19, 0x13, 0x00}, 15, 0}, -// /* Negative gamma correction */ -// {0xE1, (uint8_t []){0x00, 0x09, 0x09, 0x05, 0x13, 0x0A, 0x30, 0x78, 0x43, 0x07, 0x0E, 0x0A, 0x26, 0x2C, 0x1F}, 15, 0}, -// /* Entry mode set, Low vol detect disabled, normal display */ -// {0xB7, (uint8_t []){0x07}, 1, 0}, -// /* Display function control */ -// {0xB6, (uint8_t []){0x08, 0x82, 0x27}, 3, 0}, -// }; - -static const jd9853_lcd_init_cmd_t vendor_specific_init_default[] = { - {0x11, (uint8_t []){ 0x00 }, 0, 120}, - {0xDF, (uint8_t[]){0x98, 0x53}, 2, 0}, - {0xDF, (uint8_t[]){0x98, 0x53}, 2, 0}, - {0xB2, (uint8_t[]){0x23}, 1, 0}, - {0xB7, (uint8_t[]){0x00, 0x47, 0x00, 0x6F}, 4, 0}, - {0xBB, (uint8_t[]){0x1C, 0x1A, 0x55, 0x73, 0x63, 0xF0}, 6, 0}, - {0xC0, (uint8_t[]){0x44, 0xA4}, 2, 0}, - {0xC1, (uint8_t[]){0x16}, 1, 0}, - {0xC3, (uint8_t[]){0x7D, 0x07, 0x14, 0x06, 0xCF, 0x71, 0x72, 0x77}, 8, 0}, - {0xC4, (uint8_t[]){0x00, 0x00, 0xA0, 0x79, 0x0B, 0x0A, 0x16, 0x79, 0x0B, 0x0A, 0x16, 0x82}, 12, 0}, // 00=60Hz 06=57Hz 08=51Hz, LN=320 Line - {0xC8, (uint8_t[]){0x3F, 0x32, 0x29, 0x29, 0x27, 0x2B, 0x27, 0x28, 0x28, 0x26, 0x25, 0x17, 0x12, 0x0D, 0x04, 0x00, 0x3F, 0x32, 0x29, 0x29, 0x27, 0x2B, 0x27, 0x28, 0x28, 0x26, 0x25, 0x17, 0x12, 0x0D, 0x04, 0x00}, 32, 0}, // SET_R_GAMMA - {0xD0, (uint8_t[]){0x04, 0x06, 0x6B, 0x0F, 0x00}, 5, 0}, - {0xD7, (uint8_t[]){0x00, 0x30}, 2, 0}, - {0xE6, (uint8_t[]){0x14}, 1, 0}, - {0xDE, (uint8_t[]){0x01}, 1, 0}, - {0xB7, (uint8_t[]){0x03, 0x13, 0xEF, 0x35, 0x35}, 5, 0}, - {0xC1, (uint8_t[]){0x14, 0x15, 0xC0}, 3, 0}, - {0xC2, (uint8_t[]){0x06, 0x3A}, 2, 0}, - {0xC4, (uint8_t[]){0x72, 0x12}, 2, 0}, - {0xBE, (uint8_t[]){0x00}, 1, 0}, - {0xDE, (uint8_t[]){0x02}, 1, 0}, - {0xE5, (uint8_t[]){0x00, 0x02, 0x00}, 3, 0}, - {0xE5, (uint8_t[]){0x01, 0x02, 0x00}, 3, 0}, - {0xDE, (uint8_t[]){0x00}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 1, 0}, - {0x3A, (uint8_t[]){0x05}, 1, 0}, // 06=RGB666;05=RGB565 - {0x2A, (uint8_t[]){0x00, 0x22, 0x00, 0xCD}, 4, 0}, // Start_X=34, End_X=205 - {0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0x3F}, 4, 0}, // Start_Y=0, End_Y=319 - {0xDE, (uint8_t[]){0x02}, 1, 0}, - {0xE5, (uint8_t[]){0x00, 0x02, 0x00}, 3, 0}, - {0xDE, (uint8_t[]){0x00}, 1, 0}, - {0x29, (uint8_t []){ 0x00 }, 0, 0}, -}; - -static esp_err_t panel_jd9853_init(esp_lcd_panel_t *panel) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - - // LCD goes into sleep mode and display will be turned off after power on reset, exit sleep mode first - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_SLPOUT, NULL, 0), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){ - jd9853->madctl_val, - }, - 1), - TAG, "send command failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]){ - jd9853->colmod_val, - }, - 1), - TAG, "send command failed"); - - const jd9853_lcd_init_cmd_t *init_cmds = NULL; - uint16_t init_cmds_size = 0; - if (jd9853->init_cmds) - { - init_cmds = jd9853->init_cmds; - init_cmds_size = jd9853->init_cmds_size; - } - else - { - init_cmds = vendor_specific_init_default; - init_cmds_size = sizeof(vendor_specific_init_default) / sizeof(jd9853_lcd_init_cmd_t); - } - - bool is_cmd_overwritten = false; - for (int i = 0; i < init_cmds_size; i++) - { - // Check if the command has been used or conflicts with the internal - switch (init_cmds[i].cmd) - { - case LCD_CMD_MADCTL: - is_cmd_overwritten = true; - jd9853->madctl_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - case LCD_CMD_COLMOD: - is_cmd_overwritten = true; - jd9853->colmod_val = ((uint8_t *)init_cmds[i].data)[0]; - break; - default: - is_cmd_overwritten = false; - break; - } - - if (is_cmd_overwritten) - { - ESP_LOGW(TAG, "The %02Xh command has been used and will be overwritten by external initialization sequence", init_cmds[i].cmd); - } - - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, init_cmds[i].cmd, init_cmds[i].data, init_cmds[i].data_bytes), TAG, "send command failed"); - vTaskDelay(pdMS_TO_TICKS(init_cmds[i].delay_ms)); - } - ESP_LOGD(TAG, "send init commands success"); - - return ESP_OK; -} - -static esp_err_t panel_jd9853_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position"); - esp_lcd_panel_io_handle_t io = jd9853->io; - - x_start += jd9853->x_gap; - x_end += jd9853->x_gap; - y_start += jd9853->y_gap; - y_end += jd9853->y_gap; - - // define an area of frame memory where MCU can access - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]){ - (x_start >> 8) & 0xFF, - x_start & 0xFF, - ((x_end - 1) >> 8) & 0xFF, - (x_end - 1) & 0xFF, - }, - 4), - TAG, "send command failed"); - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]){ - (y_start >> 8) & 0xFF, - y_start & 0xFF, - ((y_end - 1) >> 8) & 0xFF, - (y_end - 1) & 0xFF, - }, - 4), - TAG, "send command failed"); - // transfer frame buffer - size_t len = (x_end - x_start) * (y_end - y_start) * jd9853->fb_bits_per_pixel / 8; - esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len); - - return ESP_OK; -} - -static esp_err_t panel_jd9853_invert_color(esp_lcd_panel_t *panel, bool invert_color_data) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - int command = 0; - if (invert_color_data) - { - command = LCD_CMD_INVON; - } - else - { - command = LCD_CMD_INVOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_jd9853_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - if (mirror_x) - { - jd9853->madctl_val |= LCD_CMD_MX_BIT; - } - else - { - jd9853->madctl_val &= ~LCD_CMD_MX_BIT; - } - if (mirror_y) - { - jd9853->madctl_val |= LCD_CMD_MY_BIT; - } - else - { - jd9853->madctl_val &= ~LCD_CMD_MY_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){jd9853->madctl_val}, 1), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_jd9853_swap_xy(esp_lcd_panel_t *panel, bool swap_axes) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - if (swap_axes) - { - jd9853->madctl_val |= LCD_CMD_MV_BIT; - } - else - { - jd9853->madctl_val &= ~LCD_CMD_MV_BIT; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]){jd9853->madctl_val}, 1), TAG, "send command failed"); - return ESP_OK; -} - -static esp_err_t panel_jd9853_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - jd9853->x_gap = x_gap; - jd9853->y_gap = y_gap; - return ESP_OK; -} - -static esp_err_t panel_jd9853_disp_on_off(esp_lcd_panel_t *panel, bool on_off) -{ - jd9853_panel_t *jd9853 = __containerof(panel, jd9853_panel_t, base); - esp_lcd_panel_io_handle_t io = jd9853->io; - int command = 0; - -#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) - on_off = !on_off; -#endif - - if (on_off) - { - command = LCD_CMD_DISPON; - } - else - { - command = LCD_CMD_DISPOFF; - } - ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG, "send command failed"); - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.h deleted file mode 100644 index 487e7497..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-audio-board/esp_lcd_jd9853.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: Apache-2.0 - */ -/** - * @file - * @brief ESP LCD: jd9853 - */ - -#pragma once - -#include "hal/spi_ll.h" -#include "esp_lcd_panel_vendor.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief LCD panel initialization commands. - * - */ -typedef struct { - int cmd; /* Board Type -> Waveshare ESP32-S3-ePaper-1.54 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc deleted file mode 100644 index 812d19f5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.cc +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include -#include -#include "board_power_bsp.h" - -void BoardPowerBsp::PowerLedTask(void *arg) { - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << GPIO_NUM_3); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - for (;;) { - gpio_set_level(GPIO_NUM_3, 0); - vTaskDelay(pdMS_TO_TICKS(200)); - gpio_set_level(GPIO_NUM_3, 1); - // 不需要频繁闪烁,间隔指示效果更好 - vTaskDelay(pdMS_TO_TICKS(4800)); - } -} - -BoardPowerBsp::BoardPowerBsp(int epdPowerPin, int audioPowerPin, int vbatPowerPin) : epdPowerPin_(epdPowerPin), audioPowerPin_(audioPowerPin), vbatPowerPin_(vbatPowerPin) { - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << epdPowerPin_) | (0x1ULL << audioPowerPin_) | (0x1ULL << vbatPowerPin_); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - xTaskCreatePinnedToCore(PowerLedTask, "PowerLedTask", 3 * 1024, NULL, 2, NULL, 0); -} - -BoardPowerBsp::~BoardPowerBsp() { -} - -void BoardPowerBsp::PowerEpdOn() { - gpio_set_level((gpio_num_t) epdPowerPin_, 0); -} - -void BoardPowerBsp::PowerEpdOff() { - gpio_set_level((gpio_num_t) epdPowerPin_, 1); -} - -void BoardPowerBsp::PowerAudioOn() { - gpio_set_level((gpio_num_t) audioPowerPin_, 0); -} - -void BoardPowerBsp::PowerAudioOff() { - gpio_set_level((gpio_num_t) audioPowerPin_, 1); -} - -void BoardPowerBsp::VbatPowerOn() { - gpio_set_level((gpio_num_t) vbatPowerPin_, 1); -} - -void BoardPowerBsp::VbatPowerOff() { - gpio_set_level((gpio_num_t) vbatPowerPin_, 0); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h deleted file mode 100644 index 1301168e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/board_power_bsp.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __BOARD_POWER_BSP_H__ -#define __BOARD_POWER_BSP_H__ - -class BoardPowerBsp { -private: - const int epdPowerPin_; - const int audioPowerPin_; - const int vbatPowerPin_; - - static void PowerLedTask(void *arg); - -public: - BoardPowerBsp(int epdPowerPin, int audioPowerPin, int vbatPowerPin); - ~BoardPowerBsp(); - void PowerEpdOn(); - void PowerEpdOff(); - void PowerAudioOn(); - void PowerAudioOff(); - void VbatPowerOn(); - void VbatPowerOff(); -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.h deleted file mode 100644 index 898f0ed4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_38 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_45 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VBAT_PWR_GPIO GPIO_NUM_18 - -/*EPD port Init*/ -#define EPD_SPI_NUM SPI3_HOST - -#define EPD_DC_PIN GPIO_NUM_10 -#define EPD_CS_PIN GPIO_NUM_11 -#define EPD_SCK_PIN GPIO_NUM_12 -#define EPD_MOSI_PIN GPIO_NUM_13 -#define EPD_RST_PIN GPIO_NUM_9 -#define EPD_BUSY_PIN GPIO_NUM_8 - -#define EXAMPLE_LCD_WIDTH 200 -#define EXAMPLE_LCD_HEIGHT 200 - -/*DEV POWER init*/ -#define EPD_PWR_PIN GPIO_NUM_6 -#define Audio_PWR_PIN GPIO_NUM_42 -#define VBAT_PWR_PIN GPIO_NUM_17 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.json deleted file mode 100644 index 11a0e67b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-epaper-1.54", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc deleted file mode 100644 index 1169c9ef..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.cc +++ /dev/null @@ -1,404 +0,0 @@ -#include -#include -#include -#include -#include -#include "custom_lcd_display.h" -#include "board.h" -#include "config.h" -#include "esp_lvgl_port.h" -#include "settings.h" - -#define TAG "CustomLcdDisplay" - -#define BYTES_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565)) -#define BUFF_SIZE (EXAMPLE_LCD_WIDTH * EXAMPLE_LCD_HEIGHT * BYTES_PER_PIXEL) - -const uint8_t WF_Full_1IN54[159] = -{ - 0x80,0x48,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x40,0x48,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x80,0x48,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x40,0x48,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0xA,0x0,0x0,0x0,0x0,0x0,0x0, - 0x8,0x1,0x0,0x8,0x1,0x0,0x2, - 0xA,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, - 0x22,0x17,0x41,0x0,0x32,0x20 -}; - -const uint8_t WF_PARTIAL_1IN54_0[159] = -{ - 0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0xF,0x0,0x0,0x0,0x0,0x0,0x0, - 0x1,0x1,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x0,0x0,0x0,0x0,0x0,0x0,0x0, - 0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, - 0x02,0x17,0x41,0xB0,0x32,0x28, -}; - -void CustomLcdDisplay::lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) { - assert(disp != NULL); - CustomLcdDisplay *driver = (CustomLcdDisplay *) lv_display_get_user_data(disp); - uint16_t *buffer = (uint16_t *) color_p; - driver->EPD_Clear(); - for (int y = area->y1; y <= area->y2; y++) { - for (int x = area->x1; x <= area->x2; x++) { - uint8_t color = (*buffer < 0x7fff) ? DRIVER_COLOR_BLACK : DRIVER_COLOR_WHITE; - driver->EPD_DrawColorPixel(x, y, color); - buffer++; - } - } - driver->EPD_DisplayPart(); - lv_disp_flush_ready(disp); -} - -CustomLcdDisplay::CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy, custom_lcd_spi_t _lcd_spi_data) : - LcdDisplay(panel_io, panel, width, height), - lcd_spi_data(_lcd_spi_data), - Width(width), Height(height) { - - ESP_LOGI(TAG, "Initialize SPI"); - spi_port_init(); - spi_gpio_init(); - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 2; - port_cfg.timer_period_ms = 50; - lvgl_port_init(&port_cfg); - lvgl_port_lock(0); - - buffer = (uint8_t *) heap_caps_malloc(lcd_spi_data.buffer_len, MALLOC_CAP_SPIRAM); - assert(buffer); - display_ = lv_display_create(width, height); /* 以水平和垂直分辨率(像素)进行基本初始化 */ - lv_display_set_flush_cb(display_, lvgl_flush_cb); - lv_display_set_user_data(display_, this); - - uint8_t *buffer_1 = NULL; - buffer_1 = (uint8_t *) heap_caps_malloc(BUFF_SIZE, MALLOC_CAP_SPIRAM); - assert(buffer_1); - lv_display_set_buffers(display_, buffer_1, NULL, BUFF_SIZE, LV_DISPLAY_RENDER_MODE_FULL); - - ESP_LOGI(TAG, "EPD init"); - EPD_Init(); - EPD_Clear(); - EPD_Display(); - EPD_DisplayPartBaseImage(); - EPD_Init_Partial(); // 局部刷新初始化 - - lvgl_port_unlock(); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - ESP_LOGI(TAG, "ui start"); - - SetupUI(); -} - -CustomLcdDisplay::~CustomLcdDisplay() { - -} - -void CustomLcdDisplay::spi_gpio_init() { - int rst = lcd_spi_data.rst; - int cs = lcd_spi_data.cs; - int dc = lcd_spi_data.dc; - int busy = lcd_spi_data.busy; - - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << rst) | (0x1ULL << dc) | (0x1ULL << cs); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - - gpio_conf.mode = GPIO_MODE_INPUT; - gpio_conf.pin_bit_mask = (0x1ULL << busy); - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - - set_rst_1(); -} - -void CustomLcdDisplay::spi_port_init() { - int mosi = lcd_spi_data.mosi; - int scl = lcd_spi_data.scl; - int spi_host = lcd_spi_data.spi_host; - esp_err_t ret; - spi_bus_config_t buscfg = {}; - buscfg.miso_io_num = -1; - buscfg.mosi_io_num = mosi; - buscfg.sclk_io_num = scl; - buscfg.quadwp_io_num = -1; - buscfg.quadhd_io_num = -1; - buscfg.max_transfer_sz = Width * Height; - - spi_device_interface_config_t devcfg = {}; - devcfg.spics_io_num = -1; - devcfg.clock_speed_hz = 40 * 1000 * 1000; // Clock out at 10 MHz - devcfg.mode = 0; // SPI mode 0 - devcfg.queue_size = 7; // We want to be able to queue 7 transactions at a time - - ret = spi_bus_initialize((spi_host_device_t) spi_host, &buscfg, SPI_DMA_CH_AUTO); - ESP_ERROR_CHECK(ret); - ret = spi_bus_add_device((spi_host_device_t) spi_host, &devcfg, &spi); - ESP_ERROR_CHECK(ret); -} - -void CustomLcdDisplay::read_busy() { - int busy = lcd_spi_data.busy; - while (gpio_get_level((gpio_num_t) busy) == 1) { - vTaskDelay(pdMS_TO_TICKS(5)); // LOW: idle, HIGH: busy - } -} - -void CustomLcdDisplay::SPI_SendByte(uint8_t data) { - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8; - t.tx_buffer = &data; - ret = spi_device_polling_transmit(spi, &t); // Transmit! - assert(ret == ESP_OK); // Should have had no issues. -} - -void CustomLcdDisplay::EPD_SendData(uint8_t data) { - set_dc_1(); - set_cs_0(); - SPI_SendByte(data); - set_cs_1(); -} - -void CustomLcdDisplay::EPD_SendCommand(uint8_t command) { - set_dc_0(); - set_cs_0(); - SPI_SendByte(command); - set_cs_1(); -} - -void CustomLcdDisplay::writeBytes(uint8_t *buffer, int len) { - set_dc_1(); - set_cs_0(); - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8 * len; - t.tx_buffer = buffer; - ret = spi_device_polling_transmit(spi, &t); // Transmit! - assert(ret == ESP_OK); - set_cs_1(); -} - -void CustomLcdDisplay::writeBytes(const uint8_t *buffer, int len) { - set_dc_1(); - set_cs_0(); - esp_err_t ret; - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 8 * len; - t.tx_buffer = buffer; - ret = spi_device_polling_transmit(spi, &t); // Transmit! - assert(ret == ESP_OK); - set_cs_1(); -} - -void CustomLcdDisplay::EPD_SetWindows(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend) { - EPD_SendCommand(0x44); // SET_RAM_X_ADDRESS_START_END_POSITION - EPD_SendData((Xstart >> 3) & 0xFF); - EPD_SendData((Xend >> 3) & 0xFF); - - EPD_SendCommand(0x45); // SET_RAM_Y_ADDRESS_START_END_POSITION - EPD_SendData(Ystart & 0xFF); - EPD_SendData((Ystart >> 8) & 0xFF); - EPD_SendData(Yend & 0xFF); - EPD_SendData((Yend >> 8) & 0xFF); -} - -void CustomLcdDisplay::EPD_SetCursor(uint16_t Xstart, uint16_t Ystart) { - EPD_SendCommand(0x4E); // SET_RAM_X_ADDRESS_COUNTER - EPD_SendData(Xstart & 0xFF); - - EPD_SendCommand(0x4F); // SET_RAM_Y_ADDRESS_COUNTER - EPD_SendData(Ystart & 0xFF); - EPD_SendData((Ystart >> 8) & 0xFF); -} - -void CustomLcdDisplay::EPD_SetLut(const uint8_t *lut) { - EPD_SendCommand(0x32); - writeBytes(lut, 153); - read_busy(); - - EPD_SendCommand(0x3f); - EPD_SendData(lut[153]); - - EPD_SendCommand(0x03); - EPD_SendData(lut[154]); - - EPD_SendCommand(0x04); - EPD_SendData(lut[155]); - EPD_SendData(lut[156]); - EPD_SendData(lut[157]); - - EPD_SendCommand(0x2c); - EPD_SendData(lut[158]); -} - -void CustomLcdDisplay::EPD_TurnOnDisplay() { - EPD_SendCommand(0x22); - EPD_SendData(0xc7); - EPD_SendCommand(0x20); - read_busy(); -} - -void CustomLcdDisplay::EPD_TurnOnDisplayPart() { - EPD_SendCommand(0x22); - EPD_SendData(0xcf); - EPD_SendCommand(0x20); - read_busy(); -} - -void CustomLcdDisplay::EPD_Init() { - set_rst_1(); - vTaskDelay(pdMS_TO_TICKS(50)); - set_rst_0(); - vTaskDelay(pdMS_TO_TICKS(20)); - set_rst_1(); - vTaskDelay(pdMS_TO_TICKS(50)); - - read_busy(); - EPD_SendCommand(0x12); // SWRESET - read_busy(); - - EPD_SendCommand(0x01); // Driver output control - EPD_SendData(0xC7); - EPD_SendData(0x00); - EPD_SendData(0x01); - - EPD_SendCommand(0x11); // data entry mode - EPD_SendData(0x01); - - EPD_SetWindows(0, Width - 1, Height - 1, 0); - - EPD_SendCommand(0x3C); // BorderWavefrom - EPD_SendData(0x01); - - EPD_SendCommand(0x18); - EPD_SendData(0x80); - - EPD_SendCommand(0x22); // Load Temperature and waveform setting. - EPD_SendData(0XB1); - EPD_SendCommand(0x20); - - EPD_SetCursor(0, Height - 1); - read_busy(); - - EPD_SetLut(WF_Full_1IN54); -} - -void CustomLcdDisplay::EPD_Clear() { - int buffer_len = lcd_spi_data.buffer_len; - memset(buffer, 0xff, buffer_len); -} - -void CustomLcdDisplay::EPD_Display() { - int buffer_len = lcd_spi_data.buffer_len; - EPD_SendCommand(0x24); - assert(buffer); - writeBytes(buffer, buffer_len); - EPD_TurnOnDisplay(); -} - -void CustomLcdDisplay::EPD_DisplayPartBaseImage() { - int buffer_len = lcd_spi_data.buffer_len; - EPD_SendCommand(0x24); - assert(buffer); - writeBytes(buffer, buffer_len); - EPD_SendCommand(0x26); - writeBytes(buffer, buffer_len); - EPD_TurnOnDisplay(); -} - -void CustomLcdDisplay::EPD_Init_Partial() { - set_rst_1(); - vTaskDelay(pdMS_TO_TICKS(50)); - set_rst_0(); - vTaskDelay(pdMS_TO_TICKS(20)); - set_rst_1(); - vTaskDelay(pdMS_TO_TICKS(50)); - - read_busy(); - - EPD_SetLut(WF_PARTIAL_1IN54_0); - - EPD_SendCommand(0x37); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x40); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x00); - EPD_SendData(0x00); - - EPD_SendCommand(0x3C); // BorderWavefrom - EPD_SendData(0x80); - - EPD_SendCommand(0x22); - EPD_SendData(0xc0); - EPD_SendCommand(0x20); - read_busy(); -} - -void CustomLcdDisplay::EPD_DisplayPart() { - EPD_SendCommand(0x24); - assert(buffer); - writeBytes(buffer, 5000); - EPD_TurnOnDisplayPart(); -} - -void CustomLcdDisplay::EPD_DrawColorPixel(uint16_t x, uint16_t y, uint8_t color) { - if (x >= Width || y >= Height) { - ESP_LOGE("EPD", "Out of bounds pixel: (%d,%d)", x, y); - return; - } - - uint16_t index = y * 25 + (x >> 3); - uint8_t bit = 7 - (x & 0x07); - if (color == DRIVER_COLOR_WHITE) { - buffer[index] |= (0x01 << bit); - } else { - buffer[index] &= ~(0x01 << bit); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h deleted file mode 100644 index 7a8f03ee..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/custom_lcd_display.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef __CUSTOM_LCD_DISPLAY_H__ -#define __CUSTOM_LCD_DISPLAY_H__ - -#include -#include "lcd_display.h" - -/* Display color */ -typedef enum { - DRIVER_COLOR_WHITE = 0xff, - DRIVER_COLOR_BLACK = 0x00, - FONT_BACKGROUND = DRIVER_COLOR_WHITE, -}COLOR_IMAGE; - -typedef struct { - uint8_t cs; - uint8_t dc; - uint8_t rst; - uint8_t busy; - uint8_t mosi; - uint8_t scl; - int spi_host; - int buffer_len; -}custom_lcd_spi_t; - - -class CustomLcdDisplay : public LcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy,custom_lcd_spi_t _lcd_spi_data); - ~CustomLcdDisplay(); - - void EPD_Init(); /* 墨水屏初始化 */ - void EPD_Clear(); /* 清空屏幕 */ - void EPD_Display(); /* 刷buffer到墨水屏 */ - - /*快速刷新*/ - void EPD_DisplayPartBaseImage(); - void EPD_Init_Partial(); - void EPD_DisplayPart(); - void EPD_DrawColorPixel(uint16_t x, uint16_t y,uint8_t color); - -private: - const custom_lcd_spi_t lcd_spi_data; - const int Width; - const int Height; - spi_device_handle_t spi; - uint8_t *buffer = NULL; - - static void lvgl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p); - - void spi_gpio_init(); - void spi_port_init(); - void read_busy(); - - void set_cs_1(){gpio_set_level((gpio_num_t)lcd_spi_data.cs,1);} - void set_cs_0(){gpio_set_level((gpio_num_t)lcd_spi_data.cs,0);} - void set_dc_1(){gpio_set_level((gpio_num_t)lcd_spi_data.dc,1);} - void set_dc_0(){gpio_set_level((gpio_num_t)lcd_spi_data.dc,0);} - void set_rst_1(){gpio_set_level((gpio_num_t)lcd_spi_data.rst,1);} - void set_rst_0(){gpio_set_level((gpio_num_t)lcd_spi_data.rst,0);} - - void SPI_SendByte(uint8_t data); - void EPD_SendData(uint8_t data); - void EPD_SendCommand(uint8_t command); - void writeBytes(uint8_t *buffer,int len); - void writeBytes(const uint8_t *buffer, int len); - void EPD_SetWindows(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend); - void EPD_SetCursor(uint16_t Xstart, uint16_t Ystart); - void EPD_SetLut(const uint8_t *lut); - void EPD_TurnOnDisplay(); - void EPD_TurnOnDisplayPart(); -}; - -#endif // __CUSTOM_LCD_DISPLAY_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc deleted file mode 100644 index f801d27e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-epaper-1.54/waveshare-s3-epaper-1.54.cc +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include "application.h" -#include "button.h" -#include "codecs/es8311_audio_codec.h" -#include "config.h" -#include "wifi_board.h" -#include "board_power_bsp.h" -#include "custom_lcd_display.h" -#include "lvgl.h" -#include "mcp_server.h" - -#define TAG "waveshare_epaper_1_54" - -class CustomBoard : public WifiBoard { - private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button pwr_button_; - CustomLcdDisplay *display_; - BoardPowerBsp *power_; - adc_oneshot_unit_handle_t adc1_handle; - adc_cali_handle_t cali_handle; - - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = {}; - i2c_bus_cfg.i2c_port = (i2c_port_t) 0; - i2c_bus_cfg.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN; - i2c_bus_cfg.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN; - i2c_bus_cfg.clk_source = I2C_CLK_SRC_DEFAULT; - i2c_bus_cfg.glitch_ignore_cnt = 7; - i2c_bus_cfg.intr_priority = 0; - i2c_bus_cfg.trans_queue_depth = 0; - i2c_bus_cfg.flags.enable_internal_pullup = 1; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto &app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - pwr_button_.OnLongPress([this]() { - GetDisplay()->SetChatMessage("system", "OFF"); - vTaskDelay(pdMS_TO_TICKS(1000)); - power_->PowerAudioOff(); - power_->PowerEpdOff(); - power_->VbatPowerOff(); - }); - } - - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(), [this](const PropertyList &) -> ReturnValue { - EnterWifiConfigMode(); - return true; - }); - } - - void InitializeLcdDisplay() { - custom_lcd_spi_t lcd_spi_data = {}; - lcd_spi_data.cs = EPD_CS_PIN; - lcd_spi_data.dc = EPD_DC_PIN; - lcd_spi_data.rst = EPD_RST_PIN; - lcd_spi_data.busy = EPD_BUSY_PIN; - lcd_spi_data.mosi = EPD_MOSI_PIN; - lcd_spi_data.scl = EPD_SCK_PIN; - lcd_spi_data.spi_host = EPD_SPI_NUM; - lcd_spi_data.buffer_len = 5000; - display_ = new CustomLcdDisplay(NULL, NULL, EXAMPLE_LCD_WIDTH, EXAMPLE_LCD_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY, lcd_spi_data); - } - - void Power_Init() { - power_ = new BoardPowerBsp(EPD_PWR_PIN, Audio_PWR_PIN, VBAT_PWR_PIN); - power_->VbatPowerOn(); - power_->PowerAudioOn(); - power_->PowerEpdOn(); - do { - vTaskDelay(pdMS_TO_TICKS(10)); - } while (!gpio_get_level(VBAT_PWR_GPIO)); - } - - uint16_t BatterygetVoltage(void) { - static bool initialized = false; - static adc_oneshot_unit_handle_t adc_handle; - static adc_cali_handle_t cali_handle = NULL; - if (!initialized) { - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - }; - adc_oneshot_new_unit(&init_config, &adc_handle); - - adc_oneshot_chan_cfg_t ch_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - adc_oneshot_config_channel(adc_handle, ADC_CHANNEL_3, &ch_config); - - adc_cali_curve_fitting_config_t cali_config = { - .unit_id = ADC_UNIT_1, - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - if (adc_cali_create_scheme_curve_fitting(&cali_config, &cali_handle) == ESP_OK) { - initialized = true; - } - } - - if (initialized) { - int raw_value = 0; - int raw_voltage = 0; - int voltage = 0; // mV - adc_oneshot_read(adc_handle, ADC_CHANNEL_3, &raw_value); - adc_cali_raw_to_voltage(cali_handle, raw_value, &raw_voltage); - voltage = raw_voltage * 2; - // ESP_LOGI(TAG, "voltage: %dmV", voltage); - return (uint16_t)voltage; - } - - return 0; - } - - uint8_t BatterygetPercent() { - int voltage = 0; - for (uint8_t i = 0; i < 10; i++) { - voltage += BatterygetVoltage(); - } - - voltage /= 10; - int percent = (-1 * voltage * voltage + 9016 * voltage - 19189000) / 10000; - percent = (percent > 100) ? 100 : (percent < 0) ? 0 : percent; - // ESP_LOGI(TAG, "voltage: %dmV, percentage: %d%%", voltage, percent); - return (uint8_t)percent; - } - - public: - CustomBoard() : boot_button_(BOOT_BUTTON_GPIO), pwr_button_(VBAT_PWR_GPIO) { - Power_Init(); - InitializeI2c(); - InitializeButtons(); - InitializeTools(); - InitializeLcdDisplay(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - charging = false; - discharging = !charging; - level = (int)BatterygetPercent(); - - return true; - } -}; - -DECLARE_BOARD(CustomBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/README.md deleted file mode 100644 index e69de29b..00000000 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.h deleted file mode 100644 index 47b6c711..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define ESP32_I2C_HOST I2C_NUM_0 -#define ESP32_LCD_HOST SPI3_HOST - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_13 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - - -#define RLCD_DC_PIN GPIO_NUM_5 -#define RLCD_CS_PIN GPIO_NUM_40 -#define RLCD_SCK_PIN GPIO_NUM_11 -#define RLCD_MOSI_PIN GPIO_NUM_12 -#define RLCD_RST_PIN GPIO_NUM_41 -#define RLCD_TE_PIN GPIO_NUM_6 - -#define RLCD_WIDTH 400 -#define RLCD_HEIGHT 300 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.json deleted file mode 100644 index 2f4bfc19..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-rlcd-4.2", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.cc deleted file mode 100644 index 668e27ca..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.cc +++ /dev/null @@ -1,339 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "custom_lcd_display.h" -#include "lcd_display.h" -#include "esp_lvgl_port.h" -#include "assets/lang_config.h" -#include "settings.h" -#include "config.h" -#include "board.h" - -void CustomLcdDisplay::Lvgl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p) -{ - assert(disp != NULL); - CustomLcdDisplay *Disp = (CustomLcdDisplay *)lv_display_get_user_data(disp); - uint16_t *buffer = (uint16_t *)color_p; - for(int y = area->y1; y <= area->y2; y++) - { - for(int x = area->x1; x <= area->x2; x++) - { - uint8_t color = (*buffer < 0x7fff) ? ColorBlack : ColorWhite; - Disp->RLCD_SetPixel(x,y,color); - buffer++; - } - } - Disp->RLCD_Display(); - lv_disp_flush_ready(disp); -} - -CustomLcdDisplay::CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, -esp_lcd_panel_handle_t panel, -int width, -int height, -int offset_x, -int offset_y, -bool mirror_x, -bool mirror_y, -bool swap_xy, -spi_display_config_t spiconfig, -spi_host_device_t spi_host) : LcdDisplay(panel_io, panel, width, height), -mosi_(spiconfig.mosi), -scl_(spiconfig.scl), -dc_(spiconfig.dc), -cs_(spiconfig.cs), -rst_(spiconfig.rst), -width_(width), -height_(height) -{ - ESP_LOGI(TAG, "Initialize SPI"); - esp_err_t ret; - spi_bus_config_t buscfg = {}; - int transfer = width_ * height_; - buscfg.miso_io_num = -1; - buscfg.mosi_io_num = mosi_; - buscfg.sclk_io_num = scl_; - buscfg.quadwp_io_num = -1; - buscfg.quadhd_io_num = -1; - buscfg.max_transfer_sz = transfer; - ret = spi_bus_initialize(spi_host, &buscfg, SPI_DMA_CH_AUTO); - ESP_ERROR_CHECK(ret); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.dc_gpio_num = dc_; - io_config.cs_gpio_num = cs_; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - io_config.spi_mode = 0; - io_config.trans_queue_depth = 7; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)spi_host, &io_config, &io_handle)); - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << rst_); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - Set_ResetIOLevel(1); - - DisplayLen = transfer >> 3; //(1byte 8ipex) - DispBuffer = (uint8_t *) heap_caps_malloc(DisplayLen, MALLOC_CAP_SPIRAM); - assert(DispBuffer); - PixelIndexLUT = (uint16_t (*)[300])heap_caps_malloc(transfer * sizeof(uint16_t), MALLOC_CAP_SPIRAM); - PixelBitLUT = (uint8_t (*)[300])heap_caps_malloc(transfer * sizeof(uint8_t), MALLOC_CAP_SPIRAM); - assert(PixelIndexLUT); - assert(PixelBitLUT); - if(width_ == 400) { - InitLandscapeLUT(); - } else { - InitPortraitLUT(); - } - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 2; - port_cfg.timer_period_ms = 50; - lvgl_port_init(&port_cfg); - lvgl_port_lock(0); - - display_ = lv_display_create(width, height); /* 以水平和垂直分辨率(像素)进行基本初始化 */ - lv_display_set_flush_cb(display_, Lvgl_flush_cb); - lv_display_set_user_data(display_, this); - size_t lvgl_buffer_size = LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565) * transfer; - uint8_t *lvgl_buffer1 = (uint8_t *) heap_caps_malloc(lvgl_buffer_size, MALLOC_CAP_SPIRAM); - assert(lvgl_buffer1); - lv_display_set_buffers(display_, lvgl_buffer1, NULL, lvgl_buffer_size, LV_DISPLAY_RENDER_MODE_PARTIAL); - - ESP_LOGI(TAG, "RLCD init"); - RLCD_Init(); - - lvgl_port_unlock(); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - ESP_LOGI(TAG, "ui start"); - - SetupUI(); -} - -CustomLcdDisplay::~CustomLcdDisplay() { -} - -void CustomLcdDisplay::InitPortraitLUT() { - uint16_t W4 = width_ >> 2; - for (uint16_t y = 0; y < height_; y++) - { - uint16_t byte_y = y >> 1; - uint8_t local_y = y & 1; - for (uint16_t x = 0; x < width_; x++) - { - uint16_t byte_x = x >> 2; - uint8_t local_x = x & 3; - - uint32_t index = byte_y * W4 + byte_x; - uint8_t bit = 7 - ((local_x << 1) | local_y); - - PixelIndexLUT[x][y] = index; - PixelBitLUT [x][y] = (1 << bit); - } - } -} - -void CustomLcdDisplay::InitLandscapeLUT() { - uint16_t H4 = height_ >> 2; - for (uint16_t y = 0; y < height_; y++) - { - uint16_t inv_y = height_ - 1 - y; - uint16_t block_y = inv_y >> 2; - uint8_t local_y = inv_y & 3; - for (uint16_t x = 0; x < width_; x++) - { - uint16_t byte_x = x >> 1; - uint8_t local_x = x & 1; - - uint32_t index = byte_x * H4 + block_y; - uint8_t bit = 7 - ((local_y << 1) | local_x); - - PixelIndexLUT[x][y] = index; - PixelBitLUT [x][y] = (1 << bit); - } - } -} - -void CustomLcdDisplay::Set_ResetIOLevel(uint8_t level) { - gpio_set_level((gpio_num_t) rst_, level ? 1 : 0); -} - -void CustomLcdDisplay::RLCD_SendCommand(uint8_t Reg) { - ESP_ERROR_CHECK(esp_lcd_panel_io_tx_param(io_handle, Reg, NULL, 0)); -} - -void CustomLcdDisplay::RLCD_SendData(uint8_t Data) { - ESP_ERROR_CHECK(esp_lcd_panel_io_tx_param(io_handle, -1, &Data, 1)); -} - -void CustomLcdDisplay::RLCD_Sendbuffera(uint8_t *Data, int len) { - ESP_ERROR_CHECK(esp_lcd_panel_io_tx_color(io_handle, -1, Data, len)); -} - -void CustomLcdDisplay::RLCD_Reset(void) { - Set_ResetIOLevel(1); - vTaskDelay(pdMS_TO_TICKS(50)); - Set_ResetIOLevel(0); - vTaskDelay(pdMS_TO_TICKS(20)); - Set_ResetIOLevel(1); - vTaskDelay(pdMS_TO_TICKS(50)); -} - -void CustomLcdDisplay::RLCD_ColorClear(uint8_t color) { - memset(DispBuffer, color, DisplayLen); -} - -void CustomLcdDisplay::RLCD_Init() { - RLCD_Reset(); - - RLCD_SendCommand(0xD6); // NVM Load Control - RLCD_SendData(0x17); - RLCD_SendData(0x02); - - RLCD_SendCommand(0xD1); //Booster Enable - RLCD_SendData(0x01); - - RLCD_SendCommand(0xC0); //Gate Voltage Control - RLCD_SendData(0x11); - RLCD_SendData(0x04); - - RLCD_SendCommand(0xC1); //VSHP Setting - RLCD_SendData(0x69); - RLCD_SendData(0x69); - RLCD_SendData(0x69); - RLCD_SendData(0x69); - - RLCD_SendCommand(0xC2); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - - RLCD_SendCommand(0xC4); - RLCD_SendData(0x4B); - RLCD_SendData(0x4B); - RLCD_SendData(0x4B); - RLCD_SendData(0x4B); - - RLCD_SendCommand(0xC5); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - RLCD_SendData(0x19); - - RLCD_SendCommand(0xD8); - RLCD_SendData(0x80); - RLCD_SendData(0xE9); - - RLCD_SendCommand(0xB2); - RLCD_SendData(0x02); - - RLCD_SendCommand(0xB3); - RLCD_SendData(0xE5); - RLCD_SendData(0xF6); - RLCD_SendData(0x05); - RLCD_SendData(0x46); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x76); - RLCD_SendData(0x45); - - RLCD_SendCommand(0xB4); - RLCD_SendData(0x05); - RLCD_SendData(0x46); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x77); - RLCD_SendData(0x76); - RLCD_SendData(0x45); - - RLCD_SendCommand(0x62); - RLCD_SendData(0x32); - RLCD_SendData(0x03); - RLCD_SendData(0x1F); - - RLCD_SendCommand(0xB7); - RLCD_SendData(0x13); - - RLCD_SendCommand(0xB0); - RLCD_SendData(0x64); - - RLCD_SendCommand(0x11); - vTaskDelay(pdMS_TO_TICKS(200)); - RLCD_SendCommand(0xC9); - RLCD_SendData(0x00); - - RLCD_SendCommand(0x36); - RLCD_SendData(0x48); - - RLCD_SendCommand(0x3A); - RLCD_SendData(0x11); - - RLCD_SendCommand(0xB9); - RLCD_SendData(0x20); - - RLCD_SendCommand(0xB8); - RLCD_SendData(0x29); - - RLCD_SendCommand(0x21); - - RLCD_SendCommand(0x2A); - RLCD_SendData(0x12); - RLCD_SendData(0x2A); - - RLCD_SendCommand(0x2B); - RLCD_SendData(0x00); - RLCD_SendData(0xC7); - - RLCD_SendCommand(0x35); - RLCD_SendData(0x00); - - RLCD_SendCommand(0xD0); - RLCD_SendData(0xFF); - - RLCD_SendCommand(0x38); - RLCD_SendCommand(0x29); - - RLCD_ColorClear(ColorWhite); -} - -void CustomLcdDisplay::RLCD_SetPixel(uint16_t x, uint16_t y, uint8_t color) { - uint32_t idx = PixelIndexLUT[x][y]; - uint8_t mask = PixelBitLUT[x][y]; - - uint8_t *p = &DispBuffer[idx]; - - if (color) - *p |= mask; - else - *p &= ~mask; -} - -void CustomLcdDisplay::RLCD_Display() { - RLCD_SendCommand(0x2A); // Column Address Set - RLCD_SendData(0x12); - RLCD_SendData(0x2A); - - RLCD_SendCommand(0x2B); // Page Address Set - RLCD_SendData(0x00); - RLCD_SendData(0xC7); - - RLCD_SendCommand(0x2c); // Page Address Set - - RLCD_Sendbuffera(DispBuffer,DisplayLen); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.h deleted file mode 100644 index 7ca91ccc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/custom_lcd_display.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef __CUSTOM_LCD_DISPLAY_H__ -#define __CUSTOM_LCD_DISPLAY_H__ - -#include -#include "lcd_display.h" - -enum ColorSelection { - ColorBlack = 0, - ColorWhite = 0xff -}; - -typedef struct { - uint8_t mosi; - uint8_t scl; - uint8_t dc; - uint8_t cs; - uint8_t rst; -} spi_display_config_t; - -class CustomLcdDisplay : public LcdDisplay { -private: - esp_lcd_panel_io_handle_t io_handle = NULL; - uint32_t i2c_data_pdMS_TICKS = 0; - uint32_t i2c_done_pdMS_TICKS = 0; - const char *TAG = "CustomDisplay"; - int mosi_; - int scl_; - int dc_; - int cs_; - int rst_; - int width_; - int height_; - uint8_t *DispBuffer = NULL; - int DisplayLen; - uint16_t (*PixelIndexLUT)[300]; - uint8_t (*PixelBitLUT )[300]; - void InitPortraitLUT(); - void InitLandscapeLUT(); - void Set_ResetIOLevel(uint8_t level); - void RLCD_SendCommand(uint8_t Reg); - void RLCD_SendData(uint8_t Data); - void RLCD_Sendbuffera(uint8_t *Data, int len); - void RLCD_Reset(void); - static void Lvgl_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * color_p); - -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy,spi_display_config_t spiconfig,spi_host_device_t spi_host = SPI3_HOST); - ~CustomLcdDisplay(); - void RLCD_Init(); - void RLCD_ColorClear(uint8_t color); - void RLCD_Display(); - void RLCD_SetPixel(uint16_t x, uint16_t y, uint8_t color); -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/waveshare-s3-rlcd-4.2.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/waveshare-s3-rlcd-4.2.cc deleted file mode 100644 index 49ce3103..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-rlcd-4.2/waveshare-s3-rlcd-4.2.cc +++ /dev/null @@ -1,100 +0,0 @@ -#include -#include -#include -#include -#include "custom_lcd_display.h" -#include "wifi_board.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "codecs/box_audio_codec.h" -#include "wifi_station.h" -#include "mcp_server.h" -#include "lvgl.h" -#include "custom_lcd_display.h" - -#define TAG "waveshare_rlcd_4_2" - -class CustomBoard : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - CustomLcdDisplay *display_; - adc_oneshot_unit_handle_t adc1_handle; - adc_cali_handle_t cali_handle; - bool vbat_status = 0; - - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = {}; - i2c_bus_cfg.i2c_port = ESP32_I2C_HOST; - i2c_bus_cfg.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN; - i2c_bus_cfg.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN; - i2c_bus_cfg.clk_source = I2C_CLK_SRC_DEFAULT; - i2c_bus_cfg.glitch_ignore_cnt = 7; - i2c_bus_cfg.intr_priority = 0; - i2c_bus_cfg.trans_queue_depth = 0; - i2c_bus_cfg.flags.enable_internal_pullup = 1; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeTools() { - auto& mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(), - [this](const PropertyList&) -> ReturnValue { - EnterWifiConfigMode(); - return true; - }); - } - - void InitializeLcdDisplay() { - spi_display_config_t spi_config = {}; - spi_config.mosi = RLCD_MOSI_PIN; - spi_config.scl = RLCD_SCK_PIN; - spi_config.dc = RLCD_DC_PIN; - spi_config.cs = RLCD_CS_PIN; - spi_config.rst = RLCD_RST_PIN; - display_ = new CustomLcdDisplay(NULL, NULL, RLCD_WIDTH,RLCD_HEIGHT,DISPLAY_OFFSET_X,DISPLAY_OFFSET_Y,DISPLAY_MIRROR_X,DISPLAY_MIRROR_Y,DISPLAY_SWAP_XY,spi_config); - } - -public: - CustomBoard() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeI2c(); - InitializeButtons(); - InitializeTools(); - InitializeLcdDisplay(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(CustomBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/README.md deleted file mode 100644 index 82eecd7b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# 产品链接 - -[微雪电子 ESP32-S3-Touch-AMOLED-1.32](https://www.waveshare.net/shop/ESP32-S3-Touch-AMOLED-1.32.htm) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -Xiaozhi Assistant -> Board Type -> Waveshare ESP32-S3-Touch-AMOLED-1.32 -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.h deleted file mode 100644 index 6534a6fe..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_38 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_41 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_39 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_40 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_42 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_17 -#define PWR_EN_GPIO GPIO_NUM_18 - - -/*disp-qspi-lcd*/ -#define LCD_CS GPIO_NUM_10 -#define LCD_PCLK GPIO_NUM_11 -#define LCD_D0 GPIO_NUM_12 -#define LCD_D1 GPIO_NUM_13 -#define LCD_D2 GPIO_NUM_14 -#define LCD_D3 GPIO_NUM_15 -#define LCD_RST GPIO_NUM_8 -#define LCD_LIGHT (-1) - -#define EXAMPLE_LCD_H_RES 466 -#define EXAMPLE_LCD_V_RES 466 - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.json deleted file mode 100644 index 0f37a293..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-amoled-1.32", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/esp32-s3-touch-amoled-1.32.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/esp32-s3-touch-amoled-1.32.cc deleted file mode 100644 index 148a243f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.32/esp32-s3-touch-amoled-1.32.cc +++ /dev/null @@ -1,215 +0,0 @@ -#include "application.h" -#include "button.h" -#include "codecs/es8311_audio_codec.h" -#include "config.h" -#include "wifi_board.h" - -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" -#include "lvgl.h" -#include "mcp_server.h" -#include -#include -#include -#include - -#define TAG "waveshare_s3_amoled_1_32" - -static const sh8601_lcd_init_cmd_t lcd_init_cmds[] = { - {0xFE, (uint8_t[]) {0x00}, 1, 0}, - {0xC4, (uint8_t[]) {0x80}, 1, 0}, - {0x3A, (uint8_t[]) {0x55}, 1, 0}, // 0x55 for RGB565, 0x77 for RGB888 - {0x35, (uint8_t[]) {0x00}, 1, 0}, - {0x53, (uint8_t[]) {0x20}, 1, 0}, - {0x51, (uint8_t[]) {0xFF}, 1, 0}, // Brightness - {0x63, (uint8_t[]) {0xFF}, 1, 0}, - {0x2A, (uint8_t[]) {0x00, 0x06, 0x01, 0xD7}, 4, 0}, - {0x2B, (uint8_t[]) {0x00, 0x00, 0x01, 0xD1}, 4, 0}, - {0x11, (uint8_t[]) {0x00}, 0, 100}, - {0x29, (uint8_t[]) {0x00}, 0, 0}, -}; - -class CustomLcdDisplay : public SpiLcdDisplay { - private: - esp_lcd_panel_io_handle_t io_handle_; - - public: - static void my_draw_event_cb(lv_event_t *e) { - lv_area_t *area = (lv_area_t *) lv_event_get_param(e); - - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - - // Round area for better performance - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - void SetMIRROR_XY(uint8_t mirror) { - uint32_t lcd_cmd = 0x36; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= 0x02 << 24; - uint8_t param = mirror; - esp_lcd_panel_io_tx_param(io_handle_, lcd_cmd, ¶m, 1); - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) : - SpiLcdDisplay(io_handle, panel_handle, width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy), - io_handle_(io_handle) { - DisplayLockGuard lock(this); - lv_display_add_event_cb(display_, my_draw_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - SetMIRROR_XY(0xC0); // Rotate 180 degrees - lv_obj_invalidate(lv_screen_active()); - } -}; - -class CustomBoard : public WifiBoard { - private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - Button pwr_button_; - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_panel_io_handle_t io_handle = NULL; - CustomLcdDisplay *display_; - lv_indev_t *touch_indev = NULL; - i2c_master_dev_handle_t disp_touch_dev_handle = NULL; - - void InitializeI2c() { - i2c_master_bus_config_t i2c_bus_cfg = {}; - i2c_bus_cfg.i2c_port = I2C_NUM_0; - i2c_bus_cfg.sda_io_num = AUDIO_CODEC_I2C_SDA_PIN; - i2c_bus_cfg.scl_io_num = AUDIO_CODEC_I2C_SCL_PIN; - i2c_bus_cfg.clk_source = I2C_CLK_SRC_DEFAULT; - i2c_bus_cfg.glitch_ignore_cnt = 7; - i2c_bus_cfg.intr_priority = 0; - i2c_bus_cfg.trans_queue_depth = 0; - i2c_bus_cfg.flags.enable_internal_pullup = 1; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void SetDispbacklight(uint8_t backlight) { - uint32_t lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= 0x02 << 24; - uint8_t param = backlight; - esp_lcd_panel_io_tx_param(io_handle, lcd_cmd, ¶m, 1); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto &app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - pwr_button_.OnLongPress([this]() { - GetDisplay()->SetChatMessage("system", "OFF"); - vTaskDelay(pdMS_TO_TICKS(1000)); - gpio_set_level(PWR_EN_GPIO, 0); - }); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.data0_io_num = LCD_D0; - buscfg.data1_io_num = LCD_D1; - buscfg.sclk_io_num = LCD_PCLK; - buscfg.data2_io_num = LCD_D2; - buscfg.data3_io_num = LCD_D3; - buscfg.max_transfer_sz = EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = LCD_CS; - io_config.dc_gpio_num = -1; - io_config.spi_mode = 0; - io_config.pclk_hz = 40 * 1000 * 1000; - io_config.trans_queue_depth = 8; - io_config.on_color_trans_done = NULL; - io_config.user_ctx = NULL; - io_config.lcd_cmd_bits = 32; - io_config.lcd_param_bits = 8; - io_config.flags.quad_mode = true; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &io_handle)); - - sh8601_vendor_config_t vendor_config = {}; - vendor_config.init_cmds = lcd_init_cmds; - vendor_config.init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]); - vendor_config.flags.use_qspi_interface = 1; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(io_handle, &panel_config, &panel_handle)); - esp_lcd_panel_set_gap(panel_handle, 0x06, 0x00); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle)); - - display_ = new CustomLcdDisplay(io_handle, panel_handle, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.disp.setbacklight", "设置屏幕亮度", PropertyList({Property("level", kPropertyTypeInteger, 0, 255)}), [this](const PropertyList &properties) -> ReturnValue { - int level = properties["level"].value(); - ESP_LOGI("setbacklight", "%d", level); - SetDispbacklight(level); - return true; - }); - - mcp_server.AddTool("self.disp.network", "重新配网", PropertyList(), [this](const PropertyList &) -> ReturnValue { - EnterWifiConfigMode(); - return true; - }); - } - - void CheckPowerKeyState() { - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = (0x1ULL << PWR_EN_GPIO); - gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - gpio_conf.pull_up_en = GPIO_PULLUP_ENABLE; - ESP_ERROR_CHECK_WITHOUT_ABORT(gpio_config(&gpio_conf)); - gpio_set_level(PWR_EN_GPIO, 1); - do { - vTaskDelay(pdMS_TO_TICKS(10)); - } while (!gpio_get_level(PWR_BUTTON_GPIO)); - } - - public: - CustomBoard() : boot_button_(BOOT_BUTTON_GPIO), pwr_button_(PWR_BUTTON_GPIO) { - CheckPowerKeyState(); - InitializeI2c(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec *GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/README.md deleted file mode 100644 index 5f99392d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Waveshare ESP32-S3-Touch-AMOLED-1.75 - - -[ESP32-S3-Touch-AMOLED-1.75](https://www.waveshare.com/esp32-s3-touch-amoled-1.75.htm) ESP32-S3-Touch-AMOLED-1.75 is a high performance, highly integrated microcontroller development board designed by Waveshare.\ -In the smaller form, the 1.75-inch capacitive HD AMOLED screen, highly integrated power management chip, six-axis sensor (three-axis accelerometer and three-axis gyroscope), RTC, low-power audio codec chip and echo cancellation circuit are mounted on the board, which is convenient for development and embedding into the product. - - -## images - -| [ESP32-S3-Touch-AMOLED-1.75](https://www.waveshare.com/esp32-s3-touch-amoled-1.75.htm) | -|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| | -| | -| | - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.h deleted file mode 100644 index 40ac5df6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_42 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define EXAMPLE_PIN_NUM_LCD_CS GPIO_NUM_12 -#define EXAMPLE_PIN_NUM_LCD_PCLK GPIO_NUM_38 -#define EXAMPLE_PIN_NUM_LCD_DATA0 GPIO_NUM_4 -#define EXAMPLE_PIN_NUM_LCD_DATA1 GPIO_NUM_5 -#define EXAMPLE_PIN_NUM_LCD_DATA2 GPIO_NUM_6 -#define EXAMPLE_PIN_NUM_LCD_DATA3 GPIO_NUM_7 -#define EXAMPLE_PIN_NUM_LCD_RST GPIO_NUM_39 -#define DISPLAY_WIDTH 466 -#define DISPLAY_HEIGHT 466 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.json deleted file mode 100644 index 6e4e8acb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-amoled-1.75", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/esp32-s3-touch-amoled-1.75.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/esp32-s3-touch-amoled-1.75.cc deleted file mode 100644 index f0c3c314..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-1.75/esp32-s3-touch-amoled-1.75.cc +++ /dev/null @@ -1,360 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" - -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" -#include "settings.h" - -#include -#include -#include - -#define TAG "WaveshareEsp32s3TouchAMOLED1inch75" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x01); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const sh8601_lcd_init_cmd_t vendor_specific_init[] = { - // set display to qspi mode - {0xFE, (uint8_t[]){0x20}, 1, 0}, - {0x19, (uint8_t[]){0x10}, 1, 0}, - {0x1C, (uint8_t[]){0xA0}, 1, 0}, - - {0xFE, (uint8_t[]){0x00}, 1, 0}, - {0xC4, (uint8_t[]){0x80}, 1, 0}, - {0x3A, (uint8_t[]){0x55}, 1, 0}, - {0x35, (uint8_t[]){0x00}, 1, 0}, - {0x53, (uint8_t[]){0x20}, 1, 0}, - {0x51, (uint8_t[]){0xFF}, 1, 0}, - {0x63, (uint8_t[]){0xFF}, 1, 0}, - {0x2A, (uint8_t[]){0x00, 0x06, 0x01, 0xD7}, 4, 0}, - {0x2B, (uint8_t[]){0x00, 0x00, 0x01, 0xD1}, 4, 600}, - {0x11, NULL, 0, 600}, - {0x29, NULL, 0, 0}, -}; - -// 在waveshare_amoled_1_75类之前添加新的显示类 -class CustomLcdDisplay : public SpiLcdDisplay { -public: - static void rounder_event_cb(lv_event_t* e) { - lv_area_t* area = (lv_area_t* )lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - - // round the start of coordinate down to the nearest 2M number - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - // round the end of coordinate up to the nearest 2N+1 number - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES* 0.1, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES* 0.1, 0); - lv_display_add_event_cb(display_, rounder_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(esp_lcd_panel_io_handle_t panel_io) : Backlight(), panel_io_(panel_io) {} - -protected: - esp_lcd_panel_io_handle_t panel_io_; - - virtual void SetBrightnessImpl(uint8_t brightness) override { - auto display = Board::GetInstance().GetDisplay(); - DisplayLockGuard lock(display); - uint8_t data[1] = {((uint8_t)((255* brightness) / 100))}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - esp_lcd_panel_io_tx_param(panel_io_, lcd_cmd, &data, sizeof(data)); - } -}; - -class WaveshareEsp32s3TouchAMOLED1inch75 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - CustomLcdDisplay* display_; - CustomBacklight* backlight_; - esp_io_expander_handle_t io_expander = NULL; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - if (ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_4, IO_EXPANDER_INPUT); - ESP_ERROR_CHECK(ret); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.sclk_io_num = EXAMPLE_PIN_NUM_LCD_PCLK; - buscfg.data0_io_num = EXAMPLE_PIN_NUM_LCD_DATA0; - buscfg.data1_io_num = EXAMPLE_PIN_NUM_LCD_DATA1; - buscfg.data2_io_num = EXAMPLE_PIN_NUM_LCD_DATA2; - buscfg.data3_io_num = EXAMPLE_PIN_NUM_LCD_DATA3; - buscfg.max_transfer_sz = DISPLAY_WIDTH* DISPLAY_HEIGHT* sizeof(uint16_t); - buscfg.flags = SPICOMMON_BUSFLAG_QUAD; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeSH8601Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG( - EXAMPLE_PIN_NUM_LCD_CS, - nullptr, - nullptr); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const sh8601_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(sh8601_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }}; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void* )&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(panel_io, &panel_config, &panel)); - esp_lcd_panel_set_gap(panel, 0x06, 0); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - backlight_ = new CustomBacklight(panel_io); - backlight_->RestoreBrightness(); - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH - 1, - .y_max = DISPLAY_HEIGHT - 1, - .rst_gpio_num = GPIO_NUM_40, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 1, - .mirror_y = 1, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST9217_CONFIG(); - tp_io_config.scl_speed_hz = 400* 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst9217(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32s3TouchAMOLED1inch75() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeTca9554(); - InitializeAxp2101(); - InitializeSpi(); - InitializeSH8601Display(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - return backlight_; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32s3TouchAMOLED1inch75); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/README.md deleted file mode 100644 index aa8bbe8f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Waveshare ESP32-S3-Touch-AMOLED-2.06 - - -[ESP32-S3-Touch-AMOLED-2.06](https://www.waveshare.com/esp32-s3-touch-amoled-2.06.htm) is a high-performance, wearable watch-style development board designed by Waveshare. Based on the ESP32-S3R8 microcontroller, it integrates a 2.06inch AMOLED capacitive touch display, 6-axis IMU, RTC chip, audio codec chip, power management IC, and so on. Comes with a custom-designed case with a smartwatch-like appearance, making it ideal for prototyping and functional verification of wearable applications. - -## images - -| [ESP32-S3-Touch-AMOLED-2.06](https://www.waveshare.com/esp32-s3-touch-amoled-2.06.htm) | -|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| | - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.h deleted file mode 100644 index 6ad75a7e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_41 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_42 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_40 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define EXAMPLE_PIN_NUM_LCD_CS GPIO_NUM_12 -#define EXAMPLE_PIN_NUM_LCD_PCLK GPIO_NUM_11 -#define EXAMPLE_PIN_NUM_LCD_DATA0 GPIO_NUM_4 -#define EXAMPLE_PIN_NUM_LCD_DATA1 GPIO_NUM_5 -#define EXAMPLE_PIN_NUM_LCD_DATA2 GPIO_NUM_6 -#define EXAMPLE_PIN_NUM_LCD_DATA3 GPIO_NUM_7 -#define EXAMPLE_PIN_NUM_LCD_RST GPIO_NUM_8 -#define DISPLAY_WIDTH 410 -#define DISPLAY_HEIGHT 502 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_NC -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.json deleted file mode 100644 index 3a95f74a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-amoled-2.06", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/esp32-s3-touch-amoled-2.06.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/esp32-s3-touch-amoled-2.06.cc deleted file mode 100644 index a8855210..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-amoled-2.06/esp32-s3-touch-amoled-2.06.cc +++ /dev/null @@ -1,346 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "esp_lcd_sh8601.h" - -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "settings.h" - -#include -#include -#include - -#define TAG "WaveshareEsp32s3TouchAMOLED2inch06" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - WriteReg(0x93, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x03); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x0A); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const sh8601_lcd_init_cmd_t vendor_specific_init[] = { - // set display to qspi mode - {0x11, (uint8_t []){0x00}, 0, 120}, - {0xC4, (uint8_t []){0x80}, 1, 0}, - {0x44, (uint8_t []){0x01, 0xD1}, 2, 0}, - {0x35, (uint8_t []){0x00}, 1, 0}, - {0x53, (uint8_t []){0x20}, 1, 10}, - {0x63, (uint8_t []){0xFF}, 1, 10}, - {0x51, (uint8_t []){0x00}, 1, 10}, - {0x2A, (uint8_t []){0x00,0x16,0x01,0xAF}, 4, 0}, - {0x2B, (uint8_t []){0x00,0x00,0x01,0xF5}, 4, 0}, - {0x29, (uint8_t []){0x00}, 0, 10}, - {0x51, (uint8_t []){0xFF}, 1, 0}, -}; - -// 在waveshare_amoled_2_06类之前添加新的显示类 -class CustomLcdDisplay : public SpiLcdDisplay { -public: - static void rounder_event_cb(lv_event_t* e) { - lv_area_t* area = (lv_area_t* )lv_event_get_param(e); - uint16_t x1 = area->x1; - uint16_t x2 = area->x2; - - uint16_t y1 = area->y1; - uint16_t y2 = area->y2; - - // round the start of coordinate down to the nearest 2M number - area->x1 = (x1 >> 1) << 1; - area->y1 = (y1 >> 1) << 1; - // round the end of coordinate up to the nearest 2N+1 number - area->x2 = ((x2 >> 1) << 1) + 1; - area->y2 = ((y2 >> 1) << 1) + 1; - } - - CustomLcdDisplay(esp_lcd_panel_io_handle_t io_handle, - esp_lcd_panel_handle_t panel_handle, - int width, - int height, - int offset_x, - int offset_y, - bool mirror_x, - bool mirror_y, - bool swap_xy) - : SpiLcdDisplay(io_handle, panel_handle, - width, height, offset_x, offset_y, mirror_x, mirror_y, swap_xy) { - DisplayLockGuard lock(this); - lv_obj_set_style_pad_left(status_bar_, LV_HOR_RES* 0.1, 0); - lv_obj_set_style_pad_right(status_bar_, LV_HOR_RES* 0.1, 0); - lv_display_add_event_cb(display_, rounder_event_cb, LV_EVENT_INVALIDATE_AREA, NULL); - } -}; - -class CustomBacklight : public Backlight { -public: - CustomBacklight(esp_lcd_panel_io_handle_t panel_io) : Backlight(), panel_io_(panel_io) {} - -protected: - esp_lcd_panel_io_handle_t panel_io_; - - virtual void SetBrightnessImpl(uint8_t brightness) override { - auto display = Board::GetInstance().GetDisplay(); - DisplayLockGuard lock(display); - uint8_t data[1] = {((uint8_t)((255* brightness) / 100))}; - int lcd_cmd = 0x51; - lcd_cmd &= 0xff; - lcd_cmd <<= 8; - lcd_cmd |= LCD_OPCODE_WRITE_CMD << 24; - esp_lcd_panel_io_tx_param(panel_io_, lcd_cmd, &data, sizeof(data)); - } -}; - -class WaveshareEsp32s3TouchAMOLED2inch06 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - CustomLcdDisplay* display_; - CustomBacklight* backlight_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.sclk_io_num = EXAMPLE_PIN_NUM_LCD_PCLK; - buscfg.data0_io_num = EXAMPLE_PIN_NUM_LCD_DATA0; - buscfg.data1_io_num = EXAMPLE_PIN_NUM_LCD_DATA1; - buscfg.data2_io_num = EXAMPLE_PIN_NUM_LCD_DATA2; - buscfg.data3_io_num = EXAMPLE_PIN_NUM_LCD_DATA3; - buscfg.max_transfer_sz = DISPLAY_WIDTH* DISPLAY_HEIGHT* sizeof(uint16_t); - buscfg.flags = SPICOMMON_BUSFLAG_QUAD; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeSH8601Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = SH8601_PANEL_IO_QSPI_CONFIG( - EXAMPLE_PIN_NUM_LCD_CS, - nullptr, - nullptr); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - const sh8601_vendor_config_t vendor_config = { - .init_cmds = &vendor_specific_init[0], - .init_cmds_size = sizeof(vendor_specific_init) / sizeof(sh8601_lcd_init_cmd_t), - .flags = { - .use_qspi_interface = 1, - }}; - - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = EXAMPLE_PIN_NUM_LCD_RST; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = (void* )&vendor_config; - ESP_ERROR_CHECK(esp_lcd_new_panel_sh8601(panel_io, &panel_config, &panel)); - esp_lcd_panel_set_gap(panel, 0x16, 0); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, false); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - backlight_ = new CustomBacklight(panel_io); - backlight_->RestoreBrightness(); - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH - 1, - .y_max = DISPLAY_HEIGHT - 1, - .rst_gpio_num = GPIO_NUM_9, - .int_gpio_num = GPIO_NUM_38, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_FT5x06_CONFIG(); - tp_io_config.scl_speed_hz = 400* 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_ft5x06(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32s3TouchAMOLED2inch06() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeAxp2101(); - InitializeSpi(); - InitializeSH8601Display(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - return backlight_; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32s3TouchAMOLED2inch06); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/README.md deleted file mode 100644 index f2d43773..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Waveshare ESP32-S3-Touch-LCD-1.83 - - -[ESP32-S3-Touch-LCD-1.83](https://www.waveshare.com/esp32-s3-touch-lcd-1.83.htm) ESP32-S3-Touch-LCD-1.83 is a high-performance and highly integrated microcontroller development board designed by Waveshare. With a compact board size, it is equipped with a 1.83-inch capacitive LCD screen, a highly integrated power management chip, six-axis sensors (three-axis accelerometer and three-axis gyroscope), RTC and low-power audio codec chip, etc., making it convenient for development and easy to be embedded in products. \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.h deleted file mode 100644 index 97bba448..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_45 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_9 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_46 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_15 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_14 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_41 - -#define DISPLAY_SPI_MODE 3 -#define DISPLAY_CS_PIN GPIO_NUM_5 -#define DISPLAY_MOSI_PIN GPIO_NUM_7 -#define DISPLAY_MISO_PIN GPIO_NUM_NC -#define DISPLAY_CLK_PIN GPIO_NUM_6 -#define DISPLAY_DC_PIN GPIO_NUM_4 -#define DISPLAY_RST_PIN GPIO_NUM_38 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 284 -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_40 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.json deleted file mode 100644 index 56900433..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-lcd-1.83", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/esp32-s3-touch-lcd-1.83.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/esp32-s3-touch-lcd-1.83.cc deleted file mode 100644 index dd466cd7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-1.83/esp32-s3-touch-lcd-1.83.cc +++ /dev/null @@ -1,261 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "settings.h" - -#include -#include -#include - -#define TAG "WaveshareEsp32s3TouchLCD1inch83" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x01); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -class WaveshareEsp32s3TouchLCD1inch83 : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - Display* display_; - PowerSaveTimer* power_save_timer_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_MOSI_PIN; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH* DISPLAY_HEIGHT* sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS_PIN; - io_config.dc_gpio_num = DISPLAY_DC_PIN; - io_config.spi_mode = 0; - io_config.pclk_hz = 24 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RST_PIN; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, true); - // esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - esp_lcd_panel_disp_on_off(panel, true); - display_ = new SpiLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH - 1, - .y_max = DISPLAY_HEIGHT - 1, - .rst_gpio_num = GPIO_NUM_39, - .int_gpio_num = GPIO_NUM_13, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_CST816S_CONFIG(); - tp_io_config.scl_speed_hz = 400* 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_cst816s(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - // 初始化工具 - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - -public: - WaveshareEsp32s3TouchLCD1inch83() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeAxp2101(); - InitializeSpi(); - InitializeDisplay(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32s3TouchLCD1inch83); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/README.md deleted file mode 100644 index 657331d3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-3.49 -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-3.49.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.h deleted file mode 100644 index e2e9b79a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include -#include "lvgl.h" - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_7 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_46 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_45 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#define Dev_Touch_I2C_SDA_PIN GPIO_NUM_17 -#define Dev_Touch_I2C_SCL_PIN GPIO_NUM_18 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define I2C_Touch_ADDRESS 0x3b -#define I2C_Touch_SDA_PIN GPIO_NUM_17 -#define I2C_Touch_SCL_PIN GPIO_NUM_18 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define PWR_BUTTON_GPIO GPIO_NUM_16 - -#define LCD_CS GPIO_NUM_9 -#define LCD_PCLK GPIO_NUM_10 -#define LCD_D0 GPIO_NUM_11 -#define LCD_D1 GPIO_NUM_12 -#define LCD_D2 GPIO_NUM_13 -#define LCD_D3 GPIO_NUM_14 -#define LCD_RST GPIO_NUM_21 -#define LCD_LIGHT (-1) - -#define DISPLAY_WIDTH 172 -#define DISPLAY_HEIGHT 640 -#define LVGL_DMA_BUFF_LEN (DISPLAY_WIDTH * 64 * 2) -#define LVGL_SPIRAM_BUFF_LEN (DISPLAY_WIDTH * DISPLAY_HEIGHT * 2) - -#define DISPLAY_ROTATION_90 false - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_8 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.json deleted file mode 100644 index 32de3cff..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-lcd-3.49", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/custom_lcd_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/custom_lcd_display.cc deleted file mode 100644 index a5a466f3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.49/custom_lcd_display.cc +++ /dev/null @@ -1,145 +0,0 @@ -#include "custom_lcd_display.h" - -#include "lcd_display.h" - -#include -#include -#include -#include -#include "assets/lang_config.h" -#include -#include "settings.h" - -#include "esp_lcd_panel_io.h" - -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/semphr.h" - -#include "config.h" - -#include "board.h" - -#define TAG "CustomLcdDisplay" - -static SemaphoreHandle_t trans_done_sem = NULL; -static uint16_t *trans_buf_1; - -#if (DISPLAY_ROTATION_90 == true) -static uint16_t *dest_map; -#endif - - -bool CustomLcdDisplay::lvgl_port_flush_io_ready_callback(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) { - BaseType_t taskAwake = pdFALSE; - lv_display_t *disp_drv = (lv_display_t *)user_ctx; - assert(disp_drv != NULL); - if (trans_done_sem) { - xSemaphoreGiveFromISR(trans_done_sem, &taskAwake); - } - return false; -} - -void CustomLcdDisplay::lvgl_port_flush_callback(lv_display_t *drv, const lv_area_t *area, uint8_t *color_map) { - assert(drv != NULL); - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)lv_display_get_user_data(drv); - assert(panel_handle != NULL); - - lv_draw_sw_rgb565_swap(color_map, lv_area_get_width(area) * lv_area_get_height(area)); - -#if (DISPLAY_ROTATION_90 == true) - lv_display_rotation_t rotation = lv_display_get_rotation(drv); - lv_area_t rotated_area; - if(rotation != LV_DISPLAY_ROTATION_0) { - lv_color_format_t cf = lv_display_get_color_format(drv); - /*Calculate the position of the rotated area*/ - rotated_area = *area; - lv_display_rotate_area(drv, &rotated_area); - /*Calculate the source stride (bytes in a line) from the width of the area*/ - uint32_t src_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), cf); - /*Calculate the stride of the destination (rotated) area too*/ - uint32_t dest_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&rotated_area), cf); - /*Have a buffer to store the rotated area and perform the rotation*/ - - int32_t src_w = lv_area_get_width(area); - int32_t src_h = lv_area_get_height(area); - lv_draw_sw_rotate(color_map, dest_map, src_w, src_h, src_stride, dest_stride, rotation, cf); - /*Use the rotated area and rotated buffer from now on*/ - area = &rotated_area; - } -#endif - const int flush_coun = (LVGL_SPIRAM_BUFF_LEN / LVGL_DMA_BUFF_LEN); - const int offgap = (DISPLAY_HEIGHT / flush_coun); - const int dmalen = (LVGL_DMA_BUFF_LEN / 2); - int offsetx1 = 0; - int offsety1 = 0; - int offsetx2 = DISPLAY_WIDTH; - int offsety2 = offgap; -#if (DISPLAY_ROTATION_90 == true) - uint16_t *map = (uint16_t*)dest_map; -#else - uint16_t *map = (uint16_t*)color_map; -#endif - xSemaphoreGive(trans_done_sem); - - for(int i = 0; i -#include "i2c_device.h" -#include -#include -#include -#include -#include - -#include -#include "esp_io_expander_tca9554.h" - -#include "esp_lcd_axs15231b.h" - -#include "custom_lcd_display.h" - -#include - -#define TAG "waveshare_lcd_3_39" - - -static const axs15231b_lcd_init_cmd_t lcd_init_cmds[] = { - {0x11, (uint8_t []){0x00}, 0, 100}, - {0x29, (uint8_t []){0x00}, 0, 100}, -}; - -class CustomBoard : public WifiBoard { -private: - Button boot_button_; - Button pwr_button_; - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - i2c_master_dev_handle_t disp_touch_dev_handle = NULL; - lv_indev_t *touch_indev = NULL; //touch - bool is_PwrControlEn = false; - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_7 | IO_EXPANDER_PIN_NUM_6, IO_EXPANDER_OUTPUT); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_7 | IO_EXPANDER_PIN_NUM_6, 1); - ESP_ERROR_CHECK(ret); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.data0_io_num = LCD_D0; - buscfg.data1_io_num = LCD_D1; - buscfg.data2_io_num = LCD_D2; - buscfg.data3_io_num = LCD_D3; - buscfg.sclk_io_num = LCD_PCLK; - buscfg.max_transfer_sz = LVGL_DMA_BUFF_LEN; - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // RESET PIN INIT - gpio_config_t gpio_conf = {}; - gpio_conf.intr_type = GPIO_INTR_DISABLE; - gpio_conf.mode = GPIO_MODE_OUTPUT; - gpio_conf.pin_bit_mask = ((uint64_t)0x01<0 && buff[1]<5) { - indevData->state = LV_INDEV_STATE_PRESSED; - if(pointX > DISPLAY_WIDTH) pointX = DISPLAY_WIDTH; - if(pointY > DISPLAY_HEIGHT) pointY = DISPLAY_HEIGHT; - indevData->point.x = pointY; - indevData->point.y = (DISPLAY_HEIGHT-pointX); - ESP_LOGE("Touch","(%ld,%ld)",indevData->point.x,indevData->point.y); - } else { - indevData->state = LV_INDEV_STATE_RELEASED; - } - } - - void GetPwrCurrentState() { - if(gpio_get_level(PWR_BUTTON_GPIO)) { - is_PwrControlEn = true; - } - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO), - pwr_button_(PWR_BUTTON_GPIO) { - InitializeI2c(); - InitializeTca9554(); - InitializeSpi(); - InitializeLcdDisplay(); - InitializeButtons(); - InitializeTouch(); - GetPwrCurrentState(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } -}; - -DECLARE_BOARD(CustomBoard); \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/README.md deleted file mode 100644 index aaadeae5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/README.md +++ /dev/null @@ -1,3 +0,0 @@ -新增 微雪 开发板: ESP32-S3-Touch-LCD-3.5B -产品链接: -https://www.waveshare.net/shop/ESP32-S3-Touch-LCD-3.5B.htm \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.h deleted file mode 100644 index c44d734c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.h +++ /dev/null @@ -1,78 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include -#include -#include "lvgl.h" - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_44 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_15 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_14 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_16 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_8 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_7 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_NC -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SPI_MODE 0 -#define DISPLAY_CS_PIN GPIO_NUM_12 -#define DISPLAY_CLK_PIN GPIO_NUM_5 -#define DISPLAY_DATA0_PIN GPIO_NUM_1 -#define DISPLAY_DATA1_PIN GPIO_NUM_2 -#define DISPLAY_DATA2_PIN GPIO_NUM_3 -#define DISPLAY_DATA3_PIN GPIO_NUM_4 - -#define DISPLAY_RST_PIN GPIO_NUM_NC - - - -#define DISPLAY_WIDTH 480 -#define DISPLAY_HEIGHT 320 -#define DISPLAY_TRANS_SIZE (DISPLAY_WIDTH * 10) - -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define DISPLAY_SWAP_XY false -#define DISPLAY_RGB_ORDER LCD_RGB_ELEMENT_ORDER_RGB -#define DISPLAY_INVERT_COLOR false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define LV_DISPLAY_ROTATION LV_DISPLAY_ROTATION_90 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_6 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define PMIC_ENABLE 0 -#define TOUCH_ENABLE 1 - -#define CAM_PIN_PWDN GPIO_NUM_NC -#define CAM_PIN_RESET GPIO_NUM_NC -#define CAM_PIN_VSYNC GPIO_NUM_17 -#define CAM_PIN_HREF GPIO_NUM_18 -#define CAM_PIN_PCLK GPIO_NUM_41 -#define CAM_PIN_XCLK GPIO_NUM_38 -#define CAM_PIN_SIOD GPIO_NUM_NC -#define CAM_PIN_SIOC GPIO_NUM_NC -#define CAM_PIN_D0 GPIO_NUM_45 -#define CAM_PIN_D1 GPIO_NUM_47 -#define CAM_PIN_D2 GPIO_NUM_48 -#define CAM_PIN_D3 GPIO_NUM_46 -#define CAM_PIN_D4 GPIO_NUM_42 -#define CAM_PIN_D5 GPIO_NUM_40 -#define CAM_PIN_D6 GPIO_NUM_39 -#define CAM_PIN_D7 GPIO_NUM_21 - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.json deleted file mode 100644 index 27c8e94c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/config.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-lcd-3.5b", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y", - "CONFIG_CAMERA_OV2640=y", - "CONFIG_CAMERA_OV2640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV2640_DVP_YUV422_640X480_6FPS=y", - "CONFIG_CAMERA_OV2640_DVP_IF_FORMAT_INDEX_DEFAULT=1", - "CONFIG_CAMERA_OV5640=y", - "CONFIG_CAMERA_OV5640_AUTO_DETECT_DVP_INTERFACE_SENSOR=y", - "CONFIG_CAMERA_OV5640_DVP_YUV422_800X600_10FPS=y", - "CONFIG_CAMERA_OV5640_DVP_IF_FORMAT_INDEX_DEFAULT=0" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.cc deleted file mode 100644 index 11d492f5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.cc +++ /dev/null @@ -1,286 +0,0 @@ - -#include "config.h" -#include "custom_lcd_display.h" -#include "lcd_display.h" -#include "assets/lang_config.h" -#include "settings.h" -#include "board.h" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define TAG "CustomLcdDisplay" - - -static SemaphoreHandle_t trans_done_sem = NULL; -static uint16_t *trans_act; -static uint16_t *trans_buf_1; -static uint16_t *trans_buf_2; - -bool CustomLcdDisplay::lvgl_port_flush_io_ready_callback(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) -{ - BaseType_t taskAwake = pdFALSE; - lv_display_t *disp_drv = (lv_display_t *)user_ctx; - assert(disp_drv != NULL); - if (trans_done_sem) { - xSemaphoreGiveFromISR(trans_done_sem, &taskAwake); - } - return false; -} - -void CustomLcdDisplay::lvgl_port_flush_callback(lv_display_t *drv, const lv_area_t *area, uint8_t *color_map) -{ - assert(drv != NULL); - esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t)lv_display_get_driver_data(drv); - assert(panel_handle != NULL); - - size_t len = lv_area_get_size(area); - lv_draw_sw_rgb565_swap(color_map, len); - - const int x_start = area->x1; - const int x_end = area->x2; - const int y_start = area->y1; - const int y_end = area->y2; - const int width = x_end - x_start + 1; - const int height = y_end - y_start + 1; - - int32_t hor_res = lv_display_get_horizontal_resolution(drv); - int32_t ver_res = lv_display_get_vertical_resolution(drv); - - // printf("hor_res: %ld, ver_res: %ld\r\n", hor_res, ver_res); - // printf("x_start: %d, x_end: %d, y_start: %d, y_end: %d, width: %d, height: %d\r\n", x_start, x_end, y_start, y_end, width, height); - uint16_t *from = (uint16_t *)color_map; - uint16_t *to = NULL; - - if (DISPLAY_TRANS_SIZE > 0) { - assert(trans_buf_1 != NULL); - - int x_draw_start = 0; - int x_draw_end = 0; - int y_draw_start = 0; - int y_draw_end = 0; - int trans_count = 0; - - trans_act = trans_buf_1; - lv_display_rotation_t rotate = LV_DISPLAY_ROTATION; - - int x_start_tmp = 0; - int x_end_tmp = 0; - int max_width = 0; - int trans_width = 0; - - int y_start_tmp = 0; - int y_end_tmp = 0; - int max_height = 0; - int trans_height = 0; - - if (LV_DISPLAY_ROTATION_270 == rotate || LV_DISPLAY_ROTATION_90 == rotate) { - max_width = ((DISPLAY_TRANS_SIZE / height) > width) ? (width) : (DISPLAY_TRANS_SIZE / height); - trans_count = width / max_width + (width % max_width ? (1) : (0)); - - x_start_tmp = x_start; - x_end_tmp = x_end; - } else { - max_height = ((DISPLAY_TRANS_SIZE / width) > height) ? (height) : (DISPLAY_TRANS_SIZE / width); - trans_count = height / max_height + (height % max_height ? (1) : (0)); - - y_start_tmp = y_start; - y_end_tmp = y_end; - } - - for (int i = 0; i < trans_count; i++) { - - if (LV_DISPLAY_ROTATION_90 == rotate) { - trans_width = (x_end - x_start_tmp + 1) > max_width ? max_width : (x_end - x_start_tmp + 1); - x_end_tmp = (x_end - x_start_tmp + 1) > max_width ? (x_start_tmp + max_width - 1) : x_end; - } else if (LV_DISPLAY_ROTATION_270 == rotate) { - trans_width = (x_end_tmp - x_start + 1) > max_width ? max_width : (x_end_tmp - x_start + 1); - x_start_tmp = (x_end_tmp - x_start + 1) > max_width ? (x_end_tmp - trans_width + 1) : x_start; - } else if (LV_DISPLAY_ROTATION_0 == rotate) { - trans_height = (y_end - y_start_tmp + 1) > max_height ? max_height : (y_end - y_start_tmp + 1); - y_end_tmp = (y_end - y_start_tmp + 1) > max_height ? (y_start_tmp + max_height - 1) : y_end; - } else { - trans_height = (y_end_tmp - y_start + 1) > max_height ? max_height : (y_end_tmp - y_start + 1); - y_start_tmp = (y_end_tmp - y_start + 1) > max_height ? (y_end_tmp - max_height + 1) : y_start; - } - - trans_act = (trans_act == trans_buf_1) ? (trans_buf_2) : (trans_buf_1); - to = trans_act; - - switch (rotate) { - case LV_DISPLAY_ROTATION_90: - for (int y = 0; y < height; y++) { - for (int x = 0; x < trans_width; x++) { - *(to + x * height + (height - y - 1)) = *(from + y * width + x_start_tmp + x); - } - } - x_draw_start = ver_res - y_end - 1; - x_draw_end = ver_res - y_start - 1; - y_draw_start = x_start_tmp; - y_draw_end = x_end_tmp; - break; - case LV_DISPLAY_ROTATION_270: - for (int y = 0; y < height; y++) { - for (int x = 0; x < trans_width; x++) { - *(to + (trans_width - x - 1) * height + y) = *(from + y * width + x_start_tmp + x); - } - } - x_draw_start = y_start; - x_draw_end = y_end; - y_draw_start = hor_res - x_end_tmp - 1; - y_draw_end = hor_res - x_start_tmp - 1; - break; - case LV_DISPLAY_ROTATION_180: - for (int y = 0; y < trans_height; y++) { - for (int x = 0; x < width; x++) { - *(to + (trans_height - y - 1)*width + (width - x - 1)) = *(from + y_start_tmp * width + y * (width) + x); - } - } - x_draw_start = hor_res - x_end - 1; - x_draw_end = hor_res - x_start - 1; - y_draw_start = ver_res - y_end_tmp - 1; - y_draw_end = ver_res - y_start_tmp - 1; - break; - case LV_DISPLAY_ROTATION_0: - for (int y = 0; y < trans_height; y++) { - for (int x = 0; x < width; x++) { - *(to + y * (width) + x) = *(from + y_start_tmp * width + y * (width) + x); - } - } - x_draw_start = x_start; - x_draw_end = x_end; - y_draw_start = y_start_tmp; - y_draw_end = y_end_tmp; - break; - default: - break; - } - - if (0 == i) { - // if (disp_ctx->draw_wait_cb) { - // disp_ctx->draw_wait_cb(disp_ctx->panel_handle->user_data); - // } - xSemaphoreGive(trans_done_sem); - } - - xSemaphoreTake(trans_done_sem, portMAX_DELAY); - // printf("i: %d, x_draw_start: %d, x_draw_end: %d, y_draw_start: %d, y_draw_end: %d\r\n", i, x_draw_start, x_draw_end, y_draw_start, y_draw_end); - esp_lcd_panel_draw_bitmap(panel_handle, x_draw_start, y_draw_start, x_draw_end + 1, y_draw_end + 1, to); - - if (LV_DISPLAY_ROTATION_90 == rotate) { - x_start_tmp += max_width; - } else if (LV_DISPLAY_ROTATION_270 == rotate) { - x_end_tmp -= max_width; - } if (LV_DISPLAY_ROTATION_0 == rotate) { - y_start_tmp += max_height; - } else { - y_end_tmp -= max_height; - } - } - } else { - esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_end + 1, y_end + 1, color_map); - } - lv_disp_flush_ready(drv); -} - -CustomLcdDisplay::CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : LcdDisplay(panel_io, panel, width, height) { - // width_ = width; - // height_ = height; - - // draw white - std::vector buffer(width_, 0xFFFF); - for (int y = 0; y < height_; y++) { - esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data()); - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - - ESP_LOGI(TAG, "Initialize LVGL port"); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 1; - port_cfg.timer_period_ms = 50; - lvgl_port_init(&port_cfg); - trans_done_sem = xSemaphoreCreateCounting(1, 0); - trans_buf_1 = (uint16_t *)heap_caps_malloc(DISPLAY_TRANS_SIZE * sizeof(uint16_t), MALLOC_CAP_DMA); - trans_buf_2 = (uint16_t *)heap_caps_malloc(DISPLAY_TRANS_SIZE * sizeof(uint16_t), MALLOC_CAP_DMA); -#if 0 - ESP_LOGI(TAG, "Adding LCD screen"); - const lvgl_port_display_cfg_t display_cfg = { - .io_handle = panel_io_, - .panel_handle = panel_, - .control_handle = nullptr, - .buffer_size = static_cast(width_ * height_), - .double_buffer = false, - .trans_size = 0, - .hres = static_cast(width_), - .vres = static_cast(height_), - .monochrome = false, - .rotation = { - .swap_xy = swap_xy, - .mirror_x = mirror_x, - .mirror_y = mirror_y, - }, - .color_format = LV_COLOR_FORMAT_RGB565, - .flags = { - .buff_dma = 0, - .buff_spiram = 1, - .sw_rotate = 0, - .swap_bytes = 1, - .full_refresh = 1, - .direct_mode = 0, - }, - }; - - display_ = lvgl_port_add_disp(&display_cfg); - lv_display_set_flush_cb(display_, lvgl_port_flush_callback); -#else - - uint32_t buffer_size = 0; - lv_color_t *buf1 = NULL; - lvgl_port_lock(0); - uint8_t color_bytes = lv_color_format_get_size(LV_COLOR_FORMAT_RGB565); - display_ = lv_display_create(width_, height_); - lv_display_set_flush_cb(display_, lvgl_port_flush_callback); - buffer_size = width_ * height_; - buf1 = (lv_color_t *)heap_caps_aligned_alloc(1, buffer_size * color_bytes, MALLOC_CAP_SPIRAM); - lv_display_set_buffers(display_, buf1, NULL, buffer_size * color_bytes, LV_DISPLAY_RENDER_MODE_FULL); - lv_display_set_driver_data(display_, panel_); - lvgl_port_unlock(); - -#endif - - esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = lvgl_port_flush_io_ready_callback, - }; - /* Register done callback */ - esp_lcd_panel_io_register_event_callbacks(panel_io_, &cbs, display_); - - esp_lcd_panel_disp_on_off(panel_, false); - - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - if (offset_x != 0 || offset_y != 0) { - lv_display_set_offset(display_, offset_x, offset_y); - } - - - SetupUI(); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.h deleted file mode 100644 index c3a99007..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/custom_lcd_display.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __CUSTOM_LCD_DISPLAY_H__ -#define __CUSTOM_LCD_DISPLAY_H__ - -#include "lcd_display.h" - -// // SPI LCD显示器 -class CustomLcdDisplay : public LcdDisplay { -public: - CustomLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy); -private: - static bool lvgl_port_flush_io_ready_callback(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx); - static void lvgl_port_flush_callback(lv_display_t *drv, const lv_area_t *area, uint8_t *color_map); -}; - - - -#endif // __CUSTOM_LCD_DISPLAY_H__ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/waveshare-s3-touch-lcd-3.5b.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/waveshare-s3-touch-lcd-3.5b.cc deleted file mode 100644 index e52dd8fa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-3.5b/waveshare-s3-touch-lcd-3.5b.cc +++ /dev/null @@ -1,365 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" - -#include -#include "i2c_device.h" -#include -#include -#include -#include -#include - -#include -#include "esp_io_expander_tca9554.h" - -#include "axp2101.h" -#include "power_save_timer.h" - -#include "esp_lcd_axs15231b.h" - -#include "custom_lcd_display.h" - -#include - -#include -#include -#include "esp32_camera.h" - -#define TAG "waveshare_lcd_3_5b" - -static const axs15231b_lcd_init_cmd_t lcd_init_cmds[] = { - {0xBB, (uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5}, 8, 0}, - {0xA0, (uint8_t[]){0xC0, 0x10, 0x00, 0x02, 0x00, 0x00, 0x04, 0x3F, 0x20, 0x05, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00}, 17, 0}, - {0xA2, (uint8_t[]){0x30, 0x3C, 0x24, 0x14, 0xD0, 0x20, 0xFF, 0xE0, 0x40, 0x19, 0x80, 0x80, 0x80, 0x20, 0xf9, 0x10, 0x02, 0xff, 0xff, 0xF0, 0x90, 0x01, 0x32, 0xA0, 0x91, 0xE0, 0x20, 0x7F, 0xFF, 0x00, 0x5A}, 31, 0}, - {0xD0, (uint8_t[]){0xE0, 0x40, 0x51, 0x24, 0x08, 0x05, 0x10, 0x01, 0x20, 0x15, 0x42, 0xC2, 0x22, 0x22, 0xAA, 0x03, 0x10, 0x12, 0x60, 0x14, 0x1E, 0x51, 0x15, 0x00, 0x8A, 0x20, 0x00, 0x03, 0x3A, 0x12}, 30, 0}, - {0xA3, (uint8_t[]){0xA0, 0x06, 0xAa, 0x00, 0x08, 0x02, 0x0A, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x55, 0x55}, 22, 0}, - {0xC1, (uint8_t[]){0x31, 0x04, 0x02, 0x02, 0x71, 0x05, 0x24, 0x55, 0x02, 0x00, 0x41, 0x00, 0x53, 0xFF, 0xFF, 0xFF, 0x4F, 0x52, 0x00, 0x4F, 0x52, 0x00, 0x45, 0x3B, 0x0B, 0x02, 0x0d, 0x00, 0xFF, 0x40}, 30, 0}, - {0xC3, (uint8_t[]){0x00, 0x00, 0x00, 0x50, 0x03, 0x00, 0x00, 0x00, 0x01, 0x80, 0x01}, 11, 0}, - {0xC4, (uint8_t[]){0x00, 0x24, 0x33, 0x80, 0x00, 0xea, 0x64, 0x32, 0xC8, 0x64, 0xC8, 0x32, 0x90, 0x90, 0x11, 0x06, 0xDC, 0xFA, 0x00, 0x00, 0x80, 0xFE, 0x10, 0x10, 0x00, 0x0A, 0x0A, 0x44, 0x50}, 29, 0}, - {0xC5, (uint8_t[]){0x18, 0x00, 0x00, 0x03, 0xFE, 0x3A, 0x4A, 0x20, 0x30, 0x10, 0x88, 0xDE, 0x0D, 0x08, 0x0F, 0x0F, 0x01, 0x3A, 0x4A, 0x20, 0x10, 0x10, 0x00}, 23, 0}, - {0xC6, (uint8_t[]){0x05, 0x0A, 0x05, 0x0A, 0x00, 0xE0, 0x2E, 0x0B, 0x12, 0x22, 0x12, 0x22, 0x01, 0x03, 0x00, 0x3F, 0x6A, 0x18, 0xC8, 0x22}, 20, 0}, - {0xC7, (uint8_t[]){0x50, 0x32, 0x28, 0x00, 0xa2, 0x80, 0x8f, 0x00, 0x80, 0xff, 0x07, 0x11, 0x9c, 0x67, 0xff, 0x24, 0x0c, 0x0d, 0x0e, 0x0f}, 20, 0}, - {0xC9, (uint8_t[]){0x33, 0x44, 0x44, 0x01}, 4, 0}, - {0xCF, (uint8_t[]){0x2C, 0x1E, 0x88, 0x58, 0x13, 0x18, 0x56, 0x18, 0x1E, 0x68, 0x88, 0x00, 0x65, 0x09, 0x22, 0xC4, 0x0C, 0x77, 0x22, 0x44, 0xAA, 0x55, 0x08, 0x08, 0x12, 0xA0, 0x08}, 27, 0}, - {0xD5, (uint8_t[]){0x40, 0x8E, 0x8D, 0x01, 0x35, 0x04, 0x92, 0x74, 0x04, 0x92, 0x74, 0x04, 0x08, 0x6A, 0x04, 0x46, 0x03, 0x03, 0x03, 0x03, 0x82, 0x01, 0x03, 0x00, 0xE0, 0x51, 0xA1, 0x00, 0x00, 0x00}, 30, 0}, - {0xD6, (uint8_t[]){0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE, 0x93, 0x00, 0x01, 0x83, 0x07, 0x07, 0x00, 0x07, 0x07, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x84, 0x00, 0x20, 0x01, 0x00}, 30, 0}, - {0xD7, (uint8_t[]){0x03, 0x01, 0x0b, 0x09, 0x0f, 0x0d, 0x1E, 0x1F, 0x18, 0x1d, 0x1f, 0x19, 0x40, 0x8E, 0x04, 0x00, 0x20, 0xA0, 0x1F}, 19, 0}, - {0xD8, (uint8_t[]){0x02, 0x00, 0x0a, 0x08, 0x0e, 0x0c, 0x1E, 0x1F, 0x18, 0x1d, 0x1f, 0x19}, 12, 0}, - {0xD9, (uint8_t[]){0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, 12, 0}, - {0xDD, (uint8_t[]){0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F}, 12, 0}, - {0xDF, (uint8_t[]){0x44, 0x73, 0x4B, 0x69, 0x00, 0x0A, 0x02, 0x90}, 8, 0}, - {0xE0, (uint8_t[]){0x3B, 0x28, 0x10, 0x16, 0x0c, 0x06, 0x11, 0x28, 0x5c, 0x21, 0x0D, 0x35, 0x13, 0x2C, 0x33, 0x28, 0x0D}, 17, 0}, - {0xE1, (uint8_t[]){0x37, 0x28, 0x10, 0x16, 0x0b, 0x06, 0x11, 0x28, 0x5C, 0x21, 0x0D, 0x35, 0x14, 0x2C, 0x33, 0x28, 0x0F}, 17, 0}, - {0xE2, (uint8_t[]){0x3B, 0x07, 0x12, 0x18, 0x0E, 0x0D, 0x17, 0x35, 0x44, 0x32, 0x0C, 0x14, 0x14, 0x36, 0x3A, 0x2F, 0x0D}, 17, 0}, - {0xE3, (uint8_t[]){0x37, 0x07, 0x12, 0x18, 0x0E, 0x0D, 0x17, 0x35, 0x44, 0x32, 0x0C, 0x14, 0x14, 0x36, 0x32, 0x2F, 0x0F}, 17, 0}, - {0xE4, (uint8_t[]){0x3B, 0x07, 0x12, 0x18, 0x0E, 0x0D, 0x17, 0x39, 0x44, 0x2E, 0x0C, 0x14, 0x14, 0x36, 0x3A, 0x2F, 0x0D}, 17, 0}, - {0xE5, (uint8_t[]){0x37, 0x07, 0x12, 0x18, 0x0E, 0x0D, 0x17, 0x39, 0x44, 0x2E, 0x0C, 0x14, 0x14, 0x36, 0x3A, 0x2F, 0x0F}, 17, 0}, - {0xA4, (uint8_t[]){0x85, 0x85, 0x95, 0x82, 0xAF, 0xAA, 0xAA, 0x80, 0x10, 0x30, 0x40, 0x40, 0x20, 0xFF, 0x60, 0x30}, 16, 0}, - {0xA4, (uint8_t[]){0x85, 0x85, 0x95, 0x85}, 4, 0}, - {0xBB, (uint8_t[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 8, 0}, - {0x13, (uint8_t[]){0x00}, 0, 0}, - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0x2C, (uint8_t[]){0x00, 0x00, 0x00, 0x00}, 4, 0}, - {0x2a, (uint8_t[]){0x00, 0x00, 0x01, 0x3f}, 4, 0}, - {0x2b, (uint8_t[]){0x00, 0x00, 0x01, 0xdf}, 4, 0}}; - -class Pmic : public Axp2101 { - public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - WriteReg(0x96, (1500 - 500) / 100); - WriteReg(0x97, (2800 - 500) / 100); - - // Enable ALDO1 BLDO1 BLDO2 - WriteReg(0x90, 0x31); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } - }; - -class CustomBoard : public WifiBoard { -private: - Button boot_button_; - Pmic* pmic_ = nullptr; - i2c_master_bus_handle_t i2c_bus_; - esp_io_expander_handle_t io_expander = NULL; - LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - Esp32Camera* camera_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(20); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - pmic_->PowerOff(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = (i2c_port_t)I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) - { - esp_err_t ret = esp_io_expander_new_i2c_tca9554(i2c_bus_, ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000, &io_expander); - if(ret != ESP_OK) - ESP_LOGE(TAG, "TCA9554 create returned error"); - ret = esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, IO_EXPANDER_OUTPUT); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_0 | IO_EXPANDER_PIN_NUM_1, 0); - ESP_ERROR_CHECK(ret); - vTaskDelay(pdMS_TO_TICKS(100)); - ret = esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_1, 1); - ESP_ERROR_CHECK(ret); - } - - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeSpi() { - ESP_LOGI(TAG, "Initialize QSPI bus"); - spi_bus_config_t buscfg = {}; - buscfg.data0_io_num = DISPLAY_DATA0_PIN; - buscfg.data1_io_num = DISPLAY_DATA1_PIN; - buscfg.data2_io_num = DISPLAY_DATA2_PIN; - buscfg.data3_io_num = DISPLAY_DATA3_PIN; - buscfg.sclk_io_num = DISPLAY_CLK_PIN; - buscfg.max_transfer_sz = DISPLAY_TRANS_SIZE * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeCamera() { - static esp_cam_ctlr_dvp_pin_config_t dvp_pin_config = { - .data_width = CAM_CTLR_DATA_WIDTH_8, - .data_io = { - [0] = CAM_PIN_D0, - [1] = CAM_PIN_D1, - [2] = CAM_PIN_D2, - [3] = CAM_PIN_D3, - [4] = CAM_PIN_D4, - [5] = CAM_PIN_D5, - [6] = CAM_PIN_D6, - [7] = CAM_PIN_D7, - }, - .vsync_io = CAM_PIN_VSYNC, - .de_io = CAM_PIN_HREF, - .pclk_io = CAM_PIN_PCLK, - .xclk_io = CAM_PIN_XCLK, - }; - - esp_video_init_sccb_config_t sccb_config = { - .init_sccb = false, // 不初始化新的 SCCB,使用现有的 I2C 总线 - .i2c_handle = i2c_bus_, // 使用现有的 I2C 总线句柄 - .freq = 100000, // 100kHz - }; - - esp_video_init_dvp_config_t dvp_config = { - .sccb_config = sccb_config, - .reset_pin = CAM_PIN_RESET, - .pwdn_pin = CAM_PIN_PWDN, - .dvp_pin = dvp_pin_config, - .xclk_freq = 12000000, - }; - - esp_video_init_config_t video_config = { - .dvp = &dvp_config, - }; - - camera_ = new Esp32Camera(video_config); - - } - - void InitializeLcdDisplay() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGI(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = AXS15231B_PANEL_IO_QSPI_CONFIG( - DISPLAY_CS_PIN, - NULL, - NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI2_HOST, &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片 - ESP_LOGI(TAG, "Install LCD driver"); - const axs15231b_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, // Uncomment these line if use custom initialization commands - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]), - .flags = { - .use_qspi_interface = 1, - }, - }; - esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = DISPLAY_RST_PIN, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .vendor_config = (void *)&vendor_config, - }; - esp_lcd_new_panel_axs15231b(panel_io, &panel_config, &panel); - - esp_lcd_panel_reset(panel); - - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, DISPLAY_INVERT_COLOR); - // esp_lcd_panel_disp_on_off(panel, false); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - - display_ = new CustomLcdDisplay(panel_io, panel, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 1, - .mirror_x = 1, - .mirror_y = 1, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_AXS15231B_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_axs15231b(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - -public: - CustomBoard() : - boot_button_(BOOT_BUTTON_GPIO) { - - InitializeI2c(); - InitializeTca9554(); - - InitializeAxp2101(); -#if PMIC_ENABLE - InitializePowerSaveTimer(); -#endif - InitializeSpi(); - InitializeLcdDisplay(); -#if TOUCH_ENABLE - InitializeTouch(); -#endif - InitializeButtons(); - InitializeCamera(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - virtual Camera* GetCamera() override { - return camera_; - } - -#if PMIC_ENABLE - virtual bool GetBatteryLevel(int &level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -#endif -}; - -DECLARE_BOARD(CustomBoard); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/README.md deleted file mode 100644 index 81dc4505..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Waveshare ESP32-S3-Touch-LCD-4B - - -[ESP32-S3-Touch-LCD-4B](https://www.waveshare.com/esp32-s3-touch-lcd-4b.htm) is waveshare electronics designed an intelligent 86 box based on ESP32-S3 module equipped with a 480*480 IPS capacitive touch screen - - -## Configuration - -Configuration in `menuconfig`. - -Selection Board Type `Xiaozhi Assistant --> Board Type` -- Waveshare ESP32-S3-Touch-LCD-4B \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.h deleted file mode 100644 index aba2eac6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_7 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_16 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_15 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_6 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_NC -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_47 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_48 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR -#define AUDIO_CODEC_ES7210_ADDR ES7210_CODEC_DEFAULT_ADDR - -#define I2C_ADDRESS ESP_IO_EXPANDER_I2C_TCA9554_ADDRESS_000 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -#define BSP_LCD_VSYNC (GPIO_NUM_3) -#define BSP_LCD_HSYNC (GPIO_NUM_46) -#define BSP_LCD_DE (GPIO_NUM_17) -#define BSP_LCD_PCLK (GPIO_NUM_9) -#define BSP_LCD_DISP (GPIO_NUM_NC) -#define BSP_LCD_DATA0 (GPIO_NUM_40) -#define BSP_LCD_DATA1 (GPIO_NUM_41) -#define BSP_LCD_DATA2 (GPIO_NUM_42) -#define BSP_LCD_DATA3 (GPIO_NUM_2) -#define BSP_LCD_DATA4 (GPIO_NUM_1) -#define BSP_LCD_DATA5 (GPIO_NUM_21) -#define BSP_LCD_DATA6 (GPIO_NUM_8) -#define BSP_LCD_DATA7 (GPIO_NUM_18) -#define BSP_LCD_DATA8 (GPIO_NUM_45) -#define BSP_LCD_DATA9 (GPIO_NUM_38) -#define BSP_LCD_DATA10 (GPIO_NUM_39) -#define BSP_LCD_DATA11 (GPIO_NUM_10) -#define BSP_LCD_DATA12 (GPIO_NUM_11) -#define BSP_LCD_DATA13 (GPIO_NUM_12) -#define BSP_LCD_DATA14 (GPIO_NUM_13) -#define BSP_LCD_DATA15 (GPIO_NUM_14) - -#define BSP_LCD_IO_SPI_CS (IO_EXPANDER_PIN_NUM_0) -#define BSP_LCD_IO_SPI_SCL (IO_EXPANDER_PIN_NUM_2) -#define BSP_LCD_IO_SPI_SDA (IO_EXPANDER_PIN_NUM_1) - -#define DISPLAY_WIDTH 480 -#define DISPLAY_HEIGHT 480 - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_4 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.json deleted file mode 100644 index f703cc0d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/config.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "waveshare-s3-touch-lcd-4b", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/esp32-s3-touch-lcd-4b.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/esp32-s3-touch-lcd-4b.cc deleted file mode 100644 index 5b65e79d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/waveshare-s3-touch-lcd-4b/esp32-s3-touch-lcd-4b.cc +++ /dev/null @@ -1,431 +0,0 @@ -#include "wifi_board.h" -#include "display/lcd_display.h" -#include "esp_lcd_st7701.h" - -#include "codecs/box_audio_codec.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "config.h" -#include "power_save_timer.h" -#include "axp2101.h" -#include "i2c_device.h" - -#include -#include -#include -#include -#include "esp_io_expander_tca9554.h" -#include "settings.h" - -#include -#include -#include - -#include -#include -#include -#include - -#define TAG "WaveshareEsp32s3TouchLCD4b" - -class Pmic : public Axp2101 { -public: - Pmic(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : Axp2101(i2c_bus, addr) { - WriteReg(0x22, 0b110); // PWRON > OFFLEVEL as POWEROFF Source enable - WriteReg(0x27, 0x10); // hold 4s to power off - - // Disable All DCs but DC1 - WriteReg(0x80, 0x01); - // Disable All LDOs - WriteReg(0x90, 0x00); - WriteReg(0x91, 0x00); - - // Set DC1 to 3.3V - WriteReg(0x82, (3300 - 1500) / 100); - - // Set ALDO1 to 3.3V - WriteReg(0x92, (3300 - 500) / 100); - - // Enable ALDO1(MIC) - WriteReg(0x90, 0x01); - - WriteReg(0x64, 0x02); // CV charger voltage setting to 4.1V - - WriteReg(0x61, 0x02); // set Main battery precharge current to 50mA - WriteReg(0x62, 0x08); // set Main battery charger current to 400mA ( 0x08-200mA, 0x09-300mA, 0x0A-400mA ) - WriteReg(0x63, 0x01); // set Main battery term charge current to 25mA - } -}; - -#define LCD_OPCODE_WRITE_CMD (0x02ULL) -#define LCD_OPCODE_READ_CMD (0x03ULL) -#define LCD_OPCODE_WRITE_COLOR (0x32ULL) - -static const st7701_lcd_init_cmd_t lcd_init_cmds[] = { -// {cmd, { data }, data_size, delay_ms} - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0xFF, (uint8_t[]){0x77, 0x01, 0x00, 0x00, 0x10}, 5, 0}, - {0xC0, (uint8_t[]){0x3B, 0x00}, 2, 0}, - {0xC1, (uint8_t[]){0x0D, 0x02}, 2, 0}, - {0xC2, (uint8_t[]){0x21, 0x08}, 2, 0}, - {0xCD, (uint8_t[]){0x08}, 1, 0}, - {0xB0, (uint8_t[]){0x00, 0x11, 0x18, 0x0E, 0x11, 0x06, 0x07, 0x08, 0x07, 0x22, 0x04, 0x12, 0x0F, 0xAA, 0x31, 0x18}, 16, 0}, - {0xB1, (uint8_t[]){0x00, 0x11, 0x19, 0x0E, 0x12, 0x07, 0x08, 0x08, 0x08, 0x22, 0x04, 0x11, 0x11, 0xA9, 0x32, 0x18}, 16, 0}, - {0xFF, (uint8_t[]){0x77, 0x01, 0x00, 0x00, 0x11}, 5, 0}, - {0xB0, (uint8_t[]){0x60}, 1, 0}, - {0xB1, (uint8_t[]){0x30}, 1, 0}, - {0xB2, (uint8_t[]){0x87}, 1, 0}, - {0xB3, (uint8_t[]){0x80}, 1, 0}, - {0xB5, (uint8_t[]){0x49}, 1, 0}, - {0xB7, (uint8_t[]){0x85}, 1, 0}, - {0xB8, (uint8_t[]){0x21}, 1, 0}, - {0xC1, (uint8_t[]){0x78}, 1, 0}, - {0xC2, (uint8_t[]){0x78}, 1, 20}, - {0xE0, (uint8_t[]){0x00, 0x1B, 0x02}, 3, 0}, - {0xE1, (uint8_t[]){0x08, 0xA0, 0x00, 0x00, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x44, 0x44}, 11, 0}, - {0xE2, (uint8_t[]){0x11, 0x11, 0x44, 0x44, 0xED, 0xA0, 0x00, 0x00, 0xEC, 0xA0, 0x00, 0x00}, 12, 0}, - {0xE3, (uint8_t[]){0x00, 0x00, 0x11, 0x11}, 4, 0}, - {0xE4, (uint8_t[]){0x44, 0x44}, 2, 0}, - {0xE5, (uint8_t[]){0x0A, 0xE9, 0xD8, 0xA0, 0x0C, 0xEB, 0xD8, 0xA0, 0x0E, 0xED, 0xD8, 0xA0, 0x10, 0xEF, 0xD8, 0xA0}, 16, 0}, - {0xE6, (uint8_t[]){0x00, 0x00, 0x11, 0x11}, 4, 0}, - {0xE7, (uint8_t[]){0x44, 0x44}, 2, 0}, - {0xE8, (uint8_t[]){0x09, 0xE8, 0xD8, 0xA0, 0x0B, 0xEA, 0xD8, 0xA0, 0x0D, 0xEC, 0xD8, 0xA0, 0x0F, 0xEE, 0xD8, 0xA0}, 16, 0}, - {0xEB, (uint8_t[]){0x02, 0x00, 0xE4, 0xE4, 0x88, 0x00, 0x40}, 7, 0}, - {0xEC, (uint8_t[]){0x3C, 0x00}, 2, 0}, - {0xED, (uint8_t[]){0xAB, 0x89, 0x76, 0x54, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x45, 0x67, 0x98, 0xBA}, 16, 0}, - {0xFF, (uint8_t[]){0x77, 0x01, 0x00, 0x00, 0x00}, 5, 0}, - {0x36, (uint8_t[]){0x00}, 1, 0}, - {0x3A, (uint8_t[]){0x66}, 1, 0}, - {0x21, (uint8_t[]){0x00}, 0, 120}, - {0x29, (uint8_t[]){0x00}, 0, 0}, -}; - -class WaveshareEsp32s3TouchLCD4b : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Pmic* pmic_ = nullptr; - Button boot_button_; - LcdDisplay* display_; - esp_io_expander_handle_t io_expander = NULL; - PowerSaveTimer* power_save_timer_; - - uint32_t key_press_start; - bool key_pressed; - bool key_handled; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(70); }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); }); - power_save_timer_->OnShutdownRequest([this](){ - pmic_->PowerOff(); }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - void InitializeTca9554(void) { - esp_io_expander_new_i2c_tca9554(i2c_bus_, I2C_ADDRESS, &io_expander); - esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_3|IO_EXPANDER_PIN_NUM_5 | IO_EXPANDER_PIN_NUM_6 , IO_EXPANDER_OUTPUT); - esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_3, 1); - esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_6, 0); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_5, 0); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_io_expander_set_level(io_expander, IO_EXPANDER_PIN_NUM_5, 1); - vTaskDelay(pdMS_TO_TICKS(200)); - esp_io_expander_set_dir(io_expander, IO_EXPANDER_PIN_NUM_4|IO_EXPANDER_PIN_NUM_6, IO_EXPANDER_INPUT); - } - void InitializeAxp2101() { - ESP_LOGI(TAG, "Init AXP2101"); - pmic_ = new Pmic(i2c_bus_, 0x34); - } - - void InitializeRGB() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - - spi_line_config_t line_config = { - .cs_io_type = IO_TYPE_EXPANDER, - .cs_expander_pin = BSP_LCD_IO_SPI_CS, - .scl_io_type = IO_TYPE_EXPANDER, - .scl_expander_pin = BSP_LCD_IO_SPI_SCL, - .sda_io_type = IO_TYPE_EXPANDER, - .sda_expander_pin = BSP_LCD_IO_SPI_SDA, - .io_expander = io_expander, - }; - esp_lcd_panel_io_3wire_spi_config_t io_config = ST7701_PANEL_IO_3WIRE_SPI_CONFIG(line_config, 0); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_3wire_spi(&io_config, &panel_io)); - esp_lcd_panel_handle_t panel_handle = NULL; - esp_lcd_rgb_panel_config_t rgb_config = { - .clk_src = LCD_CLK_SRC_DEFAULT, - .timings = { - .pclk_hz = 16 * 1000 * 1000, - .h_res = DISPLAY_WIDTH, - .v_res = DISPLAY_HEIGHT, - .hsync_pulse_width = 10, - .hsync_back_porch = 10, - .hsync_front_porch = 20, - .vsync_pulse_width = 10, - .vsync_back_porch = 10, - .vsync_front_porch = 10, - .flags = { - .pclk_active_neg = false - } - }, - .data_width = 16, - .bits_per_pixel = 16, - .num_fbs = 2, - .bounce_buffer_size_px = 480 * 20, - .psram_trans_align = 64, - .hsync_gpio_num = BSP_LCD_HSYNC, - .vsync_gpio_num = BSP_LCD_VSYNC, - .de_gpio_num = BSP_LCD_DE, - .pclk_gpio_num = BSP_LCD_PCLK, - .disp_gpio_num = BSP_LCD_DISP, - .data_gpio_nums = { - BSP_LCD_DATA0, BSP_LCD_DATA1, BSP_LCD_DATA2, BSP_LCD_DATA3, - BSP_LCD_DATA4, BSP_LCD_DATA5, BSP_LCD_DATA6, BSP_LCD_DATA7, - BSP_LCD_DATA8, BSP_LCD_DATA9, BSP_LCD_DATA10, BSP_LCD_DATA11, - BSP_LCD_DATA12, BSP_LCD_DATA13, BSP_LCD_DATA14, BSP_LCD_DATA15 - }, - .flags = { - .fb_in_psram = 1, - }, - }; - - rgb_config.timings.h_res = DISPLAY_WIDTH; - rgb_config.timings.v_res = DISPLAY_HEIGHT; - st7701_vendor_config_t vendor_config = { - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(lcd_init_cmds[0]), - .rgb_config = &rgb_config, - .flags = { - .mirror_by_cmd = 0, - .auto_del_panel_io = 1, - } - }; - const esp_lcd_panel_dev_config_t panel_config = { - .reset_gpio_num = GPIO_NUM_NC, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 18, - .vendor_config = &vendor_config, - }; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7701(panel_io, &panel_config, &panel_handle)); - esp_lcd_panel_init(panel_handle); - - display_ = new RgbLcdDisplay(panel_io, panel_handle, - DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - -#if CONFIG_USE_DEVICE_AEC - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - app.SetAecMode(app.GetAecMode() == kAecOff ? kAecOnDeviceSide : kAecOff); - } - }); -#endif - } - - void InitializeTouch() { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH - 1, - .y_max = DISPLAY_HEIGHT - 1, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_NC, - .levels = { - .reset = 0, - .interrupt = 0, - }, - .flags = { - .swap_xy = 0, - .mirror_x = 0, - .mirror_y = 0, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.scl_speed_hz = 400* 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - void InitializeTools() { - auto &mcp_server = McpServer::GetInstance(); - mcp_server.AddTool("self.system.reconfigure_wifi", - "End this conversation and enter WiFi configuration mode.\n" - "**CAUTION** You must ask the user to confirm this action.", - PropertyList(), [this](const PropertyList& properties) { - EnterWifiConfigMode(); - return true; - }); - } - void CheckKeyState() { - if (!io_expander) return; - - uint32_t current_level; - esp_err_t ret = esp_io_expander_get_level(io_expander, IO_EXPANDER_PIN_NUM_4, ¤t_level); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to read IO_EXPANDER_PIN_NUM_4 level"); - return; - } - - static uint32_t last_level = 0; - static uint64_t press_start_time_ms = 0; - - if (current_level != last_level) { - last_level = current_level; - - if (current_level > 0) { - press_start_time_ms = esp_timer_get_time() / 1000; - ESP_LOGD(TAG, "Button pressed, start time recorded"); - } else { - uint64_t press_duration = (esp_timer_get_time() / 1000) - press_start_time_ms; - ESP_LOGI(TAG, "Button released after %llums", press_duration); - - if (press_duration < 1000) { - ESP_LOGI(TAG, "Short press detected, switching to factory partition"); - - const esp_partition_t* factory_partition = esp_partition_find_first( - ESP_PARTITION_TYPE_APP, - ESP_PARTITION_SUBTYPE_APP_FACTORY, - nullptr - ); - if (factory_partition) { - ESP_LOGI(TAG, "Found factory partition: %s", factory_partition->label); - ESP_ERROR_CHECK(esp_ota_set_boot_partition(factory_partition)); - esp_restart(); - } else { - ESP_LOGE(TAG, "Factory partition not found"); - } - } else { - ESP_LOGI(TAG, "Long press detected (>1000ms), no action"); - } - } - } - } - - void InitializeKeyMonitor() { - key_press_start = 0; - key_pressed = false; - key_handled = false; - - xTaskCreatePinnedToCore( - [](void* arg) { - auto* board = static_cast(arg); - while (true) { - board->CheckKeyState(); - vTaskDelay(pdMS_TO_TICKS(20)); - } - }, - "key_monitor_task", - 4096, - this, - 5, - nullptr, - 0 - ); - } - -public: - WaveshareEsp32s3TouchLCD4b() : boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeTca9554(); - InitializeAxp2101(); - InitializeRGB(); - InitializeTouch(); - InitializeButtons(); - InitializeTools(); - InitializeKeyMonitor(); // 启动按键监听 - GetBacklight()->SetBrightness(100); - } - - virtual AudioCodec* GetAudioCodec() override { - static BoxAudioCodec audio_codec( - i2c_bus_, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_CODEC_ES7210_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int &level, bool &charging, bool &discharging) override { - static bool last_discharging = false; - charging = pmic_->IsCharging(); - discharging = pmic_->IsDischarging(); - if (discharging != last_discharging) - { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - - level = pmic_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(WaveshareEsp32s3TouchLCD4b); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/README.md deleted file mode 100644 index 381aa920..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/README.md +++ /dev/null @@ -1,45 +0,0 @@ -## Wireless-Tag WTP4C5MP07S - -[Wireless-Tag WTP4C5MP07S](https://shop.wireless-tag.com/products/7inch-lcd-touch-screen-1024x600-mipi-smart-displays-wtp4c5mp07s-esp32-lcd-board-used-with-esp32-p4-and-esp32-c5-dev-board) product is a combo of -* [Wireless-Tag WT99P4C5-S1](https://en.wireless-tag.com/product-item-66.html) ESP32-P4 development board and -* 7 inch 1024x600 ZX7D00C1060M002A MIPI DSI LCD display - -
    - -## Configuration - -### ESP32P4 Configuration - -* Set the compilation target to ESP32P4 - - idf.py set-target esp32p4 - -* Open menuconfig - - idf.py menuconfig - -* Select the board - - Xiaozhi Assistant -> Board Type -> Wireless-Tag WTP4C5MP07S - -* Select PSRAM - - Component config -> ESP PSRAM -> PSRAM config -> Try to allocate memories of WiFi and LWIP in SPIRAM firstly -> No - -* Select Wi-Fi slave target - - Component config -> Wi-Fi Remote -> choose slave target -> esp32c5 - -* Select Wi-Fi buffers - - Component config -> Wi-Fi Remote -> Wi-Fi configuration -> Max number of WiFi static RX buffers -> 10 - Component config -> Wi-Fi Remote -> Wi-Fi configuration -> Max number of WiFi dynamic RX buffers -> 24 - Component config -> Wi-Fi Remote -> Wi-Fi configuration -> Max number of WiFi static TX buffers -> 10 - -* Build - - idf.py build - -### ESP32C5 Configuration - -* Flash the slave example from the esp-hosted-mcu library for the target chip ESP32C5. The esp-hosted-mcu version must match the one used in the xiaozhi-esp32 library. diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.h deleted file mode 100644 index b3ae81ed..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.h +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_10 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_9 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_53 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_7 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_8 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_GPIO GPIO_NUM_35 - -#define DISPLAY_WIDTH 1024 -#define DISPLAY_HEIGHT 600 - -#define LCD_BIT_PER_PIXEL (16) -#define PIN_NUM_LCD_RST GPIO_NUM_23 - -#define DELAY_TIME_MS (3000) -#define LCD_MIPI_DSI_LANE_NUM (2) // 2 data lanes - -#define MIPI_DSI_PHY_PWR_LDO_CHAN (3) -#define MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV (2500) - -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -// SD Card configuration (disabled by default) -// Enable one of the following by setting to 1 and set pins accordingly. -// Note: SDMMC may conflict with ESP-Hosted SDIO. If using ESP-Hosted via SDIO, -// prefer SDSPI mode for SD card or disable hosted SDIO. - -// SDMMC 1-bit/4-bit mode -#ifndef SDCARD_SDMMC_ENABLED -#define SDCARD_SDMMC_ENABLED 0 -#endif -// SDMMC bus width: set to 1 or 4 -#ifndef SDCARD_SDMMC_BUS_WIDTH -// Use 4-bit bus width when enabling SDMMC -#define SDCARD_SDMMC_BUS_WIDTH 4 -#endif -// SDMMC pin assignments (set to actual pins when enabling SDMMC) -#ifndef SDCARD_SDMMC_CLK_PIN -#define SDCARD_SDMMC_CLK_PIN GPIO_NUM_43 // BSP_SD_CLK -#endif -#ifndef SDCARD_SDMMC_CMD_PIN -#define SDCARD_SDMMC_CMD_PIN GPIO_NUM_44 // BSP_SD_CMD -#endif -#ifndef SDCARD_SDMMC_D0_PIN -#define SDCARD_SDMMC_D0_PIN GPIO_NUM_39 // BSP_SD_D0 -#endif -#ifndef SDCARD_SDMMC_D1_PIN -#define SDCARD_SDMMC_D1_PIN GPIO_NUM_40 // BSP_SD_D1 -#endif -#ifndef SDCARD_SDMMC_D2_PIN -#define SDCARD_SDMMC_D2_PIN GPIO_NUM_41 // BSP_SD_D2 -#endif -#ifndef SDCARD_SDMMC_D3_PIN -#define SDCARD_SDMMC_D3_PIN GPIO_NUM_42 // BSP_SD_D3 -#endif - -// SDSPI mode (uses SPI bus) -#ifndef SDCARD_SDSPI_ENABLED -#define SDCARD_SDSPI_ENABLED 1 -#endif -#ifndef SDCARD_SPI_HOST -#define SDCARD_SPI_HOST SPI3_HOST -#endif -#ifndef SDCARD_SPI_MOSI -#define SDCARD_SPI_MOSI GPIO_NUM_44 // BSP_SD_SPI_MOSI -#endif -#ifndef SDCARD_SPI_MISO -#define SDCARD_SPI_MISO GPIO_NUM_39 // BSP_SD_SPI_MISO -#endif -#ifndef SDCARD_SPI_SCLK -#define SDCARD_SPI_SCLK GPIO_NUM_43 // BSP_SD_SPI_CLK -#endif -#ifndef SDCARD_SPI_CS -#define SDCARD_SPI_CS GPIO_NUM_42 // BSP_SD_SPI_CS -#endif - -#ifndef SDCARD_MOUNT_POINT -#define SDCARD_MOUNT_POINT "/sdcard" -#endif - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.json deleted file mode 100644 index 272ecfd2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/config.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "target": "esp32p4", - "builds": [ - { - "name": "wireless-tag-wtp4c5mp07s", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=n", - "CONFIG_SLAVE_IDF_TARGET_ESP32C5=y", - "CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP=n", - "CONFIG_WIFI_RMT_STATIC_RX_BUFFER_NUM=10", - "CONFIG_WIFI_RMT_DYNAMIC_RX_BUFFER_NUM=24", - "CONFIG_WIFI_RMT_STATIC_TX_BUFFER_NUM=10" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/wireless-tag-wtp4c5mp07s.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/wireless-tag-wtp4c5mp07s.cc deleted file mode 100644 index 2cef78bb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/wireless-tag-wtp4c5mp07s/wireless-tag-wtp4c5mp07s.cc +++ /dev/null @@ -1,297 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "application.h" -#include "display/lcd_display.h" -// #include "display/no_display.h" -#include "button.h" -#include "config.h" - -#include "esp_lcd_panel_ops.h" -#include "esp_lcd_mipi_dsi.h" -#include "esp_ldo_regulator.h" - -#include "esp_lcd_ek79007.h" - -#include -#include -#include -#include "esp_lcd_touch_gt911.h" - -#include -#include -#include -#include -#include "sd_pwr_ctrl_by_on_chip_ldo.h" - -#define TAG "WirelessTagEsp32p47b" - -class WirelessTagEsp32p47b : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - LcdDisplay *display_; - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_1, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - } - - static esp_err_t bsp_enable_dsi_phy_power(void) { -#if MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - // Turn on the power for MIPI DSI PHY, so it can go from "No Power" state to "Shutdown" state - static esp_ldo_channel_handle_t phy_pwr_chan = NULL; - esp_ldo_channel_config_t ldo_cfg = { - .chan_id = MIPI_DSI_PHY_PWR_LDO_CHAN, - .voltage_mv = MIPI_DSI_PHY_PWR_LDO_VOLTAGE_MV, - }; - esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan); - ESP_LOGI(TAG, "MIPI DSI PHY Powered on"); -#endif // BSP_MIPI_DSI_PHY_PWR_LDO_CHAN > 0 - - return ESP_OK; - } - - void InitializeLCD() { - bsp_enable_dsi_phy_power(); - esp_lcd_panel_io_handle_t io = NULL; - esp_lcd_panel_handle_t disp_panel = NULL; - - esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = 2, - .lane_bit_rate_mbps = 900, - }; - esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus); - - ESP_LOGI(TAG, "Install MIPI DSI LCD control panel"); - // we use DBI interface to send LCD commands and parameters - esp_lcd_dbi_io_config_t dbi_config = EK79007_PANEL_IO_DBI_CONFIG(); - esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io); - - esp_lcd_dpi_panel_config_t dpi_config = { - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = 52, - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, - .num_fbs = 1, - .video_timing = { - .h_size = 1024, - .v_size = 600, - .hsync_pulse_width = 10, - .hsync_back_porch = 160, - .hsync_front_porch = 160, - .vsync_pulse_width = 1, - .vsync_back_porch = 23, - .vsync_front_porch = 12, - }, - .flags = { - .use_dma2d = true, - }, - }; - ek79007_vendor_config_t vendor_config = { - .mipi_config = { - .dsi_bus = mipi_dsi_bus, - .dpi_config = &dpi_config, - }, - }; - - const esp_lcd_panel_dev_config_t lcd_dev_config = { - .reset_gpio_num = PIN_NUM_LCD_RST, - .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, - .bits_per_pixel = 16, - .flags = { - .reset_active_high = true, - }, - .vendor_config = &vendor_config, - }; - esp_lcd_new_panel_ek79007(io, &lcd_dev_config, &disp_panel); - esp_lcd_panel_reset(disp_panel); - esp_lcd_panel_init(disp_panel); - - display_ = new MipiLcdDisplay(io, disp_panel, DISPLAY_WIDTH, DISPLAY_HEIGHT, - DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); -#if 0 - lv_display_t *disp = lv_display_get_default(); - if (disp) { - lv_disp_set_rotation(disp, LV_DISPLAY_ROTATION_180); - ESP_LOGI(TAG, "Display rotated 180 degrees"); - } else { - ESP_LOGE(TAG, "Failed to get default display for rotation"); - } -#endif - } - - void InitializeTouch() - { - esp_lcd_touch_handle_t tp; - esp_lcd_touch_config_t tp_cfg = { - .x_max = DISPLAY_WIDTH, - .y_max = DISPLAY_HEIGHT, - .rst_gpio_num = GPIO_NUM_NC, - .int_gpio_num = GPIO_NUM_21, - .levels = { - .reset = 1, - .interrupt = 0, - }, - .flags = { - .swap_xy = DISPLAY_SWAP_XY, - .mirror_x = DISPLAY_MIRROR_X, - .mirror_y = DISPLAY_MIRROR_Y, - }, - }; - esp_lcd_panel_io_handle_t tp_io_handle = NULL; - esp_lcd_panel_io_i2c_config_t tp_io_config = ESP_LCD_TOUCH_IO_I2C_GT911_CONFIG(); - tp_io_config.scl_speed_hz = 400 * 1000; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c(i2c_bus_, &tp_io_config, &tp_io_handle)); - ESP_LOGI(TAG, "Initialize touch controller"); - ESP_ERROR_CHECK(esp_lcd_touch_new_i2c_gt911(tp_io_handle, &tp_cfg, &tp)); - const lvgl_port_touch_cfg_t touch_cfg = { - .disp = lv_display_get_default(), - .handle = tp, - }; - lvgl_port_add_touch(&touch_cfg); - ESP_LOGI(TAG, "Touch panel initialized successfully"); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT button enters Wi-Fi config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeSdCard() { -#if SDCARD_SDMMC_ENABLED - sd_pwr_ctrl_handle_t sd_ldo = NULL; - sd_pwr_ctrl_ldo_config_t ldo_cfg = { .ldo_chan_id = 4 }; - if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_cfg, &sd_ldo) == ESP_OK) { - ESP_LOGI(TAG, "SD LDO channel 4 enabled"); - } else { - ESP_LOGW(TAG, "Failed to enable SD LDO channel 4"); - } - sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); - // Map pins via GPIO matrix if needed - slot_config.clk = SDCARD_SDMMC_CLK_PIN; - slot_config.cmd = SDCARD_SDMMC_CMD_PIN; - slot_config.d0 = SDCARD_SDMMC_D0_PIN; - slot_config.width = SDCARD_SDMMC_BUS_WIDTH; - if (SDCARD_SDMMC_BUS_WIDTH == 4) { - slot_config.d1 = SDCARD_SDMMC_D1_PIN; - slot_config.d2 = SDCARD_SDMMC_D2_PIN; - slot_config.d3 = SDCARD_SDMMC_D3_PIN; - } - - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 5, - .allocation_unit_size = 0, - .disk_status_check_enable = true, - }; - sdmmc_card_t* card; - host.pwr_ctrl_handle = sd_ldo; - esp_err_t ret = esp_vfs_fat_sdmmc_mount(SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &card); - if (ret == ESP_OK) { - sdmmc_card_print_info(stdout, card); - ESP_LOGI(TAG, "SD card mounted at %s (SDMMC)", SDCARD_MOUNT_POINT); - } else { - ESP_LOGW(TAG, "Failed to mount SD card (SDMMC): %s", esp_err_to_name(ret)); - } -#elif SDCARD_SDSPI_ENABLED - sd_pwr_ctrl_handle_t sd_ldo = NULL; - sd_pwr_ctrl_ldo_config_t ldo_cfg = { .ldo_chan_id = 4 }; - if (sd_pwr_ctrl_new_on_chip_ldo(&ldo_cfg, &sd_ldo) == ESP_OK) { - ESP_LOGI(TAG, "SD LDO channel 4 enabled"); - } else { - ESP_LOGW(TAG, "Failed to enable SD LDO channel 4"); - } - sdmmc_host_t host = SDSPI_HOST_DEFAULT(); - spi_bus_config_t bus_cfg = { - .mosi_io_num = SDCARD_SPI_MOSI, - .miso_io_num = SDCARD_SPI_MISO, - .sclk_io_num = SDCARD_SPI_SCLK, - .quadwp_io_num = -1, - .quadhd_io_num = -1, - .max_transfer_sz = 4000, - }; - ESP_ERROR_CHECK_WITHOUT_ABORT(spi_bus_initialize((spi_host_device_t)SDCARD_SPI_HOST, &bus_cfg, SPI_DMA_CH_AUTO)); - sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT(); - slot_config.gpio_cs = SDCARD_SPI_CS; - slot_config.host_id = (spi_host_device_t)SDCARD_SPI_HOST; - - esp_vfs_fat_sdmmc_mount_config_t mount_config = { - .format_if_mount_failed = false, - .max_files = 5, - .allocation_unit_size = 0, - .disk_status_check_enable = true, - }; - sdmmc_card_t* card; - host.pwr_ctrl_handle = sd_ldo; - esp_err_t ret = esp_vfs_fat_sdspi_mount(SDCARD_MOUNT_POINT, &host, &slot_config, &mount_config, &card); - if (ret == ESP_OK) { - sdmmc_card_print_info(stdout, card); - ESP_LOGI(TAG, "SD card mounted at %s (SDSPI)", SDCARD_MOUNT_POINT); - } else { - ESP_LOGW(TAG, "Failed to mount SD card (SDSPI): %s", esp_err_to_name(ret)); - } -#else - ESP_LOGI(TAG, "SD card disabled (enable SDCARD_SDMMC_ENABLED or SDCARD_SDSPI_ENABLED)"); -#endif - } - -public: - WirelessTagEsp32p47b() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeLCD(); - InitializeTouch(); - InitializeSdCard(); - InitializeButtons(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_1, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, - AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual Display *GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - -}; - -DECLARE_BOARD(WirelessTagEsp32p47b); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.h deleted file mode 100644 index 7388d392..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.h +++ /dev/null @@ -1,40 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA GPIO_NUM_10 -#define DISPLAY_SCL GPIO_NUM_9 -#define DISPLAY_DC GPIO_NUM_8 -#define DISPLAY_CS GPIO_NUM_14 -#define DISPLAY_RES GPIO_NUM_18 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.json deleted file mode 100644 index 0305c46d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-0.85tft-ml307", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/xingzhi-cube-0.85tft-ml307.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/xingzhi-cube-0.85tft-ml307.cc deleted file mode 100644 index 0dac3b1a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-ml307/xingzhi-cube-0.85tft-ml307.cc +++ /dev/null @@ -1,239 +0,0 @@ -#include "ml307_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "../xingzhi-cube-1.54tft-wifi/power_manager.h" - -#include -#include - -#include -#include - -#include -#include "settings.h" - -#define TAG "XINGZHI_CUBE_0_85TFT_ML307" - -static const nv3023_lcd_init_cmd_t lcd_init_cmds[] = { - {0xff, (uint8_t[]){0xa5}, 1, 0}, - {0x3E, (uint8_t[]){0x09}, 1, 0}, - {0x3A, (uint8_t[]){0x65}, 1, 0}, - {0x82, (uint8_t[]){0x00}, 1, 0}, - {0x98, (uint8_t[]){0x00}, 1, 0}, - {0x63, (uint8_t[]){0x0f}, 1, 0}, - {0x64, (uint8_t[]){0x0f}, 1, 0}, - {0xB4, (uint8_t[]){0x34}, 1, 0}, - {0xB5, (uint8_t[]){0x30}, 1, 0}, - {0x83, (uint8_t[]){0x03}, 1, 0}, - {0x86, (uint8_t[]){0x04}, 1, 0}, - {0x87, (uint8_t[]){0x16}, 1, 0}, - {0x88, (uint8_t[]){0x0A}, 1, 0}, - {0x89, (uint8_t[]){0x27}, 1, 0}, - {0x93, (uint8_t[]){0x63}, 1, 0}, - {0x96, (uint8_t[]){0x81}, 1, 0}, - {0xC3, (uint8_t[]){0x10}, 1, 0}, - {0xE6, (uint8_t[]){0x00}, 1, 0}, - {0x99, (uint8_t[]){0x01}, 1, 0}, - {0x70, (uint8_t[]){0x09}, 1, 0}, - {0x71, (uint8_t[]){0x1D}, 1, 0}, - {0x72, (uint8_t[]){0x14}, 1, 0}, - {0x73, (uint8_t[]){0x0a}, 1, 0}, - {0x74, (uint8_t[]){0x11}, 1, 0}, - {0x75, (uint8_t[]){0x16}, 1, 0}, - {0x76, (uint8_t[]){0x38}, 1, 0}, - {0x77, (uint8_t[]){0x0B}, 1, 0}, - {0x78, (uint8_t[]){0x08}, 1, 0}, - {0x79, (uint8_t[]){0x3E}, 1, 0}, - {0x7a, (uint8_t[]){0x07}, 1, 0}, - {0x7b, (uint8_t[]){0x0D}, 1, 0}, - {0x7c, (uint8_t[]){0x16}, 1, 0}, - {0x7d, (uint8_t[]){0x0F}, 1, 0}, - {0x7e, (uint8_t[]){0x14}, 1, 0}, - {0x7f, (uint8_t[]){0x05}, 1, 0}, - {0xa0, (uint8_t[]){0x04}, 1, 0}, - {0xa1, (uint8_t[]){0x28}, 1, 0}, - {0xa2, (uint8_t[]){0x0c}, 1, 0}, - {0xa3, (uint8_t[]){0x11}, 1, 0}, - {0xa4, (uint8_t[]){0x0b}, 1, 0}, - {0xa5, (uint8_t[]){0x23}, 1, 0}, - {0xa6, (uint8_t[]){0x45}, 1, 0}, - {0xa7, (uint8_t[]){0x07}, 1, 0}, - {0xa8, (uint8_t[]){0x0a}, 1, 0}, - {0xa9, (uint8_t[]){0x3b}, 1, 0}, - {0xaa, (uint8_t[]){0x0d}, 1, 0}, - {0xab, (uint8_t[]){0x18}, 1, 0}, - {0xac, (uint8_t[]){0x14}, 1, 0}, - {0xad, (uint8_t[]){0x0F}, 1, 0}, - {0xae, (uint8_t[]){0x19}, 1, 0}, - {0xaf, (uint8_t[]){0x08}, 1, 0}, - {0xff, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0x29, (uint8_t[]){0x00}, 0, 10} -}; - -class XINGZHI_CUBE_0_85TFT_ML307 : public Ml307Board { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_HEIGHT * 80 *sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - app.ToggleChatState(); - }); - } - - void InitializeNv3023Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = NV3023_PANEL_IO_SPI_CONFIG(DISPLAY_CS, DISPLAY_DC, NULL, NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - nv3023_vendor_config_t vendor_config = { // Uncomment these lines if use custom initialization commands - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(nv3023_lcd_init_cmd_t), - }; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_nv3023(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new SpiLcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void Initializegpio21_45() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - //gpio_num_t sp_45 = GPIO_NUM_45; - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << GPIO_NUM_45); - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; - gpio_config(&io_conf); - gpio_set_level(GPIO_NUM_45, 0); - } - -public: - XINGZHI_CUBE_0_85TFT_ML307(): Ml307Board(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - Initializegpio21_45(); // 初始时,拉高21引脚,保证4g模块正常工作 - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeNv3023Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - Ml307Board::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_0_85TFT_ML307); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.h deleted file mode 100644 index 8b2bf9d3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.h +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_NC -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_NC - -#define DISPLAY_SDA GPIO_NUM_10 -#define DISPLAY_SCL GPIO_NUM_9 -#define DISPLAY_DC GPIO_NUM_8 -#define DISPLAY_CS GPIO_NUM_14 -#define DISPLAY_RES GPIO_NUM_18 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 128 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.json deleted file mode 100644 index 867160f8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-0.85tft-wifi", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/xingzhi-cube-0.85tft-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/xingzhi-cube-0.85tft-wifi.cc deleted file mode 100644 index 3b2a0b3f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.85tft-wifi/xingzhi-cube-0.85tft-wifi.cc +++ /dev/null @@ -1,244 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "../xingzhi-cube-1.54tft-wifi/power_manager.h" - -#include -#include - -#include -#include - -#include -#include "settings.h" - -#define TAG "XINGZHI_CUBE_0_85TFT_WIFI" - -static const nv3023_lcd_init_cmd_t lcd_init_cmds[] = { - {0xff, (uint8_t[]){0xa5}, 1, 0}, - {0x3E, (uint8_t[]){0x09}, 1, 0}, - {0x3A, (uint8_t[]){0x65}, 1, 0}, - {0x82, (uint8_t[]){0x00}, 1, 0}, - {0x98, (uint8_t[]){0x00}, 1, 0}, - {0x63, (uint8_t[]){0x0f}, 1, 0}, - {0x64, (uint8_t[]){0x0f}, 1, 0}, - {0xB4, (uint8_t[]){0x34}, 1, 0}, - {0xB5, (uint8_t[]){0x30}, 1, 0}, - {0x83, (uint8_t[]){0x03}, 1, 0}, - {0x86, (uint8_t[]){0x04}, 1, 0}, - {0x87, (uint8_t[]){0x16}, 1, 0}, - {0x88, (uint8_t[]){0x0A}, 1, 0}, - {0x89, (uint8_t[]){0x27}, 1, 0}, - {0x93, (uint8_t[]){0x63}, 1, 0}, - {0x96, (uint8_t[]){0x81}, 1, 0}, - {0xC3, (uint8_t[]){0x10}, 1, 0}, - {0xE6, (uint8_t[]){0x00}, 1, 0}, - {0x99, (uint8_t[]){0x01}, 1, 0}, - {0x70, (uint8_t[]){0x09}, 1, 0}, - {0x71, (uint8_t[]){0x1D}, 1, 0}, - {0x72, (uint8_t[]){0x14}, 1, 0}, - {0x73, (uint8_t[]){0x0a}, 1, 0}, - {0x74, (uint8_t[]){0x11}, 1, 0}, - {0x75, (uint8_t[]){0x16}, 1, 0}, - {0x76, (uint8_t[]){0x38}, 1, 0}, - {0x77, (uint8_t[]){0x0B}, 1, 0}, - {0x78, (uint8_t[]){0x08}, 1, 0}, - {0x79, (uint8_t[]){0x3E}, 1, 0}, - {0x7a, (uint8_t[]){0x07}, 1, 0}, - {0x7b, (uint8_t[]){0x0D}, 1, 0}, - {0x7c, (uint8_t[]){0x16}, 1, 0}, - {0x7d, (uint8_t[]){0x0F}, 1, 0}, - {0x7e, (uint8_t[]){0x14}, 1, 0}, - {0x7f, (uint8_t[]){0x05}, 1, 0}, - {0xa0, (uint8_t[]){0x04}, 1, 0}, - {0xa1, (uint8_t[]){0x28}, 1, 0}, - {0xa2, (uint8_t[]){0x0c}, 1, 0}, - {0xa3, (uint8_t[]){0x11}, 1, 0}, - {0xa4, (uint8_t[]){0x0b}, 1, 0}, - {0xa5, (uint8_t[]){0x23}, 1, 0}, - {0xa6, (uint8_t[]){0x45}, 1, 0}, - {0xa7, (uint8_t[]){0x07}, 1, 0}, - {0xa8, (uint8_t[]){0x0a}, 1, 0}, - {0xa9, (uint8_t[]){0x3b}, 1, 0}, - {0xaa, (uint8_t[]){0x0d}, 1, 0}, - {0xab, (uint8_t[]){0x18}, 1, 0}, - {0xac, (uint8_t[]){0x14}, 1, 0}, - {0xad, (uint8_t[]){0x0F}, 1, 0}, - {0xae, (uint8_t[]){0x19}, 1, 0}, - {0xaf, (uint8_t[]){0x08}, 1, 0}, - {0xff, (uint8_t[]){0x00}, 1, 0}, - {0x11, (uint8_t[]){0x00}, 0, 120}, - {0x29, (uint8_t[]){0x00}, 0, 10} -}; - -class XINGZHI_CUBE_0_85TFT_WIFI : public WifiBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_HEIGHT * 80 *sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - } - - void InitializeNv3023Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = NV3023_PANEL_IO_SPI_CONFIG(DISPLAY_CS, DISPLAY_DC, NULL, NULL); - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - nv3023_vendor_config_t vendor_config = { // Uncomment these lines if use custom initialization commands - .init_cmds = lcd_init_cmds, - .init_cmds_size = sizeof(lcd_init_cmds) / sizeof(nv3023_lcd_init_cmd_t), - }; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_BGR; - panel_config.bits_per_pixel = 16; - panel_config.vendor_config = &vendor_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_nv3023(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, false)); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new SpiLcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void Initializegpio21_45() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - //gpio_num_t sp_45 = GPIO_NUM_45; - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << GPIO_NUM_45); - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; - gpio_config(&io_conf); - gpio_set_level(GPIO_NUM_45, 0); - } - -public: - XINGZHI_CUBE_0_85TFT_WIFI(): - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - Initializegpio21_45(); // 初始时,拉高21引脚,保证4g模块正常工作 - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeNv3023Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_0_85TFT_WIFI); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.h deleted file mode 100644 index 0f3f8ce1..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA_PIN GPIO_NUM_41 -#define DISPLAY_SCL_PIN GPIO_NUM_42 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.json deleted file mode 100644 index be5919c0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-0.96oled-ml307", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/xingzhi-cube-0.96oled-ml307.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/xingzhi-cube-0.96oled-ml307.cc deleted file mode 100644 index 3ba9643a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-ml307/xingzhi-cube-0.96oled-ml307.cc +++ /dev/null @@ -1,234 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "display/oled_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "../xingzhi-cube-1.54tft-wifi/power_manager.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "XINGZHI_CUBE_0_96OLED_ML307" - -class XINGZHI_CUBE_0_96OLED_ML307 : public DualNetworkBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - Display* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - -public: - XINGZHI_CUBE_0_96OLED_ML307() : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_0_96OLED_ML307); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.h deleted file mode 100644 index b353890b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BUILTIN_LED_GPIO GPIO_NUM_48 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA_PIN GPIO_NUM_41 -#define DISPLAY_SCL_PIN GPIO_NUM_42 -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.json deleted file mode 100644 index 2cba4c6b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-0.96oled-wifi", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/xingzhi-cube-0.96oled-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/xingzhi-cube-0.96oled-wifi.cc deleted file mode 100644 index 27bf76a4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-0.96oled-wifi/xingzhi-cube-0.96oled-wifi.cc +++ /dev/null @@ -1,225 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/oled_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_save_timer.h" -#include "../xingzhi-cube-1.54tft-wifi/power_manager.h" - - -#include -#include -#include -#include -#include -#include - -#define TAG "XINGZHI_CUBE_0_96OLED_WIFI" - -class XINGZHI_CUBE_0_96OLED_WIFI : public WifiBoard { -private: - i2c_master_bus_handle_t display_i2c_bus_; - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - Display* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeDisplayI2c() { - i2c_master_bus_config_t bus_config = { - .i2c_port = (i2c_port_t)0, - .sda_io_num = DISPLAY_SDA_PIN, - .scl_io_num = DISPLAY_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&bus_config, &display_i2c_bus_)); - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(display_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - -public: - XINGZHI_CUBE_0_96OLED_WIFI() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeDisplayI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_0_96OLED_WIFI); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.h deleted file mode 100644 index 9167578a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.h +++ /dev/null @@ -1,40 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA GPIO_NUM_10 -#define DISPLAY_SCL GPIO_NUM_9 -#define DISPLAY_DC GPIO_NUM_8 -#define DISPLAY_CS GPIO_NUM_14 -#define DISPLAY_RES GPIO_NUM_18 -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.json deleted file mode 100644 index e3d5f508..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-1.54tft-ml307", - "sdkconfig_append": [] - }, - { - "name": "xingzhi-cube-1.54tft-ml307-wechatui", - "sdkconfig_append": [ - "CONFIG_USE_WECHAT_MESSAGE_STYLE=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/xingzhi-cube-1.54tft-ml307.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/xingzhi-cube-1.54tft-ml307.cc deleted file mode 100644 index bd33932e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-ml307/xingzhi-cube-1.54tft-ml307.cc +++ /dev/null @@ -1,212 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "../xingzhi-cube-1.54tft-wifi/power_manager.h" - -#include -#include - -#include -#include - -#define TAG "XINGZHI_CUBE_1_54TFT_ML307" - -class XINGZHI_CUBE_1_54TFT_ML307 : public DualNetworkBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, true)); - - display_ = new SpiLcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - XINGZHI_CUBE_1_54TFT_ML307() : - DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_1_54TFT_ML307); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.h deleted file mode 100644 index c1a998af..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.h +++ /dev/null @@ -1,36 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_40 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA GPIO_NUM_10 -#define DISPLAY_SCL GPIO_NUM_9 -#define DISPLAY_DC GPIO_NUM_8 -#define DISPLAY_CS GPIO_NUM_14 -#define DISPLAY_RES GPIO_NUM_18 -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.json deleted file mode 100644 index 6cfa0d3b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-cube-1.54tft-wifi", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/power_manager.h deleted file mode 100644 index 8d238f2c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/power_manager.h +++ /dev/null @@ -1,186 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include - - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - adc_oneshot_unit_handle_t adc_handle_; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_6, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1970, 0}, - {2062, 20}, - {2154, 40}, - {2246, 60}, - {2338, 80}, - {2430, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_2, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_6, &chan_config)); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/xingzhi-cube-1.54tft-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/xingzhi-cube-1.54tft-wifi.cc deleted file mode 100644 index e7c41dfd..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-cube-1.54tft-wifi/xingzhi-cube-1.54tft-wifi.cc +++ /dev/null @@ -1,201 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include -#include - -#include -#include - -#define TAG "XINGZHI_CUBE_1_54TFT_WIFI" - -class XINGZHI_CUBE_1_54TFT_WIFI : public WifiBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_38); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_21); - rtc_gpio_set_direction(GPIO_NUM_21, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_21, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - rtc_gpio_set_level(GPIO_NUM_21, 0); - // 启用保持功能,确保睡眠期间电平不变 - rtc_gpio_hold_en(GPIO_NUM_21); - esp_lcd_panel_disp_on_off(panel_, false); //关闭显示 - esp_deep_sleep_start(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, true)); - - display_ = new SpiLcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - -public: - XINGZHI_CUBE_1_54TFT_WIFI() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_CUBE_1_54TFT_WIFI); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/README.md deleted file mode 100644 index 2ad3efd8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# 无名科技星智 1.54 METAL (wifi) - -## 简介 -无名科技星智 1.54 METAL (wifi) 是星智 1.54 开模版的升级款,配备 1.54 寸 LCD 屏幕与 CST816 触摸芯片。它用触摸交互替代物理按键,并将外壳升级为铝合金材质,同步优化了交互体验与产品质感、手感。 - ->### 按键操作 ->- **开机**: 关机状态,长按电源键3秒后自动开机(旧版硬件长按电源键1s后自动开机) ->- **关机**: 开机状态,长按电源键5秒后自动关机(旧版硬件插入usb时不会自动关机) ->- **唤醒/打断**: 正常通话环境下,单击中间触摸按键 ->- **重新配网**: 开机后,1秒钟内单击中间触摸按键,会自动重启并进入配网界面 ->- **增加音量**: 开机状态下,单击右侧触摸按键,音量增加。长按右侧触摸按键2s,音量递增。 ->- **减小音量**: 开机状态下,单击左侧触摸按键,音量减小。长按左侧触摸按键2s,音量递减。 - ->### 休眠操作 ->- **浅睡眠**: 开机后,维持待命状态60s后,进入浅睡眠(屏幕亮度调整到1%) ->- **深睡眠**: 开机后,维持待命状态300s后,进入深睡眠(自动关机) ->- **唤醒**: 浅睡眠状态下,单击中间触摸按键,唤醒设备(屏幕亮度回调) - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -- `Xiaozhi Assistant` → `Board Type` → 选择 `无名科技星智1.54 METAL(wifi)` -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.h deleted file mode 100644 index 11dab54e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.h +++ /dev/null @@ -1,53 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -// 音频 -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_INPUT_REFERENCE true -#define AUDIO_I2S_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_17 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_15 - -#define AUDIO_CODEC_USE_PCA9557 -#define AUDIO_CODEC_I2C_PA_EN GPIO_NUM_21 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_41 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_42 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -// 按键 -#define BOOT_BUTTON_GPIO GPIO_NUM_0 - -// 屏幕 -#define DISPLAY_SPI_HOST SPI3_HOST -#define DISPLAY_SDA GPIO_NUM_10 -#define DISPLAY_SCL GPIO_NUM_9 -#define DISPLAY_DC GPIO_NUM_8 -#define DISPLAY_CS GPIO_NUM_14 -#define DISPLAY_RES GPIO_NUM_18 -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_13 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -// 电源管理 -#define POWER_USB_IN GPIO_NUM_1 -#define Power_Control GPIO_NUM_48 // 电源控制引脚 -#define Power_Dec GPIO_NUM_47 // 电源键检测引脚 -#define POWER_CBS_ADC_UNIT ADC_UNIT_1 // adc检测公共unit GPIO1 -#define POWER_USBIN_ADC_CHANNEL ADC_CHANNEL_0 // 检测usb是否插入 GPIO1 -#define POWER_BATTERY_ADC_CHANNEL ADC_CHANNEL_6 // 电池电量检测 GPIO7 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.json deleted file mode 100644 index 53bebb5f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "xingzhi-metal-1.54-wifi", - "sdkconfig_append": [ - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.cc deleted file mode 100644 index cbe64a7c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.cc +++ /dev/null @@ -1,213 +0,0 @@ -#include "cst816x.h" -#include "board.h" -#include "application.h" -#include "display.h" -#include "assets/lang_config.h" -#include "wifi_board.h" -#include "power_save_timer.h" -#include "codecs/es8311_audio_codec.h" -#include // 用于std::max/std::min - -#define TAG "Cst816x" - -const Cst816x::TouchThresholdConfig& Cst816x::getThresholdConfig(int x, int y) { - for (const auto& config : TOUCH_THRESHOLD_TABLE) { - if (config.x == x && config.y == y) { - return config; - } - } - return DEFAULT_THRESHOLD; -} - -Cst816x::Cst816x(i2c_master_bus_handle_t i2c_bus, uint8_t addr) : I2cDevice(i2c_bus, addr) { - uint8_t chip_id = ReadReg(0xA7); - ESP_LOGI(TAG, "Get CST816x chip ID: 0x%02X", chip_id); - read_buffer_ = new uint8_t[6]; -} - -Cst816x::~Cst816x() { - if (read_buffer_ != nullptr) { - delete[] read_buffer_; - read_buffer_ = nullptr; - } -} - -int64_t Cst816x::getCurrentTimeUs() { - struct timeval tv; - gettimeofday(&tv, nullptr); - return (int64_t)tv.tv_sec * 1000000L + tv.tv_usec; -} - -void Cst816x::UpdateTouchPoint() { - ReadRegs(0x02, read_buffer_, 6); - tp_.num = read_buffer_[0] & 0x0F; - tp_.x = ((read_buffer_[1] & 0x0F) << 8) | read_buffer_[2]; - tp_.y = ((read_buffer_[3] & 0x0F) << 8) | read_buffer_[4]; - memset(read_buffer_, 0, 6); -} - -void Cst816x::resetTouchCounters() { - is_touching_ = false; - touch_start_time_ = 0; - last_release_time_ = 0; - click_count_ = 0; - long_press_started_ = false; - - is_volume_long_pressing_ = false; - volume_long_press_dir_ = 0; - last_volume_adjust_time_ = 0; -} - -void Cst816x::touchpad_daemon(void* arg) { - Cst816x* cst816x = static_cast(arg); - auto& board = Board::GetInstance(); - auto codec = board.GetAudioCodec(); - auto display = board.GetDisplay(); - - while (1) { - cst816x->UpdateTouchPoint(); - auto& tp = cst816x->GetTouchPoint(); - int64_t current_time = cst816x->getCurrentTimeUs(); - - const auto& config = cst816x->getThresholdConfig(tp.x, tp.y); - if (tp.num > 0) { - ESP_LOGD(TAG, "Touch at (%d,%d) → SingleThresh:%lldms, DoubleWindow:%lldms, LongThresh:%lldms", - tp.x, tp.y, - config.single_click_thresh_us / 1000, - config.double_click_window_us / 1000, - config.long_press_thresh_us / 1000); - } - - TouchEvent current_event; - bool event_detected = false; - - if (tp.num > 0 && !cst816x->is_touching_) { - cst816x->is_touching_ = true; - cst816x->touch_start_time_ = current_time; - cst816x->long_press_started_ = false; - } - else if (tp.num > 0 && cst816x->is_touching_) { - if (!cst816x->long_press_started_ && - (current_time - cst816x->touch_start_time_ >= config.long_press_thresh_us)) { - current_event = {TouchEventType::LONG_PRESS_START, tp.x, tp.y}; - event_detected = true; - cst816x->long_press_started_ = true; - } - } - else if (tp.num == 0 && cst816x->is_touching_) { - cst816x->is_touching_ = false; - int64_t touch_duration = current_time - cst816x->touch_start_time_; - cst816x->last_release_time_ = current_time; - if (cst816x->long_press_started_) { - current_event = {TouchEventType::LONG_PRESS_END, tp.x, tp.y}; - event_detected = true; - } - else if (touch_duration <= config.single_click_thresh_us) { - cst816x->click_count_++; - } - } - else if (tp.num == 0 && !cst816x->is_touching_) { - if (cst816x->click_count_ > 0 && - (current_time - cst816x->last_release_time_ >= config.double_click_window_us)) { - if (cst816x->click_count_ == 2) { - current_event = {TouchEventType::DOUBLE_CLICK, tp.x, tp.y}; - event_detected = true; - } - else if (cst816x->click_count_ == 1) { - current_event = {TouchEventType::SINGLE_CLICK, tp.x, tp.y}; - event_detected = true; - } - cst816x->click_count_ = 0; - } - } - - if (event_detected) { - if (current_event.y == 600 && (current_event.x == 20 || current_event.x == 40 || current_event.x == 60)) { - switch (current_event.type) { - case TouchEventType::SINGLE_CLICK: - if (current_event.x == 40) { - board.SetPowerSaveLevel(PowerSaveLevel::PERFORMANCE); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - auto& wifi_board = static_cast(Board::GetInstance()); - wifi_board.EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - } else if (current_event.x == 20) { // 20,600 单击:音量+ - int current_vol = codec->output_volume(); - int new_vol = current_vol + 10; - new_vol = (new_vol >= ES8311_VOL_MAX) ? ES8311_VOL_MAX : new_vol; - ESP_LOGI(TAG, "current_vol, new_vol(%d, %d)", current_vol, new_vol); - codec->EnableOutput(true); - codec->SetOutputVolume(new_vol); - display->ShowNotification(Lang::Strings::VOLUME + std::to_string(new_vol)); - } else if (current_event.x == 60) { // 60,600 单击:音量- - int current_vol = codec->output_volume(); - int new_vol = current_vol - 10; - new_vol = (new_vol <= ES8311_VOL_MIN) ? ES8311_VOL_MIN : new_vol; - ESP_LOGI(TAG, "current_vol, new_vol(%d, %d)", current_vol, new_vol); - codec->EnableOutput(true); - codec->SetOutputVolume(new_vol); - display->ShowNotification(Lang::Strings::VOLUME + std::to_string(new_vol)); - } - break; - - case TouchEventType::DOUBLE_CLICK: - ESP_LOGI(TAG, "Double click detected at (%d, %d)", current_event.x, current_event.y); - break; - - case TouchEventType::LONG_PRESS_START: - ESP_LOGI(TAG, "Long press started at (%d, %d) → Start volume adjust", current_event.x, current_event.y); - if (current_event.x == 20) { - cst816x->is_volume_long_pressing_ = true; - cst816x->volume_long_press_dir_ = 1; - cst816x->last_volume_adjust_time_ = current_time; - } else if (current_event.x == 60) { - cst816x->is_volume_long_pressing_ = true; - cst816x->volume_long_press_dir_ = -1; - cst816x->last_volume_adjust_time_ = current_time; - } - break; - - case TouchEventType::LONG_PRESS_END: - ESP_LOGI(TAG, "Long press ended at (%d, %d) → Stop volume adjust", current_event.x, current_event.y); - if (current_event.x == 20 || current_event.x == 60) { - cst816x->is_volume_long_pressing_ = false; - cst816x->volume_long_press_dir_ = 0; - cst816x->last_volume_adjust_time_ = 0; - } - break; - } - } - } - - if (cst816x->is_volume_long_pressing_) { - int64_t now = cst816x->getCurrentTimeUs(); - if (now - cst816x->last_volume_adjust_time_ >= cst816x->VOL_ADJ_INTERVAL_US) { - int current_vol = codec->output_volume(); - int new_vol = current_vol + (cst816x->volume_long_press_dir_ * cst816x->VOL_ADJ_STEP); - - new_vol = std::max(ES8311_VOL_MIN, std::min(ES8311_VOL_MAX, new_vol)); - - if (new_vol != current_vol) { - codec->EnableOutput(true); - codec->SetOutputVolume(new_vol); - display->ShowNotification(Lang::Strings::VOLUME + std::to_string(new_vol)); - cst816x->last_volume_adjust_time_ = now; - } else { - cst816x->is_volume_long_pressing_ = false; - cst816x->volume_long_press_dir_ = 0; - ESP_LOGI(TAG, "Volume reached limit (%d), stop adjusting", new_vol); - } - } - } - - vTaskDelay(pdMS_TO_TICKS(40)); - } -} - -void Cst816x::InitCst816d() { - ESP_LOGI(TAG, "Init CST816x touch driver"); - xTaskCreate(touchpad_daemon, "touch_daemon", 2048, this, 1, NULL); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.h deleted file mode 100644 index 7a8a3d34..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/cst816x.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef _CST816X_H_ -#define _CST816X_H_ - -#include "esp_log.h" -#include "esp_err.h" -#include "driver/i2c.h" -#include "i2c_device.h" -#include -#include -#include - -#define ES8311_VOL_MIN 0 -#define ES8311_VOL_MAX 100 - -enum class TouchEventType { - SINGLE_CLICK, // 单击事件 - DOUBLE_CLICK, // 双击事件 - LONG_PRESS_START,// 长按开始事件 - LONG_PRESS_END // 长按结束事件 -}; - -struct TouchEvent { - TouchEventType type; - int x; - int y; -}; - -class Cst816x : public I2cDevice { -private: - struct TouchPoint_t { - int num = 0; - int x = -1; - int y = -1; - }; - - struct TouchThresholdConfig { - int x; // 目标X坐标 - int y; // 目标Y坐标 - int64_t single_click_thresh_us; // 单击最大时长(us) - int64_t double_click_window_us; // 双击窗口(us) - int64_t long_press_thresh_us; // 长按阈值(us) - }; - - const TouchThresholdConfig DEFAULT_THRESHOLD = { - .x = -1, .y = -1, - .single_click_thresh_us = 120000, // 150ms - .double_click_window_us = 240000, // 150ms - .long_press_thresh_us = 4000000 // 4000ms - }; - - const std::array TOUCH_THRESHOLD_TABLE = { - { - {20, 600, 200000, 240000, 2000000}, // 音量+ - {40, 600, 200000, 240000, 4000000}, // boot按键 - {60, 600, 200000, 240000, 2000000} // 音量- - } - }; - - const TouchThresholdConfig& getThresholdConfig(int x, int y); - - uint8_t* read_buffer_ = nullptr; - TouchPoint_t tp_; - - bool is_touching_ = false; - int64_t touch_start_time_ = 0; // 触摸开始时间(us) - int64_t last_release_time_ = 0; // 上次释放时间(us) - int click_count_ = 0; // 单击计数(双击检测用) - bool long_press_started_ = false; // 长按是否已触发 - - bool is_volume_long_pressing_ = false; // 是否处于音量长按调整中 - int volume_long_press_dir_ = 0; // 调整方向:1=递增,-1=递减 - int64_t last_volume_adjust_time_ = 0; // 上次调整音量的时间(us) - const int64_t VOL_ADJ_INTERVAL_US = 200000; // 音量调整间隔(100ms) - const int VOL_ADJ_STEP = 5; // 每次调整步长 - - int64_t getCurrentTimeUs(); - -public: - Cst816x(i2c_master_bus_handle_t i2c_bus, uint8_t addr); - ~Cst816x(); - - void InitCst816d(); - void UpdateTouchPoint(); - void resetTouchCounters(); - static void touchpad_daemon(void* param); - - const TouchPoint_t& GetTouchPoint() { return tp_; } -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/power_manager.h deleted file mode 100644 index 5be6ee8c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/power_manager.h +++ /dev/null @@ -1,314 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include -#include "sdkconfig.h" -#include "button.h" -#include "board.h" -#include "config.h" -#include "assets/lang_config.h" -#include - -class PowerManager { -private: - esp_timer_handle_t timer_handle_; - esp_timer_handle_t power_timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 30; - bool is_charging_ = false; - bool is_low_battery_ = false; - int ticks_ = 0; - adc_oneshot_unit_handle_t adc_handle_; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - - // power - bool pressed = false; // 是否按下电源键 - int PowerControl_ticks_ = 0; // 开机时长 - int press_ticks_ = 0; // 按下时的tick - bool is_first_boot = true; // - uint8_t PowerDec_level_ = 0; // 电源键电平 - const int power_off_ticks_ = 20; // 按键按下20/5秒准备关机; - bool new_charging_status = false; // 插入usb时无法软件关机 - bool is_shutting_down_ = false; // 标记是否进入关机流程 - int shutdown_delay_ticks_ = 0; // 关机延迟计数 - uint8_t shutdown_ticks = 5; // 5/5s后关机 预留的关机操作 - bool shutdown_first_ = true; - - // 旧版硬件软件关机逻辑 - void PowrSwitch() { - PowerDec_level_ = gpio_get_level(Power_Dec); - - // 确保开机后电源键松开再检测关机 - if (PowerDec_level_ == 1) { - is_first_boot = false; - } - - if (is_shutting_down_) { - shutdown_delay_ticks_++; - if (shutdown_delay_ticks_ >= shutdown_ticks) { - shutdown(); - is_shutting_down_ = false; - shutdown_delay_ticks_ = 0; - } - return; - } - - if (!is_first_boot) { - PowerControl_ticks_++; - if (PowerDec_level_ == 0 && pressed == false) { - press_ticks_ = PowerControl_ticks_; - pressed = true; - } - if ((press_ticks_ != 0) &&( PowerControl_ticks_ - press_ticks_ == power_off_ticks_ )&& (!new_charging_status)) { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - is_shutting_down_ = true; - shutdown_delay_ticks_ = 0; - } - if (PowerDec_level_ == 1 && press_ticks_!= 0) { - PowerDec_level_ = gpio_get_level(Power_Dec); - if (PowerDec_level_ == 1) { - pressed = false; - press_ticks_ = 0; - } - } - } - } - - void CheckBatteryStatus() { - int usb_usb_adc_value0; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, POWER_USBIN_ADC_CHANNEL, &usb_usb_adc_value0)); - new_charging_status = (1500 < usb_usb_adc_value0 && usb_usb_adc_value0 < 4000); - // ESP_LOGE("powercontrol", "USB ADC VALUE 1: %d", usb_usb_adc_value0); - - if (new_charging_status != is_charging_) { - ReadBatteryAdcData(); - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - } - - void ReadBatteryAdcData() { - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, POWER_BATTERY_ADC_CHANNEL, &adc_value)); - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += value; - } - average_adc /= adc_values_.size(); - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {1970, 0}, - {2062, 20}, - {2154, 40}, - {2246, 60}, - {2338, 80}, - {2430, 100} - }; - - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - - // Check low battery status - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - // 初始化电源键检测引脚 - gpio_config_t powerdecgpio_conf = {}; - powerdecgpio_conf.intr_type = GPIO_INTR_DISABLE; - powerdecgpio_conf.mode = GPIO_MODE_INPUT; - powerdecgpio_conf.pin_bit_mask = (1ULL << Power_Dec); - powerdecgpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - powerdecgpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&powerdecgpio_conf); - - // 初始化电源控制引脚 - gpio_config_t powercontgpio_conf = {}; - powercontgpio_conf.intr_type = GPIO_INTR_DISABLE; - powercontgpio_conf.mode = GPIO_MODE_OUTPUT; - powercontgpio_conf.pin_bit_mask = (1ULL << Power_Control); - powercontgpio_conf.pull_down_en = GPIO_PULLDOWN_ENABLE; - powercontgpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&powercontgpio_conf); - gpio_set_level(Power_Control, 1); - ESP_LOGI("powercontrol", "turnded on ..."); - - // 创建电源控制检查定时器 - esp_timer_create_args_t power_timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->PowrSwitch(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "power_cotrol_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&power_timer_args, &power_timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(power_timer_handle_, 200000)); - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = POWER_CBS_ADC_UNIT, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, POWER_BATTERY_ADC_CHANNEL, &chan_config)); // 电池电量 - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, POWER_USBIN_ADC_CHANNEL, &chan_config)); // usb - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (power_timer_handle_) { - esp_timer_stop(power_timer_handle_); - esp_timer_delete(power_timer_handle_); - } - if (adc_handle_ != nullptr) { - adc_oneshot_del_unit(adc_handle_); - } - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - uint8_t GetBatteryLevel() { - return battery_level_; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } - - void shutdown() { - if (!new_charging_status && shutdown_first_) - { - shutdown_first_ = false; // 进入后置 false ,防止再次进入关机状态 - gpio_config_t shutdown_gpio_conf = {}; - shutdown_gpio_conf.intr_type = GPIO_INTR_DISABLE; - shutdown_gpio_conf.mode = GPIO_MODE_OUTPUT; - shutdown_gpio_conf.pin_bit_mask = (1ULL << Power_Dec); - shutdown_gpio_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - shutdown_gpio_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&shutdown_gpio_conf); - gpio_set_level(DISPLAY_BACKLIGHT_PIN, 0); - gpio_set_level(Power_Control, 0); - for (int i=1;i<15;i++) { - gpio_set_level(Power_Dec, 1); - vTaskDelay(pdMS_TO_TICKS(100)); - gpio_set_level(Power_Dec, 0); - vTaskDelay(pdMS_TO_TICKS(100)); - ESP_LOGI("PowerManager","触发开关机控制"); - } - ESP_LOGI("PowerManager","关机失败,进入深睡眠"); - esp_deep_sleep_start(); - } else { - ESP_LOGI("PowerManager","检测到插入usb,无法关机"); - } - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/xingzhi-metal-1.54-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/xingzhi-metal-1.54-wifi.cc deleted file mode 100644 index c1467caf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xingzhi-metal-1.54-wifi/xingzhi-metal-1.54-wifi.cc +++ /dev/null @@ -1,201 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "i2c_device.h" -#include -#include -#include -#include -#include "power_manager.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include -#include -#include "cst816x.h" - -#define TAG "XINGZHI_METAL_1_54_WIFI" - -class XINGZHI_METAL_1_54_WIFI : public WifiBoard { -private: - i2c_master_bus_handle_t i2c_bus_; - Button boot_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - esp_err_t err; - bool is_device_found = false; - Cst816x *cst816d_; - - void InitializePowerManager() { - power_manager_ = new PowerManager(POWER_USB_IN);//USB是否插入 - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - ESP_LOGI(TAG, "Enabling sleep mode"); - display_->SetChatMessage("system", ""); - display_->SetEmotion("sleepy"); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - display_->SetChatMessage("system", ""); - display_->SetEmotion("neutral"); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - power_manager_->shutdown(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &i2c_bus_)); - for (uint8_t addr = 1; addr < 127; addr++) { - err = i2c_master_probe(i2c_bus_, addr, 100); - if (err == ESP_OK) { - ESP_LOGI(TAG, "Device found at address 0x%02X", addr); - if (addr == 0x15) { - is_device_found = true; - } - } - } - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(DISPLAY_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeSt7789Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(DISPLAY_SPI_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, true)); - - display_ = new SpiLcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - } - - void Initialtouchtask() { - if (is_device_found) { - cst816d_ = new Cst816x(i2c_bus_, 0x15); - cst816d_->InitCst816d(); - } - } - -public: - XINGZHI_METAL_1_54_WIFI() : - boot_button_(BOOT_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeI2c(); - InitializeSpi(); - InitializeSt7789Display(); - Initialtouchtask(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec( - i2c_bus_, - I2C_NUM_0, - AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, - AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, - AUDIO_I2S_GPIO_DOUT, - AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_I2C_PA_EN, - AUDIO_CODEC_ES8311_ADDR, - AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - Cst816x *GetTouchpad() { - return cst816d_; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = power_manager_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XINGZHI_METAL_1_54_WIFI); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/README.md deleted file mode 100644 index 9697085b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# 开源地址 - -https://oshwhub.com/tenclass01/xmini_c3_4g - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.h deleted file mode 100644 index 8a38e0fc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_7 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_5 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_8 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_13 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_21 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_20 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_3 -#define BOOT_BUTTON_GPIO GPIO_NUM_9 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#define ML307_TX_PIN GPIO_NUM_2 -#define ML307_RX_PIN GPIO_NUM_0 -#define ML307_DTR_PIN GPIO_NUM_1 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.json deleted file mode 100644 index b17fde6e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/config.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "xmini-c3-4g", - "sdkconfig_append": [ - "CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y", - "CONFIG_PARTITION_TABLE_CUSTOM_FILENAME=\"partitions/v2/8m.csv\"", - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc deleted file mode 100644 index 634ebbe9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-4g/xmini_c3_4g_board.cc +++ /dev/null @@ -1,203 +0,0 @@ -#include "ml307_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/oled_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "settings.h" -#include "config.h" -#include "sleep_timer.h" -#include "adc_battery_monitor.h" -#include "press_to_talk_mcp_tool.h" - -#include -#include -#include -#include -#include - -#define TAG "XminiC3Board" - -class XminiC3Board : public Ml307Board { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - SleepTimer* sleep_timer_ = nullptr; - AdcBatteryMonitor* adc_battery_monitor_ = nullptr; - PressToTalkMcpTool* press_to_talk_tool_ = nullptr; - - void InitializeBatteryMonitor() { - adc_battery_monitor_ = new AdcBatteryMonitor(ADC_UNIT_1, ADC_CHANNEL_4, 100000, 100000, GPIO_NUM_12); - adc_battery_monitor_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - sleep_timer_->SetEnabled(false); - } else { - sleep_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - // Wake word detection will be disabled in light sleep mode - sleep_timer_ = new SleepTimer(30); - sleep_timer_->OnEnterLightSleepMode([this]() { - ESP_LOGI(TAG, "Enabling sleep mode"); - // Show the standby screen - GetDisplay()->SetPowerSaveMode(true); - // Enable sleep mode, and sleep in 1 second after DTR is set to high - modem_->SetSleepMode(true, 1); - // Set the DTR pin to high to make the modem enter sleep mode - modem_->GetAtUart()->SetDtrPin(true); - }); - sleep_timer_->OnExitLightSleepMode([this]() { - // Set the DTR pin to low to make the modem wake up - modem_->GetAtUart()->SetDtrPin(false); - // Hide the standby screen - GetDisplay()->SetPowerSaveMode(false); - }); - sleep_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(codec_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { - app.ToggleChatState(); - } - }); - boot_button_.OnPressDown([this]() { - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StartListening(); - } - }); - boot_button_.OnPressUp([this]() { - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StopListening(); - } - }); - } - - void InitializeTools() { - press_to_talk_tool_ = new PressToTalkMcpTool(); - press_to_talk_tool_->Initialize(); - } - -public: - XminiC3Board() : Ml307Board(ML307_TX_PIN, ML307_RX_PIN, ML307_DTR_PIN), - boot_button_(BOOT_BUTTON_GPIO, false, 0, 0, true) { - - InitializeBatteryMonitor(); - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - charging = adc_battery_monitor_->IsCharging(); - discharging = adc_battery_monitor_->IsDischarging(); - level = adc_battery_monitor_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - sleep_timer_->WakeUp(); - } - Ml307Board::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XminiC3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/README.md deleted file mode 100644 index 87dfd43c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# 开源地址 - -https://oshwhub.com/tenclass01/xmini_c3 - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.h deleted file mode 100644 index 1f75de69..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_5 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_4 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_10 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_0 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_1 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_2 -#define BOOT_BUTTON_GPIO GPIO_NUM_9 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.json deleted file mode 100644 index e830af0d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "xmini-c3-v3", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/xmini_c3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/xmini_c3_board.cc deleted file mode 100644 index af267648..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3-v3/xmini_c3_board.cc +++ /dev/null @@ -1,201 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/oled_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "settings.h" -#include "config.h" -#include "power_save_timer.h" -#include "adc_battery_monitor.h" -#include "press_to_talk_mcp_tool.h" - -#include -#include -#include -#include -#include -#include - -#define TAG "XminiC3Board" - -class XminiC3Board : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - PowerSaveTimer* power_save_timer_ = nullptr; - AdcBatteryMonitor* adc_battery_monitor_ = nullptr; - PressToTalkMcpTool* press_to_talk_tool_ = nullptr; - - void InitializePowerManager() { - adc_battery_monitor_ = new AdcBatteryMonitor(ADC_UNIT_1, ADC_CHANNEL_3, 100000, 100000, GPIO_NUM_12); - adc_battery_monitor_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(160, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(codec_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - // During startup (before connected), pressing BOOT enters config mode without reboot - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { - app.ToggleChatState(); - } - }); - boot_button_.OnPressDown([this]() { - if (power_save_timer_) { - power_save_timer_->WakeUp(); - } - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StartListening(); - } - }); - boot_button_.OnPressUp([this]() { - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StopListening(); - } - }); - } - - void InitializeTools() { - press_to_talk_tool_ = new PressToTalkMcpTool(); - press_to_talk_tool_->Initialize(); - } - -public: - XminiC3Board() : boot_button_(BOOT_BUTTON_GPIO, false, 0, 0, true) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeCodecI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializeTools(); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - charging = adc_battery_monitor_->IsCharging(); - discharging = adc_battery_monitor_->IsDischarging(); - level = adc_battery_monitor_->GetBatteryLevel(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XminiC3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.h deleted file mode 100644 index f37a0358..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_10 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_6 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_8 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_7 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_5 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_11 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_3 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_4 -#define AUDIO_CODEC_ES8311_ADDR ES8311_CODEC_DEFAULT_ADDR - -#define BUILTIN_LED_GPIO GPIO_NUM_2 -#define BOOT_BUTTON_GPIO GPIO_NUM_9 - -#define DISPLAY_WIDTH 128 -#define DISPLAY_HEIGHT 64 -#define DISPLAY_MIRROR_X true -#define DISPLAY_MIRROR_Y true - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.json deleted file mode 100644 index 00735684..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/config.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "target": "esp32c3", - "builds": [ - { - "name": "xmini-c3", - "sdkconfig_append": [ - "CONFIG_PM_ENABLE=y", - "CONFIG_FREERTOS_USE_TICKLESS_IDLE=y", - "CONFIG_USE_ESP_WAKE_WORD=y", - "CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/xmini_c3_board.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/xmini_c3_board.cc deleted file mode 100644 index 11d4a2ea..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/xmini-c3/xmini_c3_board.cc +++ /dev/null @@ -1,182 +0,0 @@ -#include "wifi_board.h" -#include "codecs/es8311_audio_codec.h" -#include "display/oled_display.h" -#include "application.h" -#include "button.h" -#include "led/single_led.h" -#include "mcp_server.h" -#include "settings.h" -#include "config.h" -#include "power_save_timer.h" -#include "press_to_talk_mcp_tool.h" - -#include -#include -#include -#include -#include - -#define TAG "XminiC3Board" - -class XminiC3Board : public WifiBoard { -private: - i2c_master_bus_handle_t codec_i2c_bus_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - Display* display_ = nullptr; - Button boot_button_; - PowerSaveTimer* power_save_timer_ = nullptr; - PressToTalkMcpTool* press_to_talk_tool_ = nullptr; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(160, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeCodecI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - - // Print I2C bus info - if (i2c_master_probe(codec_i2c_bus_, 0x18, 1000) != ESP_OK) { - while (true) { - ESP_LOGE(TAG, "Failed to probe I2C bus, please check if you have installed the correct firmware"); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - } - } - - void InitializeSsd1306Display() { - // SSD1306 config - esp_lcd_panel_io_i2c_config_t io_config = { - .dev_addr = 0x3C, - .on_color_trans_done = nullptr, - .user_ctx = nullptr, - .control_phase_bytes = 1, - .dc_bit_offset = 6, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - .flags = { - .dc_low_on_data = 0, - .disable_control_phase = 0, - }, - .scl_speed_hz = 400 * 1000, - }; - - ESP_ERROR_CHECK(esp_lcd_new_panel_io_i2c_v2(codec_i2c_bus_, &io_config, &panel_io_)); - - ESP_LOGI(TAG, "Install SSD1306 driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = -1; - panel_config.bits_per_pixel = 1; - - esp_lcd_panel_ssd1306_config_t ssd1306_config = { - .height = static_cast(DISPLAY_HEIGHT), - }; - panel_config.vendor_config = &ssd1306_config; - - ESP_ERROR_CHECK(esp_lcd_new_panel_ssd1306(panel_io_, &panel_config, &panel_)); - ESP_LOGI(TAG, "SSD1306 driver installed"); - - // Reset the display - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - if (esp_lcd_panel_init(panel_) != ESP_OK) { - ESP_LOGE(TAG, "Failed to initialize display"); - display_ = new NoDisplay(); - return; - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_, true)); - - display_ = new OledDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - if (!press_to_talk_tool_ || !press_to_talk_tool_->IsPressToTalkEnabled()) { - app.ToggleChatState(); - } - }); - boot_button_.OnPressDown([this]() { - if (power_save_timer_) { - power_save_timer_->WakeUp(); - } - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StartListening(); - } - }); - boot_button_.OnPressUp([this]() { - if (press_to_talk_tool_ && press_to_talk_tool_->IsPressToTalkEnabled()) { - Application::GetInstance().StopListening(); - } - }); - } - - void InitializeTools() { - press_to_talk_tool_ = new PressToTalkMcpTool(); - press_to_talk_tool_->Initialize(); - } - -public: - XminiC3Board() : boot_button_(BOOT_BUTTON_GPIO) { - InitializeCodecI2c(); - InitializeSsd1306Display(); - InitializeButtons(); - InitializePowerSaveTimer(); - InitializeTools(); - - // 避免使用错误的固件,把 EFUSE 操作放在最后 - // 把 ESP32C3 的 VDD SPI 引脚作为普通 GPIO 口使用 - esp_efuse_write_field_bit(ESP_EFUSE_VDD_SPI_AS_GPIO); - } - - virtual Led* GetLed() override { - static SingleLed led(BUILTIN_LED_GPIO); - return &led; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8311AudioCodec audio_codec(codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8311_ADDR); - return &audio_codec; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(XminiC3Board); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/README.md deleted file mode 100644 index a4946b44..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# 小智云聊 S3 - -## 简介 - -小智云聊 S3 是小智 AI 的魔改项目,是首个 2.8 寸护眼大屏+大字体+2000mah 大电池的量产成品,做了大量创新和优化。 - -## 合并版 - -合并版代码在小智 AI 主项目中维护,跟随主项目的一起版本更新,便于用户自行扩展和第三方固件扩展。支持语音唤醒、语音打断、OTA、4G 自由切换等功能。 - -> ### 按键操作 -> -> - **开机**: 关机状态,长按 1 秒后释放按键,自动开机。 -> - **关机**: 开机状态,长按 1 秒后释放按键,标题栏会显示'请稍候',再等 2 秒自动关机。 -> - **唤醒/打断**: 正常通话环境下,单击按键。 -> - **切换 4G/Wifi**: 启动过程或者配网界面,1 秒钟内双击按键(需安装 4G 模块)。 -> - **重新配网**: 开机状态,1 秒钟内三击按键,会自动重启并进入配网界面。 - -> ### 语音指令 -> -> - **打开/关闭语音打断模式**: 在播放音乐时,需要关闭语音打断模式,否则可能会打断音乐播放。 -> - **切换 IPS 屏幕显示模式**: 新版小智云聊 S3 升级了 IPS 屏幕,需要切换屏幕显示模式后才能正常显示,可以来回切换。 - -## 魔改版 - -魔改版由于底层改动太大,代码单独维护,定期合并主项目代码。 - -> ### 为什么是魔改 -> -> - 首个实现微信二维码配网。 -> - 首个支持单手机配网。 -> - 首个支持扫二维码访问控制台。 -> - 首发支持繁体、日文、英文版界面。 -> - 首个全语音操控模式。 -> - 独家提供一键刷机脚本等多种刷机方式。 - -## 版本区别 - -> | 特性 | 合并版 | 魔改版 | -> | -------------- | ------ | ------ | -> | 语音打断 | ✓ | ✓ | -> | 4G 功能 | ✓ | ✓ | -> | 自动更新固件 | ✓ | X | -> | 第三方固件支持 | ✓ | X | -> | 天气待机界面 | X | ✓ | -> | 闹钟提醒 | X | ✓ | -> | 网络音乐播放 | X | ✓ | -> | 微信扫码配网 | X | ✓ | -> | 单手机配网 | X | ✓ | -> | 扫码访问控制台 | X | ✓ | -> | 繁日英文界面 | X | ✓ | -> | 多语言支持 | X | ✓ | -> | 外接蓝牙音箱 | X | ✓ | - -# 编译配置命令 - -**克隆工程** - -```bash -git clone https://github.com/78/xiaozhi-esp32.git -``` - -**进入工程** - -```bash -cd xiaozhi-esp32 -``` - -**配置编译目标为 ESP32S3** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig** - -```bash -idf.py menuconfig -``` - -**选择板子** - -```bash -- `Xiaozhi Assistant` → `Board Type` → 选择 `小智云聊-S3` → 选择 `Enable Device-Side AEC` -``` - -**编译** - -```ba -idf.py build -``` - -**下载并打开串口终端** - -```bash -idf.py build flash monitor -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.h deleted file mode 100644 index be740022..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_REFERENCE true - -#define AUDIO_INPUT_SAMPLE_RATE 24000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_DEFAULT_OUTPUT_VOLUME 70 - -#define AUDIO_I2S_GPIO_MCLK GPIO_NUM_14 -#define AUDIO_I2S_GPIO_BCLK GPIO_NUM_13 -#define AUDIO_I2S_GPIO_WS GPIO_NUM_11 -#define AUDIO_I2S_GPIO_DOUT GPIO_NUM_12 -#define AUDIO_I2S_GPIO_DIN GPIO_NUM_10 - -#define AUDIO_CODEC_PA_PIN GPIO_NUM_17 -#define AUDIO_CODEC_I2C_SCL_PIN GPIO_NUM_21 -#define AUDIO_CODEC_I2C_SDA_PIN GPIO_NUM_18 -#define AUDIO_CODEC_ES8388_ADDR ES8388_CODEC_DEFAULT_ADDR - -#define BOOT_BUTTON_PIN GPIO_NUM_2 -#define BOOT_5V_PIN GPIO_NUM_3 //5V升压输出 -#define BOOT_4G_PIN GPIO_NUM_5 //4G模块使能 -#define MON_BATT_PIN GPIO_NUM_43 //检测PMU电池指示 -#define MON_BATT_CNT 70 //检测PMU电池秒数 -#define MON_USB_PIN GPIO_NUM_47 //检测USB插入 - - -#define ML307_RX_PIN GPIO_NUM_16 -#define ML307_TX_PIN GPIO_NUM_15 - -#define DISPLAY_SPI_LCD_HOST SPI2_HOST -#define DISPLAY_SPI_CLOCK_HZ (40 * 1000 * 1000) -#define DISPLAY_SPI_PIN_SCLK 42 -#define DISPLAY_SPI_PIN_MOSI 40 -#define DISPLAY_SPI_PIN_MISO -1 -#define DISPLAY_SPI_PIN_LCD_DC 41 -#define DISPLAY_SPI_PIN_LCD_RST 45 -#define DISPLAY_SPI_PIN_LCD_CS -1 -#define DISPLAY_PIN_TOUCH_CS -1 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_46 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define DISPLAY_WIDTH 320 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY true -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y true -#define DISPLAY_INVERT_COLOR false -#define DISPLAY_RGB_ORDER_COLOR LCD_RGB_ELEMENT_ORDER_RGB - -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 -#define KEY_EXPIRE_MS 800 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.json deleted file mode 100644 index 1261a683..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "yunliao-s3", - "sdkconfig_append": [ - "CONFIG_USE_DEVICE_AEC=y" - ] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.cc deleted file mode 100644 index 6a8ef74c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.cc +++ /dev/null @@ -1,203 +0,0 @@ -#include "power_manager.h" -#include "esp_sleep.h" -#include "driver/rtc_io.h" -#include "esp_log.h" -#include "config.h" -#include -#include "esp_log.h" -#include "settings.h" - -#define TAG "PowerManager" - -static QueueHandle_t gpio_evt_queue = NULL; -uint16_t battCnt;//闪灯次数 -int battLife = 70; //电量 - -// 中断服务程序 -static void IRAM_ATTR batt_mon_isr_handler(void* arg) { - uint32_t gpio_num = (uint32_t) arg; - xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); -} - -// 添加任务处理函数 -static void batt_mon_task(void* arg) { - uint32_t io_num; - while(1) { - if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { - battCnt++; - } - } -} - -static void calBattLife() { - // 计算电量 - battLife = battCnt; - - if (battLife > 100){ - battLife = 100; - } - // ESP_LOGI(TAG, "Battery life:%d", (int)battLife); - // 重置计数器 - battCnt = 0; -} - -PowerManager::PowerManager(){ -} - -void PowerManager::Initialize(){ - // 初始化5V控制引脚 - gpio_config_t io_conf_5v = { - .pin_bit_mask = 1<(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); -} - -void PowerManager::CheckBatteryStatus(){ - call_count_++; - if(call_count_ >= MON_BATT_CNT) { - calBattLife(); - call_count_ = 0; - } - - bool new_charging_status = IsCharging(); - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (charging_callback_) { - charging_callback_(is_charging_); - } - } - - bool new_discharging_status = IsDischarging(); - if (new_discharging_status != is_discharging_) { - is_discharging_ = new_discharging_status; - if (discharging_callback_) { - discharging_callback_(is_discharging_); - } - } -} - -bool PowerManager::IsCharging() { - return gpio_get_level(MON_USB_PIN) == 1 && !IsChargingDone(); -} - -bool PowerManager::IsDischarging() { - return gpio_get_level(MON_USB_PIN) == 0; -} - -bool PowerManager::IsChargingDone() { - return battLife >= 95; -} - -int PowerManager::GetBatteryLevel() { - return battLife; -} - -void PowerManager::OnChargingStatusChanged(std::function callback) { - charging_callback_ = callback; -} - -void PowerManager::OnChargingStatusDisChanged(std::function callback) { - discharging_callback_ = callback; -} - -void PowerManager::CheckStartup() { - Settings settings1("board", true); - if(settings1.GetInt("sleep_flag", 0) > 0){ - vTaskDelay(pdMS_TO_TICKS(1000)); - if( gpio_get_level(BOOT_BUTTON_PIN) == 1) { - Sleep(); //进入休眠模式 - }else{ - settings1.SetInt("sleep_flag", 0); - } - } -} - -void PowerManager::Start5V() { - gpio_set_level(BOOT_5V_PIN, 1); -} - -void PowerManager::Shutdown5V() { - gpio_set_level(BOOT_5V_PIN, 0); -} - -void PowerManager::Start4G() { - gpio_set_level(BOOT_4G_PIN, 1); -} - -void PowerManager::Shutdown4G() { - gpio_set_level(BOOT_4G_PIN, 0); - gpio_set_level(ML307_RX_PIN,1); - gpio_set_level(ML307_TX_PIN,1); -} - -void PowerManager::Sleep() { - ESP_LOGI(TAG, "Entering deep sleep"); - Settings settings("board", true); - settings.SetInt("sleep_flag", 1); - Shutdown4G(); - Shutdown5V(); - - if(gpio_evt_queue) { - vQueueDelete(gpio_evt_queue); - gpio_evt_queue = NULL; - } - ESP_ERROR_CHECK(gpio_isr_handler_remove(BOOT_BUTTON_PIN)); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(BOOT_BUTTON_PIN, 0)); - ESP_ERROR_CHECK(rtc_gpio_pulldown_dis(BOOT_BUTTON_PIN)); - ESP_ERROR_CHECK(rtc_gpio_pullup_en(BOOT_BUTTON_PIN)); - esp_deep_sleep_start(); -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.h deleted file mode 100644 index 921cf47a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/power_manager.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __POWERMANAGER_H__ -#define __POWERMANAGER_H__ - -#include -#include "driver/gpio.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/timers.h" - -class PowerManager{ -public: - PowerManager(); - void Initialize(); - bool IsCharging(); - bool IsDischarging(); - bool IsChargingDone(); - int GetBatteryLevel(); - void CheckStartup(); - void Start5V(); - void Shutdown5V(); - void Start4G(); - void Shutdown4G(); - void Sleep(); - void CheckBatteryStatus(); - void OnChargingStatusChanged(std::function callback); - void OnChargingStatusDisChanged(std::function callback); -private: - esp_timer_handle_t timer_handle_; - std::function charging_callback_; - std::function discharging_callback_; - int is_charging_ = -1; - int is_discharging_ = -1; - int call_count_ = 0; -}; - -#endif \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/yunliao_s3.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/yunliao_s3.cc deleted file mode 100644 index 57db4985..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/yunliao-s3/yunliao_s3.cc +++ /dev/null @@ -1,255 +0,0 @@ -#include -#include -#include "settings.h" -#include "application.h" -#include "assets/lang_config.h" -#include "button.h" -#include "codecs/es8388_audio_codec.h" -#include "config.h" -#include "display/lcd_display.h" -#include "dual_network_board.h" -#include "lvgl_theme.h" -#include "power_manager.h" -#include "power_save_timer.h" -#include "mcp_server.h" - -#define TAG "YunliaoS3" - -class YunliaoS3 : public DualNetworkBoard { - private: - i2c_master_bus_handle_t codec_i2c_bus_; - Button boot_button_; - SpiLcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - - void InitializePowerSaveTimer() { - power_save_timer_ = new PowerSaveTimer(-1, 60, 600); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(10); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->OnShutdownRequest([this]() { - ESP_LOGI(TAG, "Shutting down"); - power_manager_->Sleep(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeI2c() { - // Initialize I2C peripheral - i2c_master_bus_config_t i2c_bus_cfg = { - .i2c_port = I2C_NUM_0, - .sda_io_num = AUDIO_CODEC_I2C_SDA_PIN, - .scl_io_num = AUDIO_CODEC_I2C_SCL_PIN, - .clk_source = I2C_CLK_SRC_DEFAULT, - .glitch_ignore_cnt = 7, - .intr_priority = 0, - .trans_queue_depth = 0, - .flags = - { - .enable_internal_pullup = 1, - }, - }; - ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_cfg, &codec_i2c_bus_)); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SPI_PIN_MOSI; - buscfg.miso_io_num = DISPLAY_SPI_PIN_MISO; - buscfg.sclk_io_num = DISPLAY_SPI_PIN_SCLK; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = - DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK( - spi_bus_initialize(DISPLAY_SPI_LCD_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - app.ToggleChatState(); - }); - boot_button_.OnDoubleClick([this]() { - ESP_LOGI(TAG, "Button OnDoubleClick"); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting || - app.GetDeviceState() == kDeviceStateWifiConfiguring) { - SwitchNetworkType(); - } - }); - boot_button_.OnMultipleClick( - [this]() { - ESP_LOGI(TAG, "Button OnThreeClick"); - if (GetNetworkType() == NetworkType::WIFI) { - auto& wifi_board = - static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - } - }, 3); - boot_button_.OnLongPress([this]() { - ESP_LOGI(TAG, "Button LongPress to Sleep"); - display_->SetStatus(Lang::Strings::PLEASE_WAIT); - vTaskDelay(pdMS_TO_TICKS(2000)); - power_manager_->Sleep(); - }); - } - void InitializeSt7789Display() { - esp_lcd_panel_io_handle_t panel_io = nullptr; - esp_lcd_panel_handle_t panel = nullptr; - // 液晶屏控制IO初始化 - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_SPI_PIN_LCD_CS; - io_config.dc_gpio_num = DISPLAY_SPI_PIN_LCD_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = DISPLAY_SPI_CLOCK_HZ; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(DISPLAY_SPI_LCD_HOST, - &io_config, &panel_io)); - - // 初始化液晶屏驱动芯片ST7789 - ESP_LOGD(TAG, "Install LCD driver"); - Settings settings("display", false); - bool currentIpsMode = settings.GetBool("ips_mode", DISPLAY_INVERT_COLOR); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_SPI_PIN_LCD_RST; - panel_config.rgb_ele_order = DISPLAY_RGB_ORDER_COLOR; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK( - esp_lcd_new_panel_st7789(panel_io, &panel_config, &panel)); - - esp_lcd_panel_reset(panel); - esp_lcd_panel_init(panel); - esp_lcd_panel_invert_color(panel, currentIpsMode); - esp_lcd_panel_swap_xy(panel, DISPLAY_SWAP_XY); - esp_lcd_panel_mirror(panel, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y); - display_ = new SpiLcdDisplay(panel_io, panel, DISPLAY_WIDTH, - DISPLAY_HEIGHT, DISPLAY_OFFSET_X, - DISPLAY_OFFSET_Y, DISPLAY_MIRROR_X, - DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - auto& theme_manager = LvglThemeManager::GetInstance(); - auto theme = theme_manager.GetTheme("dark"); - if (theme != nullptr) { - display_->SetTheme(theme); - } - } - void InitializeTools(){ - auto& mcp_server = McpServer::GetInstance(); - - mcp_server.AddTool("self.system.set_aec", - "Enable or disable voice interruption mode (AEC:Acoustic Echo Cancellation). When enabled, the device can detect voice interruptions and respond accordingly.", - PropertyList({ - Property("enable", kPropertyTypeBoolean) - }), [this](const PropertyList& properties) { - bool enable = properties["enable"].value(); - SetAecMode(enable); - return true; - }); - - mcp_server.AddTool("self.system.switch_TFT", - "Switch TFT display mode between normal and inverted colors. This will toggle the IPS mode and reboot the device.", - PropertyList(), [this](const PropertyList& properties) { - SwitchTFT(); - return true; - }); - } - void SetAecMode(bool enable) { - AecMode newMode = enable ? kAecOnDeviceSide : kAecOff; - auto& app = Application::GetInstance(); - app.StopListening(); - app.SetDeviceState(kDeviceStateIdle); - app.SetAecMode(newMode); - Settings settings("aec", true); - settings.SetInt("mode", newMode); - } - void SwitchTFT() { - Settings settings("display", true); - bool currentIpsMode = settings.GetBool("ips_mode", false); - settings.SetBool("ips_mode", !currentIpsMode); - ESP_LOGI(TAG, "IPS mode toggled to %s", !currentIpsMode ? "enabled" : "disabled"); - vTaskDelay(pdMS_TO_TICKS(1000)); - auto& app = Application::GetInstance(); - app.Reboot(); - } - - public: - YunliaoS3() - : DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN, GPIO_NUM_NC, 0), - boot_button_(BOOT_BUTTON_PIN), - power_manager_(new PowerManager()) { - power_manager_->Start5V(); - power_manager_->Initialize(); - InitializeI2c(); - power_manager_->CheckStartup(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeSt7789Display(); - power_manager_->OnChargingStatusDisChanged([this](bool is_discharging) { - if (power_save_timer_) { - if (is_discharging) { - power_save_timer_->SetEnabled(true); - } else { - power_save_timer_->SetEnabled(false); - } - } - }); - if (GetNetworkType() == NetworkType::WIFI) { - power_manager_->Shutdown4G(); - } else { - power_manager_->Start4G(); - } - GetBacklight()->RestoreBrightness(); - while (gpio_get_level(BOOT_BUTTON_PIN) == 0) { - vTaskDelay(pdMS_TO_TICKS(10)); - } - InitializeButtons(); - Settings settings("aec", false); - auto& app = Application::GetInstance(); - app.SetAecMode(settings.GetInt("mode",kAecOnDeviceSide) == kAecOnDeviceSide ? kAecOnDeviceSide : kAecOff); - InitializeTools(); - } - - virtual AudioCodec* GetAudioCodec() override { - static Es8388AudioCodec audio_codec( - codec_i2c_bus_, I2C_NUM_0, AUDIO_INPUT_SAMPLE_RATE, - AUDIO_OUTPUT_SAMPLE_RATE, AUDIO_I2S_GPIO_MCLK, AUDIO_I2S_GPIO_BCLK, - AUDIO_I2S_GPIO_WS, AUDIO_I2S_GPIO_DOUT, AUDIO_I2S_GPIO_DIN, - AUDIO_CODEC_PA_PIN, AUDIO_CODEC_ES8388_ADDR, AUDIO_INPUT_REFERENCE); - return &audio_codec; - } - - virtual Display* GetDisplay() override { return display_; } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, - DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, - bool& discharging) override { - level = power_manager_->GetBatteryLevel(); - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(YunliaoS3); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/README.md deleted file mode 100644 index a7f289b6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# 产品相关介绍网址 - -```http -https://e.tb.cn/h.6Gl2LC7rsrswQZp?tk=qFuaV9hzh0k CZ356 -``` - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> zhengchen-1.54tft-ml307 -``` - -``` - -**编译:** - -bash -idf.py build -``` - -**下载:** -idf.py build flash monitor - -进行下载和显示日志 - - -**固件生成:** - -```bash -idf.py merge-bin -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.h deleted file mode 100644 index 888a0523..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.h +++ /dev/null @@ -1,42 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 - -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_10 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA GPIO_NUM_41 -#define DISPLAY_SCL GPIO_NUM_42 -#define DISPLAY_RES GPIO_NUM_45 -#define DISPLAY_DC GPIO_NUM_40 -#define DISPLAY_CS GPIO_NUM_21 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - -#define ML307_RX_PIN GPIO_NUM_11 -#define ML307_TX_PIN GPIO_NUM_12 - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.json deleted file mode 100644 index 6e17be76..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "zhengchen-1.54tft-ml307", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/zhengchen-1.54tft-ml307.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/zhengchen-1.54tft-ml307.cc deleted file mode 100644 index e0563719..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-ml307/zhengchen-1.54tft-ml307.cc +++ /dev/null @@ -1,211 +0,0 @@ -#include "dual_network_board.h" -#include "codecs/no_audio_codec.h" -#include "../zhengchen-1.54tft-wifi/zhengchen_lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "../zhengchen-1.54tft-wifi/power_manager.h" - -#include -#include - -#include -#include - -#define TAG "ZHENGCHEN_1_54TFT_ML307" - -class ZHENGCHEN_1_54TFT_ML307 : public DualNetworkBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - ZHENGCHEN_LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_9); - power_manager_->OnTemperatureChanged([this](float chip_temp) { - display_->UpdateHighTempWarning(chip_temp); - }); - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - } else { - power_save_timer_->SetEnabled(true); - } - }); - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_2); - rtc_gpio_set_direction(GPIO_NUM_2, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_2, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (GetNetworkType() == NetworkType::WIFI) { - if (app.GetDeviceState() == kDeviceStateStarting) { - // cast to WifiBoard - auto& wifi_board = static_cast(GetCurrentBoard()); - wifi_board.EnterWifiConfigMode(); - return; - } - } - app.ToggleChatState(); - }); - - boot_button_.OnLongPress([this]() { - SwitchNetworkType(); - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume/10)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume/10)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, true)); - - display_ = new ZHENGCHEN_LcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - display_->SetupHighTempWarningPopup(); - } - -public: - ZHENGCHEN_1_54TFT_ML307() : - DualNetworkBoard(ML307_TX_PIN, ML307_RX_PIN), - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - GetBacklight()->RestoreBrightness(); - } - - virtual AudioCodec* GetAudioCodec() override { - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = std::max(power_manager_->GetBatteryLevel(), 20); - return true; - } - - virtual bool GetTemperature(float& esp32temp) override { - esp32temp = power_manager_->GetTemperature(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - DualNetworkBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(ZHENGCHEN_1_54TFT_ML307); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/README.md deleted file mode 100644 index 20bd9a6f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# 产品相关介绍网址 - -```http -https://e.tb.cn/h.6Gl2LC7rsrswQZp?tk=qFuaV9hzh0k CZ356 -``` - -# 编译配置命令 - -**配置编译目标为 ESP32S3:** - -```bash -idf.py set-target esp32s3 -``` - -**打开 menuconfig:** - -```bash -idf.py menuconfig -``` - -**选择板子:** - -``` -Xiaozhi Assistant -> Board Type -> zhengchen-1.54tft-wifi -``` - -``` - -**编译:** - -bash -idf.py build -``` - -**下载:** -idf.py build flash monitor - -进行下载和显示日志 - - -**固件生成:** - -```bash -idf.py merge-bin -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.h deleted file mode 100644 index f7d971a8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.h +++ /dev/null @@ -1,39 +0,0 @@ - -#ifndef _BOARD_CONFIG_H_ -#define _BOARD_CONFIG_H_ - -#include - -#define AUDIO_INPUT_SAMPLE_RATE 16000 -#define AUDIO_OUTPUT_SAMPLE_RATE 24000 -#define AUDIO_I2S_MIC_GPIO_WS GPIO_NUM_4 -#define AUDIO_I2S_MIC_GPIO_SCK GPIO_NUM_5 -#define AUDIO_I2S_MIC_GPIO_DIN GPIO_NUM_6 -#define AUDIO_I2S_SPK_GPIO_DOUT GPIO_NUM_7 -#define AUDIO_I2S_SPK_GPIO_BCLK GPIO_NUM_15 -#define AUDIO_I2S_SPK_GPIO_LRCK GPIO_NUM_16 - -#define BOOT_BUTTON_GPIO GPIO_NUM_0 -#define VOLUME_UP_BUTTON_GPIO GPIO_NUM_10 -#define VOLUME_DOWN_BUTTON_GPIO GPIO_NUM_39 - -#define DISPLAY_SDA GPIO_NUM_41 -#define DISPLAY_SCL GPIO_NUM_42 -#define DISPLAY_RES GPIO_NUM_45 -#define DISPLAY_DC GPIO_NUM_40 -#define DISPLAY_CS GPIO_NUM_21 - -#define DISPLAY_WIDTH 240 -#define DISPLAY_HEIGHT 240 -#define DISPLAY_SWAP_XY false -#define DISPLAY_MIRROR_X false -#define DISPLAY_MIRROR_Y false -#define BACKLIGHT_INVERT false -#define DISPLAY_OFFSET_X 0 -#define DISPLAY_OFFSET_Y 0 - -#define DISPLAY_BACKLIGHT_PIN GPIO_NUM_20 -#define DISPLAY_BACKLIGHT_OUTPUT_INVERT false - - -#endif // _BOARD_CONFIG_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.json deleted file mode 100644 index 3c17d116..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/config.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "target": "esp32s3", - "builds": [ - { - "name": "zhengchen-1.54tft-wifi", - "sdkconfig_append": [] - } - ] -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/power_manager.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/power_manager.h deleted file mode 100644 index de6e82d2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/power_manager.h +++ /dev/null @@ -1,238 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include -#include -#include "application.h" -#include "zhengchen_lcd_display.h" - -class PowerManager { -private: - // 定时器句柄 - esp_timer_handle_t timer_handle_; - std::function on_charging_status_changed_; - std::function on_low_battery_status_changed_; - std::function on_temperature_changed_; - - gpio_num_t charging_pin_ = GPIO_NUM_NC; - std::vector adc_values_; - uint32_t battery_level_ = 0; - bool is_charging_ = false; - bool is_low_battery_ = false; - float current_temperature_ = 0.0f; - int ticks_ = 0; - const int kBatteryAdcInterval = 60; - const int kBatteryAdcDataCount = 3; - const int kLowBatteryLevel = 20; - const int kTemperatureReadInterval = 10; // 每 10 秒读取一次温度 - - adc_oneshot_unit_handle_t adc_handle_; - temperature_sensor_handle_t temp_sensor_ = NULL; - - void CheckBatteryStatus() { - // Get charging status - bool new_charging_status = gpio_get_level(charging_pin_) == 1; - if (new_charging_status != is_charging_) { - is_charging_ = new_charging_status; - if (on_charging_status_changed_) { - on_charging_status_changed_(is_charging_); - } - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据不足,则读取电池电量数据 - if (adc_values_.size() < kBatteryAdcDataCount) { - ReadBatteryAdcData(); - return; - } - - // 如果电池电量数据充足,则每 kBatteryAdcInterval 个 tick 读取一次电池电量数据 - ticks_++; - if (ticks_ % kBatteryAdcInterval == 0) { - ReadBatteryAdcData(); - } - - // 新增:周期性读取温度 - if (ticks_ % kTemperatureReadInterval == 0) { - ReadTemperature(); - } - } - - void ReadBatteryAdcData() { - // 读取 ADC 值 - int adc_value; - ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, ADC_CHANNEL_7, &adc_value)); - - - // 将 ADC 值添加到队列中 - adc_values_.push_back(adc_value); - if (adc_values_.size() > kBatteryAdcDataCount) { - adc_values_.erase(adc_values_.begin()); - } - uint32_t average_adc = 0; - for (auto value : adc_values_) { - average_adc += (value + 80); - } - average_adc /= adc_values_.size(); - - - // 定义电池电量区间 - const struct { - uint16_t adc; - uint8_t level; - } levels[] = { - {2030, 0}, - {2134, 20}, - {2252, 40}, - {2370, 60}, - {2488, 80}, - {2606, 100} - }; - // 低于最低值时 - if (average_adc < levels[0].adc) { - battery_level_ = 0; - } - // 高于最高值时 - else if (average_adc >= levels[5].adc) { - battery_level_ = 100; - } else { - // 线性插值计算中间值 - for (int i = 0; i < 5; i++) { - if (average_adc >= levels[i].adc && average_adc < levels[i+1].adc) { - float ratio = static_cast(average_adc - levels[i].adc) / (levels[i+1].adc - levels[i].adc); - battery_level_ = levels[i].level + ratio * (levels[i+1].level - levels[i].level); - break; - } - } - } - // 检查是否达到低电量阈值 - if (adc_values_.size() >= kBatteryAdcDataCount) { - bool new_low_battery_status = battery_level_ <= kLowBatteryLevel; - if (new_low_battery_status != is_low_battery_) { - is_low_battery_ = new_low_battery_status; - if (on_low_battery_status_changed_) { - on_low_battery_status_changed_(is_low_battery_); - } - } - } - - ESP_LOGI("PowerManager", "ADC value: %d average: %ld level: %ld", adc_value, average_adc, battery_level_); - } - - void ReadTemperature() { - float temperature = 0.0f; - ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_sensor_, &temperature)); - - if (abs(temperature - current_temperature_) >= 3.5f) { // 温度变化超过3.5°C才触发回调 - current_temperature_ = temperature; - if (on_temperature_changed_) { - on_temperature_changed_(current_temperature_); - } - ESP_LOGI("PowerManager", "Temperature updated: %.1f°C", current_temperature_); - } - } - - -public: - PowerManager(gpio_num_t pin) : charging_pin_(pin) { - - // 初始化充电引脚 - gpio_config_t io_conf = {}; - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << charging_pin_); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - gpio_config(&io_conf); - - // 创建电池电量检查定时器 - esp_timer_create_args_t timer_args = { - .callback = [](void* arg) { - PowerManager* self = static_cast(arg); - self->CheckBatteryStatus(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "battery_check_timer", - .skip_unhandled_events = true, - }; - ESP_ERROR_CHECK(esp_timer_create(&timer_args, &timer_handle_)); - ESP_ERROR_CHECK(esp_timer_start_periodic(timer_handle_, 1000000)); - - // 初始化 ADC - adc_oneshot_unit_init_cfg_t init_config = { - .unit_id = ADC_UNIT_1, - .ulp_mode = ADC_ULP_MODE_DISABLE, - }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config, &adc_handle_)); - - adc_oneshot_chan_cfg_t chan_config = { - .atten = ADC_ATTEN_DB_12, - .bitwidth = ADC_BITWIDTH_12, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc_handle_, ADC_CHANNEL_7, &chan_config)); - - // 初始化温度传感器 - temperature_sensor_config_t temp_config = { - .range_min = 10, - .range_max = 80, - .clk_src = TEMPERATURE_SENSOR_CLK_SRC_DEFAULT - }; - ESP_ERROR_CHECK(temperature_sensor_install(&temp_config, &temp_sensor_)); - ESP_ERROR_CHECK(temperature_sensor_enable(temp_sensor_)); - ESP_LOGI("PowerManager", "Temperature sensor initialized (new driver)"); - } - - ~PowerManager() { - if (timer_handle_) { - esp_timer_stop(timer_handle_); - esp_timer_delete(timer_handle_); - } - if (adc_handle_) { - adc_oneshot_del_unit(adc_handle_); - } - - if (temp_sensor_) { - temperature_sensor_disable(temp_sensor_); - temperature_sensor_uninstall(temp_sensor_); - } - - } - - bool IsCharging() { - // 如果电量已经满了,则不再显示充电中 - if (battery_level_ == 100) { - return false; - } - return is_charging_; - } - - bool IsDischarging() { - // 没有区分充电和放电,所以直接返回相反状态 - return !is_charging_; - } - - // 获取电池电量 - uint8_t GetBatteryLevel() { - // 返回电池电量 - return battery_level_; - } - - float GetTemperature() const { return current_temperature_; } // 获取当前温度 - - void OnTemperatureChanged(std::function callback) { - on_temperature_changed_ = callback; - } - - void OnLowBatteryStatusChanged(std::function callback) { - on_low_battery_status_changed_ = callback; - } - - void OnChargingStatusChanged(std::function callback) { - on_charging_status_changed_ = callback; - } -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen-1.54tft-wifi.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen-1.54tft-wifi.cc deleted file mode 100644 index 5f7c305d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen-1.54tft-wifi.cc +++ /dev/null @@ -1,228 +0,0 @@ -#include "wifi_board.h" -#include "codecs/no_audio_codec.h" -#include "zhengchen_lcd_display.h" -#include "system_reset.h" -#include "application.h" -#include "button.h" -#include "config.h" -#include "power_save_timer.h" -#include "led/single_led.h" -#include "assets/lang_config.h" -#include "power_manager.h" - -#include -#include - -#include -#include - -#define TAG "ZHENGCHEN_1_54TFT_WIFI" - -class ZHENGCHEN_1_54TFT_WIFI : public WifiBoard { -private: - Button boot_button_; - Button volume_up_button_; - Button volume_down_button_; - ZHENGCHEN_LcdDisplay* display_; - PowerSaveTimer* power_save_timer_; - PowerManager* power_manager_; - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - void InitializePowerManager() { - power_manager_ = new PowerManager(GPIO_NUM_9); - power_manager_->OnTemperatureChanged([this](float chip_temp) { - display_->UpdateHighTempWarning(chip_temp); - }); - - power_manager_->OnChargingStatusChanged([this](bool is_charging) { - if (is_charging) { - power_save_timer_->SetEnabled(false); - ESP_LOGI("PowerManager", "Charging started"); - } else { - power_save_timer_->SetEnabled(true); - ESP_LOGI("PowerManager", "Charging stopped"); - } - }); - - } - - void InitializePowerSaveTimer() { - rtc_gpio_init(GPIO_NUM_2); - rtc_gpio_set_direction(GPIO_NUM_2, RTC_GPIO_MODE_OUTPUT_ONLY); - rtc_gpio_set_level(GPIO_NUM_2, 1); - - power_save_timer_ = new PowerSaveTimer(-1, 60, 300); - power_save_timer_->OnEnterSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(true); - GetBacklight()->SetBrightness(1); - }); - power_save_timer_->OnExitSleepMode([this]() { - GetDisplay()->SetPowerSaveMode(false); - GetBacklight()->RestoreBrightness(); - }); - power_save_timer_->SetEnabled(true); - } - - void InitializeSpi() { - spi_bus_config_t buscfg = {}; - buscfg.mosi_io_num = DISPLAY_SDA; - buscfg.miso_io_num = GPIO_NUM_NC; - buscfg.sclk_io_num = DISPLAY_SCL; - buscfg.quadwp_io_num = GPIO_NUM_NC; - buscfg.quadhd_io_num = GPIO_NUM_NC; - buscfg.max_transfer_sz = DISPLAY_WIDTH * DISPLAY_HEIGHT * sizeof(uint16_t); - ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST, &buscfg, SPI_DMA_CH_AUTO)); - } - - void InitializeButtons() { - - boot_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateStarting) { - EnterWifiConfigMode(); - return; - } - app.ToggleChatState(); - }); - - // 设置开机按钮的长按事件(直接进入配网模式) - boot_button_.OnLongPress([this]() { - // 唤醒电源保存定时器 - power_save_timer_->WakeUp(); - // 获取应用程序实例 - auto& app = Application::GetInstance(); - - // 进入配网模式 - app.SetDeviceState(kDeviceStateWifiConfiguring); - - // 重置WiFi配置以确保进入配网模式 - EnterWifiConfigMode(); - }); - - volume_up_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() + 10; - if (volume > 100) { - volume = 100; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume/10)); - }); - - volume_up_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(100); - GetDisplay()->ShowNotification(Lang::Strings::MAX_VOLUME); - }); - - volume_down_button_.OnClick([this]() { - power_save_timer_->WakeUp(); - auto codec = GetAudioCodec(); - auto volume = codec->output_volume() - 10; - if (volume < 0) { - volume = 0; - } - codec->SetOutputVolume(volume); - GetDisplay()->ShowNotification(Lang::Strings::VOLUME + std::to_string(volume/10)); - }); - - volume_down_button_.OnLongPress([this]() { - power_save_timer_->WakeUp(); - GetAudioCodec()->SetOutputVolume(0); - GetDisplay()->ShowNotification(Lang::Strings::MUTED); - }); - } - - void InitializeSt7789Display() { - ESP_LOGD(TAG, "Install panel IO"); - esp_lcd_panel_io_spi_config_t io_config = {}; - io_config.cs_gpio_num = DISPLAY_CS; - io_config.dc_gpio_num = DISPLAY_DC; - io_config.spi_mode = 3; - io_config.pclk_hz = 80 * 1000 * 1000; - io_config.trans_queue_depth = 10; - io_config.lcd_cmd_bits = 8; - io_config.lcd_param_bits = 8; - ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST, &io_config, &panel_io_)); - - ESP_LOGD(TAG, "Install LCD driver"); - esp_lcd_panel_dev_config_t panel_config = {}; - panel_config.reset_gpio_num = DISPLAY_RES; - panel_config.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB; - panel_config.bits_per_pixel = 16; - ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(panel_io_, &panel_config, &panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_init(panel_)); - ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_, DISPLAY_SWAP_XY)); - ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_, DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y)); - ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_, true)); - - display_ = new ZHENGCHEN_LcdDisplay(panel_io_, panel_, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_OFFSET_X, DISPLAY_OFFSET_Y, - DISPLAY_MIRROR_X, DISPLAY_MIRROR_Y, DISPLAY_SWAP_XY); - display_->SetupHighTempWarningPopup(); - } - - void InitializeTools() { - } - -public: - ZHENGCHEN_1_54TFT_WIFI() : - boot_button_(BOOT_BUTTON_GPIO), - volume_up_button_(VOLUME_UP_BUTTON_GPIO), - volume_down_button_(VOLUME_DOWN_BUTTON_GPIO) { - InitializePowerManager(); - InitializePowerSaveTimer(); - InitializeSpi(); - InitializeButtons(); - InitializeSt7789Display(); - InitializeTools(); - GetBacklight()->RestoreBrightness(); - } - - // 获取音频编解码器 - virtual AudioCodec* GetAudioCodec() override { - // 静态实例化NoAudioCodecSimplex类 - static NoAudioCodecSimplex audio_codec(AUDIO_INPUT_SAMPLE_RATE, AUDIO_OUTPUT_SAMPLE_RATE, - AUDIO_I2S_SPK_GPIO_BCLK, AUDIO_I2S_SPK_GPIO_LRCK, AUDIO_I2S_SPK_GPIO_DOUT, AUDIO_I2S_MIC_GPIO_SCK, AUDIO_I2S_MIC_GPIO_WS, AUDIO_I2S_MIC_GPIO_DIN); - // 返回音频编解码器 - return &audio_codec; - } - - virtual Display* GetDisplay() override { - return display_; - } - - virtual Backlight* GetBacklight() override { - static PwmBacklight backlight(DISPLAY_BACKLIGHT_PIN, DISPLAY_BACKLIGHT_OUTPUT_INVERT); - return &backlight; - } - - virtual bool GetBatteryLevel(int& level, bool& charging, bool& discharging) override { - static bool last_discharging = false; - charging = power_manager_->IsCharging(); - discharging = power_manager_->IsDischarging(); - if (discharging != last_discharging) { - power_save_timer_->SetEnabled(discharging); - last_discharging = discharging; - } - level = std::max(power_manager_->GetBatteryLevel(), 20); - return true; - } - - virtual bool GetTemperature(float& esp32temp) override { - esp32temp = power_manager_->GetTemperature(); - return true; - } - - virtual void SetPowerSaveLevel(PowerSaveLevel level) override { - if (level != PowerSaveLevel::LOW_POWER) { - power_save_timer_->WakeUp(); - } - WifiBoard::SetPowerSaveLevel(level); - } -}; - -DECLARE_BOARD(ZHENGCHEN_1_54TFT_WIFI); diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen_lcd_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen_lcd_display.h deleted file mode 100644 index fa6222aa..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/boards/zhengchen-1.54tft-wifi/zhengchen_lcd_display.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef ZHENGCHEN_LCD_DISPLAY_H -#define ZHENGCHEN_LCD_DISPLAY_H - -#include "display/lcd_display.h" -#include "lvgl_theme.h" -#include - -class ZHENGCHEN_LcdDisplay : public SpiLcdDisplay { -protected: - lv_obj_t* high_temp_popup_ = nullptr; // 高温警告弹窗 - lv_obj_t* high_temp_label_ = nullptr; // 高温警告标签 - -public: - // 继承构造函数 - using SpiLcdDisplay::SpiLcdDisplay; - - void SetupHighTempWarningPopup() { - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - // 创建高温警告弹窗 - high_temp_popup_ = lv_obj_create(lv_screen_active()); // 使用当前屏幕 - lv_obj_set_scrollbar_mode(high_temp_popup_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_size(high_temp_popup_, LV_HOR_RES * 0.9, text_font->line_height * 2); - lv_obj_align(high_temp_popup_, LV_ALIGN_BOTTOM_MID, 0, 0); - lv_obj_set_style_bg_color(high_temp_popup_, lv_palette_main(LV_PALETTE_RED), 0); - lv_obj_set_style_radius(high_temp_popup_, 10, 0); - - // 创建警告标签 - high_temp_label_ = lv_label_create(high_temp_popup_); - lv_label_set_text(high_temp_label_, "警告:温度过高"); - lv_obj_set_style_text_color(high_temp_label_, lv_color_white(), 0); - lv_obj_center(high_temp_label_); - - // 默认隐藏 - lv_obj_add_flag(high_temp_popup_, LV_OBJ_FLAG_HIDDEN); - } - - void UpdateHighTempWarning(float chip_temp, float threshold = 75.0f) { - if (high_temp_popup_ == nullptr) { - ESP_LOGW("ZHENGCHEN_LcdDisplay", "High temp popup not initialized!"); - return; - } - - if (chip_temp >= threshold) { - ShowHighTempWarning(); - } else { - HideHighTempWarning(); - } - } - - void ShowHighTempWarning() { - if (high_temp_popup_ && lv_obj_has_flag(high_temp_popup_, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_remove_flag(high_temp_popup_, LV_OBJ_FLAG_HIDDEN); - } - } - - void HideHighTempWarning() { - if (high_temp_popup_ && !lv_obj_has_flag(high_temp_popup_, LV_OBJ_FLAG_HIDDEN)) { - lv_obj_add_flag(high_temp_popup_, LV_OBJ_FLAG_HIDDEN); - } - } -}; - - - -#endif // ZHENGCHEN_LCD_DISPLAY_H \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state.h deleted file mode 100644 index 4ffafae2..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _DEVICE_STATE_H_ -#define _DEVICE_STATE_H_ - -enum DeviceState { - kDeviceStateUnknown, - kDeviceStateStarting, - kDeviceStateWifiConfiguring, - kDeviceStateIdle, - kDeviceStateConnecting, - kDeviceStateListening, - kDeviceStateSpeaking, - kDeviceStateUpgrading, - kDeviceStateActivating, - kDeviceStateAudioTesting, - kDeviceStateFatalError -}; - -#endif // _DEVICE_STATE_H_ \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.cc deleted file mode 100644 index 30581de6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.cc +++ /dev/null @@ -1,161 +0,0 @@ -#include "device_state_machine.h" - -#include -#include - -static const char* TAG = "StateMachine"; - -// State name strings for logging -static const char* const STATE_STRINGS[] = { - "unknown", - "starting", - "wifi_configuring", - "idle", - "connecting", - "listening", - "speaking", - "upgrading", - "activating", - "audio_testing", - "fatal_error", - "invalid_state" -}; - -DeviceStateMachine::DeviceStateMachine() { -} - -const char* DeviceStateMachine::GetStateName(DeviceState state) { - if (state >= 0 && state <= kDeviceStateFatalError) { - return STATE_STRINGS[state]; - } - return STATE_STRINGS[kDeviceStateFatalError + 1]; -} - -bool DeviceStateMachine::IsValidTransition(DeviceState from, DeviceState to) const { - // Allow transition to the same state (no-op) - if (from == to) { - return true; - } - - // Define valid state transitions based on the state diagram - switch (from) { - case kDeviceStateUnknown: - // Can only go to starting - return to == kDeviceStateStarting; - - case kDeviceStateStarting: - // Can go to wifi configuring or activating - return to == kDeviceStateWifiConfiguring || - to == kDeviceStateActivating; - - case kDeviceStateWifiConfiguring: - // Can go to activating (after wifi connected) or audio testing - return to == kDeviceStateActivating || - to == kDeviceStateAudioTesting; - - case kDeviceStateAudioTesting: - // Can go back to wifi configuring - return to == kDeviceStateWifiConfiguring; - - case kDeviceStateActivating: - // Can go to upgrading, idle, or back to wifi configuring (on error) - return to == kDeviceStateUpgrading || - to == kDeviceStateIdle || - to == kDeviceStateWifiConfiguring; - - case kDeviceStateUpgrading: - // Can go to idle (upgrade failed) or activating - return to == kDeviceStateIdle || - to == kDeviceStateActivating; - - case kDeviceStateIdle: - // Can go to connecting, listening (manual mode), speaking, activating, upgrading, or wifi configuring - return to == kDeviceStateConnecting || - to == kDeviceStateListening || - to == kDeviceStateSpeaking || - to == kDeviceStateActivating || - to == kDeviceStateUpgrading || - to == kDeviceStateWifiConfiguring; - - case kDeviceStateConnecting: - // Can go to idle (failed) or listening (success) - return to == kDeviceStateIdle || - to == kDeviceStateListening; - - case kDeviceStateListening: - // Can go to speaking or idle - return to == kDeviceStateSpeaking || - to == kDeviceStateIdle; - - case kDeviceStateSpeaking: - // Can go to listening or idle - return to == kDeviceStateListening || - to == kDeviceStateIdle; - - case kDeviceStateFatalError: - // Cannot transition out of fatal error - return false; - - default: - return false; - } -} - -bool DeviceStateMachine::CanTransitionTo(DeviceState target) const { - return IsValidTransition(current_state_.load(), target); -} - -bool DeviceStateMachine::TransitionTo(DeviceState new_state) { - DeviceState old_state = current_state_.load(); - - // No-op if already in the target state - if (old_state == new_state) { - return true; - } - - // Validate transition - if (!IsValidTransition(old_state, new_state)) { - ESP_LOGW(TAG, "Invalid state transition: %s -> %s", - GetStateName(old_state), GetStateName(new_state)); - return false; - } - - // Perform transition - current_state_.store(new_state); - ESP_LOGI(TAG, "State: %s -> %s", - GetStateName(old_state), GetStateName(new_state)); - - // Notify callback - NotifyStateChange(old_state, new_state); - return true; -} - -int DeviceStateMachine::AddStateChangeListener(StateCallback callback) { - std::lock_guard lock(mutex_); - int id = next_listener_id_++; - listeners_.emplace_back(id, std::move(callback)); - return id; -} - -void DeviceStateMachine::RemoveStateChangeListener(int listener_id) { - std::lock_guard lock(mutex_); - listeners_.erase( - std::remove_if(listeners_.begin(), listeners_.end(), - [listener_id](const auto& p) { return p.first == listener_id; }), - listeners_.end()); -} - -void DeviceStateMachine::NotifyStateChange(DeviceState old_state, DeviceState new_state) { - std::vector callbacks_copy; - { - std::lock_guard lock(mutex_); - callbacks_copy.reserve(listeners_.size()); - for (const auto& [id, cb] : listeners_) { - callbacks_copy.push_back(cb); - } - } - - for (const auto& cb : callbacks_copy) { - cb(old_state, new_state); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.h deleted file mode 100644 index 9566fdeb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/device_state_machine.h +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef DEVICE_STATE_MACHINE_H -#define DEVICE_STATE_MACHINE_H - -#include -#include -#include -#include - -#include "device_state.h" - -/** - * DeviceStateMachine - Manages device state transitions with validation - * - * This class ensures strict state transition rules and provides a callback mechanism - * for components to react to state changes. - */ -class DeviceStateMachine { -public: - DeviceStateMachine(); - ~DeviceStateMachine() = default; - - // Delete copy constructor and assignment operator - DeviceStateMachine(const DeviceStateMachine&) = delete; - DeviceStateMachine& operator=(const DeviceStateMachine&) = delete; - - /** - * Get the current device state - */ - DeviceState GetState() const { return current_state_.load(); } - - /** - * Attempt to transition to a new state - * @param new_state The target state - * @return true if transition was successful, false if invalid transition - */ - bool TransitionTo(DeviceState new_state); - - /** - * Check if transition to target state is valid from current state - */ - bool CanTransitionTo(DeviceState target) const; - - /** - * State change callback type - * Parameters: old_state, new_state - */ - using StateCallback = std::function; - - /** - * Add a state change listener (observer pattern) - * Callback is invoked in the context of the caller of TransitionTo() - * @return listener id for removal - */ - int AddStateChangeListener(StateCallback callback); - - /** - * Remove a state change listener by id - */ - void RemoveStateChangeListener(int listener_id); - - /** - * Get state name string for logging - */ - static const char* GetStateName(DeviceState state); - -private: - std::atomic current_state_{kDeviceStateUnknown}; - std::vector> listeners_; - int next_listener_id_{0}; - std::mutex mutex_; - - /** - * Check if transition from source to target is valid - */ - bool IsValidTransition(DeviceState from, DeviceState to) const; - - /** - * Notify callback of state change - */ - void NotifyStateChange(DeviceState old_state, DeviceState new_state); -}; - -#endif // DEVICE_STATE_MACHINE_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.cc deleted file mode 100644 index d352e026..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.cc +++ /dev/null @@ -1,56 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "display.h" -#include "board.h" -#include "application.h" -#include "audio_codec.h" -#include "settings.h" -#include "assets/lang_config.h" - -#define TAG "Display" - -Display::Display() { -} - -Display::~Display() { -} - -void Display::SetStatus(const char* status) { - ESP_LOGW(TAG, "SetStatus: %s", status); -} - -void Display::ShowNotification(const std::string ¬ification, int duration_ms) { - ShowNotification(notification.c_str(), duration_ms); -} - -void Display::ShowNotification(const char* notification, int duration_ms) { - ESP_LOGW(TAG, "ShowNotification: %s", notification); -} - -void Display::UpdateStatusBar(bool update_all) { -} - - -void Display::SetEmotion(const char* emotion) { - ESP_LOGW(TAG, "SetEmotion: %s", emotion); -} - -void Display::SetChatMessage(const char* role, const char* content) { - ESP_LOGW(TAG, "Role:%s", role); - ESP_LOGW(TAG, " %s", content); -} - -void Display::SetTheme(Theme* theme) { - current_theme_ = theme; - Settings settings("display", true); - settings.SetString("theme", theme->name()); -} - -void Display::SetPowerSaveMode(bool on) { - ESP_LOGW(TAG, "SetPowerSaveMode: %d", on); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.h deleted file mode 100644 index b24da4eb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/display.h +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef DISPLAY_H -#define DISPLAY_H - -#include "emoji_collection.h" - -#ifndef CONFIG_USE_EMOTE_MESSAGE_STYLE -#define HAVE_LVGL 1 -#include -#endif - -#include -#include -#include - -#include -#include - -class Theme { -public: - Theme(const std::string& name) : name_(name) {} - virtual ~Theme() = default; - - inline std::string name() const { return name_; } -private: - std::string name_; -}; - -class Display { -public: - Display(); - virtual ~Display(); - - virtual void SetStatus(const char* status); - virtual void ShowNotification(const char* notification, int duration_ms = 3000); - virtual void ShowNotification(const std::string ¬ification, int duration_ms = 3000); - virtual void SetEmotion(const char* emotion); - virtual void SetChatMessage(const char* role, const char* content); - virtual void SetTheme(Theme* theme); - virtual Theme* GetTheme() { return current_theme_; } - virtual void UpdateStatusBar(bool update_all = false); - virtual void SetPowerSaveMode(bool on); - - inline int width() const { return width_; } - inline int height() const { return height_; } - -protected: - int width_ = 0; - int height_ = 0; - - Theme* current_theme_ = nullptr; - - friend class DisplayLockGuard; - virtual bool Lock(int timeout_ms = 0) = 0; - virtual void Unlock() = 0; -}; - - -class DisplayLockGuard { -public: - DisplayLockGuard(Display *display) : display_(display) { - if (!display_->Lock(30000)) { - ESP_LOGE("Display", "Failed to lock display"); - } - } - ~DisplayLockGuard() { - display_->Unlock(); - } - -private: - Display *display_; -}; - -class NoDisplay : public Display { -private: - virtual bool Lock(int timeout_ms = 0) override { - return true; - } - virtual void Unlock() override {} -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.cc deleted file mode 100644 index e4a3f76a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.cc +++ /dev/null @@ -1,658 +0,0 @@ -#include "emote_display.h" - -// Standard C++ headers -#include -#include -#include -#include - -// Standard C headers -#include -#include - -// ESP-IDF headers -#include -#include -#include - -// FreeRTOS headers -#include -#include - -// Project headers -#include "assets.h" -#include "assets/lang_config.h" -#include "board.h" -#include "gfx.h" - -LV_FONT_DECLARE(BUILTIN_TEXT_FONT); - -namespace emote { - -// ============================================================================ -// Constants and Type Definitions -// ============================================================================ - -static const char* TAG = "EmoteDisplay"; - -// UI Element Names - Centralized Management -#define UI_ELEMENT_EYE_ANIM "eye_anim" -#define UI_ELEMENT_TOAST_LABEL "toast_label" -#define UI_ELEMENT_CLOCK_LABEL "clock_label" -#define UI_ELEMENT_LISTEN_ANIM "listen_anim" -#define UI_ELEMENT_STATUS_ICON "status_icon" - -// Icon Names - Centralized Management -#define ICON_MIC "icon_mic" -#define ICON_BATTERY "icon_Battery" -#define ICON_SPEAKER_ZZZ "icon_speaker_zzz" -#define ICON_WIFI_FAILED "icon_WiFi_failed" -#define ICON_WIFI_OK "icon_wifi" -#define ICON_LISTEN "listen" - -using FlushIoReadyCallback = std::function; -using FlushCallback = std::function; - -// ============================================================================ -// Global Variables -// ============================================================================ - -// UI element management -static gfx_obj_t* g_obj_label_toast = nullptr; -static gfx_obj_t* g_obj_label_clock = nullptr; -static gfx_obj_t* g_obj_anim_eye = nullptr; -static gfx_obj_t* g_obj_anim_listen = nullptr; -static gfx_obj_t* g_obj_img_status = nullptr; - -// Track current icon to determine when to show time -static std::string g_current_icon_type = ICON_WIFI_FAILED; -static gfx_image_dsc_t g_icon_img_dsc; - - -// ============================================================================ -// Forward Declarations -// ============================================================================ - -class EmoteDisplay; -class EmoteEngine; - -enum class UIDisplayMode : uint8_t { - SHOW_LISTENING = 1, // Show g_obj_anim_listen - SHOW_TIME = 2, // Show g_obj_label_clock - SHOW_TIPS = 3 // Show g_obj_label_toast -}; - -// ============================================================================ -// Helper Functions -// ============================================================================ - -// Function to convert align string to GFX_ALIGN enum value -char StringToGfxAlign(const std::string &align_str) -{ - static const std::unordered_map align_map = { - {"GFX_ALIGN_DEFAULT", GFX_ALIGN_DEFAULT}, - {"GFX_ALIGN_TOP_LEFT", GFX_ALIGN_TOP_LEFT}, - {"GFX_ALIGN_TOP_MID", GFX_ALIGN_TOP_MID}, - {"GFX_ALIGN_TOP_RIGHT", GFX_ALIGN_TOP_RIGHT}, - {"GFX_ALIGN_LEFT_MID", GFX_ALIGN_LEFT_MID}, - {"GFX_ALIGN_CENTER", GFX_ALIGN_CENTER}, - {"GFX_ALIGN_RIGHT_MID", GFX_ALIGN_RIGHT_MID}, - {"GFX_ALIGN_BOTTOM_LEFT", GFX_ALIGN_BOTTOM_LEFT}, - {"GFX_ALIGN_BOTTOM_MID", GFX_ALIGN_BOTTOM_MID}, - {"GFX_ALIGN_BOTTOM_RIGHT", GFX_ALIGN_BOTTOM_RIGHT}, - {"GFX_ALIGN_OUT_TOP_LEFT", GFX_ALIGN_OUT_TOP_LEFT}, - {"GFX_ALIGN_OUT_TOP_MID", GFX_ALIGN_OUT_TOP_MID}, - {"GFX_ALIGN_OUT_TOP_RIGHT", GFX_ALIGN_OUT_TOP_RIGHT}, - {"GFX_ALIGN_OUT_LEFT_TOP", GFX_ALIGN_OUT_LEFT_TOP}, - {"GFX_ALIGN_OUT_LEFT_MID", GFX_ALIGN_OUT_LEFT_MID}, - {"GFX_ALIGN_OUT_LEFT_BOTTOM", GFX_ALIGN_OUT_LEFT_BOTTOM}, - {"GFX_ALIGN_OUT_RIGHT_TOP", GFX_ALIGN_OUT_RIGHT_TOP}, - {"GFX_ALIGN_OUT_RIGHT_MID", GFX_ALIGN_OUT_RIGHT_MID}, - {"GFX_ALIGN_OUT_RIGHT_BOTTOM", GFX_ALIGN_OUT_RIGHT_BOTTOM}, - {"GFX_ALIGN_OUT_BOTTOM_LEFT", GFX_ALIGN_OUT_BOTTOM_LEFT}, - {"GFX_ALIGN_OUT_BOTTOM_MID", GFX_ALIGN_OUT_BOTTOM_MID}, - {"GFX_ALIGN_OUT_BOTTOM_RIGHT", GFX_ALIGN_OUT_BOTTOM_RIGHT} - }; - - const auto it = align_map.find(align_str); - if (it != align_map.cend()) { - return it->second; - } - - ESP_LOGW(TAG, "Unknown align string: %s, using GFX_ALIGN_DEFAULT", align_str.c_str()); - return GFX_ALIGN_DEFAULT; -} - -// ============================================================================ -// EmoteEngine Class Declaration -// ============================================================================ - -class EmoteEngine { -public: - EmoteEngine(const esp_lcd_panel_handle_t panel, const esp_lcd_panel_io_handle_t panel_io, - const int width, const int height, EmoteDisplay* const display); - ~EmoteEngine(); - - void SetEyes(const std::string &emoji_name, const bool repeat, const int fps, EmoteDisplay* const display); - void SetIcon(const std::string &icon_name, EmoteDisplay* const display); - - void* GetEngineHandle() const - { - return engine_handle_; - } - - // Callback functions (public to be accessible from static helper functions) - static bool OnFlushIoReady(const esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t* const edata, void* const user_ctx); - static void OnFlush(const gfx_handle_t handle, const int x_start, const int y_start, const int x_end, const int y_end, const void* const color_data); - -private: - gfx_handle_t engine_handle_; -}; - -// ============================================================================ -// UI Management Functions -// ============================================================================ - -static void SetUIDisplayMode(const UIDisplayMode mode, EmoteDisplay* const display) -{ - if (!display) { - ESP_LOGE(TAG, "SetUIDisplayMode: display is nullptr"); - return; - } - - gfx_obj_set_visible(g_obj_anim_listen, false); - gfx_obj_set_visible(g_obj_label_clock, false); - gfx_obj_set_visible(g_obj_label_toast, false); - - // Show the selected control - switch (mode) { - case UIDisplayMode::SHOW_LISTENING: { - gfx_obj_set_visible(g_obj_anim_listen, true); - const AssetData emoji_data = display->GetIconData(ICON_LISTEN); - if (emoji_data.data) { - gfx_anim_set_src(g_obj_anim_listen, emoji_data.data, emoji_data.size); - gfx_anim_set_segment(g_obj_anim_listen, 0, 0xFFFF, 20, true); - gfx_anim_start(g_obj_anim_listen); - } - break; - } - case UIDisplayMode::SHOW_TIME: - gfx_obj_set_visible(g_obj_label_clock, true); - break; - case UIDisplayMode::SHOW_TIPS: - gfx_obj_set_visible(g_obj_label_toast, true); - break; - } -} - -// ============================================================================ -// Graphics Initialization Functions -// ============================================================================ - -static void InitializeGraphics(const esp_lcd_panel_handle_t panel, gfx_handle_t* const engine_handle, - const int width, const int height) -{ - if (!panel || !engine_handle) { - ESP_LOGE(TAG, "InitializeGraphics: Invalid parameters"); - return; - } - - gfx_core_config_t gfx_cfg = { - .flush_cb = EmoteEngine::OnFlush, - .user_data = panel, - .flags = { - .swap = true, - .double_buffer = true, - .buff_dma = true, - }, - .h_res = static_cast(width), - .v_res = static_cast(height), - .fps = 30, - .buffers = { - .buf1 = nullptr, - .buf2 = nullptr, - .buf_pixels = static_cast(width * 16), - }, - .task = GFX_EMOTE_INIT_CONFIG() - }; - - gfx_cfg.task.task_stack_caps = MALLOC_CAP_DEFAULT; - gfx_cfg.task.task_affinity = 0; - gfx_cfg.task.task_priority = 5; - gfx_cfg.task.task_stack = 8 * 1024; - - *engine_handle = gfx_emote_init(&gfx_cfg); -} - -static void SetupUI(const gfx_handle_t engine_handle, EmoteDisplay* const display) -{ - if (!display) { - ESP_LOGE(TAG, "SetupUI: display is nullptr"); - return; - } - - gfx_emote_set_bg_color(engine_handle, GFX_COLOR_HEX(0x000000)); - - g_obj_anim_eye = gfx_anim_create(engine_handle); - gfx_obj_align(g_obj_anim_eye, GFX_ALIGN_LEFT_MID, 10, 30); - gfx_anim_set_auto_mirror(g_obj_anim_eye, true); - gfx_obj_set_visible(g_obj_anim_eye, false); - - g_obj_label_toast = gfx_label_create(engine_handle); - gfx_obj_align(g_obj_label_toast, GFX_ALIGN_TOP_MID, 0, 20); - gfx_obj_set_size(g_obj_label_toast, 200, 40); - gfx_label_set_text(g_obj_label_toast, Lang::Strings::INITIALIZING); - gfx_label_set_color(g_obj_label_toast, GFX_COLOR_HEX(0xFFFFFF)); - gfx_label_set_text_align(g_obj_label_toast, GFX_TEXT_ALIGN_CENTER); - gfx_label_set_long_mode(g_obj_label_toast, GFX_LABEL_LONG_SCROLL); - gfx_label_set_scroll_speed(g_obj_label_toast, 20); - gfx_label_set_scroll_loop(g_obj_label_toast, true); - gfx_label_set_font(g_obj_label_toast, (gfx_font_t)&BUILTIN_TEXT_FONT); - - g_obj_label_clock = gfx_label_create(engine_handle); - gfx_obj_align(g_obj_label_clock, GFX_ALIGN_TOP_MID, 0, 15); - gfx_obj_set_size(g_obj_label_clock, 200, 50); - gfx_label_set_text(g_obj_label_clock, "--:--"); - gfx_label_set_color(g_obj_label_clock, GFX_COLOR_HEX(0xFFFFFF)); - gfx_label_set_text_align(g_obj_label_clock, GFX_TEXT_ALIGN_CENTER); - gfx_label_set_font(g_obj_label_clock, (gfx_font_t)&BUILTIN_TEXT_FONT); - - g_obj_anim_listen = gfx_anim_create(engine_handle); - gfx_obj_align(g_obj_anim_listen, GFX_ALIGN_TOP_MID, 0, 5); - gfx_anim_start(g_obj_anim_listen); - gfx_obj_set_visible(g_obj_anim_listen, false); - - g_obj_img_status = gfx_img_create(engine_handle); - gfx_obj_align(g_obj_img_status, GFX_ALIGN_TOP_MID, -120, 18); - - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, display); -} - -static void RegisterCallbacks(const esp_lcd_panel_io_handle_t panel_io, const gfx_handle_t engine_handle) -{ - if (!panel_io) { - ESP_LOGE(TAG, "RegisterCallbacks: panel_io is nullptr"); - return; - } - - const esp_lcd_panel_io_callbacks_t cbs = { - .on_color_trans_done = EmoteEngine::OnFlushIoReady, - }; - esp_lcd_panel_io_register_event_callbacks(panel_io, &cbs, engine_handle); -} - -// ============================================================================ -// EmoteEngine Class Implementation -// ============================================================================ - -EmoteEngine::EmoteEngine(const esp_lcd_panel_handle_t panel, const esp_lcd_panel_io_handle_t panel_io, - const int width, const int height, EmoteDisplay* const display) -{ - InitializeGraphics(panel, &engine_handle_, width, height); - - if (display) { - gfx_emote_lock(engine_handle_); - SetupUI(engine_handle_, display); - gfx_emote_unlock(engine_handle_); - } - - RegisterCallbacks(panel_io, engine_handle_); -} - -EmoteEngine::~EmoteEngine() -{ - if (engine_handle_) { - gfx_emote_deinit(engine_handle_); - engine_handle_ = nullptr; - } -} - -void EmoteEngine::SetEyes(const std::string &emoji_name, const bool repeat, const int fps, EmoteDisplay* const display) -{ - if (!engine_handle_) { - ESP_LOGE(TAG, "SetEyes: engine_handle_ is nullptr"); - return; - } - - if (!display) { - ESP_LOGE(TAG, "SetEyes: display is nullptr"); - return; - } - - const AssetData emoji_data = display->GetEmojiData(emoji_name); - if (emoji_data.data) { - DisplayLockGuard lock(display); - gfx_anim_set_src(g_obj_anim_eye, emoji_data.data, emoji_data.size); - gfx_anim_set_segment(g_obj_anim_eye, 0, 0xFFFF, fps, repeat); - gfx_obj_set_visible(g_obj_anim_eye, true); - gfx_anim_start(g_obj_anim_eye); - } else { - ESP_LOGW(TAG, "SetEyes: No emoji data found for %s", emoji_name.c_str()); - } -} - -void EmoteEngine::SetIcon(const std::string &icon_name, EmoteDisplay* const display) -{ - if (!engine_handle_) { - ESP_LOGE(TAG, "SetIcon: engine_handle_ is nullptr"); - return; - } - - if (!display) { - ESP_LOGE(TAG, "SetIcon: display is nullptr"); - return; - } - - const AssetData icon_data = display->GetIconData(icon_name); - if (icon_data.data) { - DisplayLockGuard lock(display); - - std::memcpy(&g_icon_img_dsc.header, icon_data.data, sizeof(gfx_image_header_t)); - g_icon_img_dsc.data = static_cast(icon_data.data) + sizeof(gfx_image_header_t); - g_icon_img_dsc.data_size = icon_data.size - sizeof(gfx_image_header_t); - - gfx_img_set_src(g_obj_img_status, &g_icon_img_dsc); - } else { - ESP_LOGW(TAG, "SetIcon: No icon data found for %s", icon_name.c_str()); - } - g_current_icon_type = icon_name; -} - -bool EmoteEngine::OnFlushIoReady(const esp_lcd_panel_io_handle_t panel_io, - esp_lcd_panel_io_event_data_t* const edata, - void* const user_ctx) -{ - gfx_handle_t handle = static_cast(user_ctx); - if (handle) { - gfx_emote_flush_ready(handle, true); - } - return false; -} - -void EmoteEngine::OnFlush(const gfx_handle_t handle, const int x_start, const int y_start, - const int x_end, const int y_end, const void* const color_data) -{ - auto* const panel = static_cast(gfx_emote_get_user_data(handle)); - if (panel) { - esp_lcd_panel_draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data); - } -} - -// ============================================================================ -// EmoteDisplay Class Implementation -// ============================================================================ - -EmoteDisplay::EmoteDisplay(const esp_lcd_panel_handle_t panel, const esp_lcd_panel_io_handle_t panel_io, - const int width, const int height) -{ - InitializeEngine(panel, panel_io, width, height); -} - -EmoteDisplay::~EmoteDisplay() = default; - -void EmoteDisplay::SetEmotion(const char* const emotion) -{ - if (!emotion) { - ESP_LOGE(TAG, "SetEmotion: emotion is nullptr"); - return; - } - - ESP_LOGI(TAG, "SetEmotion: %s", emotion); - if (!engine_) { - return; - } - - const AssetData emoji_data = GetEmojiData(emotion); - bool repeat = emoji_data.loop; - int fps = emoji_data.fps > 0 ? emoji_data.fps : 20; - - if (std::strcmp(emotion, "idle") == 0 || std::strcmp(emotion, "neutral") == 0) { - repeat = false; - } - - DisplayLockGuard lock(this); - engine_->SetEyes(emotion, repeat, fps, this); -} - -void EmoteDisplay::SetChatMessage(const char* const role, const char* const content) -{ - if (!engine_) { - return; - } - - DisplayLockGuard lock(this); - if (content && strlen(content) > 0) { - gfx_label_set_text(g_obj_label_toast, content); - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, this); - } -} - -void EmoteDisplay::SetStatus(const char* const status) -{ - if (!status) { - ESP_LOGE(TAG, "SetStatus: status is nullptr"); - return; - } - - if (!engine_) { - return; - } - - DisplayLockGuard lock(this); - - if (std::strcmp(status, Lang::Strings::LISTENING) == 0) { - SetUIDisplayMode(UIDisplayMode::SHOW_LISTENING, this); - engine_->SetEyes("happy", true, 20, this); - engine_->SetIcon(ICON_MIC, this); - } else if (std::strcmp(status, Lang::Strings::STANDBY) == 0) { - SetUIDisplayMode(UIDisplayMode::SHOW_TIME, this); - engine_->SetIcon(ICON_BATTERY, this); - } else if (std::strcmp(status, Lang::Strings::SPEAKING) == 0) { - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, this); - engine_->SetIcon(ICON_SPEAKER_ZZZ, this); - } else if (std::strcmp(status, Lang::Strings::ERROR) == 0) { - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, this); - engine_->SetIcon(ICON_WIFI_FAILED, this); - } - - if (std::strcmp(status, Lang::Strings::CONNECTING) != 0) { - gfx_label_set_text(g_obj_label_toast, status); - } -} - -void EmoteDisplay::ShowNotification(const char* notification, int duration_ms) -{ - if (!notification || !engine_) { - return; - } - ESP_LOGI(TAG, "ShowNotification: %s", notification); - - DisplayLockGuard lock(this); - gfx_label_set_text(g_obj_label_toast, notification); - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, this); -} - -void EmoteDisplay::UpdateStatusBar(bool update_all) -{ - if (!engine_) { - return; - } - - // Only display time when battery icon is shown - DisplayLockGuard lock(this); - if (g_current_icon_type == ICON_BATTERY) { - time_t now; - struct tm timeinfo; - time(&now); - - setenv("TZ", "GMT+0", 1); - tzset(); - localtime_r(&now, &timeinfo); - - char time_str[6]; - snprintf(time_str, sizeof(time_str), "%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); - - DisplayLockGuard lock(this); - gfx_label_set_text(g_obj_label_clock, time_str); - SetUIDisplayMode(UIDisplayMode::SHOW_TIME, this); - } -} - -void EmoteDisplay::SetPowerSaveMode(bool on) -{ - if (!engine_) { - return; - } - - DisplayLockGuard lock(this); - ESP_LOGI(TAG, "SetPowerSaveMode: %s", on ? "ON" : "OFF"); - if (on) { - gfx_anim_stop(g_obj_anim_eye); - } else { - gfx_anim_start(g_obj_anim_eye); - } -} - -void EmoteDisplay::SetPreviewImage(const void* image) -{ - if (image) { - ESP_LOGI(TAG, "SetPreviewImage: Preview image not supported, using default icon"); - if (engine_) { - } - } -} - -void EmoteDisplay::SetTheme(Theme* const theme) -{ - ESP_LOGI(TAG, "SetTheme: %p", theme); - -} -void EmoteDisplay::AddEmojiData(const std::string &name, const void* const data, const size_t size, - uint8_t fps, bool loop, bool lack) -{ - emoji_data_map_[name] = AssetData(data, size, fps, loop, lack); - ESP_LOGD(TAG, "Added emoji data: %s, size: %d, fps: %d, loop: %s, lack: %s", - name.c_str(), size, fps, loop ? "true" : "false", lack ? "true" : "false"); - - DisplayLockGuard lock(this); - if (name == "happy") { - engine_->SetEyes("happy", loop, fps > 0 ? fps : 20, this); - } -} - -void EmoteDisplay::AddIconData(const std::string &name, const void* const data, const size_t size) -{ - icon_data_map_[name] = AssetData(data, size); - ESP_LOGD(TAG, "Added icon data: %s, size: %d", name.c_str(), size); - - DisplayLockGuard lock(this); - if (name == ICON_WIFI_FAILED) { - SetUIDisplayMode(UIDisplayMode::SHOW_TIPS, this); - engine_->SetIcon(ICON_WIFI_FAILED, this); - } -} - -void EmoteDisplay::AddLayoutData(const std::string &name, const std::string &align_str, - const int x, const int y, const int width, const int height) -{ - const char align_enum = StringToGfxAlign(align_str); - ESP_LOGI(TAG, "layout: %-12s | %-20s(%d) | %4d, %4d | %4dx%-4d", - name.c_str(), align_str.c_str(), align_enum, x, y, width, height); - - struct UIElement { - gfx_obj_t* obj; - const char* name; - }; - - const UIElement elements[] = { - {g_obj_anim_eye, UI_ELEMENT_EYE_ANIM}, - {g_obj_label_toast, UI_ELEMENT_TOAST_LABEL}, - {g_obj_label_clock, UI_ELEMENT_CLOCK_LABEL}, - {g_obj_anim_listen, UI_ELEMENT_LISTEN_ANIM}, - {g_obj_img_status, UI_ELEMENT_STATUS_ICON} - }; - - DisplayLockGuard lock(this); - for (const auto &element : elements) { - if (name == element.name && element.obj) { - gfx_obj_align(element.obj, align_enum, x, y); - if (width > 0 && height > 0) { - gfx_obj_set_size(element.obj, width, height); - } - return; - } - } - - ESP_LOGW(TAG, "AddLayoutData: UI element '%s' not found", name.c_str()); -} - -void EmoteDisplay::AddTextFont(std::shared_ptr text_font) -{ - if (!text_font) { - ESP_LOGW(TAG, "AddTextFont: text_font is nullptr"); - return; - } - - text_font_ = text_font; - ESP_LOGD(TAG, "AddTextFont: Text font added successfully"); - - DisplayLockGuard lock(this); - if (g_obj_label_toast && text_font_) { - gfx_label_set_font(g_obj_label_toast, const_cast(static_cast(text_font_->font()))); - } - if (g_obj_label_clock && text_font_) { - gfx_label_set_font(g_obj_label_clock, const_cast(static_cast(text_font_->font()))); - } -} - -AssetData EmoteDisplay::GetEmojiData(const std::string &name) const -{ - const auto it = emoji_data_map_.find(name); - if (it != emoji_data_map_.cend()) { - return it->second; - } - return AssetData(); -} - -AssetData EmoteDisplay::GetIconData(const std::string &name) const -{ - const auto it = icon_data_map_.find(name); - if (it != icon_data_map_.cend()) { - return it->second; - } - return AssetData(); -} - -EmoteEngine* EmoteDisplay::GetEngine() const -{ - return engine_.get(); -} - -void* EmoteDisplay::GetEngineHandle() const -{ - return engine_ ? engine_->GetEngineHandle() : nullptr; -} - -void EmoteDisplay::InitializeEngine(const esp_lcd_panel_handle_t panel, const esp_lcd_panel_io_handle_t panel_io, - const int width, const int height) -{ - engine_ = std::make_unique(panel, panel_io, width, height, this); -} - -bool EmoteDisplay::Lock(const int timeout_ms) -{ - if (engine_ && engine_->GetEngineHandle()) { - gfx_emote_lock(engine_->GetEngineHandle()); - return true; - } - return false; -} - -void EmoteDisplay::Unlock() -{ - if (engine_ && engine_->GetEngineHandle()) { - gfx_emote_unlock(engine_->GetEngineHandle()); - } -} - -} // namespace emote \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.h deleted file mode 100644 index ffa02a4c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/emote_display.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include "display.h" -#include "lvgl_font.h" -#include -#include -#include -#include -#include -#include - -namespace emote { - -// Simple data structure for storing asset data without LVGL dependency -struct AssetData { - const void* data; - size_t size; - union { - uint8_t flags; // 1 byte for all animation flags - struct { - uint8_t fps : 6; // FPS (0-63) - 6 bits - uint8_t loop : 1; // Loop animation - 1 bit - uint8_t lack : 1; // Lack animation - 1 bit - }; - }; - - AssetData() : data(nullptr), size(0), flags(0) {} - AssetData(const void* d, size_t s) : data(d), size(s), flags(0) {} - AssetData(const void* d, size_t s, uint8_t f, bool l, bool k) - : data(d), size(s) - { - fps = f > 63 ? 63 : f; // 限制 FPS 到 6 位范围 - loop = l; - lack = k; - } -}; - -// Layout element data structure -struct LayoutData { - char align; // Store as char instead of string - int x; - int y; - int width; - int height; - bool has_size; - - LayoutData() : align(0), x(0), y(0), width(0), height(0), has_size(false) {} - LayoutData(char a, int x_pos, int y_pos, int w = 0, int h = 0) - : align(a), x(x_pos), y(y_pos), width(w), height(h), has_size(w > 0 && h > 0) {} -}; - -// Function to convert align string to GFX_ALIGN enum value -char StringToGfxAlign(const std::string &align_str); - -class EmoteEngine; - -class EmoteDisplay : public Display { -public: - EmoteDisplay(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io, int width, int height); - virtual ~EmoteDisplay(); - - virtual void SetEmotion(const char* emotion) override; - virtual void SetStatus(const char* status) override; - virtual void SetChatMessage(const char* role, const char* content) override; - virtual void SetTheme(Theme* theme) override; - virtual void ShowNotification(const char* notification, int duration_ms = 3000) override; - virtual void UpdateStatusBar(bool update_all = false) override; - virtual void SetPowerSaveMode(bool on) override; - virtual void SetPreviewImage(const void* image); - - void AddEmojiData(const std::string &name, const void* data, size_t size, uint8_t fps = 0, bool loop = false, bool lack = false); - void AddIconData(const std::string &name, const void* data, size_t size); - void AddLayoutData(const std::string &name, const std::string &align_str, int x, int y, int width = 0, int height = 0); - void AddTextFont(std::shared_ptr text_font); - AssetData GetEmojiData(const std::string &name) const; - AssetData GetIconData(const std::string &name) const; - - EmoteEngine* GetEngine() const; - void* GetEngineHandle() const; - - inline std::shared_ptr text_font() const - { - return text_font_; - } - -private: - void InitializeEngine(esp_lcd_panel_handle_t panel, esp_lcd_panel_io_handle_t panel_io, int width, int height); - virtual bool Lock(int timeout_ms = 0) override; - virtual void Unlock() override; - - std::unique_ptr engine_; - - // Font management - std::shared_ptr text_font_ = nullptr; - - // Non-LVGL asset data storage - std::map emoji_data_map_; - std::map icon_data_map_; - -}; - -} // namespace emote diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.cc deleted file mode 100644 index c00a8a7d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.cc +++ /dev/null @@ -1,1196 +0,0 @@ -#include "lcd_display.h" -#include "gif/lvgl_gif.h" -#include "settings.h" -#include "lvgl_theme.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "board.h" - -#define TAG "LcdDisplay" - -LV_FONT_DECLARE(BUILTIN_TEXT_FONT); -LV_FONT_DECLARE(BUILTIN_ICON_FONT); -LV_FONT_DECLARE(font_awesome_30_4); - -void LcdDisplay::InitializeLcdThemes() { - auto text_font = std::make_shared(&BUILTIN_TEXT_FONT); - auto icon_font = std::make_shared(&BUILTIN_ICON_FONT); - auto large_icon_font = std::make_shared(&font_awesome_30_4); - - // light theme - auto light_theme = new LvglTheme("light"); - light_theme->set_background_color(lv_color_hex(0xFFFFFF)); - light_theme->set_text_color(lv_color_hex(0x000000)); - light_theme->set_chat_background_color(lv_color_hex(0xE0E0E0)); - light_theme->set_user_bubble_color(lv_color_hex(0x00FF00)); - light_theme->set_assistant_bubble_color(lv_color_hex(0xDDDDDD)); - light_theme->set_system_bubble_color(lv_color_hex(0xFFFFFF)); - light_theme->set_system_text_color(lv_color_hex(0x000000)); - light_theme->set_border_color(lv_color_hex(0x000000)); - light_theme->set_low_battery_color(lv_color_hex(0x000000)); - light_theme->set_text_font(text_font); - light_theme->set_icon_font(icon_font); - light_theme->set_large_icon_font(large_icon_font); - - // dark theme - auto dark_theme = new LvglTheme("dark"); - dark_theme->set_background_color(lv_color_hex(0x000000)); - dark_theme->set_text_color(lv_color_hex(0xFFFFFF)); - dark_theme->set_chat_background_color(lv_color_hex(0x1F1F1F)); - dark_theme->set_user_bubble_color(lv_color_hex(0x00FF00)); - dark_theme->set_assistant_bubble_color(lv_color_hex(0x222222)); - dark_theme->set_system_bubble_color(lv_color_hex(0x000000)); - dark_theme->set_system_text_color(lv_color_hex(0xFFFFFF)); - dark_theme->set_border_color(lv_color_hex(0xFFFFFF)); - dark_theme->set_low_battery_color(lv_color_hex(0xFF0000)); - dark_theme->set_text_font(text_font); - dark_theme->set_icon_font(icon_font); - dark_theme->set_large_icon_font(large_icon_font); - - auto& theme_manager = LvglThemeManager::GetInstance(); - theme_manager.RegisterTheme("light", light_theme); - theme_manager.RegisterTheme("dark", dark_theme); -} - -LcdDisplay::LcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height) - : panel_io_(panel_io), panel_(panel) { - width_ = width; - height_ = height; - - // Initialize LCD themes - InitializeLcdThemes(); - - // Load theme from settings - Settings settings("display", false); - std::string theme_name = settings.GetString("theme", "light"); - current_theme_ = LvglThemeManager::GetInstance().GetTheme(theme_name); - - // Create a timer to hide the preview image - esp_timer_create_args_t preview_timer_args = { - .callback = [](void* arg) { - LcdDisplay* display = static_cast(arg); - display->SetPreviewImage(nullptr); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "preview_timer", - .skip_unhandled_events = false, - }; - esp_timer_create(&preview_timer_args, &preview_timer_); -} - -SpiLcdDisplay::SpiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) - : LcdDisplay(panel_io, panel, width, height) { - - // draw white - std::vector buffer(width_, 0xFFFF); - for (int y = 0; y < height_; y++) { - esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data()); - } - - // Set the display to on - ESP_LOGI(TAG, "Turning display on"); - { - esp_err_t __err = esp_lcd_panel_disp_on_off(panel_, true); - if (__err == ESP_ERR_NOT_SUPPORTED) { - ESP_LOGW(TAG, "Panel does not support disp_on_off; assuming ON"); - } else { - ESP_ERROR_CHECK(__err); - } - } - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - -#if CONFIG_SPIRAM - // lv image cache, currently only PNG is supported - size_t psram_size_mb = esp_psram_get_size() / 1024 / 1024; - if (psram_size_mb >= 8) { - lv_image_cache_resize(2 * 1024 * 1024, true); - ESP_LOGI(TAG, "Use 2MB of PSRAM for image cache"); - } else if (psram_size_mb >= 2) { - lv_image_cache_resize(512 * 1024, true); - ESP_LOGI(TAG, "Use 512KB of PSRAM for image cache"); - } -#endif - - ESP_LOGI(TAG, "Initialize LVGL port"); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 1; -#if CONFIG_SOC_CPU_CORES_NUM > 1 - port_cfg.task_affinity = 1; -#endif - lvgl_port_init(&port_cfg); - - ESP_LOGI(TAG, "Adding LCD display"); - const lvgl_port_display_cfg_t display_cfg = { - .io_handle = panel_io_, - .panel_handle = panel_, - .control_handle = nullptr, - .buffer_size = static_cast(width_ * 20), - .double_buffer = false, - .trans_size = 0, - .hres = static_cast(width_), - .vres = static_cast(height_), - .monochrome = false, - .rotation = { - .swap_xy = swap_xy, - .mirror_x = mirror_x, - .mirror_y = mirror_y, - }, - .color_format = LV_COLOR_FORMAT_RGB565, - .flags = { - .buff_dma = 1, - .buff_spiram = 0, - .sw_rotate = 0, - .swap_bytes = 1, - .full_refresh = 0, - .direct_mode = 0, - }, - }; - - display_ = lvgl_port_add_disp(&display_cfg); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - if (offset_x != 0 || offset_y != 0) { - lv_display_set_offset(display_, offset_x, offset_y); - } - - SetupUI(); -} - - -// RGB LCD implementation -RgbLcdDisplay::RgbLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy) - : LcdDisplay(panel_io, panel, width, height) { - - // draw white - std::vector buffer(width_, 0xFFFF); - for (int y = 0; y < height_; y++) { - esp_lcd_panel_draw_bitmap(panel_, 0, y, width_, y + 1, buffer.data()); - } - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - - ESP_LOGI(TAG, "Initialize LVGL port"); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 1; - port_cfg.timer_period_ms = 50; - lvgl_port_init(&port_cfg); - - ESP_LOGI(TAG, "Adding LCD display"); - const lvgl_port_display_cfg_t display_cfg = { - .io_handle = panel_io_, - .panel_handle = panel_, - .buffer_size = static_cast(width_ * 20), - .double_buffer = true, - .hres = static_cast(width_), - .vres = static_cast(height_), - .rotation = { - .swap_xy = swap_xy, - .mirror_x = mirror_x, - .mirror_y = mirror_y, - }, - .flags = { - .buff_dma = 1, - .swap_bytes = 0, - .full_refresh = 1, - .direct_mode = 1, - }, - }; - - const lvgl_port_display_rgb_cfg_t rgb_cfg = { - .flags = { - .bb_mode = true, - .avoid_tearing = true, - } - }; - - display_ = lvgl_port_add_disp_rgb(&display_cfg, &rgb_cfg); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add RGB display"); - return; - } - - if (offset_x != 0 || offset_y != 0) { - lv_display_set_offset(display_, offset_x, offset_y); - } - - SetupUI(); -} - -MipiLcdDisplay::MipiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy) - : LcdDisplay(panel_io, panel, width, height) { - - ESP_LOGI(TAG, "Initialize LVGL library"); - lv_init(); - - ESP_LOGI(TAG, "Initialize LVGL port"); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - lvgl_port_init(&port_cfg); - - ESP_LOGI(TAG, "Adding LCD display"); - const lvgl_port_display_cfg_t disp_cfg = { - .io_handle = panel_io, - .panel_handle = panel, - .control_handle = nullptr, - .buffer_size = static_cast(width_ * 50), - .double_buffer = false, - .hres = static_cast(width_), - .vres = static_cast(height_), - .monochrome = false, - /* Rotation values must be same as used in esp_lcd for initial settings of the screen */ - .rotation = { - .swap_xy = swap_xy, - .mirror_x = mirror_x, - .mirror_y = mirror_y, - }, - .flags = { - .buff_dma = true, - .buff_spiram =false, - .sw_rotate = true, - }, - }; - - const lvgl_port_display_dsi_cfg_t dpi_cfg = { - .flags = { - .avoid_tearing = false, - } - }; - display_ = lvgl_port_add_disp_dsi(&disp_cfg, &dpi_cfg); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - if (offset_x != 0 || offset_y != 0) { - lv_display_set_offset(display_, offset_x, offset_y); - } - - SetupUI(); -} - -LcdDisplay::~LcdDisplay() { - SetPreviewImage(nullptr); - - // Clean up GIF controller - if (gif_controller_) { - gif_controller_->Stop(); - gif_controller_.reset(); - } - - if (preview_timer_ != nullptr) { - esp_timer_stop(preview_timer_); - esp_timer_delete(preview_timer_); - } - - if (preview_image_ != nullptr) { - lv_obj_del(preview_image_); - } - if (chat_message_label_ != nullptr) { - lv_obj_del(chat_message_label_); - } - if (emoji_label_ != nullptr) { - lv_obj_del(emoji_label_); - } - if (emoji_image_ != nullptr) { - lv_obj_del(emoji_image_); - } - if (emoji_box_ != nullptr) { - lv_obj_del(emoji_box_); - } - if (content_ != nullptr) { - lv_obj_del(content_); - } - if (bottom_bar_ != nullptr) { - lv_obj_del(bottom_bar_); - } - if (status_bar_ != nullptr) { - lv_obj_del(status_bar_); - } - if (top_bar_ != nullptr) { - lv_obj_del(top_bar_); - } - if (side_bar_ != nullptr) { - lv_obj_del(side_bar_); - } - if (container_ != nullptr) { - lv_obj_del(container_); - } - if (display_ != nullptr) { - lv_display_delete(display_); - } - - if (panel_ != nullptr) { - esp_lcd_panel_del(panel_); - } - if (panel_io_ != nullptr) { - esp_lcd_panel_io_del(panel_io_); - } -} - -bool LcdDisplay::Lock(int timeout_ms) { - return lvgl_port_lock(timeout_ms); -} - -void LcdDisplay::Unlock() { - lvgl_port_unlock(); -} - -#if CONFIG_USE_WECHAT_MESSAGE_STYLE -void LcdDisplay::SetupUI() { - DisplayLockGuard lock(this); - - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - auto large_icon_font = lvgl_theme->large_icon_font()->font(); - - auto screen = lv_screen_active(); - lv_obj_set_style_text_font(screen, text_font, 0); - lv_obj_set_style_text_color(screen, lvgl_theme->text_color(), 0); - lv_obj_set_style_bg_color(screen, lvgl_theme->background_color(), 0); - - /* Container */ - container_ = lv_obj_create(screen); - lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); - lv_obj_set_style_radius(container_, 0, 0); - lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(container_, 0, 0); - lv_obj_set_style_border_width(container_, 0, 0); - lv_obj_set_style_pad_row(container_, 0, 0); - lv_obj_set_style_bg_color(container_, lvgl_theme->background_color(), 0); - lv_obj_set_style_border_color(container_, lvgl_theme->border_color(), 0); - - /* Layer 1: Top bar - for status icons */ - top_bar_ = lv_obj_create(container_); - lv_obj_set_size(top_bar_, LV_HOR_RES, LV_SIZE_CONTENT); - lv_obj_set_style_radius(top_bar_, 0, 0); - lv_obj_set_style_bg_opa(top_bar_, LV_OPA_50, 0); // 50% opacity background - lv_obj_set_style_bg_color(top_bar_, lvgl_theme->background_color(), 0); - lv_obj_set_style_border_width(top_bar_, 0, 0); - lv_obj_set_style_pad_all(top_bar_, 0, 0); - lv_obj_set_style_pad_top(top_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_bottom(top_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_left(top_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_style_pad_right(top_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_flex_flow(top_bar_, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(top_bar_, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_set_scrollbar_mode(top_bar_, LV_SCROLLBAR_MODE_OFF); - - // Left icon - network_label_ = lv_label_create(top_bar_); - lv_label_set_text(network_label_, ""); - lv_obj_set_style_text_font(network_label_, icon_font, 0); - lv_obj_set_style_text_color(network_label_, lvgl_theme->text_color(), 0); - - // Right icons container - lv_obj_t* right_icons = lv_obj_create(top_bar_); - lv_obj_set_size(right_icons, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_set_style_bg_opa(right_icons, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(right_icons, 0, 0); - lv_obj_set_style_pad_all(right_icons, 0, 0); - lv_obj_set_flex_flow(right_icons, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(right_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - mute_label_ = lv_label_create(right_icons); - lv_label_set_text(mute_label_, ""); - lv_obj_set_style_text_font(mute_label_, icon_font, 0); - lv_obj_set_style_text_color(mute_label_, lvgl_theme->text_color(), 0); - - battery_label_ = lv_label_create(right_icons); - lv_label_set_text(battery_label_, ""); - lv_obj_set_style_text_font(battery_label_, icon_font, 0); - lv_obj_set_style_text_color(battery_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_margin_left(battery_label_, lvgl_theme->spacing(2), 0); - - /* Layer 2: Status bar - for center text labels */ - status_bar_ = lv_obj_create(screen); - lv_obj_set_size(status_bar_, LV_HOR_RES, LV_SIZE_CONTENT); - lv_obj_set_style_radius(status_bar_, 0, 0); - lv_obj_set_style_bg_opa(status_bar_, LV_OPA_TRANSP, 0); // Transparent background - lv_obj_set_style_border_width(status_bar_, 0, 0); - lv_obj_set_style_pad_all(status_bar_, 0, 0); - lv_obj_set_style_pad_top(status_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_bottom(status_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_scrollbar_mode(status_bar_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_layout(status_bar_, LV_LAYOUT_NONE, 0); // Use absolute positioning - lv_obj_align(status_bar_, LV_ALIGN_TOP_MID, 0, 0); // Overlap with top_bar_ - - notification_label_ = lv_label_create(status_bar_); - lv_obj_set_width(notification_label_, LV_HOR_RES * 0.8); - lv_obj_set_style_text_align(notification_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_set_style_text_color(notification_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(notification_label_, ""); - lv_obj_align(notification_label_, LV_ALIGN_CENTER, 0, 0); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - status_label_ = lv_label_create(status_bar_); - lv_obj_set_width(status_label_, LV_HOR_RES * 0.8); - lv_label_set_long_mode(status_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_style_text_align(status_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_set_style_text_color(status_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(status_label_, Lang::Strings::INITIALIZING); - lv_obj_align(status_label_, LV_ALIGN_CENTER, 0, 0); - - /* Content - Chat area */ - content_ = lv_obj_create(container_); - lv_obj_set_style_radius(content_, 0, 0); - lv_obj_set_width(content_, LV_HOR_RES); - lv_obj_set_flex_grow(content_, 1); - lv_obj_set_style_pad_all(content_, lvgl_theme->spacing(4), 0); - lv_obj_set_style_border_width(content_, 0, 0); - lv_obj_set_style_bg_color(content_, lvgl_theme->chat_background_color(), 0); // Background for chat area - - // Enable scrolling for chat content - lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_scroll_dir(content_, LV_DIR_VER); - - // Create a flex container for chat messages - lv_obj_set_flex_flow(content_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_flex_align(content_, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); - lv_obj_set_style_pad_row(content_, lvgl_theme->spacing(4), 0); // Space between messages - - // We'll create chat messages dynamically in SetChatMessage - chat_message_label_ = nullptr; - - low_battery_popup_ = lv_obj_create(screen); - lv_obj_set_scrollbar_mode(low_battery_popup_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_size(low_battery_popup_, LV_HOR_RES * 0.9, text_font->line_height * 2); - lv_obj_align(low_battery_popup_, LV_ALIGN_BOTTOM_MID, 0, -lvgl_theme->spacing(4)); - lv_obj_set_style_bg_color(low_battery_popup_, lvgl_theme->low_battery_color(), 0); - lv_obj_set_style_radius(low_battery_popup_, lvgl_theme->spacing(4), 0); - low_battery_label_ = lv_label_create(low_battery_popup_); - lv_label_set_text(low_battery_label_, Lang::Strings::BATTERY_NEED_CHARGE); - lv_obj_set_style_text_color(low_battery_label_, lv_color_white(), 0); - lv_obj_center(low_battery_label_); - lv_obj_add_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN); - - emoji_image_ = lv_img_create(screen); - lv_obj_align(emoji_image_, LV_ALIGN_TOP_MID, 0, text_font->line_height + lvgl_theme->spacing(8)); - - // Display AI logo while booting - emoji_label_ = lv_label_create(screen); - lv_obj_center(emoji_label_); - lv_obj_set_style_text_font(emoji_label_, large_icon_font, 0); - lv_obj_set_style_text_color(emoji_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(emoji_label_, FONT_AWESOME_MICROCHIP_AI); -} -#if CONFIG_IDF_TARGET_ESP32P4 -#define MAX_MESSAGES 40 -#else -#define MAX_MESSAGES 20 -#endif -void LcdDisplay::SetChatMessage(const char* role, const char* content) { - DisplayLockGuard lock(this); - if (content_ == nullptr) { - return; - } - - // Check if message count exceeds limit - uint32_t child_count = lv_obj_get_child_cnt(content_); - if (child_count >= MAX_MESSAGES) { - // Delete the oldest message (first child object) - lv_obj_t* first_child = lv_obj_get_child(content_, 0); - lv_obj_t* last_child = lv_obj_get_child(content_, child_count - 1); - if (first_child != nullptr) { - lv_obj_del(first_child); - } - // Scroll to the last message immediately - if (last_child != nullptr) { - lv_obj_scroll_to_view_recursive(last_child, LV_ANIM_OFF); - } - } - - // Collapse system messages (if it's a system message, check if the last message is also a system message) - if (strcmp(role, "system") == 0) { - if (child_count > 0) { - // Get the last message container - lv_obj_t* last_container = lv_obj_get_child(content_, child_count - 1); - if (last_container != nullptr && lv_obj_get_child_cnt(last_container) > 0) { - // Get the bubble inside the container - lv_obj_t* last_bubble = lv_obj_get_child(last_container, 0); - if (last_bubble != nullptr) { - // Check if bubble type is system message - void* bubble_type_ptr = lv_obj_get_user_data(last_bubble); - if (bubble_type_ptr != nullptr && strcmp((const char*)bubble_type_ptr, "system") == 0) { - // If the last message is also a system message, delete it - lv_obj_del(last_container); - } - } - } - } - } else { - // Hide the centered AI logo - lv_obj_add_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN); - } - - // Avoid empty message boxes - if(strlen(content) == 0) { - return; - } - - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - - // Create a message bubble - lv_obj_t* msg_bubble = lv_obj_create(content_); - lv_obj_set_style_radius(msg_bubble, 8, 0); - lv_obj_set_scrollbar_mode(msg_bubble, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_border_width(msg_bubble, 0, 0); - lv_obj_set_style_pad_all(msg_bubble, lvgl_theme->spacing(4), 0); - - // Create the message text - lv_obj_t* msg_text = lv_label_create(msg_bubble); - lv_label_set_text(msg_text, content); - - // Calculate actual text width - lv_coord_t text_width = lv_txt_get_width(content, strlen(content), text_font, 0); - - // Calculate bubble width - lv_coord_t max_width = LV_HOR_RES * 85 / 100 - 16; // 85% of screen width - lv_coord_t min_width = 20; - lv_coord_t bubble_width; - - // Ensure text width is not less than minimum width - if (text_width < min_width) { - text_width = min_width; - } - - // If text width is less than max width, use text width - if (text_width < max_width) { - bubble_width = text_width; - } else { - bubble_width = max_width; - } - - // Set message text width - lv_obj_set_width(msg_text, bubble_width); // Subtract padding - lv_label_set_long_mode(msg_text, LV_LABEL_LONG_WRAP); - - // Set bubble width - lv_obj_set_width(msg_bubble, bubble_width); - lv_obj_set_height(msg_bubble, LV_SIZE_CONTENT); - - // Set alignment and style based on message role - if (strcmp(role, "user") == 0) { - // User messages are right-aligned with green background - lv_obj_set_style_bg_color(msg_bubble, lvgl_theme->user_bubble_color(), 0); - lv_obj_set_style_bg_opa(msg_bubble, LV_OPA_70, 0); - // Set text color for contrast - lv_obj_set_style_text_color(msg_text, lvgl_theme->text_color(), 0); - - // Set custom attribute to mark bubble type - lv_obj_set_user_data(msg_bubble, (void*)"user"); - - // Set appropriate width for content - lv_obj_set_width(msg_bubble, LV_SIZE_CONTENT); - lv_obj_set_height(msg_bubble, LV_SIZE_CONTENT); - - // Don't grow - lv_obj_set_style_flex_grow(msg_bubble, 0, 0); - } else if (strcmp(role, "assistant") == 0) { - // Assistant messages are left-aligned with white background - lv_obj_set_style_bg_color(msg_bubble, lvgl_theme->assistant_bubble_color(), 0); - lv_obj_set_style_bg_opa(msg_bubble, LV_OPA_70, 0); - // Set text color for contrast - lv_obj_set_style_text_color(msg_text, lvgl_theme->text_color(), 0); - - // Set custom attribute to mark bubble type - lv_obj_set_user_data(msg_bubble, (void*)"assistant"); - - // Set appropriate width for content - lv_obj_set_width(msg_bubble, LV_SIZE_CONTENT); - lv_obj_set_height(msg_bubble, LV_SIZE_CONTENT); - - // Don't grow - lv_obj_set_style_flex_grow(msg_bubble, 0, 0); - } else if (strcmp(role, "system") == 0) { - // System messages are center-aligned with light gray background - lv_obj_set_style_bg_color(msg_bubble, lvgl_theme->system_bubble_color(), 0); - lv_obj_set_style_bg_opa(msg_bubble, LV_OPA_70, 0); - // Set text color for contrast - lv_obj_set_style_text_color(msg_text, lvgl_theme->system_text_color(), 0); - - // Set custom attribute to mark bubble type - lv_obj_set_user_data(msg_bubble, (void*)"system"); - - // Set appropriate width for content - lv_obj_set_width(msg_bubble, LV_SIZE_CONTENT); - lv_obj_set_height(msg_bubble, LV_SIZE_CONTENT); - - // Don't grow - lv_obj_set_style_flex_grow(msg_bubble, 0, 0); - } - - // Create a full-width container for user messages to ensure right alignment - if (strcmp(role, "user") == 0) { - // Create a full-width container - lv_obj_t* container = lv_obj_create(content_); - lv_obj_set_width(container, LV_HOR_RES); - lv_obj_set_height(container, LV_SIZE_CONTENT); - - // Make container transparent and borderless - lv_obj_set_style_bg_opa(container, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(container, 0, 0); - lv_obj_set_style_pad_all(container, 0, 0); - - // Move the message bubble into this container - lv_obj_set_parent(msg_bubble, container); - - // Right align the bubble in the container - lv_obj_align(msg_bubble, LV_ALIGN_RIGHT_MID, -25, 0); - - // Auto-scroll to this container - lv_obj_scroll_to_view_recursive(container, LV_ANIM_ON); - } else if (strcmp(role, "system") == 0) { - // Create full-width container for system messages to ensure center alignment - lv_obj_t* container = lv_obj_create(content_); - lv_obj_set_width(container, LV_HOR_RES); - lv_obj_set_height(container, LV_SIZE_CONTENT); - - lv_obj_set_style_bg_opa(container, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(container, 0, 0); - lv_obj_set_style_pad_all(container, 0, 0); - - lv_obj_set_parent(msg_bubble, container); - lv_obj_align(msg_bubble, LV_ALIGN_CENTER, 0, 0); - lv_obj_scroll_to_view_recursive(container, LV_ANIM_ON); - } else { - // For assistant messages - // Left align assistant messages - lv_obj_align(msg_bubble, LV_ALIGN_LEFT_MID, 0, 0); - - // Auto-scroll to the message bubble - lv_obj_scroll_to_view_recursive(msg_bubble, LV_ANIM_ON); - } - - // Store reference to the latest message label - chat_message_label_ = msg_text; -} - -void LcdDisplay::SetPreviewImage(std::unique_ptr image) { - DisplayLockGuard lock(this); - if (content_ == nullptr) { - return; - } - - if (image == nullptr) { - return; - } - - auto lvgl_theme = static_cast(current_theme_); - // Create a message bubble for image preview - lv_obj_t* img_bubble = lv_obj_create(content_); - lv_obj_set_style_radius(img_bubble, 8, 0); - lv_obj_set_scrollbar_mode(img_bubble, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_border_width(img_bubble, 0, 0); - lv_obj_set_style_pad_all(img_bubble, lvgl_theme->spacing(4), 0); - - // Set image bubble background color (similar to system message) - lv_obj_set_style_bg_color(img_bubble, lvgl_theme->assistant_bubble_color(), 0); - lv_obj_set_style_bg_opa(img_bubble, LV_OPA_70, 0); - - // Set custom attribute to mark bubble type - lv_obj_set_user_data(img_bubble, (void*)"image"); - - // Create the image object inside the bubble - lv_obj_t* preview_image = lv_image_create(img_bubble); - - // Calculate appropriate size for the image - lv_coord_t max_width = LV_HOR_RES * 70 / 100; // 70% of screen width - lv_coord_t max_height = LV_VER_RES * 50 / 100; // 50% of screen height - - // Calculate zoom factor to fit within maximum dimensions - auto img_dsc = image->image_dsc(); - lv_coord_t img_width = img_dsc->header.w; - lv_coord_t img_height = img_dsc->header.h; - if (img_width == 0 || img_height == 0) { - img_width = max_width; - img_height = max_height; - ESP_LOGW(TAG, "Invalid image dimensions: %ld x %ld, using default dimensions: %ld x %ld", img_width, img_height, max_width, max_height); - } - - lv_coord_t zoom_w = (max_width * 256) / img_width; - lv_coord_t zoom_h = (max_height * 256) / img_height; - lv_coord_t zoom = (zoom_w < zoom_h) ? zoom_w : zoom_h; - - // Ensure zoom doesn't exceed 256 (100%) - if (zoom > 256) zoom = 256; - - // Set image properties - lv_image_set_src(preview_image, img_dsc); - lv_image_set_scale(preview_image, zoom); - - // Add event handler to clean up LvglImage when image is deleted - // We need to transfer ownership of the unique_ptr to the event callback - LvglImage* raw_image = image.release(); // Release ownership of smart pointer - lv_obj_add_event_cb(preview_image, [](lv_event_t* e) { - LvglImage* img = (LvglImage*)lv_event_get_user_data(e); - if (img != nullptr) { - delete img; // Properly release memory by deleting LvglImage object - } - }, LV_EVENT_DELETE, (void*)raw_image); - - // Calculate actual scaled image dimensions - lv_coord_t scaled_width = (img_width * zoom) / 256; - lv_coord_t scaled_height = (img_height * zoom) / 256; - - // Set bubble size to be 16 pixels larger than the image (8 pixels on each side) - lv_obj_set_width(img_bubble, scaled_width + 16); - lv_obj_set_height(img_bubble, scaled_height + 16); - - // Don't grow in flex layout - lv_obj_set_style_flex_grow(img_bubble, 0, 0); - - // Center the image within the bubble - lv_obj_center(preview_image); - - // Left align the image bubble like assistant messages - lv_obj_align(img_bubble, LV_ALIGN_LEFT_MID, 0, 0); - - // Auto-scroll to the image bubble - lv_obj_scroll_to_view_recursive(img_bubble, LV_ANIM_ON); -} -#else -void LcdDisplay::SetupUI() { - DisplayLockGuard lock(this); - LvglTheme* lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - auto large_icon_font = lvgl_theme->large_icon_font()->font(); - - auto screen = lv_screen_active(); - lv_obj_set_style_text_font(screen, text_font, 0); - lv_obj_set_style_text_color(screen, lvgl_theme->text_color(), 0); - lv_obj_set_style_bg_color(screen, lvgl_theme->background_color(), 0); - - /* Container - used as background */ - container_ = lv_obj_create(screen); - lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); - lv_obj_set_style_radius(container_, 0, 0); - lv_obj_set_style_pad_all(container_, 0, 0); - lv_obj_set_style_border_width(container_, 0, 0); - lv_obj_set_style_bg_color(container_, lvgl_theme->background_color(), 0); - lv_obj_set_style_border_color(container_, lvgl_theme->border_color(), 0); - - /* Bottom layer: emoji_box_ - centered display */ - emoji_box_ = lv_obj_create(screen); - lv_obj_set_size(emoji_box_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_set_style_bg_opa(emoji_box_, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(emoji_box_, 0, 0); - lv_obj_set_style_border_width(emoji_box_, 0, 0); - lv_obj_align(emoji_box_, LV_ALIGN_CENTER, 0, 0); - - emoji_label_ = lv_label_create(emoji_box_); - lv_obj_set_style_text_font(emoji_label_, large_icon_font, 0); - lv_obj_set_style_text_color(emoji_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(emoji_label_, FONT_AWESOME_MICROCHIP_AI); - - emoji_image_ = lv_img_create(emoji_box_); - lv_obj_center(emoji_image_); - lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN); - - /* Middle layer: preview_image_ - centered display */ - preview_image_ = lv_image_create(screen); - lv_obj_set_size(preview_image_, width_ / 2, height_ / 2); - lv_obj_align(preview_image_, LV_ALIGN_CENTER, 0, 0); - lv_obj_add_flag(preview_image_, LV_OBJ_FLAG_HIDDEN); - - /* Layer 1: Top bar - for status icons */ - top_bar_ = lv_obj_create(screen); - lv_obj_set_size(top_bar_, LV_HOR_RES, LV_SIZE_CONTENT); - lv_obj_set_style_radius(top_bar_, 0, 0); - lv_obj_set_style_bg_opa(top_bar_, LV_OPA_50, 0); // 50% opacity background - lv_obj_set_style_bg_color(top_bar_, lvgl_theme->background_color(), 0); - lv_obj_set_style_border_width(top_bar_, 0, 0); - lv_obj_set_style_pad_all(top_bar_, 0, 0); - lv_obj_set_style_pad_top(top_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_bottom(top_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_left(top_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_style_pad_right(top_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_flex_flow(top_bar_, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(top_bar_, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_set_scrollbar_mode(top_bar_, LV_SCROLLBAR_MODE_OFF); - lv_obj_align(top_bar_, LV_ALIGN_TOP_MID, 0, 0); - - // Left icon - network_label_ = lv_label_create(top_bar_); - lv_label_set_text(network_label_, ""); - lv_obj_set_style_text_font(network_label_, icon_font, 0); - lv_obj_set_style_text_color(network_label_, lvgl_theme->text_color(), 0); - - // Right icons container - lv_obj_t* right_icons = lv_obj_create(top_bar_); - lv_obj_set_size(right_icons, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_set_style_bg_opa(right_icons, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(right_icons, 0, 0); - lv_obj_set_style_pad_all(right_icons, 0, 0); - lv_obj_set_flex_flow(right_icons, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(right_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - mute_label_ = lv_label_create(right_icons); - lv_label_set_text(mute_label_, ""); - lv_obj_set_style_text_font(mute_label_, icon_font, 0); - lv_obj_set_style_text_color(mute_label_, lvgl_theme->text_color(), 0); - - battery_label_ = lv_label_create(right_icons); - lv_label_set_text(battery_label_, ""); - lv_obj_set_style_text_font(battery_label_, icon_font, 0); - lv_obj_set_style_text_color(battery_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_margin_left(battery_label_, lvgl_theme->spacing(2), 0); - - /* Layer 2: Status bar - for center text labels */ - status_bar_ = lv_obj_create(screen); - lv_obj_set_size(status_bar_, LV_HOR_RES, LV_SIZE_CONTENT); - lv_obj_set_style_radius(status_bar_, 0, 0); - lv_obj_set_style_bg_opa(status_bar_, LV_OPA_TRANSP, 0); // Transparent background - lv_obj_set_style_border_width(status_bar_, 0, 0); - lv_obj_set_style_pad_all(status_bar_, 0, 0); - lv_obj_set_style_pad_top(status_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_bottom(status_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_scrollbar_mode(status_bar_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_layout(status_bar_, LV_LAYOUT_NONE, 0); // Use absolute positioning - lv_obj_align(status_bar_, LV_ALIGN_TOP_MID, 0, 0); // Overlap with top_bar_ - - notification_label_ = lv_label_create(status_bar_); - lv_obj_set_width(notification_label_, LV_HOR_RES * 0.75); - lv_obj_set_style_text_align(notification_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_set_style_text_color(notification_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(notification_label_, ""); - lv_obj_align(notification_label_, LV_ALIGN_CENTER, 0, 0); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - status_label_ = lv_label_create(status_bar_); - lv_obj_set_width(status_label_, LV_HOR_RES * 0.75); - lv_label_set_long_mode(status_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_style_text_align(status_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_obj_set_style_text_color(status_label_, lvgl_theme->text_color(), 0); - lv_label_set_text(status_label_, Lang::Strings::INITIALIZING); - lv_obj_align(status_label_, LV_ALIGN_CENTER, 0, 0); - - /* Top layer: Bottom bar - fixed at bottom, minimum height 48, height can be adaptive */ - bottom_bar_ = lv_obj_create(screen); - lv_obj_set_width(bottom_bar_, LV_HOR_RES); - lv_obj_set_height(bottom_bar_, LV_SIZE_CONTENT); - lv_obj_set_style_min_height(bottom_bar_, 48, 0); // Set minimum height 48 - lv_obj_set_style_radius(bottom_bar_, 0, 0); - lv_obj_set_style_bg_color(bottom_bar_, lvgl_theme->background_color(), 0); - lv_obj_set_style_text_color(bottom_bar_, lvgl_theme->text_color(), 0); - lv_obj_set_style_pad_top(bottom_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_bottom(bottom_bar_, lvgl_theme->spacing(2), 0); - lv_obj_set_style_pad_left(bottom_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_style_pad_right(bottom_bar_, lvgl_theme->spacing(4), 0); - lv_obj_set_style_border_width(bottom_bar_, 0, 0); - lv_obj_align(bottom_bar_, LV_ALIGN_BOTTOM_MID, 0, 0); - - /* chat_message_label_ placed in bottom_bar_ and vertically centered */ - chat_message_label_ = lv_label_create(bottom_bar_); - lv_label_set_text(chat_message_label_, ""); - lv_obj_set_width(chat_message_label_, LV_HOR_RES - lvgl_theme->spacing(8)); // Subtract left and right padding - lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_WRAP); // Auto wrap mode - lv_obj_set_style_text_align(chat_message_label_, LV_TEXT_ALIGN_CENTER, 0); // Center text alignment - lv_obj_set_style_text_color(chat_message_label_, lvgl_theme->text_color(), 0); - lv_obj_align(chat_message_label_, LV_ALIGN_CENTER, 0, 0); // Vertically and horizontally centered in bottom_bar_ - - low_battery_popup_ = lv_obj_create(screen); - lv_obj_set_scrollbar_mode(low_battery_popup_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_size(low_battery_popup_, LV_HOR_RES * 0.9, text_font->line_height * 2); - lv_obj_align(low_battery_popup_, LV_ALIGN_BOTTOM_MID, 0, -lvgl_theme->spacing(4)); - lv_obj_set_style_bg_color(low_battery_popup_, lvgl_theme->low_battery_color(), 0); - lv_obj_set_style_radius(low_battery_popup_, lvgl_theme->spacing(4), 0); - - low_battery_label_ = lv_label_create(low_battery_popup_); - lv_label_set_text(low_battery_label_, Lang::Strings::BATTERY_NEED_CHARGE); - lv_obj_set_style_text_color(low_battery_label_, lv_color_white(), 0); - lv_obj_center(low_battery_label_); - lv_obj_add_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN); -} - -void LcdDisplay::SetPreviewImage(std::unique_ptr image) { - DisplayLockGuard lock(this); - if (preview_image_ == nullptr) { - ESP_LOGE(TAG, "Preview image is not initialized"); - return; - } - - if (image == nullptr) { - esp_timer_stop(preview_timer_); - lv_obj_remove_flag(emoji_box_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(preview_image_, LV_OBJ_FLAG_HIDDEN); - preview_image_cached_.reset(); - if (gif_controller_) { - gif_controller_->Start(); - } - return; - } - - preview_image_cached_ = std::move(image); - auto img_dsc = preview_image_cached_->image_dsc(); - lv_image_set_src(preview_image_, img_dsc); - if (img_dsc->header.w > 0 && img_dsc->header.h > 0) { - // zoom factor 0.5 - lv_image_set_scale(preview_image_, 128 * width_ / img_dsc->header.w); - } - - // Hide emoji_box_ - if (gif_controller_) { - gif_controller_->Stop(); - } - lv_obj_add_flag(emoji_box_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(preview_image_, LV_OBJ_FLAG_HIDDEN); - esp_timer_stop(preview_timer_); - ESP_ERROR_CHECK(esp_timer_start_once(preview_timer_, PREVIEW_IMAGE_DURATION_MS * 1000)); -} - -void LcdDisplay::SetChatMessage(const char* role, const char* content) { - DisplayLockGuard lock(this); - if (chat_message_label_ == nullptr) { - return; - } - lv_label_set_text(chat_message_label_, content); -} -#endif - -void LcdDisplay::SetEmotion(const char* emotion) { - // Stop any running GIF animation - if (gif_controller_) { - DisplayLockGuard lock(this); - gif_controller_->Stop(); - gif_controller_.reset(); - } - - if (emoji_image_ == nullptr) { - return; - } - - auto emoji_collection = static_cast(current_theme_)->emoji_collection(); - auto image = emoji_collection != nullptr ? emoji_collection->GetEmojiImage(emotion) : nullptr; - if (image == nullptr) { - const char* utf8 = font_awesome_get_utf8(emotion); - if (utf8 != nullptr && emoji_label_ != nullptr) { - DisplayLockGuard lock(this); - lv_label_set_text(emoji_label_, utf8); - lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN); - } - return; - } - - DisplayLockGuard lock(this); - if (image->IsGif()) { - // Create new GIF controller - gif_controller_ = std::make_unique(image->image_dsc()); - - if (gif_controller_->IsLoaded()) { - // Set up frame update callback - gif_controller_->SetFrameCallback([this]() { - lv_image_set_src(emoji_image_, gif_controller_->image_dsc()); - }); - - // Set initial frame and start animation - lv_image_set_src(emoji_image_, gif_controller_->image_dsc()); - gif_controller_->Start(); - - // Show GIF, hide others - lv_obj_add_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN); - } else { - ESP_LOGE(TAG, "Failed to load GIF for emotion: %s", emotion); - gif_controller_.reset(); - } - } else { - lv_image_set_src(emoji_image_, image->image_dsc()); - lv_obj_add_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN); - } - -#if CONFIG_USE_WECHAT_MESSAGE_STYLE - // In WeChat message style, if emotion is neutral, don't display it - uint32_t child_count = lv_obj_get_child_cnt(content_); - if (strcmp(emotion, "neutral") == 0 && child_count > 0) { - // Stop GIF animation if running - if (gif_controller_) { - gif_controller_->Stop(); - gif_controller_.reset(); - } - - lv_obj_add_flag(emoji_image_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(emoji_label_, LV_OBJ_FLAG_HIDDEN); - } -#endif -} - -void LcdDisplay::SetTheme(Theme* theme) { - DisplayLockGuard lock(this); - - auto lvgl_theme = static_cast(theme); - - // Get the active screen - lv_obj_t* screen = lv_screen_active(); - - // Set font - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - auto large_icon_font = lvgl_theme->large_icon_font()->font(); - - if (text_font->line_height >= 40) { - lv_obj_set_style_text_font(mute_label_, large_icon_font, 0); - lv_obj_set_style_text_font(battery_label_, large_icon_font, 0); - lv_obj_set_style_text_font(network_label_, large_icon_font, 0); - } else { - lv_obj_set_style_text_font(mute_label_, icon_font, 0); - lv_obj_set_style_text_font(battery_label_, icon_font, 0); - lv_obj_set_style_text_font(network_label_, icon_font, 0); - } - - // Set parent text color - lv_obj_set_style_text_font(screen, text_font, 0); - lv_obj_set_style_text_color(screen, lvgl_theme->text_color(), 0); - - // Set background image - if (lvgl_theme->background_image() != nullptr) { - lv_obj_set_style_bg_image_src(container_, lvgl_theme->background_image()->image_dsc(), 0); - } else { - lv_obj_set_style_bg_image_src(container_, nullptr, 0); - lv_obj_set_style_bg_color(container_, lvgl_theme->background_color(), 0); - } - - // Update top bar background color with 50% opacity - if (top_bar_ != nullptr) { - lv_obj_set_style_bg_opa(top_bar_, LV_OPA_50, 0); - lv_obj_set_style_bg_color(top_bar_, lvgl_theme->background_color(), 0); - } - - // Update status bar elements - lv_obj_set_style_text_color(network_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_text_color(status_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_text_color(notification_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_text_color(mute_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_text_color(battery_label_, lvgl_theme->text_color(), 0); - lv_obj_set_style_text_color(emoji_label_, lvgl_theme->text_color(), 0); - - // If we have the chat message style, update all message bubbles -#if CONFIG_USE_WECHAT_MESSAGE_STYLE - // Set content background opacity - lv_obj_set_style_bg_opa(content_, LV_OPA_TRANSP, 0); - - // Iterate through all children of content (message containers or bubbles) - uint32_t child_count = lv_obj_get_child_cnt(content_); - for (uint32_t i = 0; i < child_count; i++) { - lv_obj_t* obj = lv_obj_get_child(content_, i); - if (obj == nullptr) continue; - - lv_obj_t* bubble = nullptr; - - // Check if this object is a container or bubble - // If it's a container (user or system message), get its child as bubble - // If it's a bubble (assistant message), use it directly - if (lv_obj_get_child_cnt(obj) > 0) { - // Might be a container, check if it's a user or system message container - // User and system message containers are transparent - lv_opa_t bg_opa = lv_obj_get_style_bg_opa(obj, 0); - if (bg_opa == LV_OPA_TRANSP) { - // This is a user or system message container - bubble = lv_obj_get_child(obj, 0); - } else { - // This might be an assistant message bubble itself - bubble = obj; - } - } else { - // No child elements, might be other UI elements, skip - continue; - } - - if (bubble == nullptr) continue; - - // Use saved user data to identify bubble type - void* bubble_type_ptr = lv_obj_get_user_data(bubble); - if (bubble_type_ptr != nullptr) { - const char* bubble_type = static_cast(bubble_type_ptr); - - // Apply correct color based on bubble type - if (strcmp(bubble_type, "user") == 0) { - lv_obj_set_style_bg_color(bubble, lvgl_theme->user_bubble_color(), 0); - } else if (strcmp(bubble_type, "assistant") == 0) { - lv_obj_set_style_bg_color(bubble, lvgl_theme->assistant_bubble_color(), 0); - } else if (strcmp(bubble_type, "system") == 0) { - lv_obj_set_style_bg_color(bubble, lvgl_theme->system_bubble_color(), 0); - } else if (strcmp(bubble_type, "image") == 0) { - lv_obj_set_style_bg_color(bubble, lvgl_theme->system_bubble_color(), 0); - } - - // Update border color - lv_obj_set_style_border_color(bubble, lvgl_theme->border_color(), 0); - - // Update text color for the message - if (lv_obj_get_child_cnt(bubble) > 0) { - lv_obj_t* text = lv_obj_get_child(bubble, 0); - if (text != nullptr) { - // Set text color based on bubble type - if (strcmp(bubble_type, "system") == 0) { - lv_obj_set_style_text_color(text, lvgl_theme->system_text_color(), 0); - } else { - lv_obj_set_style_text_color(text, lvgl_theme->text_color(), 0); - } - } - } - } else { - ESP_LOGW(TAG, "child[%lu] Bubble type is not found", i); - } - } -#else - // Simple UI mode - just update the main chat message - if (chat_message_label_ != nullptr) { - lv_obj_set_style_text_color(chat_message_label_, lvgl_theme->text_color(), 0); - } - - if (emoji_label_ != nullptr) { - lv_obj_set_style_text_color(emoji_label_, lvgl_theme->text_color(), 0); - } - - // Update bottom bar background color with 50% opacity - if (bottom_bar_ != nullptr) { - lv_obj_set_style_bg_opa(bottom_bar_, LV_OPA_50, 0); - lv_obj_set_style_bg_color(bottom_bar_, lvgl_theme->background_color(), 0); - } -#endif - - // Update low battery popup - lv_obj_set_style_bg_color(low_battery_popup_, lvgl_theme->low_battery_color(), 0); - - // No errors occurred. Save theme to settings - Display::SetTheme(lvgl_theme); -} - -void LcdDisplay::SetHideSubtitle(bool hide) { - DisplayLockGuard lock(this); - hide_subtitle_ = hide; - - // Immediately update UI visibility based on the setting - if (bottom_bar_ != nullptr) { - if (hide) { - lv_obj_add_flag(bottom_bar_, LV_OBJ_FLAG_HIDDEN); - } else { - lv_obj_remove_flag(bottom_bar_, LV_OBJ_FLAG_HIDDEN); - } - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.h deleted file mode 100644 index 1dc2a8d7..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lcd_display.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef LCD_DISPLAY_H -#define LCD_DISPLAY_H - -#include "lvgl_display.h" -#include "gif/lvgl_gif.h" - -#include -#include -#include - -#include -#include - -#define PREVIEW_IMAGE_DURATION_MS 5000 - - -class LcdDisplay : public LvglDisplay { -protected: - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - lv_draw_buf_t draw_buf_; - lv_obj_t* top_bar_ = nullptr; - lv_obj_t* status_bar_ = nullptr; - lv_obj_t* content_ = nullptr; - lv_obj_t* container_ = nullptr; - lv_obj_t* side_bar_ = nullptr; - lv_obj_t* bottom_bar_ = nullptr; - lv_obj_t* preview_image_ = nullptr; - lv_obj_t* emoji_label_ = nullptr; - lv_obj_t* emoji_image_ = nullptr; - std::unique_ptr gif_controller_ = nullptr; - lv_obj_t* emoji_box_ = nullptr; - lv_obj_t* chat_message_label_ = nullptr; - esp_timer_handle_t preview_timer_ = nullptr; - std::unique_ptr preview_image_cached_ = nullptr; - bool hide_subtitle_ = false; // Control whether to hide chat messages/subtitles - - void InitializeLcdThemes(); - void SetupUI(); - virtual bool Lock(int timeout_ms = 0) override; - virtual void Unlock() override; - -protected: - // Add protected constructor - LcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height); - -public: - ~LcdDisplay(); - virtual void SetEmotion(const char* emotion) override; - virtual void SetChatMessage(const char* role, const char* content) override; - virtual void SetPreviewImage(std::unique_ptr image) override; - - // Add theme switching function - virtual void SetTheme(Theme* theme) override; - - // Set whether to hide chat messages/subtitles - void SetHideSubtitle(bool hide); -}; - -// SPI LCD display -class SpiLcdDisplay : public LcdDisplay { -public: - SpiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy); -}; - -// RGB LCD display -class RgbLcdDisplay : public LcdDisplay { -public: - RgbLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy); -}; - -// MIPI LCD display -class MipiLcdDisplay : public LcdDisplay { -public: - MipiLcdDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, int offset_x, int offset_y, - bool mirror_x, bool mirror_y, bool swap_xy); -}; - -#endif // LCD_DISPLAY_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.cc deleted file mode 100644 index c9a1a605..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.cc +++ /dev/null @@ -1,123 +0,0 @@ -#include "emoji_collection.h" - -#include -#include -#include - -#define TAG "EmojiCollection" - -void EmojiCollection::AddEmoji(const std::string& name, LvglImage* image) { - emoji_collection_[name] = image; -} - -const LvglImage* EmojiCollection::GetEmojiImage(const char* name) { - auto it = emoji_collection_.find(name); - if (it != emoji_collection_.end()) { - return it->second; - } - - ESP_LOGW(TAG, "Emoji not found: %s", name); - return nullptr; -} - -EmojiCollection::~EmojiCollection() { - for (auto it = emoji_collection_.begin(); it != emoji_collection_.end(); ++it) { - delete it->second; - } - emoji_collection_.clear(); -} - -// These are declared in xiaozhi-fonts/src/font_emoji_32.c -extern const lv_image_dsc_t emoji_1f636_32; // neutral -extern const lv_image_dsc_t emoji_1f642_32; // happy -extern const lv_image_dsc_t emoji_1f606_32; // laughing -extern const lv_image_dsc_t emoji_1f602_32; // funny -extern const lv_image_dsc_t emoji_1f614_32; // sad -extern const lv_image_dsc_t emoji_1f620_32; // angry -extern const lv_image_dsc_t emoji_1f62d_32; // crying -extern const lv_image_dsc_t emoji_1f60d_32; // loving -extern const lv_image_dsc_t emoji_1f633_32; // embarrassed -extern const lv_image_dsc_t emoji_1f62f_32; // surprised -extern const lv_image_dsc_t emoji_1f631_32; // shocked -extern const lv_image_dsc_t emoji_1f914_32; // thinking -extern const lv_image_dsc_t emoji_1f609_32; // winking -extern const lv_image_dsc_t emoji_1f60e_32; // cool -extern const lv_image_dsc_t emoji_1f60c_32; // relaxed -extern const lv_image_dsc_t emoji_1f924_32; // delicious -extern const lv_image_dsc_t emoji_1f618_32; // kissy -extern const lv_image_dsc_t emoji_1f60f_32; // confident -extern const lv_image_dsc_t emoji_1f634_32; // sleepy -extern const lv_image_dsc_t emoji_1f61c_32; // silly -extern const lv_image_dsc_t emoji_1f644_32; // confused - -Twemoji32::Twemoji32() { - AddEmoji("neutral", new LvglSourceImage(&emoji_1f636_32)); - AddEmoji("happy", new LvglSourceImage(&emoji_1f642_32)); - AddEmoji("laughing", new LvglSourceImage(&emoji_1f606_32)); - AddEmoji("funny", new LvglSourceImage(&emoji_1f602_32)); - AddEmoji("sad", new LvglSourceImage(&emoji_1f614_32)); - AddEmoji("angry", new LvglSourceImage(&emoji_1f620_32)); - AddEmoji("crying", new LvglSourceImage(&emoji_1f62d_32)); - AddEmoji("loving", new LvglSourceImage(&emoji_1f60d_32)); - AddEmoji("embarrassed", new LvglSourceImage(&emoji_1f633_32)); - AddEmoji("surprised", new LvglSourceImage(&emoji_1f62f_32)); - AddEmoji("shocked", new LvglSourceImage(&emoji_1f631_32)); - AddEmoji("thinking", new LvglSourceImage(&emoji_1f914_32)); - AddEmoji("winking", new LvglSourceImage(&emoji_1f609_32)); - AddEmoji("cool", new LvglSourceImage(&emoji_1f60e_32)); - AddEmoji("relaxed", new LvglSourceImage(&emoji_1f60c_32)); - AddEmoji("delicious", new LvglSourceImage(&emoji_1f924_32)); - AddEmoji("kissy", new LvglSourceImage(&emoji_1f618_32)); - AddEmoji("confident", new LvglSourceImage(&emoji_1f60f_32)); - AddEmoji("sleepy", new LvglSourceImage(&emoji_1f634_32)); - AddEmoji("silly", new LvglSourceImage(&emoji_1f61c_32)); - AddEmoji("confused", new LvglSourceImage(&emoji_1f644_32)); -} - - -// These are declared in xiaozhi-fonts/src/font_emoji_64.c -extern const lv_image_dsc_t emoji_1f636_64; // neutral -extern const lv_image_dsc_t emoji_1f642_64; // happy -extern const lv_image_dsc_t emoji_1f606_64; // laughing -extern const lv_image_dsc_t emoji_1f602_64; // funny -extern const lv_image_dsc_t emoji_1f614_64; // sad -extern const lv_image_dsc_t emoji_1f620_64; // angry -extern const lv_image_dsc_t emoji_1f62d_64; // crying -extern const lv_image_dsc_t emoji_1f60d_64; // loving -extern const lv_image_dsc_t emoji_1f633_64; // embarrassed -extern const lv_image_dsc_t emoji_1f62f_64; // surprised -extern const lv_image_dsc_t emoji_1f631_64; // shocked -extern const lv_image_dsc_t emoji_1f914_64; // thinking -extern const lv_image_dsc_t emoji_1f609_64; // winking -extern const lv_image_dsc_t emoji_1f60e_64; // cool -extern const lv_image_dsc_t emoji_1f60c_64; // relaxed -extern const lv_image_dsc_t emoji_1f924_64; // delicious -extern const lv_image_dsc_t emoji_1f618_64; // kissy -extern const lv_image_dsc_t emoji_1f60f_64; // confident -extern const lv_image_dsc_t emoji_1f634_64; // sleepy -extern const lv_image_dsc_t emoji_1f61c_64; // silly -extern const lv_image_dsc_t emoji_1f644_64; // confused - -Twemoji64::Twemoji64() { - AddEmoji("neutral", new LvglSourceImage(&emoji_1f636_64)); - AddEmoji("happy", new LvglSourceImage(&emoji_1f642_64)); - AddEmoji("laughing", new LvglSourceImage(&emoji_1f606_64)); - AddEmoji("funny", new LvglSourceImage(&emoji_1f602_64)); - AddEmoji("sad", new LvglSourceImage(&emoji_1f614_64)); - AddEmoji("angry", new LvglSourceImage(&emoji_1f620_64)); - AddEmoji("crying", new LvglSourceImage(&emoji_1f62d_64)); - AddEmoji("loving", new LvglSourceImage(&emoji_1f60d_64)); - AddEmoji("embarrassed", new LvglSourceImage(&emoji_1f633_64)); - AddEmoji("surprised", new LvglSourceImage(&emoji_1f62f_64)); - AddEmoji("shocked", new LvglSourceImage(&emoji_1f631_64)); - AddEmoji("thinking", new LvglSourceImage(&emoji_1f914_64)); - AddEmoji("winking", new LvglSourceImage(&emoji_1f609_64)); - AddEmoji("cool", new LvglSourceImage(&emoji_1f60e_64)); - AddEmoji("relaxed", new LvglSourceImage(&emoji_1f60c_64)); - AddEmoji("delicious", new LvglSourceImage(&emoji_1f924_64)); - AddEmoji("kissy", new LvglSourceImage(&emoji_1f618_64)); - AddEmoji("confident", new LvglSourceImage(&emoji_1f60f_64)); - AddEmoji("sleepy", new LvglSourceImage(&emoji_1f634_64)); - AddEmoji("silly", new LvglSourceImage(&emoji_1f61c_64)); - AddEmoji("confused", new LvglSourceImage(&emoji_1f644_64)); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.h deleted file mode 100644 index c9eac054..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/emoji_collection.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef EMOJI_COLLECTION_H -#define EMOJI_COLLECTION_H - -#include "lvgl_image.h" - -#include - -#include -#include -#include - - -// Define interface for emoji collection -class EmojiCollection { -public: - virtual void AddEmoji(const std::string& name, LvglImage* image); - virtual const LvglImage* GetEmojiImage(const char* name); - virtual ~EmojiCollection(); - -private: - std::map emoji_collection_; -}; - -class Twemoji32 : public EmojiCollection { -public: - Twemoji32(); -}; - -class Twemoji64 : public EmojiCollection { -public: - Twemoji64(); -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/LICENSE.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/LICENSE.txt deleted file mode 100644 index c53d5199..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/LICENSE.txt +++ /dev/null @@ -1,2 +0,0 @@ -All of the source code and documentation for gifdec is released into the -public domain and provided without warranty of any kind. diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/README.md deleted file mode 100644 index 935cfebc..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# 说明 / Description - -## 中文 - -本目录代码移植自 LVGL 的 GIF 程序。 - -主要修复和改进: -- 修复了透明背景问题 -- 兼容了 87a 版本的 GIF 格式 - -## English - -The code in this directory is ported from LVGL's GIF program. - -Main fixes and improvements: -- Fixed transparent background issues -- Added compatibility for GIF 87a version format diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.c deleted file mode 100644 index 1e74aabb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.c +++ /dev/null @@ -1,821 +0,0 @@ -#include "gifdec.h" - -#include -#include -#include -#include - -#define TAG "GIF" - -#define MIN(A, B) ((A) < (B) ? (A) : (B)) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) - -typedef struct Entry { - uint16_t length; - uint16_t prefix; - uint8_t suffix; -} Entry; - -typedef struct Table { - int bulk; - int nentries; - Entry * entries; -} Table; - -#if LV_GIF_CACHE_DECODE_DATA -#define LZW_MAXBITS 12 -#define LZW_TABLE_SIZE (1 << LZW_MAXBITS) -#define LZW_CACHE_SIZE (LZW_TABLE_SIZE * 4) -#endif - -static gd_GIF * gif_open(gd_GIF * gif); -static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file); -static void f_gif_read(gd_GIF * gif, void * buf, size_t len); -static int f_gif_seek(gd_GIF * gif, size_t pos, int k); -static void f_gif_close(gd_GIF * gif); - -#if LV_USE_DRAW_SW_ASM == LV_DRAW_SW_ASM_HELIUM - #include "gifdec_mve.h" -#endif - -static uint16_t -read_num(gd_GIF * gif) -{ - uint8_t bytes[2]; - - f_gif_read(gif, bytes, 2); - return bytes[0] + (((uint16_t) bytes[1]) << 8); -} - -gd_GIF * -gd_open_gif_file(const char * fname) -{ - gd_GIF gif_base; - memset(&gif_base, 0, sizeof(gif_base)); - - bool res = f_gif_open(&gif_base, fname, true); - if(!res) return NULL; - - return gif_open(&gif_base); -} - -gd_GIF * -gd_open_gif_data(const void * data) -{ - gd_GIF gif_base; - memset(&gif_base, 0, sizeof(gif_base)); - - bool res = f_gif_open(&gif_base, data, false); - if(!res) return NULL; - - return gif_open(&gif_base); -} - -static gd_GIF * gif_open(gd_GIF * gif_base) -{ - uint8_t sigver[3]; - uint16_t width, height, depth; - uint8_t fdsz, bgidx, aspect; - uint8_t * bgcolor; - int gct_sz; - gd_GIF * gif = NULL; - - /* Header */ - f_gif_read(gif_base, sigver, 3); - if(memcmp(sigver, "GIF", 3) != 0) { - ESP_LOGW(TAG, "invalid signature"); - goto fail; - } - /* Version */ - f_gif_read(gif_base, sigver, 3); - if(memcmp(sigver, "89a", 3) != 0 && memcmp(sigver, "87a", 3) != 0) { - ESP_LOGW(TAG, "invalid version"); - goto fail; - } - /* Width x Height */ - width = read_num(gif_base); - height = read_num(gif_base); - /* FDSZ */ - f_gif_read(gif_base, &fdsz, 1); - /* Presence of GCT */ - if(!(fdsz & 0x80)) { - ESP_LOGW(TAG, "no global color table"); - goto fail; - } - /* Color Space's Depth */ - depth = ((fdsz >> 4) & 7) + 1; - /* Ignore Sort Flag. */ - /* GCT Size */ - gct_sz = 1 << ((fdsz & 0x07) + 1); - /* Background Color Index */ - f_gif_read(gif_base, &bgidx, 1); - /* Aspect Ratio */ - f_gif_read(gif_base, &aspect, 1); - /* Create gd_GIF Structure. */ - if(0 == width || 0 == height){ - ESP_LOGW(TAG, "Zero size image"); - goto fail; - } -#if LV_GIF_CACHE_DECODE_DATA - if(0 == (INT_MAX - sizeof(gd_GIF) - LZW_CACHE_SIZE) / width / height / 5){ - ESP_LOGW(TAG, "Image dimensions are too large"); - goto fail; - } - gif = lv_malloc(sizeof(gd_GIF) + 5 * width * height + LZW_CACHE_SIZE); -#else - if(0 == (INT_MAX - sizeof(gd_GIF)) / width / height / 5){ - ESP_LOGW(TAG, "Image dimensions are too large"); - goto fail; - } - gif = lv_malloc(sizeof(gd_GIF) + 5 * width * height); -#endif - if(!gif) goto fail; - memcpy(gif, gif_base, sizeof(gd_GIF)); - gif->width = width; - gif->height = height; - gif->depth = depth; - /* Read GCT */ - gif->gct.size = gct_sz; - f_gif_read(gif, gif->gct.colors, 3 * gif->gct.size); - gif->palette = &gif->gct; - gif->bgindex = bgidx; - gif->canvas = (uint8_t *) &gif[1]; - gif->frame = &gif->canvas[4 * width * height]; - if(gif->bgindex) { - memset(gif->frame, gif->bgindex, gif->width * gif->height); - } - bgcolor = &gif->palette->colors[gif->bgindex * 3]; - #if LV_GIF_CACHE_DECODE_DATA - gif->lzw_cache = gif->frame + width * height; - #endif - -#ifdef GIFDEC_FILL_BG - GIFDEC_FILL_BG(gif->canvas, gif->width * gif->height, 1, gif->width * gif->height, bgcolor, 0x00); -#else - for(int i = 0; i < gif->width * gif->height; i++) { - gif->canvas[i * 4 + 0] = *(bgcolor + 2); - gif->canvas[i * 4 + 1] = *(bgcolor + 1); - gif->canvas[i * 4 + 2] = *(bgcolor + 0); - gif->canvas[i * 4 + 3] = 0x00; // 初始化为透明,让第一帧根据自己的透明度设置来渲染 - } -#endif - gif->anim_start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - gif->loop_count = -1; - goto ok; -fail: - f_gif_close(gif_base); -ok: - return gif; -} - -static void -discard_sub_blocks(gd_GIF * gif) -{ - uint8_t size; - - do { - f_gif_read(gif, &size, 1); - f_gif_seek(gif, size, LV_FS_SEEK_CUR); - } while(size); -} - -static void -read_plain_text_ext(gd_GIF * gif) -{ - if(gif->plain_text) { - uint16_t tx, ty, tw, th; - uint8_t cw, ch, fg, bg; - size_t sub_block; - f_gif_seek(gif, 1, LV_FS_SEEK_CUR); /* block size = 12 */ - tx = read_num(gif); - ty = read_num(gif); - tw = read_num(gif); - th = read_num(gif); - f_gif_read(gif, &cw, 1); - f_gif_read(gif, &ch, 1); - f_gif_read(gif, &fg, 1); - f_gif_read(gif, &bg, 1); - sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg); - f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); - } - else { - /* Discard plain text metadata. */ - f_gif_seek(gif, 13, LV_FS_SEEK_CUR); - } - /* Discard plain text sub-blocks. */ - discard_sub_blocks(gif); -} - -static void -read_graphic_control_ext(gd_GIF * gif) -{ - uint8_t rdit; - - /* Discard block size (always 0x04). */ - f_gif_seek(gif, 1, LV_FS_SEEK_CUR); - f_gif_read(gif, &rdit, 1); - gif->gce.disposal = (rdit >> 2) & 3; - gif->gce.input = rdit & 2; - gif->gce.transparency = rdit & 1; - gif->gce.delay = read_num(gif); - f_gif_read(gif, &gif->gce.tindex, 1); - /* Skip block terminator. */ - f_gif_seek(gif, 1, LV_FS_SEEK_CUR); -} - -static void -read_comment_ext(gd_GIF * gif) -{ - if(gif->comment) { - size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - gif->comment(gif); - f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); - } - /* Discard comment sub-blocks. */ - discard_sub_blocks(gif); -} - -static void -read_application_ext(gd_GIF * gif) -{ - char app_id[8]; - char app_auth_code[3]; - uint16_t loop_count; - - /* Discard block size (always 0x0B). */ - f_gif_seek(gif, 1, LV_FS_SEEK_CUR); - /* Application Identifier. */ - f_gif_read(gif, app_id, 8); - /* Application Authentication Code. */ - f_gif_read(gif, app_auth_code, 3); - if(!strncmp(app_id, "NETSCAPE", sizeof(app_id))) { - /* Discard block size (0x03) and constant byte (0x01). */ - f_gif_seek(gif, 2, LV_FS_SEEK_CUR); - loop_count = read_num(gif); - if(gif->loop_count < 0) { - if(loop_count == 0) { - gif->loop_count = 0; - } - else { - gif->loop_count = loop_count + 1; - } - } - /* Skip block terminator. */ - f_gif_seek(gif, 1, LV_FS_SEEK_CUR); - } - else if(gif->application) { - size_t sub_block = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - gif->application(gif, app_id, app_auth_code); - f_gif_seek(gif, sub_block, LV_FS_SEEK_SET); - discard_sub_blocks(gif); - } - else { - discard_sub_blocks(gif); - } -} - -static void -read_ext(gd_GIF * gif) -{ - uint8_t label; - - f_gif_read(gif, &label, 1); - switch(label) { - case 0x01: - read_plain_text_ext(gif); - break; - case 0xF9: - read_graphic_control_ext(gif); - break; - case 0xFE: - read_comment_ext(gif); - break; - case 0xFF: - read_application_ext(gif); - break; - default: - ESP_LOGW(TAG, "unknown extension: %02X\n", label); - } -} - -static uint16_t -get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *byte) -{ - int bits_read; - int rpad; - int frag_size; - uint16_t key; - - key = 0; - for (bits_read = 0; bits_read < key_size; bits_read += frag_size) { - rpad = (*shift + bits_read) % 8; - if (rpad == 0) { - /* Update byte. */ - if (*sub_len == 0) { - f_gif_read(gif, sub_len, 1); /* Must be nonzero! */ - if (*sub_len == 0) return 0x1000; - } - f_gif_read(gif, byte, 1); - (*sub_len)--; - } - frag_size = MIN(key_size - bits_read, 8 - rpad); - key |= ((uint16_t) ((*byte) >> rpad)) << bits_read; - } - /* Clear extra bits to the left. */ - key &= (1 << key_size) - 1; - *shift = (*shift + key_size) % 8; - return key; -} - -#if LV_GIF_CACHE_DECODE_DATA -/* Decompress image pixels. - * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table) or parse error. */ -static int -read_image_data(gd_GIF *gif, int interlace) -{ - uint8_t sub_len, shift, byte; - int ret = 0; - int key_size; - int y, pass, linesize; - uint8_t *ptr = NULL; - uint8_t *ptr_row_start = NULL; - uint8_t *ptr_base = NULL; - size_t start, end; - uint16_t key, clear_code, stop_code, curr_code; - int frm_off, frm_size,curr_size,top_slot,new_codes,slot; - /* The first value of the value sequence corresponding to key */ - int first_value; - int last_key; - uint8_t *sp = NULL; - uint8_t *p_stack = NULL; - uint8_t *p_suffix = NULL; - uint16_t *p_prefix = NULL; - - /* get initial key size and clear code, stop code */ - f_gif_read(gif, &byte, 1); - key_size = (int) byte; - clear_code = 1 << key_size; - stop_code = clear_code + 1; - key = 0; - - start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - discard_sub_blocks(gif); - end = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - f_gif_seek(gif, start, LV_FS_SEEK_SET); - - linesize = gif->width; - ptr_base = &gif->frame[gif->fy * linesize + gif->fx]; - ptr_row_start = ptr_base; - ptr = ptr_row_start; - sub_len = shift = 0; - /* decoder */ - pass = 0; - y = 0; - p_stack = gif->lzw_cache; - p_suffix = gif->lzw_cache + LZW_TABLE_SIZE; - p_prefix = (uint16_t*)(gif->lzw_cache + LZW_TABLE_SIZE * 2); - frm_off = 0; - frm_size = gif->fw * gif->fh; - curr_size = key_size + 1; - top_slot = 1 << curr_size; - new_codes = clear_code + 2; - slot = new_codes; - first_value = -1; - last_key = -1; - sp = p_stack; - - while (frm_off < frm_size) { - /* copy data to frame buffer */ - while (sp > p_stack) { - if(frm_off >= frm_size){ - ESP_LOGW(TAG, "LZW table token overflows the frame buffer"); - return -1; - } - *ptr++ = *(--sp); - frm_off += 1; - /* read one line */ - if ((ptr - ptr_row_start) == gif->fw) { - if (interlace) { - switch(pass) { - case 0: - case 1: - y += 8; - ptr_row_start += linesize * 8; - break; - case 2: - y += 4; - ptr_row_start += linesize * 4; - break; - case 3: - y += 2; - ptr_row_start += linesize * 2; - break; - default: - break; - } - while (y >= gif->fh) { - y = 4 >> pass; - ptr_row_start = ptr_base + linesize * y; - pass++; - } - } else { - ptr_row_start += linesize; - } - ptr = ptr_row_start; - } - } - - key = get_key(gif, curr_size, &sub_len, &shift, &byte); - - if (key == stop_code || key >= LZW_TABLE_SIZE) - break; - - if (key == clear_code) { - curr_size = key_size + 1; - slot = new_codes; - top_slot = 1 << curr_size; - first_value = last_key = -1; - sp = p_stack; - continue; - } - - curr_code = key; - /* - * If the current code is a code that will be added to the decoding - * dictionary, it is composed of the data list corresponding to the - * previous key and its first data. - * */ - if (curr_code == slot && first_value >= 0) { - *sp++ = first_value; - curr_code = last_key; - }else if(curr_code >= slot) - break; - - while (curr_code >= new_codes) { - *sp++ = p_suffix[curr_code]; - curr_code = p_prefix[curr_code]; - } - *sp++ = curr_code; - - /* Add code to decoding dictionary */ - if (slot < top_slot && last_key >= 0) { - p_suffix[slot] = curr_code; - p_prefix[slot++] = last_key; - } - first_value = curr_code; - last_key = key; - if (slot >= top_slot) { - if (curr_size < LZW_MAXBITS) { - top_slot <<= 1; - curr_size += 1; - } - } - } - - if (key == stop_code) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ - f_gif_seek(gif, end, LV_FS_SEEK_SET); - return ret; -} -#else -static Table * -new_table(int key_size) -{ - int key; - int init_bulk = MAX(1 << (key_size + 1), 0x100); - Table * table = lv_malloc(sizeof(*table) + sizeof(Entry) * init_bulk); - if(table) { - table->bulk = init_bulk; - table->nentries = (1 << key_size) + 2; - table->entries = (Entry *) &table[1]; - for(key = 0; key < (1 << key_size); key++) - table->entries[key] = (Entry) { - 1, 0xFFF, key - }; - } - return table; -} - -/* Add table entry. Return value: - * 0 on success - * +1 if key size must be incremented after this addition - * -1 if could not realloc table */ -static int -add_entry(Table ** tablep, uint16_t length, uint16_t prefix, uint8_t suffix) -{ - Table * table = *tablep; - if(table->nentries == table->bulk) { - table->bulk *= 2; - table = lv_realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); - if(!table) return -1; - table->entries = (Entry *) &table[1]; - *tablep = table; - } - table->entries[table->nentries] = (Entry) { - length, prefix, suffix - }; - table->nentries++; - if((table->nentries & (table->nentries - 1)) == 0) - return 1; - return 0; -} - -/* Compute output index of y-th input line, in frame of height h. */ -static int -interlaced_line_index(int h, int y) -{ - int p; /* number of lines in current pass */ - - p = (h - 1) / 8 + 1; - if(y < p) /* pass 1 */ - return y * 8; - y -= p; - p = (h - 5) / 8 + 1; - if(y < p) /* pass 2 */ - return y * 8 + 4; - y -= p; - p = (h - 3) / 4 + 1; - if(y < p) /* pass 3 */ - return y * 4 + 2; - y -= p; - /* pass 4 */ - return y * 2 + 1; -} - -/* Decompress image pixels. - * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table) or parse error. */ -static int -read_image_data(gd_GIF * gif, int interlace) -{ - uint8_t sub_len, shift, byte; - int init_key_size, key_size, table_is_full = 0; - int frm_off, frm_size, str_len = 0, i, p, x, y; - uint16_t key, clear, stop; - int ret; - Table * table; - Entry entry = {0}; - size_t start, end; - - f_gif_read(gif, &byte, 1); - key_size = (int) byte; - start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - discard_sub_blocks(gif); - end = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); - f_gif_seek(gif, start, LV_FS_SEEK_SET); - clear = 1 << key_size; - stop = clear + 1; - table = new_table(key_size); - key_size++; - init_key_size = key_size; - sub_len = shift = 0; - key = get_key(gif, key_size, &sub_len, &shift, &byte); /* clear code */ - frm_off = 0; - ret = 0; - frm_size = gif->fw * gif->fh; - while(frm_off < frm_size) { - if(key == clear) { - key_size = init_key_size; - table->nentries = (1 << (key_size - 1)) + 2; - table_is_full = 0; - } - else if(!table_is_full) { - ret = add_entry(&table, str_len + 1, key, entry.suffix); - if(ret == -1) { - lv_free(table); - return -1; - } - if(table->nentries == 0x1000) { - ret = 0; - table_is_full = 1; - } - } - key = get_key(gif, key_size, &sub_len, &shift, &byte); - if(key == clear) continue; - if(key == stop || key == 0x1000) break; - if(ret == 1) key_size++; - entry = table->entries[key]; - str_len = entry.length; - if(frm_off + str_len > frm_size){ - ESP_LOGW(TAG, "LZW table token overflows the frame buffer"); - lv_free(table); - return -1; - } - for(i = 0; i < str_len; i++) { - p = frm_off + entry.length - 1; - x = p % gif->fw; - y = p / gif->fw; - if(interlace) - y = interlaced_line_index((int) gif->fh, y); - gif->frame[(gif->fy + y) * gif->width + gif->fx + x] = entry.suffix; - if(entry.prefix == 0xFFF) - break; - else - entry = table->entries[entry.prefix]; - } - frm_off += str_len; - if(key < table->nentries - 1 && !table_is_full) - table->entries[table->nentries - 1].suffix = entry.suffix; - } - lv_free(table); - if(key == stop) f_gif_read(gif, &sub_len, 1); /* Must be zero! */ - f_gif_seek(gif, end, LV_FS_SEEK_SET); - return 0; -} - -#endif - -/* Read image. - * Return 0 on success or -1 on out-of-memory (w.r.t. LZW code table) or parse error. */ -static int -read_image(gd_GIF * gif) -{ - uint8_t fisrz; - int interlace; - - /* Image Descriptor. */ - gif->fx = read_num(gif); - gif->fy = read_num(gif); - gif->fw = read_num(gif); - gif->fh = read_num(gif); - if(gif->fx + (uint32_t)gif->fw > gif->width || gif->fy + (uint32_t)gif->fh > gif->height){ - ESP_LOGW(TAG, "Frame coordinates out of image bounds"); - return -1; - } - f_gif_read(gif, &fisrz, 1); - interlace = fisrz & 0x40; - /* Ignore Sort Flag. */ - /* Local Color Table? */ - if(fisrz & 0x80) { - /* Read LCT */ - gif->lct.size = 1 << ((fisrz & 0x07) + 1); - f_gif_read(gif, gif->lct.colors, 3 * gif->lct.size); - gif->palette = &gif->lct; - } - else - gif->palette = &gif->gct; - /* Image Data. */ - return read_image_data(gif, interlace); -} - -static void -render_frame_rect(gd_GIF * gif, uint8_t * buffer) -{ - int i = gif->fy * gif->width + gif->fx; -#ifdef GIFDEC_RENDER_FRAME - GIFDEC_RENDER_FRAME(&buffer[i * 4], gif->fw, gif->fh, gif->width, - &gif->frame[i], gif->palette->colors, - gif->gce.transparency ? gif->gce.tindex : 0x100); -#else - int j, k; - uint8_t index, * color; - - for(j = 0; j < gif->fh; j++) { - for(k = 0; k < gif->fw; k++) { - index = gif->frame[(gif->fy + j) * gif->width + gif->fx + k]; - color = &gif->palette->colors[index * 3]; - if(!gif->gce.transparency || index != gif->gce.tindex) { - buffer[(i + k) * 4 + 0] = *(color + 2); - buffer[(i + k) * 4 + 1] = *(color + 1); - buffer[(i + k) * 4 + 2] = *(color + 0); - buffer[(i + k) * 4 + 3] = 0xFF; - } - } - i += gif->width; - } -#endif -} - -static void -dispose(gd_GIF * gif) -{ - int i; - uint8_t * bgcolor; - switch(gif->gce.disposal) { - case 2: /* Restore to background color. */ - bgcolor = &gif->palette->colors[gif->bgindex * 3]; - - uint8_t opa = 0xff; - if(gif->gce.transparency) opa = 0x00; - - i = gif->fy * gif->width + gif->fx; -#ifdef GIFDEC_FILL_BG - GIFDEC_FILL_BG(&(gif->canvas[i * 4]), gif->fw, gif->fh, gif->width, bgcolor, opa); -#else - int j, k; - for(j = 0; j < gif->fh; j++) { - for(k = 0; k < gif->fw; k++) { - gif->canvas[(i + k) * 4 + 0] = *(bgcolor + 2); - gif->canvas[(i + k) * 4 + 1] = *(bgcolor + 1); - gif->canvas[(i + k) * 4 + 2] = *(bgcolor + 0); - gif->canvas[(i + k) * 4 + 3] = opa; - } - i += gif->width; - } -#endif - break; - case 3: /* Restore to previous, i.e., don't update canvas.*/ - break; - default: - /* Add frame non-transparent pixels to canvas. */ - render_frame_rect(gif, gif->canvas); - } -} - -/* Return 1 if got a frame; 0 if got GIF trailer; -1 if error. */ -int -gd_get_frame(gd_GIF * gif) -{ - char sep; - - dispose(gif); - f_gif_read(gif, &sep, 1); - while(sep != ',') { - if(sep == ';') { - f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET); - if(gif->loop_count == 1 || gif->loop_count < 0) { - return 0; - } - else if(gif->loop_count > 1) { - gif->loop_count--; - } - } - else if(sep == '!') - read_ext(gif); - else return -1; - f_gif_read(gif, &sep, 1); - } - if(read_image(gif) == -1) - return -1; - return 1; -} - -void -gd_render_frame(gd_GIF * gif, uint8_t * buffer) -{ - render_frame_rect(gif, buffer); -} - -void -gd_rewind(gd_GIF * gif) -{ - gif->loop_count = -1; - f_gif_seek(gif, gif->anim_start, LV_FS_SEEK_SET); -} - -void -gd_close_gif(gd_GIF * gif) -{ - f_gif_close(gif); - lv_free(gif); -} - -static bool f_gif_open(gd_GIF * gif, const void * path, bool is_file) -{ - gif->f_rw_p = 0; - gif->data = NULL; - gif->is_file = is_file; - - if(is_file) { - lv_fs_res_t res = lv_fs_open(&gif->fd, path, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return false; - else return true; - } - else { - gif->data = path; - return true; - } -} - -static void f_gif_read(gd_GIF * gif, void * buf, size_t len) -{ - if(gif->is_file) { - lv_fs_read(&gif->fd, buf, len, NULL); - } - else { - memcpy(buf, &gif->data[gif->f_rw_p], len); - gif->f_rw_p += len; - } -} - -static int f_gif_seek(gd_GIF * gif, size_t pos, int k) -{ - if(gif->is_file) { - lv_fs_seek(&gif->fd, pos, k); - uint32_t x; - lv_fs_tell(&gif->fd, &x); - return x; - } - else { - if(k == LV_FS_SEEK_CUR) gif->f_rw_p += pos; - else if(k == LV_FS_SEEK_SET) gif->f_rw_p = pos; - return gif->f_rw_p; - } -} - -static void f_gif_close(gd_GIF * gif) -{ - if(gif->is_file) { - lv_fs_close(&gif->fd); - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.h deleted file mode 100644 index 12c171e8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef GIFDEC_H -#define GIFDEC_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#include - -typedef struct _gd_Palette { - int size; - uint8_t colors[0x100 * 3]; -} gd_Palette; - -typedef struct _gd_GCE { - uint16_t delay; - uint8_t tindex; - uint8_t disposal; - int input; - int transparency; -} gd_GCE; - - - -typedef struct _gd_GIF { - lv_fs_file_t fd; - const char * data; - uint8_t is_file; - uint32_t f_rw_p; - int32_t anim_start; - uint16_t width, height; - uint16_t depth; - int32_t loop_count; - gd_GCE gce; - gd_Palette * palette; - gd_Palette lct, gct; - void (*plain_text)( - struct _gd_GIF * gif, uint16_t tx, uint16_t ty, - uint16_t tw, uint16_t th, uint8_t cw, uint8_t ch, - uint8_t fg, uint8_t bg - ); - void (*comment)(struct _gd_GIF * gif); - void (*application)(struct _gd_GIF * gif, char id[8], char auth[3]); - uint16_t fx, fy, fw, fh; - uint8_t bgindex; - uint8_t * canvas, * frame; -#if LV_GIF_CACHE_DECODE_DATA - uint8_t *lzw_cache; -#endif -} gd_GIF; - -gd_GIF * gd_open_gif_file(const char * fname); - -gd_GIF * gd_open_gif_data(const void * data); - -void gd_render_frame(gd_GIF * gif, uint8_t * buffer); - -int gd_get_frame(gd_GIF * gif); -void gd_rewind(gd_GIF * gif); -void gd_close_gif(gd_GIF * gif); - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* GIFDEC_H */ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec_mve.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec_mve.h deleted file mode 100644 index 6d833934..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/gifdec_mve.h +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @file gifdec_mve.h - * - */ - -#ifndef GIFDEC_MVE_H -#define GIFDEC_MVE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ -#include -#include "../../misc/lv_color.h" - -/********************* - * DEFINES - *********************/ - -#define GIFDEC_FILL_BG(dst, w, h, stride, color, opa) \ - _gifdec_fill_bg_mve(dst, w, h, stride, color, opa) - -#define GIFDEC_RENDER_FRAME(dst, w, h, stride, frame, pattern, tindex) \ - _gifdec_render_frame_mve(dst, w, h, stride, frame, pattern, tindex) - -/********************** - * MACROS - **********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -static inline void _gifdec_fill_bg_mve(uint8_t * dst, uint16_t w, uint16_t h, uint16_t stride, uint8_t * color, - uint8_t opa) -{ - lv_color32_t c = lv_color32_make(*(color + 0), *(color + 1), *(color + 2), opa); - uint32_t color_32 = *(uint32_t *)&c; - - __asm volatile( - ".p2align 2 \n" - "vdup.32 q0, %[src] \n" - "3: \n" - "mov r0, %[dst] \n" - - "wlstp.32 lr, %[w], 1f \n" - "2: \n" - - "vstrw.32 q0, [r0], #16 \n" - "letp lr, 2b \n" - "1: \n" - "add %[dst], %[iTargetStride] \n" - "subs %[h], #1 \n" - "bne 3b \n" - : [dst] "+r"(dst), - [h] "+r"(h) - : [src] "r"(color_32), - [w] "r"(w), - [iTargetStride] "r"(stride * sizeof(uint32_t)) - : "r0", "q0", "memory", "r14", "cc"); -} - -static inline void _gifdec_render_frame_mve(uint8_t * dst, uint16_t w, uint16_t h, uint16_t stride, uint8_t * frame, - uint8_t * pattern, uint16_t tindex) -{ - if(w == 0 || h == 0) { - return; - } - - __asm volatile( - "vmov.u16 q3, #255 \n" - "vshl.u16 q3, q3, #8 \n" /* left shift 8 for a*/ - - "mov r0, #2 \n" - "vidup.u16 q6, r0, #4 \n" /* [2, 6, 10, 14, 18, 22, 26, 30] */ - "mov r0, #0 \n" - "vidup.u16 q7, r0, #4 \n" /* [0, 4, 8, 12, 16, 20, 24, 28] */ - - "3: \n" - "mov r1, %[dst] \n" - "mov r2, %[frame] \n" - - "wlstp.16 lr, %[w], 1f \n" - "2: \n" - - "mov r0, #3 \n" - "vldrb.u16 q4, [r2], #8 \n" - "vmul.u16 q5, q4, r0 \n" - - "mov r0, #1 \n" - "vldrb.u16 q2, [%[pattern], q5] \n" /* load 8 pixel r*/ - - "vadd.u16 q5, q5, r0 \n" - "vldrb.u16 q1, [%[pattern], q5] \n" /* load 8 pixel g*/ - - "vadd.u16 q5, q5, r0 \n" - "vldrb.u16 q0, [%[pattern], q5] \n" /* load 8 pixel b*/ - - "vshl.u16 q1, q1, #8 \n" /* left shift 8 for g*/ - - "vorr.u16 q0, q0, q1 \n" /* make 8 pixel gb*/ - "vorr.u16 q1, q2, q3 \n" /* make 8 pixel ar*/ - - "vcmp.i16 ne, q4, %[tindex] \n" - "vpstt \n" - "vstrht.16 q0, [r1, q7] \n" - "vstrht.16 q1, [r1, q6] \n" - "add r1, r1, #32 \n" - - "letp lr, 2b \n" - - "1: \n" - "mov r0, %[stride], LSL #2 \n" - "add %[dst], r0 \n" - "add %[frame], %[stride] \n" - "subs %[h], #1 \n" - "bne 3b \n" - - : [dst] "+r"(dst), - [frame] "+r"(frame), - [h] "+r"(h) - : [pattern] "r"(pattern), - [w] "r"(w), - [stride] "r"(stride), - [tindex] "r"(tindex) - : "r0", "r1", "r2", "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "memory", "r14", "cc"); -} - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /*GIFDEC_MVE_H*/ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.cc deleted file mode 100644 index 172d5ba3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.cc +++ /dev/null @@ -1,208 +0,0 @@ -#include "lvgl_gif.h" -#include -#include - -#define TAG "LvglGif" - -LvglGif::LvglGif(const lv_img_dsc_t* img_dsc) - : gif_(nullptr), timer_(nullptr), last_call_(0), playing_(false), loaded_(false) { - if (!img_dsc || !img_dsc->data) { - ESP_LOGE(TAG, "Invalid image descriptor"); - return; - } - - gif_ = gd_open_gif_data(img_dsc->data); - if (!gif_) { - ESP_LOGE(TAG, "Failed to open GIF from image descriptor"); - return; - } - - // Setup LVGL image descriptor - memset(&img_dsc_, 0, sizeof(img_dsc_)); - img_dsc_.header.magic = LV_IMAGE_HEADER_MAGIC; - img_dsc_.header.flags = LV_IMAGE_FLAGS_MODIFIABLE; - img_dsc_.header.cf = LV_COLOR_FORMAT_ARGB8888; - img_dsc_.header.w = gif_->width; - img_dsc_.header.h = gif_->height; - img_dsc_.header.stride = gif_->width * 4; - img_dsc_.data = gif_->canvas; - img_dsc_.data_size = gif_->width * gif_->height * 4; - - // Render first frame - if (gif_->canvas) { - gd_render_frame(gif_, gif_->canvas); - } - - loaded_ = true; - ESP_LOGD(TAG, "GIF loaded from image descriptor: %dx%d", gif_->width, gif_->height); -} - -// Destructor -LvglGif::~LvglGif() { - Cleanup(); -} - -// LvglImage interface implementation -const lv_img_dsc_t* LvglGif::image_dsc() const { - if (!loaded_) { - return nullptr; - } - return &img_dsc_; -} - -// Animation control methods -void LvglGif::Start() { - if (!loaded_ || !gif_) { - ESP_LOGW(TAG, "GIF not loaded, cannot start"); - return; - } - - if (!timer_) { - timer_ = lv_timer_create([](lv_timer_t* timer) { - LvglGif* gif_obj = static_cast(lv_timer_get_user_data(timer)); - gif_obj->NextFrame(); - }, 10, this); - } - - if (timer_) { - playing_ = true; - last_call_ = lv_tick_get(); - lv_timer_resume(timer_); - lv_timer_reset(timer_); - - // Render first frame - NextFrame(); - - ESP_LOGD(TAG, "GIF animation started"); - } -} - -void LvglGif::Pause() { - if (timer_) { - playing_ = false; - lv_timer_pause(timer_); - ESP_LOGD(TAG, "GIF animation paused"); - } -} - -void LvglGif::Resume() { - if (!loaded_ || !gif_) { - ESP_LOGW(TAG, "GIF not loaded, cannot resume"); - return; - } - - if (timer_) { - playing_ = true; - lv_timer_resume(timer_); - ESP_LOGD(TAG, "GIF animation resumed"); - } -} - -void LvglGif::Stop() { - if (timer_) { - playing_ = false; - lv_timer_pause(timer_); - } - - if (gif_) { - gd_rewind(gif_); - NextFrame(); - ESP_LOGD(TAG, "GIF animation stopped and rewound"); - } -} - -bool LvglGif::IsPlaying() const { - return playing_; -} - -bool LvglGif::IsLoaded() const { - return loaded_; -} - -int32_t LvglGif::GetLoopCount() const { - if (!loaded_ || !gif_) { - return -1; - } - return gif_->loop_count; -} - -void LvglGif::SetLoopCount(int32_t count) { - if (!loaded_ || !gif_) { - ESP_LOGW(TAG, "GIF not loaded, cannot set loop count"); - return; - } - gif_->loop_count = count; -} - -uint16_t LvglGif::width() const { - if (!loaded_ || !gif_) { - return 0; - } - return gif_->width; -} - -uint16_t LvglGif::height() const { - if (!loaded_ || !gif_) { - return 0; - } - return gif_->height; -} - -void LvglGif::SetFrameCallback(std::function callback) { - frame_callback_ = callback; -} - -void LvglGif::NextFrame() { - if (!loaded_ || !gif_ || !playing_) { - return; - } - - // Check if enough time has passed for the next frame - uint32_t elapsed = lv_tick_elaps(last_call_); - if (elapsed < gif_->gce.delay * 10) { - return; - } - - last_call_ = lv_tick_get(); - - // Get next frame - int has_next = gd_get_frame(gif_); - if (has_next == 0) { - // Animation finished, pause timer - playing_ = false; - if (timer_) { - lv_timer_pause(timer_); - } - ESP_LOGD(TAG, "GIF animation completed"); - } - - // Render current frame - if (gif_->canvas) { - gd_render_frame(gif_, gif_->canvas); - - // Call frame callback if set - if (frame_callback_) { - frame_callback_(); - } - } -} - -void LvglGif::Cleanup() { - // Stop and delete timer - if (timer_) { - lv_timer_delete(timer_); - timer_ = nullptr; - } - - // Close GIF decoder - if (gif_) { - gd_close_gif(gif_); - gif_ = nullptr; - } - - playing_ = false; - loaded_ = false; - - // Clear image descriptor - memset(&img_dsc_, 0, sizeof(img_dsc_)); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.h deleted file mode 100644 index afa2959e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/gif/lvgl_gif.h +++ /dev/null @@ -1,101 +0,0 @@ -#pragma once - -#include "../lvgl_image.h" -#include "gifdec.h" -#include -#include -#include - -/** - * C++ implementation of LVGL GIF widget - * Provides GIF animation functionality using gifdec library - */ -class LvglGif { -public: - explicit LvglGif(const lv_img_dsc_t* img_dsc); - virtual ~LvglGif(); - - // LvglImage interface implementation - virtual const lv_img_dsc_t* image_dsc() const; - - /** - * Start/restart GIF animation - */ - void Start(); - - /** - * Pause GIF animation - */ - void Pause(); - - /** - * Resume GIF animation - */ - void Resume(); - - /** - * Stop GIF animation and rewind to first frame - */ - void Stop(); - - /** - * Check if GIF is currently playing - */ - bool IsPlaying() const; - - /** - * Check if GIF was loaded successfully - */ - bool IsLoaded() const; - - /** - * Get loop count - */ - int32_t GetLoopCount() const; - - /** - * Set loop count - */ - void SetLoopCount(int32_t count); - - /** - * Get GIF dimensions - */ - uint16_t width() const; - uint16_t height() const; - - /** - * Set frame update callback - */ - void SetFrameCallback(std::function callback); - -private: - // GIF decoder instance - gd_GIF* gif_; - - // LVGL image descriptor - lv_img_dsc_t img_dsc_; - - // Animation timer - lv_timer_t* timer_; - - // Last frame update time - uint32_t last_call_; - - // Animation state - bool playing_; - bool loaded_; - - // Frame update callback - std::function frame_callback_; - - /** - * Update to next frame - */ - void NextFrame(); - - /** - * Cleanup resources - */ - void Cleanup(); -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.cpp b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.cpp deleted file mode 100644 index 485ca8ba..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.cpp +++ /dev/null @@ -1,467 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "esp_jpeg_common.h" -#include "esp_jpeg_enc.h" -#include "esp_imgfx_color_convert.h" - -#if CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER -#include "driver/jpeg_encode.h" -#endif -#include "image_to_jpeg.h" - -#define TAG "image_to_jpeg" - -static void* malloc_psram(size_t size) { - void* p = malloc(size); - if (p) - return p; -#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) - return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); -#else - return NULL; -#endif -} - -static __always_inline uint8_t expand_5_to_8(uint8_t v) { - return (uint8_t)((v << 3) | (v >> 2)); -} - -static __always_inline uint8_t expand_6_to_8(uint8_t v) { - return (uint8_t)((v << 2) | (v >> 4)); -} - -static uint8_t* convert_input_to_encoder_buf(const uint8_t* src, uint16_t width, uint16_t height, v4l2_pix_fmt_t format, - jpeg_pixel_format_t* out_fmt, int* out_size) { - // GRAY 直接作为 JPEG_PIXEL_FORMAT_GRAY 输入 - if (format == V4L2_PIX_FMT_GREY) { - int sz = (int)width * (int)height; - uint8_t* buf = (uint8_t*)jpeg_calloc_align(sz, 16); - if (!buf) - return NULL; - memcpy(buf, src, sz); - if (out_fmt) - *out_fmt = JPEG_PIXEL_FORMAT_GRAY; - if (out_size) - *out_size = sz; - return buf; - } - - // V4L2 YUYV (Y Cb Y Cr) 可直接作为 JPEG_PIXEL_FORMAT_YCbYCr 输入 - if (format == V4L2_PIX_FMT_YUYV) { - int sz = (int)width * (int)height * 2; - uint8_t* buf = (uint8_t*)jpeg_calloc_align(sz, 16); - if (!buf) - return NULL; - memcpy(buf, src, sz); - if (out_fmt) - *out_fmt = JPEG_PIXEL_FORMAT_YCbYCr; - if (out_size) - *out_size = sz; - return buf; - } - - // V4L2 UYVY (Cb Y Cr Y) -> 重排为 YUYV 再作为 YCbYCr 输入 - // 当前版本暂时不会出现 UYVY 格式 - if (format == V4L2_PIX_FMT_UYVY) [[unlikely]] { - int sz = (int)width * (int)height * 2; - const uint8_t* s = src; - uint8_t* buf = (uint8_t*)jpeg_calloc_align(sz, 16); - if (!buf) - return NULL; - uint8_t* d = buf; - for (int i = 0; i < sz; i += 4) { - // src: Cb, Y0, Cr, Y1 -> dst: Y0, Cb, Y1, Cr - d[0] = s[1]; - d[1] = s[0]; - d[2] = s[3]; - d[3] = s[2]; - s += 4; - d += 4; - } - if (out_fmt) - *out_fmt = JPEG_PIXEL_FORMAT_YCbYCr; - if (out_size) - *out_size = sz; - return buf; - } - - // V4L2 YUV422P (YUV422 Planar) -> 重排为 YUYV (YCbYCr) - // 当前版本暂时不会出现 YUV422P 格式 - if (format == V4L2_PIX_FMT_YUV422P) [[unlikely]] { - int sz = (int)width * (int)height * 2; - const uint8_t* y_plane = src; - const uint8_t* u_plane = y_plane + (int)width * (int)height; - const uint8_t* v_plane = u_plane + ((int)width / 2) * (int)height; - uint8_t* buf = (uint8_t*)jpeg_calloc_align(sz, 16); - if (!buf) - return NULL; - uint8_t* dst = buf; - for (int y = 0; y < height; y++) { - const uint8_t* y_row = y_plane + y * (int)width; - const uint8_t* u_row = u_plane + y * ((int)width / 2); - const uint8_t* v_row = v_plane + y * ((int)width / 2); - for (int x = 0; x < width; x += 2) { - uint8_t y0 = y_row[x + 0]; - uint8_t y1 = y_row[x + 1]; - uint8_t cb = u_row[x / 2]; - uint8_t cr = v_row[x / 2]; - dst[0] = y0; - dst[1] = cb; - dst[2] = y1; - dst[3] = cr; - dst += 4; - } - } - if (out_fmt) - *out_fmt = JPEG_PIXEL_FORMAT_YCbYCr; - if (out_size) - *out_size = sz; - return buf; - } - - // RGB 转换为 YUV422 (YCbYCr) 再输入 - // 见 https://github.com/78/xiaozhi-esp32/issues/1380#issuecomment-3497156378 - else if (format == V4L2_PIX_FMT_RGB24 || format == V4L2_PIX_FMT_RGB565 || format == V4L2_PIX_FMT_RGB565X) { - esp_imgfx_pixel_fmt_t in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888; - uint32_t src_len = 0; - switch (format) { - case V4L2_PIX_FMT_RGB24: - in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB888; - src_len = static_cast(width * height * 3); - break; - case V4L2_PIX_FMT_RGB565: - in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_LE; - src_len = static_cast(width * height * 2); - break; - [[unlikely]] case V4L2_PIX_FMT_RGB565X: // 当前版本暂时不会出现 RGB565X - in_pixel_fmt = ESP_IMGFX_PIXEL_FMT_RGB565_BE; - src_len = static_cast(width * height * 2); - break; - [[unlikely]] default: - ESP_LOGE(TAG, "[Unreachable Case] unsupported format: 0x%08lx", format); - std::unreachable(); - } - int sz = (int)width * (int)height * 2; - uint8_t* buf = (uint8_t*)jpeg_calloc_align(sz, 16); - if (!buf) - return nullptr; - esp_imgfx_color_convert_cfg_t convert_cfg = { - .in_res = {.width = static_cast(width), - .height = static_cast(height)}, - .in_pixel_fmt = in_pixel_fmt, - .out_pixel_fmt = ESP_IMGFX_PIXEL_FMT_YUYV, - .color_space_std = ESP_IMGFX_COLOR_SPACE_STD_BT601, - }; - esp_imgfx_color_convert_handle_t convert_handle = nullptr; - esp_imgfx_err_t err = esp_imgfx_color_convert_open(&convert_cfg, &convert_handle); - if (err != ESP_IMGFX_ERR_OK || convert_handle == nullptr) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_open failed"); - jpeg_free_align(buf); - return nullptr; - } - esp_imgfx_data_t convert_input_data = { - .data = const_cast(src), - .data_len = static_cast(src_len), - }; - esp_imgfx_data_t convert_output_data = { - .data = buf, - .data_len = static_cast(sz), - }; - err = esp_imgfx_color_convert_process(convert_handle, &convert_input_data, &convert_output_data); - if (err != ESP_IMGFX_ERR_OK) { - ESP_LOGE(TAG, "esp_imgfx_color_convert_process failed"); - jpeg_free_align(buf); - return nullptr; - } - esp_imgfx_color_convert_close(convert_handle); - convert_handle = nullptr; - if (out_fmt) - *out_fmt = JPEG_PIXEL_FORMAT_YCbYCr; - if (out_size) - *out_size = sz; - return buf; - } - ESP_LOGE(TAG, "unsupported format: 0x%08lx", format); - if (out_size) - *out_size = 0; - return nullptr; -} - -#if CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER -static jpeg_encoder_handle_t s_hw_jpeg_handle = NULL; - -static bool hw_jpeg_ensure_inited(void) { - if (s_hw_jpeg_handle) { - return true; - } - jpeg_encode_engine_cfg_t eng_cfg = { - .intr_priority = 0, - .timeout_ms = 100, - }; - esp_err_t er = jpeg_new_encoder_engine(&eng_cfg, &s_hw_jpeg_handle); - if (er != ESP_OK) { - ESP_LOGE(TAG, "jpeg_new_encoder_engine failed: %d", (int)er); - s_hw_jpeg_handle = NULL; - return false; - } - return true; -} - -static uint8_t* convert_input_to_hw_encoder_buf(const uint8_t* src, uint16_t width, uint16_t height, v4l2_pix_fmt_t format, - jpeg_enc_input_format_t* out_fmt, int* out_size) { - if (format == V4L2_PIX_FMT_GREY) { - int sz = (int)width * (int)height; - uint8_t* buf = (uint8_t*)malloc_psram(sz); - if (!buf) - return NULL; - memcpy(buf, src, sz); - if (out_fmt) - *out_fmt = JPEG_ENCODE_IN_FORMAT_GRAY; - if (out_size) - *out_size = sz; - return buf; - } - - if (format == V4L2_PIX_FMT_RGB24) { - int sz = (int)width * (int)height * 3; - uint8_t* buf = (uint8_t*)malloc_psram(sz); - if (!buf) { - ESP_LOGE(TAG, "malloc_psram failed"); - return NULL; - } - memcpy(buf, src, sz); - if (out_fmt) - *out_fmt = JPEG_ENCODE_IN_FORMAT_RGB888; - if (out_size) - *out_size = sz; - return buf; - } - - if (format == V4L2_PIX_FMT_RGB565) { - int sz = (int)width * (int)height * 2; - uint8_t* buf = (uint8_t*)malloc_psram(sz); - if (!buf) - return NULL; - memcpy(buf, src, sz); - if (out_fmt) - *out_fmt = JPEG_ENCODE_IN_FORMAT_RGB565; - if (out_size) - *out_size = sz; - return buf; - } - - if (format == V4L2_PIX_FMT_YUYV) { - // 硬件需要 | Y1 V Y0 U | 的“大端”格式,因此需要 bswap16 - int sz = (int)width * (int)height * 2; - uint16_t* buf = (uint16_t*)malloc_psram(sz); - if (!buf) - return NULL; - const uint16_t* bsrc = (const uint16_t*)src; - for (int i = 0; i < sz / 2; i++) { - buf[i] = __builtin_bswap16(bsrc[i]); - } - if (out_fmt) - *out_fmt = JPEG_ENCODE_IN_FORMAT_YUV422; - if (out_size) - *out_size = sz; - return (uint8_t*)buf; - } - - return NULL; -} - -static bool encode_with_hw_jpeg(const uint8_t* src, size_t src_len, uint16_t width, uint16_t height, - v4l2_pix_fmt_t format, uint8_t quality, uint8_t** jpg_out, size_t* jpg_out_len, - jpg_out_cb cb, void* cb_arg) { - if (quality < 1) - quality = 1; - if (quality > 100) - quality = 100; - - jpeg_enc_input_format_t enc_src_type = JPEG_ENCODE_IN_FORMAT_RGB888; - int enc_in_size = 0; - uint8_t* enc_in = convert_input_to_hw_encoder_buf(src, width, height, format, &enc_src_type, &enc_in_size); - if (!enc_in) { - ESP_LOGW(TAG, "hw jpeg: unsupported format, fallback to sw"); - return false; - } - - if (!hw_jpeg_ensure_inited()) { - free(enc_in); - return false; - } - - jpeg_encode_cfg_t enc_cfg = {0}; - enc_cfg.width = width; - enc_cfg.height = height; - enc_cfg.src_type = enc_src_type; - enc_cfg.image_quality = quality; - enc_cfg.sub_sample = (enc_src_type == JPEG_ENCODE_IN_FORMAT_GRAY) ? JPEG_DOWN_SAMPLING_GRAY : JPEG_DOWN_SAMPLING_YUV422; - - size_t out_cap = (size_t)width * (size_t)height * 3 / 2 + 64 * 1024; - if (out_cap < 128 * 1024) - out_cap = 128 * 1024; - jpeg_encode_memory_alloc_cfg_t jpeg_enc_output_mem_cfg = { .buffer_direction = JPEG_ENC_ALLOC_OUTPUT_BUFFER }; - size_t out_cap_aligned = 0; - uint8_t* outbuf = (uint8_t*)jpeg_alloc_encoder_mem(out_cap, &jpeg_enc_output_mem_cfg, &out_cap_aligned); - if (!outbuf) { - free(enc_in); - ESP_LOGE(TAG, "alloc out buffer failed"); - return false; - } - - uint32_t out_len = 0; - esp_err_t er = jpeg_encoder_process(s_hw_jpeg_handle, &enc_cfg, enc_in, (uint32_t)enc_in_size, outbuf, (uint32_t)out_cap_aligned, &out_len); - free(enc_in); - - if (er != ESP_OK) { - free(outbuf); - ESP_LOGE(TAG, "jpeg_encoder_process failed: %d", (int)er); - return false; - } - - if (cb) { - cb(cb_arg, 0, outbuf, (size_t)out_len); - cb(cb_arg, 1, NULL, 0); - free(outbuf); - if (jpg_out) - *jpg_out = NULL; - if (jpg_out_len) - *jpg_out_len = 0; - return true; - } - - if (jpg_out && jpg_out_len) { - *jpg_out = outbuf; - *jpg_out_len = (size_t)out_len; - return true; - } - - free(outbuf); - return true; -} -#endif // CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - -static bool encode_with_esp_new_jpeg(const uint8_t* src, size_t src_len, uint16_t width, uint16_t height, - v4l2_pix_fmt_t format, uint8_t quality, uint8_t** jpg_out, size_t* jpg_out_len, - jpg_out_cb cb, void* cb_arg) { - if (quality < 1) - quality = 1; - if (quality > 100) - quality = 100; - - jpeg_pixel_format_t enc_src_type = JPEG_PIXEL_FORMAT_RGB888; - int enc_in_size = 0; - uint8_t* enc_in = convert_input_to_encoder_buf(src, width, height, format, &enc_src_type, &enc_in_size); - if (!enc_in) { - ESP_LOGE(TAG, "alloc/convert input failed"); - return false; - } - - jpeg_enc_config_t cfg = DEFAULT_JPEG_ENC_CONFIG(); - cfg.width = width; - cfg.height = height; - cfg.src_type = enc_src_type; - cfg.subsampling = (enc_src_type == JPEG_PIXEL_FORMAT_GRAY) ? JPEG_SUBSAMPLE_GRAY : JPEG_SUBSAMPLE_420; - cfg.quality = quality; - cfg.rotate = JPEG_ROTATE_0D; - cfg.task_enable = false; - - jpeg_enc_handle_t h = NULL; - jpeg_error_t ret = jpeg_enc_open(&cfg, &h); - if (ret != JPEG_ERR_OK) { - jpeg_free_align(enc_in); - ESP_LOGE(TAG, "jpeg_enc_open failed: %d", (int)ret); - return false; - } - - // 估算输出缓冲区:宽高的 1.5 倍 + 64KB - size_t out_cap = (size_t)width * (size_t)height * 3 / 2 + 64 * 1024; - if (out_cap < 128 * 1024) - out_cap = 128 * 1024; - uint8_t* outbuf = (uint8_t*)malloc_psram(out_cap); - if (!outbuf) { - jpeg_enc_close(h); - jpeg_free_align(enc_in); - ESP_LOGE(TAG, "alloc out buffer failed"); - return false; - } - - int out_len = 0; - ret = jpeg_enc_process(h, enc_in, enc_in_size, outbuf, (int)out_cap, &out_len); - jpeg_enc_close(h); - jpeg_free_align(enc_in); - - if (ret != JPEG_ERR_OK) { - free(outbuf); - ESP_LOGE(TAG, "jpeg_enc_process failed: %d", (int)ret); - return false; - } - - if (cb) { - cb(cb_arg, 0, outbuf, (size_t)out_len); - cb(cb_arg, 1, NULL, 0); // 结束信号 - free(outbuf); - if (jpg_out) - *jpg_out = NULL; - if (jpg_out_len) - *jpg_out_len = 0; - return true; - } - - if (jpg_out && jpg_out_len) { - *jpg_out = outbuf; - *jpg_out_len = (size_t)out_len; - return true; - } - - free(outbuf); - return true; -} - -bool image_to_jpeg(uint8_t* src, size_t src_len, uint16_t width, uint16_t height, v4l2_pix_fmt_t format, - uint8_t quality, uint8_t** out, size_t* out_len) { -#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - if (format == V4L2_PIX_FMT_JPEG) { - uint8_t * out_data = (uint8_t*)heap_caps_malloc(src_len, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (!out_data) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG output"); - return false; - } - memcpy(out_data, src, src_len); - *out = out_data; - *out_len = src_len; - return true; - } -#endif // CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT -#if CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - if (encode_with_hw_jpeg(src, src_len, width, height, format, quality, out, out_len, NULL, NULL)) { - return true; - } - // Fallback to esp_new_jpeg -#endif - return encode_with_esp_new_jpeg(src, src_len, width, height, format, quality, out, out_len, NULL, NULL); -} - -bool image_to_jpeg_cb(uint8_t* src, size_t src_len, uint16_t width, uint16_t height, v4l2_pix_fmt_t format, - uint8_t quality, jpg_out_cb cb, void* arg) { -#ifdef CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT - if (format == V4L2_PIX_FMT_JPEG) { - cb(arg, 0, src, src_len); - cb(arg, 1, nullptr, 0); // end signal - return true; - } -#endif // CONFIG_XIAOZHI_CAMERA_ALLOW_JPEG_INPUT -#if CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_ENCODER - if (encode_with_hw_jpeg(src, src_len, width, height, format, quality, NULL, NULL, cb, arg)) { - return true; - } - // Fallback to esp_new_jpeg -#endif - return encode_with_esp_new_jpeg(src, src_len, width, height, format, quality, NULL, NULL, cb, arg); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.h deleted file mode 100644 index 61898c2d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/image_to_jpeg.h +++ /dev/null @@ -1,70 +0,0 @@ -// image_to_jpeg.h - 图像到JPEG转换的高效编码接口 -// 节省约8KB SRAM的JPEG编码实现 -#pragma once -#include "sdkconfig.h" -#ifndef CONFIG_IDF_TARGET_ESP32 - -#include -#include -#include - -typedef uint32_t v4l2_pix_fmt_t; // see linux/videodev2.h for details - -#ifdef __cplusplus -extern "C" { -#endif - -// JPEG输出回调函数类型 -// arg: 用户自定义参数, index: 当前数据索引, data: JPEG数据块, len: 数据块长度 -// 返回: 实际处理的字节数 -typedef size_t (*jpg_out_cb)(void *arg, size_t index, const void *data, size_t len); - -/** - * @brief 将图像格式高效转换为JPEG - * - * 这个函数使用优化的JPEG编码器进行编码,主要特点: - * - 节省约8KB的SRAM使用(静态变量改为堆分配) - * - 支持多种图像格式输入 - * - 高质量JPEG输出 - * - * @param src 源图像数据 - * @param src_len 源图像数据长度 - * @param width 图像宽度 - * @param height 图像高度 - * @param format 图像格式 (PIXFORMAT_RGB565, PIXFORMAT_RGB888, 等) - * @param quality JPEG质量 (1-100) - * @param out 输出JPEG数据指针 (需要调用者释放) - * @param out_len 输出JPEG数据长度 - * - * @return true 成功, false 失败 - */ -bool image_to_jpeg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, - v4l2_pix_fmt_t format, uint8_t quality, uint8_t **out, size_t *out_len); - -/** - * @brief 将图像格式转换为JPEG(回调版本) - * - * 使用回调函数处理JPEG输出数据,适合流式传输或分块处理: - * - 节省约8KB的SRAM使用(静态变量改为堆分配) - * - 支持流式输出,无需预分配大缓冲区 - * - 通过回调函数逐块处理JPEG数据 - * - * @param src 源图像数据 - * @param src_len 源图像数据长度 - * @param width 图像宽度 - * @param height 图像高度 - * @param format 图像格式 - * @param quality JPEG质量 (1-100) - * @param cb 输出回调函数 - * @param arg 传递给回调函数的用户参数 - * - * @return true 成功, false 失败 - */ -bool image_to_jpeg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, - v4l2_pix_fmt_t format, uint8_t quality, jpg_out_cb cb, void *arg); - -#ifdef __cplusplus -} -#endif - -#endif // ndef CONFIG_IDF_TARGET_ESP32 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.c b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.c deleted file mode 100644 index da924555..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.c +++ /dev/null @@ -1,264 +0,0 @@ -#include -#include -#include -#include - -#include "esp_jpeg_common.h" -#include "esp_jpeg_dec.h" - -#include "jpeg_to_image.h" - -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE -#undef LOG_LOCAL_LEVEL -#define LOG_LOCAL_LEVEL MAX(CONFIG_LOG_DEFAULT_LEVEL, ESP_LOG_DEBUG) -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE -#include - -#ifdef CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER -#include "driver/jpeg_decode.h" -#endif - -#define TAG "jpeg_to_image" - -static esp_err_t decode_with_new_jpeg(const uint8_t* src, size_t src_len, uint8_t** out, size_t* out_len, size_t* width, - size_t* height, size_t* stride) { - ESP_LOGD(TAG, "Decoding JPEG with software decoder"); - esp_err_t ret = ESP_OK; - jpeg_error_t jpeg_ret = JPEG_ERR_OK; - uint8_t* out_buf = NULL; - jpeg_dec_io_t jpeg_io = {0}; - jpeg_dec_header_info_t out_info = {0}; - - jpeg_dec_config_t config = DEFAULT_JPEG_DEC_CONFIG(); - config.output_type = JPEG_PIXEL_FORMAT_RGB565_LE; - config.rotate = JPEG_ROTATE_0D; - - jpeg_dec_handle_t jpeg_dec = NULL; - jpeg_ret = jpeg_dec_open(&config, &jpeg_dec); - if (jpeg_ret != JPEG_ERR_OK) { - ESP_LOGE(TAG, "Failed to open JPEG decoder"); - ret = ESP_FAIL; - goto jpeg_dec_failed; - } - - jpeg_io.inbuf = (uint8_t*)src; - jpeg_io.inbuf_len = (int)src_len; - - jpeg_ret = jpeg_dec_parse_header(jpeg_dec, &jpeg_io, &out_info); - if (jpeg_ret != JPEG_ERR_OK) { - ESP_LOGE(TAG, "Failed to parse JPEG header"); - ret = ESP_ERR_INVALID_ARG; - goto jpeg_dec_failed; - } - - ESP_LOGD(TAG, "JPEG header info: width=%d, height=%d", out_info.width, out_info.height); - - out_buf = jpeg_calloc_align(out_info.width * out_info.height * 2, 16); - if (out_buf == NULL) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG output buffer"); - ret = ESP_ERR_NO_MEM; - goto jpeg_dec_failed; - } - - jpeg_io.outbuf = out_buf; - jpeg_ret = jpeg_dec_process(jpeg_dec, &jpeg_io); - if (jpeg_ret != JPEG_ERR_OK) { - ESP_LOGE(TAG, "Failed to decode JPEG"); - ret = ESP_FAIL; - goto jpeg_dec_failed; - } - - ESP_LOG_BUFFER_HEXDUMP(TAG, out_buf, MIN(out_info.width * out_info.height * 2, 256), ESP_LOG_DEBUG); - - *out = out_buf; - out_buf = NULL; - *out_len = (size_t)(out_info.width * out_info.height * 2); - *width = (size_t)out_info.width; - *height = (size_t)out_info.height; - *stride = (size_t)out_info.width * 2; - jpeg_dec_close(jpeg_dec); - jpeg_dec = NULL; - - return ret; - -jpeg_dec_failed: - if (jpeg_dec) { - jpeg_dec_close(jpeg_dec); - jpeg_dec = NULL; - } - if (out_buf) { - jpeg_free_align(out_buf); - out_buf = NULL; - } - - *out = NULL; - *out_len = 0; - *width = 0; - *height = 0; - *stride = 0; - return ret; -} - -#ifdef CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER -static esp_err_t decode_with_hardware_jpeg(const uint8_t* src, size_t src_len, uint8_t** out, size_t* out_len, - size_t* width, size_t* height, size_t* stride) { - ESP_LOGD(TAG, "Decoding JPEG with hardware decoder"); - esp_err_t ret = ESP_OK; - - jpeg_decoder_handle_t jpeg_dec = NULL; - uint8_t* bit_stream = NULL; - uint8_t* out_buf = NULL; - size_t out_buf_len = 0; - size_t tx_buffer_size = 0; - size_t rx_buffer_size = 0; - - jpeg_decode_engine_cfg_t eng_cfg = { - .intr_priority = 1, - .timeout_ms = 1000, - }; - - jpeg_decode_cfg_t decode_cfg_rgb = { - .output_format = JPEG_DECODE_OUT_FORMAT_RGB565, - .rgb_order = JPEG_DEC_RGB_ELEMENT_ORDER_BGR, - }; - - ret = jpeg_new_decoder_engine(&eng_cfg, &jpeg_dec); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "Failed to create JPEG decoder engine"); - goto jpeg_hw_dec_failed; - } - - jpeg_decode_memory_alloc_cfg_t tx_mem_cfg = { - .buffer_direction = JPEG_DEC_ALLOC_INPUT_BUFFER, - }; - - jpeg_decode_memory_alloc_cfg_t rx_mem_cfg = { - .buffer_direction = JPEG_DEC_ALLOC_OUTPUT_BUFFER, - }; - - bit_stream = (uint8_t*)jpeg_alloc_decoder_mem(src_len, &tx_mem_cfg, &tx_buffer_size); - if (bit_stream == NULL || tx_buffer_size < src_len) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG bit stream"); - ret = ESP_ERR_NO_MEM; - goto jpeg_hw_dec_failed; - } - - memcpy(bit_stream, src, src_len); - - jpeg_decode_picture_info_t header_info; - ESP_GOTO_ON_ERROR(jpeg_decoder_get_info(bit_stream, src_len, &header_info), jpeg_hw_dec_failed, TAG, - "Failed to get JPEG header info"); - - ESP_LOGD(TAG, "JPEG header info: width=%d, height=%d, sample_method=%d", header_info.width, header_info.height, - (int)header_info.sample_method); - - switch (header_info.sample_method) { - case JPEG_DOWN_SAMPLING_GRAY: - case JPEG_DOWN_SAMPLING_YUV444: - out_buf_len = header_info.width * header_info.height * 2; - *stride = header_info.width * 2; - break; - case JPEG_DOWN_SAMPLING_YUV422: - case JPEG_DOWN_SAMPLING_YUV420: - out_buf_len = ((header_info.width + 15) & ~15) * ((header_info.height + 15) & ~15) * 2; - *stride = ((header_info.width + 15) & ~15) * 2; - break; - default: - ESP_LOGE(TAG, "Unsupported JPEG sample method"); - ret = ESP_ERR_NOT_SUPPORTED; - goto jpeg_hw_dec_failed; - } - - out_buf = (uint8_t*)jpeg_alloc_decoder_mem(out_buf_len, &rx_mem_cfg, &rx_buffer_size); - if (out_buf == NULL || rx_buffer_size < out_buf_len) { - ESP_LOGE(TAG, "Failed to allocate memory for JPEG output buffer"); - ret = ESP_ERR_NO_MEM; - goto jpeg_hw_dec_failed; - } - - uint32_t out_size = 0; - - ESP_GOTO_ON_ERROR( - jpeg_decoder_process(jpeg_dec, &decode_cfg_rgb, bit_stream, src_len, out_buf, out_buf_len, &out_size), - jpeg_hw_dec_failed, TAG, "Failed to decode JPEG"); - - ESP_LOGD(TAG, "Expected %d bytes, got %" PRIu32 " bytes", out_buf_len, out_size); - - if (out_size != out_buf_len) { - ESP_LOGE(TAG, "Decoded image size mismatch: Expected %zu bytes, got %" PRIu32 " bytes", out_buf_len, out_size); - ret = ESP_ERR_INVALID_SIZE; - goto jpeg_hw_dec_failed; - } - - if (header_info.sample_method == JPEG_DOWN_SAMPLING_GRAY) { - // convert GRAY8 to RGB565 - uint32_t i = header_info.width * header_info.height; - do { - --i; - uint8_t r = (out_buf[i] >> 3) & 0x1F; - uint8_t g = (out_buf[i] >> 2) & 0x3F; - // b is same as r - uint16_t rgb565 = (r << 11) | (g << 5) | r; - out_buf[2 * i + 1] = (rgb565 >> 8) & 0xFF; - out_buf[2 * i] = rgb565 & 0xFF; - } while (i != 0); - out_size = header_info.width * header_info.height * 2; - ESP_LOGD(TAG, "Converted GRAY8 to RGB565, new size: %zu", out_size); - } - - ESP_LOG_BUFFER_HEXDUMP(TAG, out_buf, MIN(out_size, 256), ESP_LOG_DEBUG); - - *out = out_buf; - out_buf = NULL; - *out_len = (size_t)out_size; - jpeg_del_decoder_engine(jpeg_dec); - jpeg_dec = NULL; - heap_caps_free(bit_stream); - bit_stream = NULL; - *width = header_info.width; - *height = header_info.height; - - return ret; - -jpeg_hw_dec_failed: - if (out_buf) { - heap_caps_free(out_buf); - out_buf = NULL; - } - if (bit_stream) { - heap_caps_free(bit_stream); - bit_stream = NULL; - } - if (jpeg_dec) { - jpeg_del_decoder_engine(jpeg_dec); - jpeg_dec = NULL; - } - *out = NULL; - *out_len = 0; - *width = 0; - *height = 0; - *stride = 0; - return ret; -} -#endif // CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER - -esp_err_t jpeg_to_image(const uint8_t* src, size_t src_len, uint8_t** out, size_t* out_len, size_t* width, - size_t* height, size_t* stride) { -#ifdef CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - esp_log_level_set(TAG, ESP_LOG_DEBUG); -#endif // CONFIG_XIAOZHI_ENABLE_CAMERA_DEBUG_MODE - if (src == NULL || src_len == 0 || out == NULL || out_len == NULL || width == NULL || height == NULL || - stride == NULL) { - ESP_LOGE(TAG, "Invalid parameters"); - return ESP_ERR_INVALID_ARG; - } -#ifdef CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER - esp_err_t ret = decode_with_hardware_jpeg(src, src_len, out, out_len, width, height, stride); - if (ret == ESP_OK) { - return ret; - } - ESP_LOGW(TAG, "Failed to decode with hardware JPEG, fallback to software decoder"); - // Fallback to esp_new_jpeg -#endif - return decode_with_new_jpeg(src, src_len, out, out_len, width, height, stride); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.h deleted file mode 100644 index b33dcef3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/jpg/jpeg_to_image.h +++ /dev/null @@ -1,62 +0,0 @@ -#include "sdkconfig.h" -#ifndef CONFIG_IDF_TARGET_ESP32 - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Decodes a JPEG image from memory to raw RGB565 pixel data - * - * This function attempts to decode a JPEG image using hardware acceleration first (if enabled), - * falling back to a software decoder if hardware decoding fails or is unavailable. - * - * @param[in] src Pointer to the JPEG bitstream in memory - * @param[in] src_len Length of the JPEG bitstream in bytes - * @param[out] out Pointer to a buffer pointer that will be set to the decoded image data. - * This buffer is allocated internally and MUST be freed by the caller using heap_caps_free(). - * @param[out] out_len Pointer to a variable that will receive the size of the decoded image data in bytes - * @param[out] width Pointer to a variable that will receive the image width in pixels - * @param[out] height Pointer to a variable that will receive the image height in pixels - * @param[out] stride Pointer to a variable that will receive the image stride in bytes - * - * @return ESP_OK on successful decoding - * @return ESP_ERR_INVALID_ARG on invalid parameters - * @return ESP_ERR_NO_MEM on memory allocation failure - * @return ESP_FAIL on failure - * - * @attention Memory Management for `*out`: - * - The function allocates memory for the decoded image internally - * - On success, the caller takes ownership of this memory and SHOULD free it using heap_caps_free() - * - On failure, `*out` is guaranteed to be NULL and no freeing is required - * - Example usage: - * @code{.c} - * uint8_t *image = NULL; - * size_t len, width, height; - * if (jpeg_to_image(jpeg_data, jpeg_len, &image, &len, &width, &height)) { - * // Use image data... - * heap_caps_free(image); // Critical: use heap_caps_free - * } - * @endcode - * - * @note Configuration dependency: - * - When CONFIG_XIAOZHI_ENABLE_HARDWARE_JPEG_DECODER is enabled, hardware acceleration is attempted first - * - Both hardware and software paths allocate memory that requires heap_caps_free() for deallocation - * - The decoded image format is always RGB565 (2 bytes per pixel) - * - * @note When using hardware decoder, the decoded image dimensions might be aligned up to 16-byte boundaries. - * For YUV420 or YUV422 compressed images, both width and height will be rounded up to the nearest multiple of 16. - * See details at - * - * - */ -esp_err_t jpeg_to_image(const uint8_t* src, size_t src_len, uint8_t** out, size_t* out_len, size_t* width, - size_t* height, size_t* stride); - -#ifdef __cplusplus -} -#endif - -#endif // CONFIG_IDF_TARGET_ESP32 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.cc deleted file mode 100644 index 8942a593..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.cc +++ /dev/null @@ -1,258 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "lvgl_display.h" -#include "board.h" -#include "application.h" -#include "audio_codec.h" -#include "settings.h" -#include "assets/lang_config.h" -#include "jpg/image_to_jpeg.h" - -#define TAG "Display" - -LvglDisplay::LvglDisplay() { - // Notification timer - esp_timer_create_args_t notification_timer_args = { - .callback = [](void *arg) { - LvglDisplay *display = static_cast(arg); - DisplayLockGuard lock(display); - lv_obj_add_flag(display->notification_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_remove_flag(display->status_label_, LV_OBJ_FLAG_HIDDEN); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "notification_timer", - .skip_unhandled_events = false, - }; - ESP_ERROR_CHECK(esp_timer_create(¬ification_timer_args, ¬ification_timer_)); - - // Create a power management lock - auto ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "display_update", &pm_lock_); - if (ret == ESP_ERR_NOT_SUPPORTED) { - ESP_LOGI(TAG, "Power management not supported"); - } else { - ESP_ERROR_CHECK(ret); - } -} - -LvglDisplay::~LvglDisplay() { - if (notification_timer_ != nullptr) { - esp_timer_stop(notification_timer_); - esp_timer_delete(notification_timer_); - } - - if (network_label_ != nullptr) { - lv_obj_del(network_label_); - } - if (notification_label_ != nullptr) { - lv_obj_del(notification_label_); - } - if (status_label_ != nullptr) { - lv_obj_del(status_label_); - } - if (mute_label_ != nullptr) { - lv_obj_del(mute_label_); - } - if (battery_label_ != nullptr) { - lv_obj_del(battery_label_); - } - if( low_battery_popup_ != nullptr ) { - lv_obj_del(low_battery_popup_); - } - if (pm_lock_ != nullptr) { - esp_pm_lock_delete(pm_lock_); - } -} - -void LvglDisplay::SetStatus(const char* status) { - DisplayLockGuard lock(this); - if (status_label_ == nullptr) { - return; - } - lv_label_set_text(status_label_, status); - lv_obj_remove_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - last_status_update_time_ = std::chrono::system_clock::now(); -} - -void LvglDisplay::ShowNotification(const std::string ¬ification, int duration_ms) { - ShowNotification(notification.c_str(), duration_ms); -} - -void LvglDisplay::ShowNotification(const char* notification, int duration_ms) { - DisplayLockGuard lock(this); - if (notification_label_ == nullptr) { - return; - } - lv_label_set_text(notification_label_, notification); - lv_obj_remove_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - lv_obj_add_flag(status_label_, LV_OBJ_FLAG_HIDDEN); - - esp_timer_stop(notification_timer_); - ESP_ERROR_CHECK(esp_timer_start_once(notification_timer_, duration_ms * 1000)); -} - -void LvglDisplay::UpdateStatusBar(bool update_all) { - auto& app = Application::GetInstance(); - auto& board = Board::GetInstance(); - auto codec = board.GetAudioCodec(); - - // Update mute icon - { - DisplayLockGuard lock(this); - if (mute_label_ == nullptr) { - return; - } - - // Update icon if mute state changes - if (codec->output_volume() == 0 && !muted_) { - muted_ = true; - lv_label_set_text(mute_label_, FONT_AWESOME_VOLUME_XMARK); - } else if (codec->output_volume() > 0 && muted_) { - muted_ = false; - lv_label_set_text(mute_label_, ""); - } - } - - // Update time - if (app.GetDeviceState() == kDeviceStateIdle) { - if (last_status_update_time_ + std::chrono::seconds(10) < std::chrono::system_clock::now()) { - // Set status to clock "HH:MM" - time_t now = time(NULL); - struct tm* tm = localtime(&now); - // Check if the we have already set the time - if (tm->tm_year >= 2025 - 1900) { - char time_str[16]; - strftime(time_str, sizeof(time_str), "%H:%M", tm); - SetStatus(time_str); - } else { - ESP_LOGW(TAG, "System time is not set, tm_year: %d", tm->tm_year); - } - } - } - - esp_pm_lock_acquire(pm_lock_); - // Update battery icon - int battery_level; - bool charging, discharging; - const char* icon = nullptr; - if (board.GetBatteryLevel(battery_level, charging, discharging)) { - if (charging) { - icon = FONT_AWESOME_BATTERY_BOLT; - } else { - const char* levels[] = { - FONT_AWESOME_BATTERY_EMPTY, // 0-19% - FONT_AWESOME_BATTERY_QUARTER, // 20-39% - FONT_AWESOME_BATTERY_HALF, // 40-59% - FONT_AWESOME_BATTERY_THREE_QUARTERS, // 60-79% - FONT_AWESOME_BATTERY_FULL, // 80-99% - FONT_AWESOME_BATTERY_FULL, // 100% - }; - icon = levels[battery_level / 20]; - } - DisplayLockGuard lock(this); - if (battery_label_ != nullptr && battery_icon_ != icon) { - battery_icon_ = icon; - lv_label_set_text(battery_label_, battery_icon_); - } - - if (low_battery_popup_ != nullptr) { - if (strcmp(icon, FONT_AWESOME_BATTERY_EMPTY) == 0 && discharging) { - if (lv_obj_has_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN)) { // Show if low battery popup is hidden - lv_obj_remove_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN); - app.PlaySound(Lang::Sounds::OGG_LOW_BATTERY); - } - } else { - // Hide the low battery popup when the battery is not empty - if (!lv_obj_has_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN)) { // Hide if low battery popup is shown - lv_obj_add_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN); - } - } - } - } - - // Update network icon every 10 seconds - static int seconds_counter = 0; - if (update_all || seconds_counter++ % 10 == 0) { - // Don't read 4G network status during firmware upgrade to avoid occupying UART resources - auto device_state = Application::GetInstance().GetDeviceState(); - static const std::vector allowed_states = { - kDeviceStateIdle, - kDeviceStateStarting, - kDeviceStateWifiConfiguring, - kDeviceStateListening, - kDeviceStateActivating, - }; - if (std::find(allowed_states.begin(), allowed_states.end(), device_state) != allowed_states.end()) { - icon = board.GetNetworkStateIcon(); - if (network_label_ != nullptr && icon != nullptr && network_icon_ != icon) { - DisplayLockGuard lock(this); - network_icon_ = icon; - lv_label_set_text(network_label_, network_icon_); - } - } - } - - esp_pm_lock_release(pm_lock_); -} - -void LvglDisplay::SetPreviewImage(std::unique_ptr image) { -} - -void LvglDisplay::SetPowerSaveMode(bool on) { - if (on) { - SetChatMessage("system", ""); - SetEmotion("sleepy"); - } else { - SetChatMessage("system", ""); - SetEmotion("neutral"); - } -} - -bool LvglDisplay::SnapshotToJpeg(std::string& jpeg_data, int quality) { -#if CONFIG_LV_USE_SNAPSHOT - DisplayLockGuard lock(this); - - lv_obj_t* screen = lv_screen_active(); - lv_draw_buf_t* draw_buffer = lv_snapshot_take(screen, LV_COLOR_FORMAT_RGB565); - if (draw_buffer == nullptr) { - ESP_LOGE(TAG, "Failed to take snapshot, draw_buffer is nullptr"); - return false; - } - - // swap bytes - uint16_t* data = (uint16_t*)draw_buffer->data; - size_t pixel_count = draw_buffer->data_size / 2; - for (size_t i = 0; i < pixel_count; i++) { - data[i] = __builtin_bswap16(data[i]); - } - - // Clear output string and use callback version to avoid pre-allocating large memory blocks - jpeg_data.clear(); - - // Use callback-based JPEG encoder to further save memory - bool ret = image_to_jpeg_cb((uint8_t*)draw_buffer->data, draw_buffer->data_size, draw_buffer->header.w, draw_buffer->header.h, V4L2_PIX_FMT_RGB565, quality, - [](void *arg, size_t index, const void *data, size_t len) -> size_t { - std::string* output = static_cast(arg); - if (data && len > 0) { - output->append(static_cast(data), len); - } - return len; - }, &jpeg_data); - if (!ret) { - ESP_LOGE(TAG, "Failed to convert image to JPEG"); - } - - lv_draw_buf_destroy(draw_buffer); - return ret; -#else - ESP_LOGE(TAG, "LV_USE_SNAPSHOT is not enabled"); - return false; -#endif -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.h deleted file mode 100644 index 226a6ff4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_display.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef LVGL_DISPLAY_H -#define LVGL_DISPLAY_H - -#include "display.h" -#include "lvgl_image.h" - -#include -#include -#include -#include - -#include -#include - -class LvglDisplay : public Display { -public: - LvglDisplay(); - virtual ~LvglDisplay(); - - virtual void SetStatus(const char* status); - virtual void ShowNotification(const char* notification, int duration_ms = 3000); - virtual void ShowNotification(const std::string ¬ification, int duration_ms = 3000); - virtual void SetPreviewImage(std::unique_ptr image); - virtual void UpdateStatusBar(bool update_all = false); - virtual void SetPowerSaveMode(bool on); - virtual bool SnapshotToJpeg(std::string& jpeg_data, int quality = 80); - -protected: - esp_pm_lock_handle_t pm_lock_ = nullptr; - lv_display_t *display_ = nullptr; - - lv_obj_t *network_label_ = nullptr; - lv_obj_t *status_label_ = nullptr; - lv_obj_t *notification_label_ = nullptr; - lv_obj_t *mute_label_ = nullptr; - lv_obj_t *battery_label_ = nullptr; - lv_obj_t* low_battery_popup_ = nullptr; - lv_obj_t* low_battery_label_ = nullptr; - - const char* battery_icon_ = nullptr; - const char* network_icon_ = nullptr; - bool muted_ = false; - - std::chrono::system_clock::time_point last_status_update_time_; - esp_timer_handle_t notification_timer_ = nullptr; - - friend class DisplayLockGuard; - virtual bool Lock(int timeout_ms = 0) = 0; - virtual void Unlock() = 0; -}; - - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.cc deleted file mode 100644 index b0a45c70..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.cc +++ /dev/null @@ -1,13 +0,0 @@ -#include "lvgl_font.h" -#include - - -LvglCBinFont::LvglCBinFont(void* data) { - font_ = cbin_font_create(static_cast(data)); -} - -LvglCBinFont::~LvglCBinFont() { - if (font_ != nullptr) { - cbin_font_delete(font_); - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.h deleted file mode 100644 index d539dc01..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_font.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include - - -class LvglFont { -public: - virtual const lv_font_t* font() const = 0; - virtual ~LvglFont() = default; -}; - -// Built-in font -class LvglBuiltInFont : public LvglFont { -public: - LvglBuiltInFont(const lv_font_t* font) : font_(font) {} - virtual const lv_font_t* font() const override { return font_; } - -private: - const lv_font_t* font_; -}; - - -class LvglCBinFont : public LvglFont { -public: - LvglCBinFont(void* data); - virtual ~LvglCBinFont(); - virtual const lv_font_t* font() const override { return font_; } - -private: - lv_font_t* font_; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.cc deleted file mode 100644 index eefc0314..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.cc +++ /dev/null @@ -1,64 +0,0 @@ -#include "lvgl_image.h" -#include - -#include -#include -#include -#include - -#define TAG "LvglImage" - - -LvglRawImage::LvglRawImage(void* data, size_t size) { - bzero(&image_dsc_, sizeof(image_dsc_)); - image_dsc_.data_size = size; - image_dsc_.data = static_cast(data); - image_dsc_.header.magic = LV_IMAGE_HEADER_MAGIC; - image_dsc_.header.cf = LV_COLOR_FORMAT_RAW_ALPHA; - image_dsc_.header.w = 0; - image_dsc_.header.h = 0; -} - -bool LvglRawImage::IsGif() const { - auto ptr = (const uint8_t*)image_dsc_.data; - return ptr[0] == 'G' && ptr[1] == 'I' && ptr[2] == 'F'; -} - -LvglCBinImage::LvglCBinImage(void* data) { - image_dsc_ = cbin_img_dsc_create(static_cast(data)); -} - -LvglCBinImage::~LvglCBinImage() { - if (image_dsc_ != nullptr) { - cbin_img_dsc_delete(image_dsc_); - } -} - -LvglAllocatedImage::LvglAllocatedImage(void* data, size_t size) { - bzero(&image_dsc_, sizeof(image_dsc_)); - image_dsc_.data_size = size; - image_dsc_.data = static_cast(data); - - if (lv_image_decoder_get_info(&image_dsc_, &image_dsc_.header) != LV_RESULT_OK) { - ESP_LOGE(TAG, "Failed to get image info, data: %p size: %u", data, size); - throw std::runtime_error("Failed to get image info"); - } -} - -LvglAllocatedImage::LvglAllocatedImage(void* data, size_t size, int width, int height, int stride, int color_format) { - bzero(&image_dsc_, sizeof(image_dsc_)); - image_dsc_.data_size = size; - image_dsc_.data = static_cast(data); - image_dsc_.header.magic = LV_IMAGE_HEADER_MAGIC; - image_dsc_.header.cf = color_format; - image_dsc_.header.w = width; - image_dsc_.header.h = height; - image_dsc_.header.stride = stride; -} - -LvglAllocatedImage::~LvglAllocatedImage() { - if (image_dsc_.data) { - heap_caps_free((void*)image_dsc_.data); - image_dsc_.data = nullptr; - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.h deleted file mode 100644 index 0bbf39be..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_image.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include - - -// Wrap around lv_img_dsc_t -class LvglImage { -public: - virtual const lv_img_dsc_t* image_dsc() const = 0; - virtual bool IsGif() const { return false; } - virtual ~LvglImage() = default; -}; - - -class LvglRawImage : public LvglImage { -public: - LvglRawImage(void* data, size_t size); - virtual const lv_img_dsc_t* image_dsc() const override { return &image_dsc_; } - virtual bool IsGif() const; - -private: - lv_img_dsc_t image_dsc_; -}; - -class LvglCBinImage : public LvglImage { -public: - LvglCBinImage(void* data); - virtual ~LvglCBinImage(); - virtual const lv_img_dsc_t* image_dsc() const override { return image_dsc_; } - -private: - lv_img_dsc_t* image_dsc_ = nullptr; -}; - -class LvglSourceImage : public LvglImage { -public: - LvglSourceImage(const lv_img_dsc_t* image_dsc) : image_dsc_(image_dsc) {} - virtual const lv_img_dsc_t* image_dsc() const override { return image_dsc_; } - -private: - const lv_img_dsc_t* image_dsc_; -}; - -class LvglAllocatedImage : public LvglImage { -public: - LvglAllocatedImage(void* data, size_t size); - LvglAllocatedImage(void* data, size_t size, int width, int height, int stride, int color_format); - virtual ~LvglAllocatedImage(); - virtual const lv_img_dsc_t* image_dsc() const override { return &image_dsc_; } - -private: - lv_img_dsc_t image_dsc_; -}; \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.cc deleted file mode 100644 index f1bdffea..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include "lvgl_theme.h" - -LvglTheme::LvglTheme(const std::string& name) : Theme(name) { -} - -lv_color_t LvglTheme::ParseColor(const std::string& color) { - if (color.find("#") == 0) { - // Convert #112233 to lv_color_t - uint8_t r = strtol(color.substr(1, 2).c_str(), nullptr, 16); - uint8_t g = strtol(color.substr(3, 2).c_str(), nullptr, 16); - uint8_t b = strtol(color.substr(5, 2).c_str(), nullptr, 16); - return lv_color_make(r, g, b); - } - return lv_color_black(); -} - -LvglThemeManager::LvglThemeManager() { -} - -LvglTheme* LvglThemeManager::GetTheme(const std::string& theme_name) { - auto it = themes_.find(theme_name); - if (it != themes_.end()) { - return it->second; - } - return nullptr; -} - -void LvglThemeManager::RegisterTheme(const std::string& theme_name, LvglTheme* theme) { - themes_[theme_name] = theme; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.h deleted file mode 100644 index 85527a9a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/lvgl_display/lvgl_theme.h +++ /dev/null @@ -1,94 +0,0 @@ -#pragma once - -#include "display.h" -#include "lvgl_image.h" -#include "lvgl_font.h" -#include "emoji_collection.h" - -#include -#include -#include -#include - - -class LvglTheme : public Theme { -public: - static lv_color_t ParseColor(const std::string& color); - - LvglTheme(const std::string& name); - - // Properties - inline lv_color_t background_color() const { return background_color_; } - inline lv_color_t text_color() const { return text_color_; } - inline lv_color_t chat_background_color() const { return chat_background_color_; } - inline lv_color_t user_bubble_color() const { return user_bubble_color_; } - inline lv_color_t assistant_bubble_color() const { return assistant_bubble_color_; } - inline lv_color_t system_bubble_color() const { return system_bubble_color_; } - inline lv_color_t system_text_color() const { return system_text_color_; } - inline lv_color_t border_color() const { return border_color_; } - inline lv_color_t low_battery_color() const { return low_battery_color_; } - inline std::shared_ptr background_image() const { return background_image_; } - inline std::shared_ptr emoji_collection() const { return emoji_collection_; } - inline std::shared_ptr text_font() const { return text_font_; } - inline std::shared_ptr icon_font() const { return icon_font_; } - inline std::shared_ptr large_icon_font() const { return large_icon_font_; } - inline int spacing(int scale) const { return spacing_ * scale; } - - inline void set_background_color(lv_color_t background) { background_color_ = background; } - inline void set_text_color(lv_color_t text) { text_color_ = text; } - inline void set_chat_background_color(lv_color_t chat_background) { chat_background_color_ = chat_background; } - inline void set_user_bubble_color(lv_color_t user_bubble) { user_bubble_color_ = user_bubble; } - inline void set_assistant_bubble_color(lv_color_t assistant_bubble) { assistant_bubble_color_ = assistant_bubble; } - inline void set_system_bubble_color(lv_color_t system_bubble) { system_bubble_color_ = system_bubble; } - inline void set_system_text_color(lv_color_t system_text) { system_text_color_ = system_text; } - inline void set_border_color(lv_color_t border) { border_color_ = border; } - inline void set_low_battery_color(lv_color_t low_battery) { low_battery_color_ = low_battery; } - inline void set_background_image(std::shared_ptr background_image) { background_image_ = background_image; } - inline void set_emoji_collection(std::shared_ptr emoji_collection) { emoji_collection_ = emoji_collection; } - inline void set_text_font(std::shared_ptr text_font) { text_font_ = text_font; } - inline void set_icon_font(std::shared_ptr icon_font) { icon_font_ = icon_font; } - inline void set_large_icon_font(std::shared_ptr large_icon_font) { large_icon_font_ = large_icon_font; } - -private: - int spacing_ = 2; - - // Colors - lv_color_t background_color_; - lv_color_t text_color_; - lv_color_t chat_background_color_; - lv_color_t user_bubble_color_; - lv_color_t assistant_bubble_color_; - lv_color_t system_bubble_color_; - lv_color_t system_text_color_; - lv_color_t border_color_; - lv_color_t low_battery_color_; - - // Background image - std::shared_ptr background_image_ = nullptr; - - // fonts - std::shared_ptr text_font_ = nullptr; - std::shared_ptr icon_font_ = nullptr; - std::shared_ptr large_icon_font_ = nullptr; - - // Emoji collection - std::shared_ptr emoji_collection_ = nullptr; -}; - - -class LvglThemeManager { -public: - static LvglThemeManager& GetInstance() { - static LvglThemeManager instance; - return instance; - } - - void RegisterTheme(const std::string& theme_name, LvglTheme* theme); - LvglTheme* GetTheme(const std::string& theme_name); - -private: - LvglThemeManager(); - void InitializeDefaultThemes(); - - std::map themes_; -}; diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.cc deleted file mode 100644 index 74469148..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.cc +++ /dev/null @@ -1,396 +0,0 @@ -#include "oled_display.h" -#include "assets/lang_config.h" -#include "lvgl_theme.h" -#include "lvgl_font.h" - -#include -#include - -#include -#include -#include -#include - -#define TAG "OledDisplay" - -LV_FONT_DECLARE(BUILTIN_TEXT_FONT); -LV_FONT_DECLARE(BUILTIN_ICON_FONT); -LV_FONT_DECLARE(font_awesome_30_1); - -OledDisplay::OledDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, - int width, int height, bool mirror_x, bool mirror_y) - : panel_io_(panel_io), panel_(panel) { - width_ = width; - height_ = height; - - auto text_font = std::make_shared(&BUILTIN_TEXT_FONT); - auto icon_font = std::make_shared(&BUILTIN_ICON_FONT); - auto large_icon_font = std::make_shared(&font_awesome_30_1); - - auto dark_theme = new LvglTheme("dark"); - dark_theme->set_text_font(text_font); - dark_theme->set_icon_font(icon_font); - dark_theme->set_large_icon_font(large_icon_font); - - auto& theme_manager = LvglThemeManager::GetInstance(); - theme_manager.RegisterTheme("dark", dark_theme); - current_theme_ = dark_theme; - - ESP_LOGI(TAG, "Initialize LVGL"); - lvgl_port_cfg_t port_cfg = ESP_LVGL_PORT_INIT_CONFIG(); - port_cfg.task_priority = 1; - port_cfg.task_stack = 6144; -#if CONFIG_SOC_CPU_CORES_NUM > 1 - port_cfg.task_affinity = 1; -#endif - lvgl_port_init(&port_cfg); - - ESP_LOGI(TAG, "Adding OLED display"); - const lvgl_port_display_cfg_t display_cfg = { - .io_handle = panel_io_, - .panel_handle = panel_, - .control_handle = nullptr, - .buffer_size = static_cast(width_ * height_), - .double_buffer = false, - .trans_size = 0, - .hres = static_cast(width_), - .vres = static_cast(height_), - .monochrome = true, - .rotation = { - .swap_xy = false, - .mirror_x = mirror_x, - .mirror_y = mirror_y, - }, - .flags = { - .buff_dma = 1, - .buff_spiram = 0, - .sw_rotate = 0, - .full_refresh = 0, - .direct_mode = 0, - }, - }; - - display_ = lvgl_port_add_disp(&display_cfg); - if (display_ == nullptr) { - ESP_LOGE(TAG, "Failed to add display"); - return; - } - - if (height_ == 64) { - SetupUI_128x64(); - } else { - SetupUI_128x32(); - } -} - -OledDisplay::~OledDisplay() { - if (content_ != nullptr) { - lv_obj_del(content_); - } - - bool is_128x64_layout = (top_bar_ != nullptr); - if (status_bar_ != nullptr && is_128x64_layout) { - status_label_ = nullptr; - notification_label_ = nullptr; - lv_obj_del(status_bar_); - } - if (top_bar_ != nullptr) { - network_label_ = nullptr; - mute_label_ = nullptr; - battery_label_ = nullptr; - lv_obj_del(top_bar_); - } - if (side_bar_ != nullptr) { - if (!is_128x64_layout) { - status_label_ = nullptr; - notification_label_ = nullptr; - network_label_ = nullptr; - mute_label_ = nullptr; - battery_label_ = nullptr; - } - lv_obj_del(side_bar_); - } - if (container_ != nullptr) { - lv_obj_del(container_); - } - - if (panel_ != nullptr) { - esp_lcd_panel_del(panel_); - } - if (panel_io_ != nullptr) { - esp_lcd_panel_io_del(panel_io_); - } - lvgl_port_deinit(); -} - -bool OledDisplay::Lock(int timeout_ms) { - return lvgl_port_lock(timeout_ms); -} - -void OledDisplay::Unlock() { - lvgl_port_unlock(); -} - -void OledDisplay::SetChatMessage(const char* role, const char* content) { - DisplayLockGuard lock(this); - if (chat_message_label_ == nullptr) { - return; - } - - // Replace all newlines with spaces - std::string content_str = content; - std::replace(content_str.begin(), content_str.end(), '\n', ' '); - - if (content_right_ == nullptr) { - lv_label_set_text(chat_message_label_, content_str.c_str()); - } else { - if (content == nullptr || content[0] == '\0') { - lv_obj_add_flag(content_right_, LV_OBJ_FLAG_HIDDEN); - } else { - lv_label_set_text(chat_message_label_, content_str.c_str()); - lv_obj_remove_flag(content_right_, LV_OBJ_FLAG_HIDDEN); - } - } -} - -void OledDisplay::SetupUI_128x64() { - DisplayLockGuard lock(this); - - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - auto large_icon_font = lvgl_theme->large_icon_font()->font(); - - auto screen = lv_screen_active(); - lv_obj_set_style_text_font(screen, text_font, 0); - lv_obj_set_style_text_color(screen, lv_color_black(), 0); - - /* Container */ - container_ = lv_obj_create(screen); - lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); - lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(container_, 0, 0); - lv_obj_set_style_border_width(container_, 0, 0); - lv_obj_set_style_pad_row(container_, 0, 0); - - /* Layer 1: Top bar - for status icons */ - top_bar_ = lv_obj_create(container_); - lv_obj_set_size(top_bar_, LV_HOR_RES, 16); - lv_obj_set_style_radius(top_bar_, 0, 0); - lv_obj_set_style_bg_opa(top_bar_, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(top_bar_, 0, 0); - lv_obj_set_style_pad_all(top_bar_, 0, 0); - lv_obj_set_flex_flow(top_bar_, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(top_bar_, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - lv_obj_set_scrollbar_mode(top_bar_, LV_SCROLLBAR_MODE_OFF); - - network_label_ = lv_label_create(top_bar_); - lv_label_set_text(network_label_, ""); - lv_obj_set_style_text_font(network_label_, icon_font, 0); - - lv_obj_t* right_icons = lv_obj_create(top_bar_); - lv_obj_set_size(right_icons, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_set_style_bg_opa(right_icons, LV_OPA_TRANSP, 0); - lv_obj_set_style_border_width(right_icons, 0, 0); - lv_obj_set_style_pad_all(right_icons, 0, 0); - lv_obj_set_flex_flow(right_icons, LV_FLEX_FLOW_ROW); - lv_obj_set_flex_align(right_icons, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); - - mute_label_ = lv_label_create(right_icons); - lv_label_set_text(mute_label_, ""); - lv_obj_set_style_text_font(mute_label_, icon_font, 0); - - battery_label_ = lv_label_create(right_icons); - lv_label_set_text(battery_label_, ""); - lv_obj_set_style_text_font(battery_label_, icon_font, 0); - - /* Layer 2: Status bar - for center text labels */ - status_bar_ = lv_obj_create(screen); - lv_obj_set_size(status_bar_, LV_HOR_RES, 16); - lv_obj_set_style_radius(status_bar_, 0, 0); - lv_obj_set_style_bg_opa(status_bar_, LV_OPA_TRANSP, 0); // Transparent background - lv_obj_set_style_border_width(status_bar_, 0, 0); - lv_obj_set_style_pad_all(status_bar_, 0, 0); - lv_obj_set_scrollbar_mode(status_bar_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_layout(status_bar_, LV_LAYOUT_NONE, 0); // Use absolute positioning - lv_obj_align(status_bar_, LV_ALIGN_TOP_MID, 0, 0); // Overlap with top_bar_ - - notification_label_ = lv_label_create(status_bar_); - lv_obj_set_width(notification_label_, LV_HOR_RES); - lv_obj_set_style_text_align(notification_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_label_set_text(notification_label_, ""); - lv_obj_align(notification_label_, LV_ALIGN_CENTER, 0, 0); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - status_label_ = lv_label_create(status_bar_); - lv_obj_set_width(status_label_, LV_HOR_RES); - lv_label_set_long_mode(status_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_style_text_align(status_label_, LV_TEXT_ALIGN_CENTER, 0); - lv_label_set_text(status_label_, Lang::Strings::INITIALIZING); - lv_obj_align(status_label_, LV_ALIGN_CENTER, 0, 0); - - /* Content */ - content_ = lv_obj_create(container_); - lv_obj_set_scrollbar_mode(content_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_style_radius(content_, 0, 0); - lv_obj_set_style_pad_all(content_, 0, 0); - lv_obj_set_width(content_, LV_HOR_RES); - lv_obj_set_flex_grow(content_, 1); - lv_obj_set_flex_flow(content_, LV_FLEX_FLOW_ROW); - lv_obj_set_style_flex_main_place(content_, LV_FLEX_ALIGN_CENTER, 0); - - content_left_ = lv_obj_create(content_); - lv_obj_set_size(content_left_, 32, LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(content_left_, 0, 0); - lv_obj_set_style_border_width(content_left_, 0, 0); - - emotion_label_ = lv_label_create(content_left_); - lv_obj_set_style_text_font(emotion_label_, large_icon_font, 0); - lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI); - lv_obj_center(emotion_label_); - lv_obj_set_style_pad_top(emotion_label_, 8, 0); - - content_right_ = lv_obj_create(content_); - lv_obj_set_size(content_right_, LV_SIZE_CONTENT, LV_SIZE_CONTENT); - lv_obj_set_style_pad_all(content_right_, 0, 0); - lv_obj_set_style_border_width(content_right_, 0, 0); - lv_obj_set_flex_grow(content_right_, 1); - lv_obj_add_flag(content_right_, LV_OBJ_FLAG_HIDDEN); - - chat_message_label_ = lv_label_create(content_right_); - lv_label_set_text(chat_message_label_, ""); - lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_style_text_align(chat_message_label_, LV_TEXT_ALIGN_LEFT, 0); - lv_obj_set_width(chat_message_label_, width_ - 32); - lv_obj_set_style_pad_top(chat_message_label_, 14, 0); - - // Start scrolling subtitle after a delay - static lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_delay(&a, 1000); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); - lv_obj_set_style_anim(chat_message_label_, &a, LV_PART_MAIN); - lv_obj_set_style_anim_duration(chat_message_label_, lv_anim_speed_clamped(60, 300, 60000), LV_PART_MAIN); - - low_battery_popup_ = lv_obj_create(screen); - lv_obj_set_scrollbar_mode(low_battery_popup_, LV_SCROLLBAR_MODE_OFF); - lv_obj_set_size(low_battery_popup_, LV_HOR_RES * 0.9, text_font->line_height * 2); - lv_obj_align(low_battery_popup_, LV_ALIGN_BOTTOM_MID, 0, 0); - lv_obj_set_style_bg_color(low_battery_popup_, lv_color_black(), 0); - lv_obj_set_style_radius(low_battery_popup_, 10, 0); - low_battery_label_ = lv_label_create(low_battery_popup_); - lv_label_set_text(low_battery_label_, Lang::Strings::BATTERY_NEED_CHARGE); - lv_obj_set_style_text_color(low_battery_label_, lv_color_white(), 0); - lv_obj_center(low_battery_label_); - lv_obj_add_flag(low_battery_popup_, LV_OBJ_FLAG_HIDDEN); -} - -void OledDisplay::SetupUI_128x32() { - DisplayLockGuard lock(this); - - auto lvgl_theme = static_cast(current_theme_); - auto text_font = lvgl_theme->text_font()->font(); - auto icon_font = lvgl_theme->icon_font()->font(); - auto large_icon_font = lvgl_theme->large_icon_font()->font(); - - auto screen = lv_screen_active(); - lv_obj_set_style_text_font(screen, text_font, 0); - - /* Container */ - container_ = lv_obj_create(screen); - lv_obj_set_size(container_, LV_HOR_RES, LV_VER_RES); - lv_obj_set_flex_flow(container_, LV_FLEX_FLOW_ROW); - lv_obj_set_style_pad_all(container_, 0, 0); - lv_obj_set_style_border_width(container_, 0, 0); - lv_obj_set_style_pad_column(container_, 0, 0); - - /* Emotion label on the left side */ - content_ = lv_obj_create(container_); - lv_obj_set_size(content_, 32, 32); - lv_obj_set_style_pad_all(content_, 0, 0); - lv_obj_set_style_border_width(content_, 0, 0); - lv_obj_set_style_radius(content_, 0, 0); - - emotion_label_ = lv_label_create(content_); - lv_obj_set_style_text_font(emotion_label_, large_icon_font, 0); - lv_label_set_text(emotion_label_, FONT_AWESOME_MICROCHIP_AI); - lv_obj_center(emotion_label_); - - /* Right side */ - side_bar_ = lv_obj_create(container_); - lv_obj_set_size(side_bar_, width_ - 32, 32); - lv_obj_set_flex_flow(side_bar_, LV_FLEX_FLOW_COLUMN); - lv_obj_set_style_pad_all(side_bar_, 0, 0); - lv_obj_set_style_border_width(side_bar_, 0, 0); - lv_obj_set_style_radius(side_bar_, 0, 0); - lv_obj_set_style_pad_row(side_bar_, 0, 0); - - /* Status bar */ - status_bar_ = lv_obj_create(side_bar_); - lv_obj_set_size(status_bar_, width_ - 32, 16); - lv_obj_set_style_radius(status_bar_, 0, 0); - lv_obj_set_flex_flow(status_bar_, LV_FLEX_FLOW_ROW); - lv_obj_set_style_pad_all(status_bar_, 0, 0); - lv_obj_set_style_border_width(status_bar_, 0, 0); - lv_obj_set_style_pad_column(status_bar_, 0, 0); - - status_label_ = lv_label_create(status_bar_); - lv_obj_set_flex_grow(status_label_, 1); - lv_obj_set_style_pad_left(status_label_, 2, 0); - lv_label_set_text(status_label_, Lang::Strings::INITIALIZING); - - notification_label_ = lv_label_create(status_bar_); - lv_obj_set_flex_grow(notification_label_, 1); - lv_obj_set_style_pad_left(notification_label_, 2, 0); - lv_label_set_text(notification_label_, ""); - lv_obj_add_flag(notification_label_, LV_OBJ_FLAG_HIDDEN); - - mute_label_ = lv_label_create(status_bar_); - lv_label_set_text(mute_label_, ""); - lv_obj_set_style_text_font(mute_label_, icon_font, 0); - - network_label_ = lv_label_create(status_bar_); - lv_label_set_text(network_label_, ""); - lv_obj_set_style_text_font(network_label_, icon_font, 0); - - battery_label_ = lv_label_create(status_bar_); - lv_label_set_text(battery_label_, ""); - lv_obj_set_style_text_font(battery_label_, icon_font, 0); - - chat_message_label_ = lv_label_create(side_bar_); - lv_obj_set_size(chat_message_label_, width_ - 32, LV_SIZE_CONTENT); - lv_obj_set_style_pad_left(chat_message_label_, 2, 0); - lv_label_set_long_mode(chat_message_label_, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_label_set_text(chat_message_label_, ""); - - // Start scrolling subtitle after a delay - static lv_anim_t a; - lv_anim_init(&a); - lv_anim_set_delay(&a, 1000); - lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); - lv_obj_set_style_anim(chat_message_label_, &a, LV_PART_MAIN); - lv_obj_set_style_anim_duration(chat_message_label_, lv_anim_speed_clamped(60, 300, 60000), LV_PART_MAIN); -} - -void OledDisplay::SetEmotion(const char* emotion) { - const char* utf8 = font_awesome_get_utf8(emotion); - DisplayLockGuard lock(this); - if (emotion_label_ == nullptr) { - return; - } - if (utf8 != nullptr) { - lv_label_set_text(emotion_label_, utf8); - } else { - lv_label_set_text(emotion_label_, FONT_AWESOME_NEUTRAL); - } -} - -void OledDisplay::SetTheme(Theme* theme) { - DisplayLockGuard lock(this); - - auto lvgl_theme = static_cast(theme); - auto text_font = lvgl_theme->text_font()->font(); - - auto screen = lv_screen_active(); - lv_obj_set_style_text_font(screen, text_font, 0); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.h deleted file mode 100644 index c7f40779..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/display/oled_display.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef OLED_DISPLAY_H -#define OLED_DISPLAY_H - -#include "lvgl_display.h" - -#include -#include - - -class OledDisplay : public LvglDisplay { -private: - esp_lcd_panel_io_handle_t panel_io_ = nullptr; - esp_lcd_panel_handle_t panel_ = nullptr; - - lv_obj_t* top_bar_ = nullptr; - lv_obj_t* status_bar_ = nullptr; - lv_obj_t* content_ = nullptr; - lv_obj_t* content_left_ = nullptr; - lv_obj_t* content_right_ = nullptr; - lv_obj_t* container_ = nullptr; - lv_obj_t* side_bar_ = nullptr; - lv_obj_t *emotion_label_ = nullptr; - lv_obj_t* chat_message_label_ = nullptr; - - virtual bool Lock(int timeout_ms = 0) override; - virtual void Unlock() override; - - void SetupUI_128x64(); - void SetupUI_128x32(); - -public: - OledDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, bool mirror_x, bool mirror_y); - ~OledDisplay(); - - virtual void SetChatMessage(const char* role, const char* content) override; - virtual void SetEmotion(const char* emotion) override; - virtual void SetTheme(Theme* theme) override; -}; - -#endif // OLED_DISPLAY_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/idf_component.yml b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/idf_component.yml deleted file mode 100644 index bd674aa3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/idf_component.yml +++ /dev/null @@ -1,110 +0,0 @@ -## IDF Component Manager Manifest File -dependencies: - waveshare/esp_lcd_sh8601: 1.0.2 - espressif/esp_lcd_ili9341: ==1.2.0 - espressif/esp_lcd_gc9a01: ==2.0.1 - espressif/esp_lcd_st77916: ^1.0.1 - espressif/esp_lcd_axs15231b: ^1.0.0 - - espressif/esp_lcd_st7701: - version: ^1.1.4 - rules: - - if: target in [esp32s3, esp32p4] - espressif/esp_lcd_st7796: - version: 1.3.5 - rules: - - if: target in [esp32, esp32s2, esp32s3, esp32p4] - espressif/esp_lcd_spd2010: ==1.0.2 - espressif/esp_io_expander_tca9554: ==2.0.0 - espressif/esp_lcd_panel_io_additions: ^1.0.1 - 78/esp_lcd_nv3023: ~1.0.0 - 78/esp-wifi-connect: ~3.0.2 - 78/esp-opus-encoder: ~2.4.1 - 78/esp-ml307: ~3.5.3 - 78/xiaozhi-fonts: ~1.5.5 - espressif/led_strip: ~3.0.1 - espressif/esp_codec_dev: ~1.5 - espressif/esp-sr: ~2.2.0 - espressif/button: ~4.1.3 - espressif/knob: ^1.0.0 - espressif/esp_video: - version: ==1.3.1 # for compatibility. update version may need to modify this project code. - rules: - - if: target not in [esp32] - espressif/esp_image_effects: - version: ^1.0.1 - rules: - - if: target not in [esp32] - espressif/esp_lcd_touch_ft5x06: ~1.0.7 - espressif/esp_lcd_touch_gt911: ^1 - espressif/esp_lcd_touch_gt1151: ^1 - waveshare/esp_lcd_touch_cst9217: ^1.0.3 - espressif/esp_lcd_touch_cst816s: ^1.0.6 - lvgl/lvgl: ~9.3.0 - esp_lvgl_port: ~2.6.0 - espressif/esp_io_expander_tca95xx_16bit: ^2.0.0 - espressif2022/image_player: ^1.1.1 - espressif2022/esp_emote_gfx: ==2.0.0 - espressif/adc_mic: ^0.2.1 - espressif/esp_mmap_assets: '>=1.2' - txp666/otto-emoji-gif-component: - version: ^1.0.3 - rules: - - if: target in [esp32s3] - espressif/adc_battery_estimation: ^0.2.0 - espressif/esp_new_jpeg: ^0.6.1 - - # SenseCAP Watcher Board - wvirgil123/sscma_client: - version: 1.0.2 - rules: - - if: target in [esp32s3] - - tny-robotics/sh1106-esp-idf: ^1.0.0 - waveshare/esp_lcd_jd9365_10_1: - version: '*' - rules: - - if: target in [esp32p4] - waveshare/esp_lcd_st7703: - version: '*' - rules: - - if: target in [esp32p4] - espressif/esp32_p4_function_ev_board: - version: ^5.0.3 - rules: - - if: target in [esp32p4] - espressif/esp_lcd_ili9881c: - version: ^1.0.1 - rules: - - if: target in [esp32p4] - espressif/esp_lcd_ek79007: - version: ^1.0.3 - rules: - - if: target in [esp32p4] - espressif/esp_hosted: - version: 2.0.17 - rules: - - if: target in [esp32h2, esp32p4] - espressif/esp_wifi_remote: - version: '*' - rules: - - if: target in [esp32p4] - espfriends/servo_dog_ctrl: - version: ^0.1.8 - rules: - - if: target in [esp32c3] - - llgok/cpp_bus_driver: - version: 1.1.0 - rules: - - if: target in [esp32p4] - - espressif/bmi270_sensor: - version: ^0.1.0 - rules: - - if: target in [esp32s3, esp32c5] - - ## Required IDF version - idf: - version: '>=5.4.0' - espressif/esp_lcd_touch_st7123: ^1.0.0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.cc deleted file mode 100644 index cb428ad3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.cc +++ /dev/null @@ -1,233 +0,0 @@ -#include "circular_strip.h" -#include "application.h" -#include - -#define TAG "CircularStrip" - -#define BLINK_INFINITE -1 - -CircularStrip::CircularStrip(gpio_num_t gpio, uint8_t max_leds) : max_leds_(max_leds) { - // If the gpio is not connected, you should use NoLed class - assert(gpio != GPIO_NUM_NC); - - colors_.resize(max_leds_); - - led_strip_config_t strip_config = {}; - strip_config.strip_gpio_num = gpio; - strip_config.max_leds = max_leds_; - strip_config.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB; - strip_config.led_model = LED_MODEL_WS2812; - - led_strip_rmt_config_t rmt_config = {}; - rmt_config.resolution_hz = 10 * 1000 * 1000; // 10MHz - - ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip_)); - led_strip_clear(led_strip_); - - esp_timer_create_args_t strip_timer_args = { - .callback = [](void *arg) { - auto strip = static_cast(arg); - std::lock_guard lock(strip->mutex_); - if (strip->strip_callback_ != nullptr) { - strip->strip_callback_(); - } - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "strip_timer", - .skip_unhandled_events = false, - }; - ESP_ERROR_CHECK(esp_timer_create(&strip_timer_args, &strip_timer_)); -} - -CircularStrip::~CircularStrip() { - esp_timer_stop(strip_timer_); - if (led_strip_ != nullptr) { - led_strip_del(led_strip_); - } -} - - -void CircularStrip::SetAllColor(StripColor color) { - std::lock_guard lock(mutex_); - esp_timer_stop(strip_timer_); - for (int i = 0; i < max_leds_; i++) { - colors_[i] = color; - led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue); - } - led_strip_refresh(led_strip_); -} - -void CircularStrip::SetSingleColor(uint8_t index, StripColor color) { - std::lock_guard lock(mutex_); - esp_timer_stop(strip_timer_); - colors_[index] = color; - led_strip_set_pixel(led_strip_, index, color.red, color.green, color.blue); - led_strip_refresh(led_strip_); -} - -void CircularStrip::Blink(StripColor color, int interval_ms) { - for (int i = 0; i < max_leds_; i++) { - colors_[i] = color; - } - StartStripTask(interval_ms, [this]() { - static bool on = true; - if (on) { - for (int i = 0; i < max_leds_; i++) { - led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue); - } - led_strip_refresh(led_strip_); - } else { - led_strip_clear(led_strip_); - } - on = !on; - }); -} - -void CircularStrip::FadeOut(int interval_ms) { - StartStripTask(interval_ms, [this]() { - bool all_off = true; - for (int i = 0; i < max_leds_; i++) { - colors_[i].red /= 2; - colors_[i].green /= 2; - colors_[i].blue /= 2; - if (colors_[i].red != 0 || colors_[i].green != 0 || colors_[i].blue != 0) { - all_off = false; - } - led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue); - } - if (all_off) { - led_strip_clear(led_strip_); - esp_timer_stop(strip_timer_); - } else { - led_strip_refresh(led_strip_); - } - }); -} - -void CircularStrip::Breathe(StripColor low, StripColor high, int interval_ms) { - StartStripTask(interval_ms, [this, low, high]() { - static bool increase = true; - static StripColor color = low; - if (increase) { - if (color.red < high.red) { - color.red++; - } - if (color.green < high.green) { - color.green++; - } - if (color.blue < high.blue) { - color.blue++; - } - if (color.red == high.red && color.green == high.green && color.blue == high.blue) { - increase = false; - } - } else { - if (color.red > low.red) { - color.red--; - } - if (color.green > low.green) { - color.green--; - } - if (color.blue > low.blue) { - color.blue--; - } - if (color.red == low.red && color.green == low.green && color.blue == low.blue) { - increase = true; - } - } - for (int i = 0; i < max_leds_; i++) { - led_strip_set_pixel(led_strip_, i, color.red, color.green, color.blue); - } - led_strip_refresh(led_strip_); - }); -} - -void CircularStrip::Scroll(StripColor low, StripColor high, int length, int interval_ms) { - for (int i = 0; i < max_leds_; i++) { - colors_[i] = low; - } - StartStripTask(interval_ms, [this, low, high, length]() { - static int offset = 0; - for (int i = 0; i < max_leds_; i++) { - colors_[i] = low; - } - for (int j = 0; j < length; j++) { - int i = (offset + j) % max_leds_; - colors_[i] = high; - } - for (int i = 0; i < max_leds_; i++) { - led_strip_set_pixel(led_strip_, i, colors_[i].red, colors_[i].green, colors_[i].blue); - } - led_strip_refresh(led_strip_); - offset = (offset + 1) % max_leds_; - }); -} - -void CircularStrip::StartStripTask(int interval_ms, std::function cb) { - if (led_strip_ == nullptr) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(strip_timer_); - - strip_callback_ = cb; - esp_timer_start_periodic(strip_timer_, interval_ms * 1000); -} - -void CircularStrip::SetBrightness(uint8_t default_brightness, uint8_t low_brightness) { - default_brightness_ = default_brightness; - low_brightness_ = low_brightness; - OnStateChanged(); -} - -void CircularStrip::OnStateChanged() { - auto& app = Application::GetInstance(); - auto device_state = app.GetDeviceState(); - switch (device_state) { - case kDeviceStateStarting: { - StripColor low = { 0, 0, 0 }; - StripColor high = { low_brightness_, low_brightness_, default_brightness_ }; - Scroll(low, high, 3, 100); - break; - } - case kDeviceStateWifiConfiguring: { - StripColor color = { low_brightness_, low_brightness_, default_brightness_ }; - Blink(color, 500); - break; - } - case kDeviceStateIdle: - FadeOut(50); - break; - case kDeviceStateConnecting: { - StripColor color = { low_brightness_, low_brightness_, default_brightness_ }; - SetAllColor(color); - break; - } - case kDeviceStateListening: - case kDeviceStateAudioTesting: { - StripColor color = { default_brightness_, low_brightness_, low_brightness_ }; - SetAllColor(color); - break; - } - case kDeviceStateSpeaking: { - StripColor color = { low_brightness_, default_brightness_, low_brightness_ }; - SetAllColor(color); - break; - } - case kDeviceStateUpgrading: { - StripColor color = { low_brightness_, default_brightness_, low_brightness_ }; - Blink(color, 100); - break; - } - case kDeviceStateActivating: { - StripColor color = { low_brightness_, default_brightness_, low_brightness_ }; - Blink(color, 500); - break; - } - default: - ESP_LOGW(TAG, "Unknown led strip event: %d", device_state); - return; - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.h deleted file mode 100644 index d5d6c225..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/circular_strip.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _CIRCULAR_STRIP_H_ -#define _CIRCULAR_STRIP_H_ - -#include "led.h" -#include -#include -#include -#include -#include -#include - -#define DEFAULT_BRIGHTNESS 32 -#define LOW_BRIGHTNESS 4 - -struct StripColor { - uint8_t red = 0, green = 0, blue = 0; -}; - -class CircularStrip : public Led { -public: - CircularStrip(gpio_num_t gpio, uint8_t max_leds); - virtual ~CircularStrip(); - - void OnStateChanged() override; - void SetBrightness(uint8_t default_brightness, uint8_t low_brightness); - void SetAllColor(StripColor color); - void SetSingleColor(uint8_t index, StripColor color); - void Blink(StripColor color, int interval_ms); - void Breathe(StripColor low, StripColor high, int interval_ms); - void Scroll(StripColor low, StripColor high, int length, int interval_ms); - -private: - std::mutex mutex_; - TaskHandle_t blink_task_ = nullptr; - led_strip_handle_t led_strip_ = nullptr; - int max_leds_ = 0; - std::vector colors_; - int blink_counter_ = 0; - int blink_interval_ms_ = 0; - esp_timer_handle_t strip_timer_ = nullptr; - std::function strip_callback_ = nullptr; - - uint8_t default_brightness_ = DEFAULT_BRIGHTNESS; - uint8_t low_brightness_ = LOW_BRIGHTNESS; - - void StartStripTask(int interval_ms, std::function cb); - void Rainbow(StripColor low, StripColor high, int interval_ms); - void FadeOut(int interval_ms); -}; - -#endif // _CIRCULAR_STRIP_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.cc deleted file mode 100644 index 30eeeb20..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.cc +++ /dev/null @@ -1,263 +0,0 @@ -#include "gpio_led.h" -#include "application.h" -#include "device_state.h" -#include - -#define TAG "GpioLed" - -#define DEFAULT_BRIGHTNESS 50 -#define HIGH_BRIGHTNESS 100 -#define LOW_BRIGHTNESS 10 - -#define IDLE_BRIGHTNESS 5 -#define SPEAKING_BRIGHTNESS 75 -#define UPGRADING_BRIGHTNESS 25 -#define ACTIVATING_BRIGHTNESS 35 - -#define BLINK_INFINITE -1 - -// GPIO_LED -#define LEDC_LS_TIMER LEDC_TIMER_1 -#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE -#define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0 - -#define LEDC_DUTY (8191) -#define LEDC_FADE_TIME (1000) -// GPIO_LED - -GpioLed::GpioLed(gpio_num_t gpio) - : GpioLed(gpio, 0, LEDC_LS_TIMER, LEDC_LS_CH0_CHANNEL) { -} - -GpioLed::GpioLed(gpio_num_t gpio, int output_invert) - : GpioLed(gpio, output_invert, LEDC_LS_TIMER, LEDC_LS_CH0_CHANNEL) { -} - -GpioLed::GpioLed(gpio_num_t gpio, int output_invert, ledc_timer_t timer_num, ledc_channel_t channel) { - // If the gpio is not connected, you should use NoLed class - assert(gpio != GPIO_NUM_NC); - - /* - * Prepare and set configuration of timers - * that will be used by LED Controller - */ - ledc_timer_config_t ledc_timer = {}; - ledc_timer.duty_resolution = LEDC_TIMER_13_BIT; // resolution of PWM duty - ledc_timer.freq_hz = 4000; // frequency of PWM signal - ledc_timer.speed_mode = LEDC_LS_MODE; // timer mode - ledc_timer.timer_num = timer_num; // timer index - ledc_timer.clk_cfg = LEDC_AUTO_CLK; // Auto select the source clock - - ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); - - ledc_channel_.channel = channel, - ledc_channel_.duty = 0, - ledc_channel_.gpio_num = gpio, - ledc_channel_.speed_mode = LEDC_LS_MODE, - ledc_channel_.hpoint = 0, - ledc_channel_.timer_sel = timer_num, - ledc_channel_.flags.output_invert = output_invert & 0x01, - - // Set LED Controller with previously prepared configuration - ledc_channel_config(&ledc_channel_); - - // Initialize fade service. - ledc_fade_func_install(0); - - // When the callback registered by ledc_cb_degister is called, run led ->OnFadeEnd() - ledc_cbs_t ledc_callbacks = { - .fade_cb = FadeCallback - }; - ledc_cb_register(ledc_channel_.speed_mode, ledc_channel_.channel, &ledc_callbacks, this); - - esp_timer_create_args_t blink_timer_args = { - .callback = [](void *arg) { - auto led = static_cast(arg); - led->OnBlinkTimer(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "Blink Timer", - .skip_unhandled_events = false, - }; - ESP_ERROR_CHECK(esp_timer_create(&blink_timer_args, &blink_timer_)); - - xTaskCreate(EventTask, "LedEvent", 2048, this, - tskIDLE_PRIORITY + 2, &event_task_handle_); - - ledc_initialized_ = true; -} - -GpioLed::~GpioLed() { - esp_timer_stop(blink_timer_); - if (ledc_initialized_) { - ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel); - ledc_fade_func_uninstall(); - } -} - - -void GpioLed::SetBrightness(uint8_t brightness) { - if (brightness == 100) { - duty_ = LEDC_DUTY; - } else { - duty_ = brightness * LEDC_DUTY / 100; - } -} - -void GpioLed::TurnOn() { - if (!ledc_initialized_) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel); - ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_); - ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel); -} - -void GpioLed::TurnOff() { - if (!ledc_initialized_) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel); - ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0); - ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel); -} - -void GpioLed::BlinkOnce() { - Blink(1, 100); -} - -void GpioLed::Blink(int times, int interval_ms) { - StartBlinkTask(times, interval_ms); -} - -void GpioLed::StartContinuousBlink(int interval_ms) { - StartBlinkTask(BLINK_INFINITE, interval_ms); -} - -void GpioLed::StartBlinkTask(int times, int interval_ms) { - if (!ledc_initialized_) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel); - - blink_counter_ = times * 2; - blink_interval_ms_ = interval_ms; - esp_timer_start_periodic(blink_timer_, interval_ms * 1000); -} - -void GpioLed::OnBlinkTimer() { - std::lock_guard lock(mutex_); - blink_counter_--; - if (blink_counter_ & 1) { - ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_); - } else { - ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0); - - if (blink_counter_ == 0) { - esp_timer_stop(blink_timer_); - } - } - ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel); -} - -void GpioLed::StartFadeTask() { - if (!ledc_initialized_) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel); - fade_up_ = true; - ledc_set_fade_with_time(ledc_channel_.speed_mode, - ledc_channel_.channel, LEDC_DUTY, LEDC_FADE_TIME); - ledc_fade_start(ledc_channel_.speed_mode, - ledc_channel_.channel, LEDC_FADE_NO_WAIT); -} - -void GpioLed::OnFadeEnd() { - std::lock_guard lock(mutex_); - fade_up_ = !fade_up_; - ledc_set_fade_with_time(ledc_channel_.speed_mode, - ledc_channel_.channel, fade_up_ ? LEDC_DUTY : 0, LEDC_FADE_TIME); - ledc_fade_start(ledc_channel_.speed_mode, - ledc_channel_.channel, LEDC_FADE_NO_WAIT); -} - -bool IRAM_ATTR GpioLed::FadeCallback(const ledc_cb_param_t *param, void *user_arg) { - if (param->event == LEDC_FADE_END_EVT) { - auto led = static_cast(user_arg); - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - xTaskNotifyFromISR(led->event_task_handle_, 0x01, eSetValueWithOverwrite, - &xHigherPriorityTaskWoken); - } - return true; -} - -void GpioLed::OnStateChanged() { - auto& app = Application::GetInstance(); - auto device_state = app.GetDeviceState(); - switch (device_state) { - case kDeviceStateStarting: - SetBrightness(DEFAULT_BRIGHTNESS); - StartContinuousBlink(100); - break; - case kDeviceStateWifiConfiguring: - SetBrightness(DEFAULT_BRIGHTNESS); - StartContinuousBlink(500); - break; - case kDeviceStateIdle: - SetBrightness(IDLE_BRIGHTNESS); - TurnOn(); - // TurnOff(); - break; - case kDeviceStateConnecting: - SetBrightness(DEFAULT_BRIGHTNESS); - TurnOn(); - break; - case kDeviceStateListening: - case kDeviceStateAudioTesting: - if (app.IsVoiceDetected()) { - SetBrightness(HIGH_BRIGHTNESS); - } else { - SetBrightness(LOW_BRIGHTNESS); - } - // TurnOn(); - StartFadeTask(); - break; - case kDeviceStateSpeaking: - SetBrightness(SPEAKING_BRIGHTNESS); - TurnOn(); - break; - case kDeviceStateUpgrading: - SetBrightness(UPGRADING_BRIGHTNESS); - StartContinuousBlink(100); - break; - case kDeviceStateActivating: - SetBrightness(ACTIVATING_BRIGHTNESS); - StartContinuousBlink(500); - break; - default: - ESP_LOGE(TAG, "Unknown gpio led event: %d", device_state); - return; - } -} - -void GpioLed::EventTask(void* arg) { - GpioLed* led = static_cast(arg); - - while (1) { - ulTaskNotifyTake(pdTRUE, portMAX_DELAY); - led->OnFadeEnd(); - } -} \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.h deleted file mode 100644 index 390d23c6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/gpio_led.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef _GPIO_LED_H_ -#define _GPIO_LED_H_ - -#include -#include -#include "led.h" -#include -#include -#include -#include -#include - -class GpioLed : public Led { - public: - GpioLed(gpio_num_t gpio); - GpioLed(gpio_num_t gpio, int output_invert); - GpioLed(gpio_num_t gpio, int output_invert, ledc_timer_t timer_num, ledc_channel_t channel); - virtual ~GpioLed(); - - void OnStateChanged() override; - void TurnOn(); - void TurnOff(); - void SetBrightness(uint8_t brightness); - - private: - std::mutex mutex_; - TaskHandle_t blink_task_ = nullptr; - ledc_channel_config_t ledc_channel_ = {0}; - bool ledc_initialized_ = false; - uint32_t duty_ = 0; - int blink_counter_ = 0; - int blink_interval_ms_ = 0; - esp_timer_handle_t blink_timer_ = nullptr; - bool fade_up_ = true; - TaskHandle_t event_task_handle_; - - static void EventTask(void* arg); - void StartBlinkTask(int times, int interval_ms); - void OnBlinkTimer(); - - void BlinkOnce(); - void Blink(int times, int interval_ms); - void StartContinuousBlink(int interval_ms); - void StartFadeTask(); - void OnFadeEnd(); - static bool IRAM_ATTR FadeCallback(const ledc_cb_param_t *param, void *user_arg); -}; - -#endif // _GPIO_LED_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/led.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/led.h deleted file mode 100644 index 251fd6a4..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/led.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _LED_H_ -#define _LED_H_ - -class Led { -public: - virtual ~Led() = default; - // Set the led state based on the device state - virtual void OnStateChanged() = 0; -}; - - -class NoLed : public Led { -public: - virtual void OnStateChanged() override {} -}; - -#endif // _LED_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.cc deleted file mode 100644 index 338af0ab..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.cc +++ /dev/null @@ -1,163 +0,0 @@ -#include "single_led.h" -#include "application.h" -#include - -#define TAG "SingleLed" - -#define DEFAULT_BRIGHTNESS 4 -#define HIGH_BRIGHTNESS 16 -#define LOW_BRIGHTNESS 2 - -#define BLINK_INFINITE -1 - - -SingleLed::SingleLed(gpio_num_t gpio) { - // If the gpio is not connected, you should use NoLed class - assert(gpio != GPIO_NUM_NC); - - led_strip_config_t strip_config = {}; - strip_config.strip_gpio_num = gpio; - strip_config.max_leds = 1; - strip_config.color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB; - strip_config.led_model = LED_MODEL_WS2812; - - led_strip_rmt_config_t rmt_config = {}; - rmt_config.resolution_hz = 10 * 1000 * 1000; // 10MHz - - ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &led_strip_)); - led_strip_clear(led_strip_); - - esp_timer_create_args_t blink_timer_args = { - .callback = [](void *arg) { - auto led = static_cast(arg); - led->OnBlinkTimer(); - }, - .arg = this, - .dispatch_method = ESP_TIMER_TASK, - .name = "blink_timer", - .skip_unhandled_events = false, - }; - ESP_ERROR_CHECK(esp_timer_create(&blink_timer_args, &blink_timer_)); -} - -SingleLed::~SingleLed() { - esp_timer_stop(blink_timer_); - if (led_strip_ != nullptr) { - led_strip_del(led_strip_); - } -} - - -void SingleLed::SetColor(uint8_t r, uint8_t g, uint8_t b) { - r_ = r; - g_ = g; - b_ = b; -} - -void SingleLed::TurnOn() { - if (led_strip_ == nullptr) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - led_strip_set_pixel(led_strip_, 0, r_, g_, b_); - led_strip_refresh(led_strip_); -} - -void SingleLed::TurnOff() { - if (led_strip_ == nullptr) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - led_strip_clear(led_strip_); -} - -void SingleLed::BlinkOnce() { - Blink(1, 100); -} - -void SingleLed::Blink(int times, int interval_ms) { - StartBlinkTask(times, interval_ms); -} - -void SingleLed::StartContinuousBlink(int interval_ms) { - StartBlinkTask(BLINK_INFINITE, interval_ms); -} - -void SingleLed::StartBlinkTask(int times, int interval_ms) { - if (led_strip_ == nullptr) { - return; - } - - std::lock_guard lock(mutex_); - esp_timer_stop(blink_timer_); - - blink_counter_ = times * 2; - blink_interval_ms_ = interval_ms; - esp_timer_start_periodic(blink_timer_, interval_ms * 1000); -} - -void SingleLed::OnBlinkTimer() { - std::lock_guard lock(mutex_); - blink_counter_--; - if (blink_counter_ & 1) { - led_strip_set_pixel(led_strip_, 0, r_, g_, b_); - led_strip_refresh(led_strip_); - } else { - led_strip_clear(led_strip_); - - if (blink_counter_ == 0) { - esp_timer_stop(blink_timer_); - } - } -} - - -void SingleLed::OnStateChanged() { - auto& app = Application::GetInstance(); - auto device_state = app.GetDeviceState(); - switch (device_state) { - case kDeviceStateStarting: - SetColor(0, 0, DEFAULT_BRIGHTNESS); - StartContinuousBlink(100); - break; - case kDeviceStateWifiConfiguring: - SetColor(0, 0, DEFAULT_BRIGHTNESS); - StartContinuousBlink(500); - break; - case kDeviceStateIdle: - TurnOff(); - break; - case kDeviceStateConnecting: - SetColor(0, 0, DEFAULT_BRIGHTNESS); - TurnOn(); - break; - case kDeviceStateListening: - case kDeviceStateAudioTesting: - if (app.IsVoiceDetected()) { - SetColor(HIGH_BRIGHTNESS, 0, 0); - } else { - SetColor(LOW_BRIGHTNESS, 0, 0); - } - TurnOn(); - break; - case kDeviceStateSpeaking: - SetColor(0, DEFAULT_BRIGHTNESS, 0); - TurnOn(); - break; - case kDeviceStateUpgrading: - SetColor(0, DEFAULT_BRIGHTNESS, 0); - StartContinuousBlink(100); - break; - case kDeviceStateActivating: - SetColor(0, DEFAULT_BRIGHTNESS, 0); - StartContinuousBlink(500); - break; - default: - ESP_LOGW(TAG, "Unknown led strip event: %d", device_state); - return; - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.h deleted file mode 100644 index b949f747..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/led/single_led.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef _SINGLE_LED_H_ -#define _SINGLE_LED_H_ - -#include "led.h" -#include -#include -#include -#include -#include - -class SingleLed : public Led { -public: - SingleLed(gpio_num_t gpio); - virtual ~SingleLed(); - - void OnStateChanged() override; - -private: - std::mutex mutex_; - TaskHandle_t blink_task_ = nullptr; - led_strip_handle_t led_strip_ = nullptr; - uint8_t r_ = 0, g_ = 0, b_ = 0; - int blink_counter_ = 0; - int blink_interval_ms_ = 0; - esp_timer_handle_t blink_timer_ = nullptr; - - void StartBlinkTask(int times, int interval_ms); - void OnBlinkTimer(); - - void BlinkOnce(); - void Blink(int times, int interval_ms); - void StartContinuousBlink(int interval_ms); - void TurnOn(); - void TurnOff(); - void SetColor(uint8_t r, uint8_t g, uint8_t b); -}; - -#endif // _SINGLE_LED_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/main.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/main.cc deleted file mode 100644 index 0d4e5e1d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/main.cc +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "application.h" -#include "system_info.h" - -#define TAG "main" - -extern "C" void app_main(void) -{ - // Initialize NVS flash for WiFi configuration - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - ESP_LOGW(TAG, "Erasing NVS flash to fix corruption"); - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - - // Initialize and run the application - auto& app = Application::GetInstance(); - app.Initialize(); - app.Run(); // This function runs the main event loop and never returns -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.cc deleted file mode 100644 index f09d3a33..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.cc +++ /dev/null @@ -1,563 +0,0 @@ -/* - * MCP Server Implementation - * Reference: https://modelcontextprotocol.io/specification/2024-11-05 - */ - -#include "mcp_server.h" -#include -#include -#include -#include -#include - -#include "application.h" -#include "display.h" -#include "oled_display.h" -#include "board.h" -#include "settings.h" -#include "lvgl_theme.h" -#include "lvgl_display.h" - -#define TAG "MCP" - -McpServer::McpServer() { -} - -McpServer::~McpServer() { - for (auto tool : tools_) { - delete tool; - } - tools_.clear(); -} - -void McpServer::AddCommonTools() { - // *Important* To speed up the response time, we add the common tools to the beginning of - // the tools list to utilize the prompt cache. - // **重要** 为了提升响应速度,我们把常用的工具放在前面,利用 prompt cache 的特性。 - - // Backup the original tools list and restore it after adding the common tools. - auto original_tools = std::move(tools_); - auto& board = Board::GetInstance(); - - // Do not add custom tools here. - // Custom tools must be added in the board's InitializeTools function. - - AddTool("self.get_device_status", - "Provides the real-time information of the device, including the current status of the audio speaker, screen, battery, network, etc.\n" - "Use this tool for: \n" - "1. Answering questions about current condition (e.g. what is the current volume of the audio speaker?)\n" - "2. As the first step to control the device (e.g. turn up / down the volume of the audio speaker, etc.)", - PropertyList(), - [&board](const PropertyList& properties) -> ReturnValue { - return board.GetDeviceStatusJson(); - }); - - AddTool("self.audio_speaker.set_volume", - "Set the volume of the audio speaker. If the current volume is unknown, you must call `self.get_device_status` tool first and then call this tool.", - PropertyList({ - Property("volume", kPropertyTypeInteger, 0, 100) - }), - [&board](const PropertyList& properties) -> ReturnValue { - auto codec = board.GetAudioCodec(); - codec->SetOutputVolume(properties["volume"].value()); - return true; - }); - - auto backlight = board.GetBacklight(); - if (backlight) { - AddTool("self.screen.set_brightness", - "Set the brightness of the screen.", - PropertyList({ - Property("brightness", kPropertyTypeInteger, 0, 100) - }), - [backlight](const PropertyList& properties) -> ReturnValue { - uint8_t brightness = static_cast(properties["brightness"].value()); - backlight->SetBrightness(brightness, true); - return true; - }); - } - -#ifdef HAVE_LVGL - auto display = board.GetDisplay(); - if (display && display->GetTheme() != nullptr) { - AddTool("self.screen.set_theme", - "Set the theme of the screen. The theme can be `light` or `dark`.", - PropertyList({ - Property("theme", kPropertyTypeString) - }), - [display](const PropertyList& properties) -> ReturnValue { - auto theme_name = properties["theme"].value(); - auto& theme_manager = LvglThemeManager::GetInstance(); - auto theme = theme_manager.GetTheme(theme_name); - if (theme != nullptr) { - display->SetTheme(theme); - return true; - } - return false; - }); - } - - auto camera = board.GetCamera(); - if (camera) { - AddTool("self.camera.take_photo", - "Take a photo and explain it. Use this tool after the user asks you to see something.\n" - "Args:\n" - " `question`: The question that you want to ask about the photo.\n" - "Return:\n" - " A JSON object that provides the photo information.", - PropertyList({ - Property("question", kPropertyTypeString) - }), - [camera](const PropertyList& properties) -> ReturnValue { - // Lower the priority to do the camera capture - TaskPriorityReset priority_reset(1); - - if (!camera->Capture()) { - throw std::runtime_error("Failed to capture photo"); - } - auto question = properties["question"].value(); - return camera->Explain(question); - }); - } -#endif - - // Restore the original tools list to the end of the tools list - tools_.insert(tools_.end(), original_tools.begin(), original_tools.end()); -} - -void McpServer::AddUserOnlyTools() { - // System tools - AddUserOnlyTool("self.get_system_info", - "Get the system information", - PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - auto& board = Board::GetInstance(); - return board.GetSystemInfoJson(); - }); - - AddUserOnlyTool("self.reboot", "Reboot the system", - PropertyList(), - [this](const PropertyList& properties) -> ReturnValue { - auto& app = Application::GetInstance(); - app.Schedule([&app]() { - ESP_LOGW(TAG, "User requested reboot"); - vTaskDelay(pdMS_TO_TICKS(1000)); - - app.Reboot(); - }); - return true; - }); - - // Firmware upgrade - AddUserOnlyTool("self.upgrade_firmware", "Upgrade firmware from a specific URL. This will download and install the firmware, then reboot the device.", - PropertyList({ - Property("url", kPropertyTypeString, "The URL of the firmware binary file to download and install") - }), - [this](const PropertyList& properties) -> ReturnValue { - auto url = properties["url"].value(); - ESP_LOGI(TAG, "User requested firmware upgrade from URL: %s", url.c_str()); - - auto& app = Application::GetInstance(); - app.Schedule([url, &app]() { - bool success = app.UpgradeFirmware(url); - if (!success) { - ESP_LOGE(TAG, "Firmware upgrade failed"); - } - }); - - return true; - }); - - // Display control -#ifdef HAVE_LVGL - auto display = dynamic_cast(Board::GetInstance().GetDisplay()); - if (display) { - AddUserOnlyTool("self.screen.get_info", "Information about the screen, including width, height, etc.", - PropertyList(), - [display](const PropertyList& properties) -> ReturnValue { - cJSON *json = cJSON_CreateObject(); - cJSON_AddNumberToObject(json, "width", display->width()); - cJSON_AddNumberToObject(json, "height", display->height()); - if (dynamic_cast(display)) { - cJSON_AddBoolToObject(json, "monochrome", true); - } else { - cJSON_AddBoolToObject(json, "monochrome", false); - } - return json; - }); - -#if CONFIG_LV_USE_SNAPSHOT - AddUserOnlyTool("self.screen.snapshot", "Snapshot the screen and upload it to a specific URL", - PropertyList({ - Property("url", kPropertyTypeString), - Property("quality", kPropertyTypeInteger, 80, 1, 100) - }), - [display](const PropertyList& properties) -> ReturnValue { - auto url = properties["url"].value(); - auto quality = properties["quality"].value(); - - std::string jpeg_data; - if (!display->SnapshotToJpeg(jpeg_data, quality)) { - throw std::runtime_error("Failed to snapshot screen"); - } - - ESP_LOGI(TAG, "Upload snapshot %u bytes to %s", jpeg_data.size(), url.c_str()); - - // 构造multipart/form-data请求体 - std::string boundary = "----ESP32_SCREEN_SNAPSHOT_BOUNDARY"; - - auto http = Board::GetInstance().GetNetwork()->CreateHttp(3); - http->SetHeader("Content-Type", "multipart/form-data; boundary=" + boundary); - if (!http->Open("POST", url)) { - throw std::runtime_error("Failed to open URL: " + url); - } - { - // 文件字段头部 - std::string file_header; - file_header += "--" + boundary + "\r\n"; - file_header += "Content-Disposition: form-data; name=\"file\"; filename=\"screenshot.jpg\"\r\n"; - file_header += "Content-Type: image/jpeg\r\n"; - file_header += "\r\n"; - http->Write(file_header.c_str(), file_header.size()); - } - - // JPEG数据 - http->Write((const char*)jpeg_data.data(), jpeg_data.size()); - - { - // multipart尾部 - std::string multipart_footer; - multipart_footer += "\r\n--" + boundary + "--\r\n"; - http->Write(multipart_footer.c_str(), multipart_footer.size()); - } - http->Write("", 0); - - if (http->GetStatusCode() != 200) { - throw std::runtime_error("Unexpected status code: " + std::to_string(http->GetStatusCode())); - } - std::string result = http->ReadAll(); - http->Close(); - ESP_LOGI(TAG, "Snapshot screen result: %s", result.c_str()); - return true; - }); - - AddUserOnlyTool("self.screen.preview_image", "Preview an image on the screen", - PropertyList({ - Property("url", kPropertyTypeString) - }), - [display](const PropertyList& properties) -> ReturnValue { - auto url = properties["url"].value(); - auto http = Board::GetInstance().GetNetwork()->CreateHttp(3); - - if (!http->Open("GET", url)) { - throw std::runtime_error("Failed to open URL: " + url); - } - int status_code = http->GetStatusCode(); - if (status_code != 200) { - throw std::runtime_error("Unexpected status code: " + std::to_string(status_code)); - } - - size_t content_length = http->GetBodyLength(); - char* data = (char*)heap_caps_malloc(content_length, MALLOC_CAP_8BIT); - if (data == nullptr) { - throw std::runtime_error("Failed to allocate memory for image: " + url); - } - size_t total_read = 0; - while (total_read < content_length) { - int ret = http->Read(data + total_read, content_length - total_read); - if (ret < 0) { - heap_caps_free(data); - throw std::runtime_error("Failed to download image: " + url); - } - if (ret == 0) { - break; - } - total_read += ret; - } - http->Close(); - - auto image = std::make_unique(data, content_length); - display->SetPreviewImage(std::move(image)); - return true; - }); -#endif // CONFIG_LV_USE_SNAPSHOT - } -#endif // HAVE_LVGL - - // Assets download url - auto& assets = Assets::GetInstance(); - if (assets.partition_valid()) { - AddUserOnlyTool("self.assets.set_download_url", "Set the download url for the assets", - PropertyList({ - Property("url", kPropertyTypeString) - }), - [](const PropertyList& properties) -> ReturnValue { - auto url = properties["url"].value(); - Settings settings("assets", true); - settings.SetString("download_url", url); - return true; - }); - } -} - -void McpServer::AddTool(McpTool* tool) { - // Prevent adding duplicate tools - if (std::find_if(tools_.begin(), tools_.end(), [tool](const McpTool* t) { return t->name() == tool->name(); }) != tools_.end()) { - ESP_LOGW(TAG, "Tool %s already added", tool->name().c_str()); - return; - } - - ESP_LOGI(TAG, "Add tool: %s%s", tool->name().c_str(), tool->user_only() ? " [user]" : ""); - tools_.push_back(tool); -} - -void McpServer::AddTool(const std::string& name, const std::string& description, const PropertyList& properties, std::function callback) { - AddTool(new McpTool(name, description, properties, callback)); -} - -void McpServer::AddUserOnlyTool(const std::string& name, const std::string& description, const PropertyList& properties, std::function callback) { - auto tool = new McpTool(name, description, properties, callback); - tool->set_user_only(true); - AddTool(tool); -} - -void McpServer::ParseMessage(const std::string& message) { - cJSON* json = cJSON_Parse(message.c_str()); - if (json == nullptr) { - ESP_LOGE(TAG, "Failed to parse MCP message: %s", message.c_str()); - return; - } - ParseMessage(json); - cJSON_Delete(json); -} - -void McpServer::ParseCapabilities(const cJSON* capabilities) { - auto vision = cJSON_GetObjectItem(capabilities, "vision"); - if (cJSON_IsObject(vision)) { - auto url = cJSON_GetObjectItem(vision, "url"); - auto token = cJSON_GetObjectItem(vision, "token"); - if (cJSON_IsString(url)) { - auto camera = Board::GetInstance().GetCamera(); - if (camera) { - std::string url_str = std::string(url->valuestring); - std::string token_str; - if (cJSON_IsString(token)) { - token_str = std::string(token->valuestring); - } - camera->SetExplainUrl(url_str, token_str); - } - } - } -} - -void McpServer::ParseMessage(const cJSON* json) { - // Check JSONRPC version - auto version = cJSON_GetObjectItem(json, "jsonrpc"); - if (version == nullptr || !cJSON_IsString(version) || strcmp(version->valuestring, "2.0") != 0) { - ESP_LOGE(TAG, "Invalid JSONRPC version: %s", version ? version->valuestring : "null"); - return; - } - - // Check method - auto method = cJSON_GetObjectItem(json, "method"); - if (method == nullptr || !cJSON_IsString(method)) { - ESP_LOGE(TAG, "Missing method"); - return; - } - - auto method_str = std::string(method->valuestring); - if (method_str.find("notifications") == 0) { - return; - } - - // Check params - auto params = cJSON_GetObjectItem(json, "params"); - if (params != nullptr && !cJSON_IsObject(params)) { - ESP_LOGE(TAG, "Invalid params for method: %s", method_str.c_str()); - return; - } - - auto id = cJSON_GetObjectItem(json, "id"); - if (id == nullptr || !cJSON_IsNumber(id)) { - ESP_LOGE(TAG, "Invalid id for method: %s", method_str.c_str()); - return; - } - auto id_int = id->valueint; - - if (method_str == "initialize") { - if (cJSON_IsObject(params)) { - auto capabilities = cJSON_GetObjectItem(params, "capabilities"); - if (cJSON_IsObject(capabilities)) { - ParseCapabilities(capabilities); - } - } - auto app_desc = esp_app_get_description(); - std::string message = "{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{\"tools\":{}},\"serverInfo\":{\"name\":\"" BOARD_NAME "\",\"version\":\""; - message += app_desc->version; - message += "\"}}"; - ReplyResult(id_int, message); - } else if (method_str == "tools/list") { - std::string cursor_str = ""; - bool list_user_only_tools = false; - if (params != nullptr) { - auto cursor = cJSON_GetObjectItem(params, "cursor"); - if (cJSON_IsString(cursor)) { - cursor_str = std::string(cursor->valuestring); - } - auto with_user_tools = cJSON_GetObjectItem(params, "withUserTools"); - if (cJSON_IsBool(with_user_tools)) { - list_user_only_tools = with_user_tools->valueint == 1; - } - } - GetToolsList(id_int, cursor_str, list_user_only_tools); - } else if (method_str == "tools/call") { - if (!cJSON_IsObject(params)) { - ESP_LOGE(TAG, "tools/call: Missing params"); - ReplyError(id_int, "Missing params"); - return; - } - auto tool_name = cJSON_GetObjectItem(params, "name"); - if (!cJSON_IsString(tool_name)) { - ESP_LOGE(TAG, "tools/call: Missing name"); - ReplyError(id_int, "Missing name"); - return; - } - auto tool_arguments = cJSON_GetObjectItem(params, "arguments"); - if (tool_arguments != nullptr && !cJSON_IsObject(tool_arguments)) { - ESP_LOGE(TAG, "tools/call: Invalid arguments"); - ReplyError(id_int, "Invalid arguments"); - return; - } - DoToolCall(id_int, std::string(tool_name->valuestring), tool_arguments); - } else { - ESP_LOGE(TAG, "Method not implemented: %s", method_str.c_str()); - ReplyError(id_int, "Method not implemented: " + method_str); - } -} - -void McpServer::ReplyResult(int id, const std::string& result) { - std::string payload = "{\"jsonrpc\":\"2.0\",\"id\":"; - payload += std::to_string(id) + ",\"result\":"; - payload += result; - payload += "}"; - Application::GetInstance().SendMcpMessage(payload); -} - -void McpServer::ReplyError(int id, const std::string& message) { - std::string payload = "{\"jsonrpc\":\"2.0\",\"id\":"; - payload += std::to_string(id); - payload += ",\"error\":{\"message\":\""; - payload += message; - payload += "\"}}"; - Application::GetInstance().SendMcpMessage(payload); -} - -void McpServer::GetToolsList(int id, const std::string& cursor, bool list_user_only_tools) { - const int max_payload_size = 8000; - std::string json = "{\"tools\":["; - - bool found_cursor = cursor.empty(); - auto it = tools_.begin(); - std::string next_cursor = ""; - - while (it != tools_.end()) { - // 如果我们还没有找到起始位置,继续搜索 - if (!found_cursor) { - if ((*it)->name() == cursor) { - found_cursor = true; - } else { - ++it; - continue; - } - } - - if (!list_user_only_tools && (*it)->user_only()) { - ++it; - continue; - } - - // 添加tool前检查大小 - std::string tool_json = (*it)->to_json() + ","; - if (json.length() + tool_json.length() + 30 > max_payload_size) { - // 如果添加这个tool会超出大小限制,设置next_cursor并退出循环 - next_cursor = (*it)->name(); - break; - } - - json += tool_json; - ++it; - } - - if (json.back() == ',') { - json.pop_back(); - } - - if (json.back() == '[' && !tools_.empty()) { - // 如果没有添加任何tool,返回错误 - ESP_LOGE(TAG, "tools/list: Failed to add tool %s because of payload size limit", next_cursor.c_str()); - ReplyError(id, "Failed to add tool " + next_cursor + " because of payload size limit"); - return; - } - - if (next_cursor.empty()) { - json += "]}"; - } else { - json += "],\"nextCursor\":\"" + next_cursor + "\"}"; - } - - ReplyResult(id, json); -} - -void McpServer::DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments) { - auto tool_iter = std::find_if(tools_.begin(), tools_.end(), - [&tool_name](const McpTool* tool) { - return tool->name() == tool_name; - }); - - if (tool_iter == tools_.end()) { - ESP_LOGE(TAG, "tools/call: Unknown tool: %s", tool_name.c_str()); - ReplyError(id, "Unknown tool: " + tool_name); - return; - } - - PropertyList arguments = (*tool_iter)->properties(); - try { - for (auto& argument : arguments) { - bool found = false; - if (cJSON_IsObject(tool_arguments)) { - auto value = cJSON_GetObjectItem(tool_arguments, argument.name().c_str()); - if (argument.type() == kPropertyTypeBoolean && cJSON_IsBool(value)) { - argument.set_value(value->valueint == 1); - found = true; - } else if (argument.type() == kPropertyTypeInteger && cJSON_IsNumber(value)) { - argument.set_value(value->valueint); - found = true; - } else if (argument.type() == kPropertyTypeString && cJSON_IsString(value)) { - argument.set_value(value->valuestring); - found = true; - } - } - - if (!argument.has_default_value() && !found) { - ESP_LOGE(TAG, "tools/call: Missing valid argument: %s", argument.name().c_str()); - ReplyError(id, "Missing valid argument: " + argument.name()); - return; - } - } - } catch (const std::exception& e) { - ESP_LOGE(TAG, "tools/call: %s", e.what()); - ReplyError(id, e.what()); - return; - } - - // Use main thread to call the tool - auto& app = Application::GetInstance(); - app.Schedule([this, id, tool_iter, arguments = std::move(arguments)]() { - try { - ReplyResult(id, (*tool_iter)->Call(arguments)); - } catch (const std::exception& e) { - ESP_LOGE(TAG, "tools/call: %s", e.what()); - ReplyError(id, e.what()); - } - }); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.h deleted file mode 100644 index dacdd551..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/mcp_server.h +++ /dev/null @@ -1,344 +0,0 @@ -#ifndef MCP_SERVER_H -#define MCP_SERVER_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -class ImageContent { -private: - std::string encoded_data_; - std::string mime_type_; - - static std::string Base64Encode(const std::string& data) { - size_t dlen = 0, olen = 0; - mbedtls_base64_encode((unsigned char*)nullptr, 0, &dlen, (const unsigned char*)data.data(), data.size()); - std::string result(dlen, 0); - mbedtls_base64_encode((unsigned char*)result.data(), result.size(), &olen, (const unsigned char*)data.data(), data.size()); - return result; - } - -public: - ImageContent(const std::string& mime_type, const std::string& data) { - mime_type_ = mime_type; - // base64 encode data - encoded_data_ = Base64Encode(data); - } - - std::string to_json() const { - cJSON *json = cJSON_CreateObject(); - cJSON_AddStringToObject(json, "type", "image"); - cJSON_AddStringToObject(json, "mimeType", mime_type_.c_str()); - cJSON_AddStringToObject(json, "data", encoded_data_.c_str()); - char* json_str = cJSON_PrintUnformatted(json); - std::string result(json_str); - cJSON_free(json_str); - cJSON_Delete(json); - return result; - } -}; - -// 添加类型别名 -using ReturnValue = std::variant; - -enum PropertyType { - kPropertyTypeBoolean, - kPropertyTypeInteger, - kPropertyTypeString -}; - -class Property { -private: - std::string name_; - PropertyType type_; - std::variant value_; - bool has_default_value_; - std::optional min_value_; // 新增:整数最小值 - std::optional max_value_; // 新增:整数最大值 - -public: - // Required field constructor - Property(const std::string& name, PropertyType type) - : name_(name), type_(type), has_default_value_(false) {} - - // Optional field constructor with default value - template - Property(const std::string& name, PropertyType type, const T& default_value) - : name_(name), type_(type), has_default_value_(true) { - value_ = default_value; - } - - Property(const std::string& name, PropertyType type, int min_value, int max_value) - : name_(name), type_(type), has_default_value_(false), min_value_(min_value), max_value_(max_value) { - if (type != kPropertyTypeInteger) { - throw std::invalid_argument("Range limits only apply to integer properties"); - } - } - - Property(const std::string& name, PropertyType type, int default_value, int min_value, int max_value) - : name_(name), type_(type), has_default_value_(true), min_value_(min_value), max_value_(max_value) { - if (type != kPropertyTypeInteger) { - throw std::invalid_argument("Range limits only apply to integer properties"); - } - if (default_value < min_value || default_value > max_value) { - throw std::invalid_argument("Default value must be within the specified range"); - } - value_ = default_value; - } - - inline const std::string& name() const { return name_; } - inline PropertyType type() const { return type_; } - inline bool has_default_value() const { return has_default_value_; } - inline bool has_range() const { return min_value_.has_value() && max_value_.has_value(); } - inline int min_value() const { return min_value_.value_or(0); } - inline int max_value() const { return max_value_.value_or(0); } - - template - inline T value() const { - return std::get(value_); - } - - template - inline void set_value(const T& value) { - // 添加对设置的整数值进行范围检查 - if constexpr (std::is_same_v) { - if (min_value_.has_value() && value < min_value_.value()) { - throw std::invalid_argument("Value is below minimum allowed: " + std::to_string(min_value_.value())); - } - if (max_value_.has_value() && value > max_value_.value()) { - throw std::invalid_argument("Value exceeds maximum allowed: " + std::to_string(max_value_.value())); - } - } - value_ = value; - } - - std::string to_json() const { - cJSON *json = cJSON_CreateObject(); - - if (type_ == kPropertyTypeBoolean) { - cJSON_AddStringToObject(json, "type", "boolean"); - if (has_default_value_) { - cJSON_AddBoolToObject(json, "default", value()); - } - } else if (type_ == kPropertyTypeInteger) { - cJSON_AddStringToObject(json, "type", "integer"); - if (has_default_value_) { - cJSON_AddNumberToObject(json, "default", value()); - } - if (min_value_.has_value()) { - cJSON_AddNumberToObject(json, "minimum", min_value_.value()); - } - if (max_value_.has_value()) { - cJSON_AddNumberToObject(json, "maximum", max_value_.value()); - } - } else if (type_ == kPropertyTypeString) { - cJSON_AddStringToObject(json, "type", "string"); - if (has_default_value_) { - cJSON_AddStringToObject(json, "default", value().c_str()); - } - } - - char *json_str = cJSON_PrintUnformatted(json); - std::string result(json_str); - cJSON_free(json_str); - cJSON_Delete(json); - - return result; - } -}; - -class PropertyList { -private: - std::vector properties_; - -public: - PropertyList() = default; - PropertyList(const std::vector& properties) : properties_(properties) {} - void AddProperty(const Property& property) { - properties_.push_back(property); - } - - const Property& operator[](const std::string& name) const { - for (const auto& property : properties_) { - if (property.name() == name) { - return property; - } - } - throw std::runtime_error("Property not found: " + name); - } - - auto begin() { return properties_.begin(); } - auto end() { return properties_.end(); } - - std::vector GetRequired() const { - std::vector required; - for (auto& property : properties_) { - if (!property.has_default_value()) { - required.push_back(property.name()); - } - } - return required; - } - - std::string to_json() const { - cJSON *json = cJSON_CreateObject(); - - for (const auto& property : properties_) { - cJSON *prop_json = cJSON_Parse(property.to_json().c_str()); - cJSON_AddItemToObject(json, property.name().c_str(), prop_json); - } - - char *json_str = cJSON_PrintUnformatted(json); - std::string result(json_str); - cJSON_free(json_str); - cJSON_Delete(json); - - return result; - } -}; - -class McpTool { -private: - std::string name_; - std::string description_; - PropertyList properties_; - std::function callback_; - bool user_only_ = false; - -public: - McpTool(const std::string& name, - const std::string& description, - const PropertyList& properties, - std::function callback) - : name_(name), - description_(description), - properties_(properties), - callback_(callback) {} - - void set_user_only(bool user_only) { user_only_ = user_only; } - inline const std::string& name() const { return name_; } - inline const std::string& description() const { return description_; } - inline const PropertyList& properties() const { return properties_; } - inline bool user_only() const { return user_only_; } - - std::string to_json() const { - std::vector required = properties_.GetRequired(); - - cJSON *json = cJSON_CreateObject(); - cJSON_AddStringToObject(json, "name", name_.c_str()); - cJSON_AddStringToObject(json, "description", description_.c_str()); - - cJSON *input_schema = cJSON_CreateObject(); - cJSON_AddStringToObject(input_schema, "type", "object"); - - cJSON *properties = cJSON_Parse(properties_.to_json().c_str()); - cJSON_AddItemToObject(input_schema, "properties", properties); - - if (!required.empty()) { - cJSON *required_array = cJSON_CreateArray(); - for (const auto& property : required) { - cJSON_AddItemToArray(required_array, cJSON_CreateString(property.c_str())); - } - cJSON_AddItemToObject(input_schema, "required", required_array); - } - - cJSON_AddItemToObject(json, "inputSchema", input_schema); - - // Add audience annotation if the tool is user only (invisible to AI) - if (user_only_) { - cJSON *annotations = cJSON_CreateObject(); - cJSON *audience = cJSON_CreateArray(); - cJSON_AddItemToArray(audience, cJSON_CreateString("user")); - cJSON_AddItemToObject(annotations, "audience", audience); - cJSON_AddItemToObject(json, "annotations", annotations); - } - - char *json_str = cJSON_PrintUnformatted(json); - std::string result(json_str); - cJSON_free(json_str); - cJSON_Delete(json); - - return result; - } - - std::string Call(const PropertyList& properties) { - ReturnValue return_value = callback_(properties); - // 返回结果 - cJSON* result = cJSON_CreateObject(); - cJSON* content = cJSON_CreateArray(); - - if (std::holds_alternative(return_value)) { - auto image_content = std::get(return_value); - cJSON* image = cJSON_CreateObject(); - cJSON_AddStringToObject(image, "type", "image"); - cJSON_AddStringToObject(image, "image", image_content->to_json().c_str()); - cJSON_AddItemToArray(content, image); - delete image_content; - } else { - cJSON* text = cJSON_CreateObject(); - cJSON_AddStringToObject(text, "type", "text"); - if (std::holds_alternative(return_value)) { - cJSON_AddStringToObject(text, "text", std::get(return_value).c_str()); - } else if (std::holds_alternative(return_value)) { - cJSON_AddStringToObject(text, "text", std::get(return_value) ? "true" : "false"); - } else if (std::holds_alternative(return_value)) { - cJSON_AddStringToObject(text, "text", std::to_string(std::get(return_value)).c_str()); - } else if (std::holds_alternative(return_value)) { - cJSON* json = std::get(return_value); - char* json_str = cJSON_PrintUnformatted(json); - cJSON_AddStringToObject(text, "text", json_str); - cJSON_free(json_str); - cJSON_Delete(json); - } - cJSON_AddItemToArray(content, text); - } - cJSON_AddItemToObject(result, "content", content); - cJSON_AddBoolToObject(result, "isError", false); - - auto json_str = cJSON_PrintUnformatted(result); - std::string result_str(json_str); - cJSON_free(json_str); - cJSON_Delete(result); - return result_str; - } -}; - -class McpServer { -public: - static McpServer& GetInstance() { - static McpServer instance; - return instance; - } - - void AddCommonTools(); - void AddUserOnlyTools(); - void AddTool(McpTool* tool); - void AddTool(const std::string& name, const std::string& description, const PropertyList& properties, std::function callback); - void AddUserOnlyTool(const std::string& name, const std::string& description, const PropertyList& properties, std::function callback); - void ParseMessage(const cJSON* json); - void ParseMessage(const std::string& message); - -private: - McpServer(); - ~McpServer(); - - void ParseCapabilities(const cJSON* capabilities); - - void ReplyResult(int id, const std::string& result); - void ReplyError(int id, const std::string& message); - - void GetToolsList(int id, const std::string& cursor, bool list_user_only_tools); - void DoToolCall(int id, const std::string& tool_name, const cJSON* tool_arguments); - - std::vector tools_; -}; - -#endif // MCP_SERVER_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.cc deleted file mode 100644 index 768ba665..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.cc +++ /dev/null @@ -1,473 +0,0 @@ -#include "ota.h" -#include "system_info.h" -#include "settings.h" -#include "assets/lang_config.h" - -#include -#include -#include -#include -#include -#include -#include -#ifdef SOC_HMAC_SUPPORTED -#include -#endif - -#include -#include -#include -#include - -#define TAG "Ota" - - -Ota::Ota() { -#ifdef ESP_EFUSE_BLOCK_USR_DATA - // Read Serial Number from efuse user_data - uint8_t serial_number[33] = {0}; - if (esp_efuse_read_field_blob(ESP_EFUSE_USER_DATA, serial_number, 32 * 8) == ESP_OK) { - if (serial_number[0] == 0) { - has_serial_number_ = false; - } else { - serial_number_ = std::string(reinterpret_cast(serial_number), 32); - has_serial_number_ = true; - } - } -#endif -} - -Ota::~Ota() { -} - -std::string Ota::GetCheckVersionUrl() { - Settings settings("wifi", false); - std::string url = settings.GetString("ota_url"); - if (url.empty()) { - url = CONFIG_OTA_URL; - } - return url; -} - -std::unique_ptr Ota::SetupHttp() { - auto& board = Board::GetInstance(); - auto network = board.GetNetwork(); - auto http = network->CreateHttp(0); - auto user_agent = SystemInfo::GetUserAgent(); - http->SetHeader("Activation-Version", has_serial_number_ ? "2" : "1"); - http->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); - http->SetHeader("Client-Id", board.GetUuid()); - if (has_serial_number_) { - http->SetHeader("Serial-Number", serial_number_.c_str()); - ESP_LOGI(TAG, "Setup HTTP, User-Agent: %s, Serial-Number: %s", user_agent.c_str(), serial_number_.c_str()); - } - http->SetHeader("User-Agent", user_agent); - http->SetHeader("Accept-Language", Lang::CODE); - http->SetHeader("Content-Type", "application/json"); - - return http; -} - -/* - * Specification: https://ccnphfhqs21z.feishu.cn/wiki/FjW6wZmisimNBBkov6OcmfvknVd - */ -esp_err_t Ota::CheckVersion() { - auto& board = Board::GetInstance(); - auto app_desc = esp_app_get_description(); - - // Check if there is a new firmware version available - current_version_ = app_desc->version; - ESP_LOGI(TAG, "Current version: %s", current_version_.c_str()); - - std::string url = GetCheckVersionUrl(); - if (url.length() < 10) { - ESP_LOGE(TAG, "Check version URL is not properly set"); - return ESP_ERR_INVALID_ARG; - } - - auto http = SetupHttp(); - - std::string data = board.GetSystemInfoJson(); - std::string method = data.length() > 0 ? "POST" : "GET"; - http->SetContent(std::move(data)); - - if (!http->Open(method, url)) { - int last_error = http->GetLastError(); - ESP_LOGE(TAG, "Failed to open HTTP connection, code=0x%x", last_error); - return last_error; - } - - auto status_code = http->GetStatusCode(); - if (status_code != 200) { - ESP_LOGE(TAG, "Failed to check version, status code: %d", status_code); - return status_code; - } - - data = http->ReadAll(); - http->Close(); - - // Response: { "firmware": { "version": "1.0.0", "url": "http://" } } - // Parse the JSON response and check if the version is newer - // If it is, set has_new_version_ to true and store the new version and URL - - cJSON *root = cJSON_Parse(data.c_str()); - if (root == NULL) { - ESP_LOGE(TAG, "Failed to parse JSON response"); - return ESP_ERR_INVALID_RESPONSE; - } - - has_activation_code_ = false; - has_activation_challenge_ = false; - cJSON *activation = cJSON_GetObjectItem(root, "activation"); - if (cJSON_IsObject(activation)) { - cJSON* message = cJSON_GetObjectItem(activation, "message"); - if (cJSON_IsString(message)) { - activation_message_ = message->valuestring; - } - cJSON* code = cJSON_GetObjectItem(activation, "code"); - if (cJSON_IsString(code)) { - activation_code_ = code->valuestring; - has_activation_code_ = true; - } - cJSON* challenge = cJSON_GetObjectItem(activation, "challenge"); - if (cJSON_IsString(challenge)) { - activation_challenge_ = challenge->valuestring; - has_activation_challenge_ = true; - } - cJSON* timeout_ms = cJSON_GetObjectItem(activation, "timeout_ms"); - if (cJSON_IsNumber(timeout_ms)) { - activation_timeout_ms_ = timeout_ms->valueint; - } - } - - has_mqtt_config_ = false; - cJSON *mqtt = cJSON_GetObjectItem(root, "mqtt"); - if (cJSON_IsObject(mqtt)) { - Settings settings("mqtt", true); - cJSON *item = NULL; - cJSON_ArrayForEach(item, mqtt) { - if (cJSON_IsString(item)) { - if (settings.GetString(item->string) != item->valuestring) { - settings.SetString(item->string, item->valuestring); - } - } else if (cJSON_IsNumber(item)) { - if (settings.GetInt(item->string) != item->valueint) { - settings.SetInt(item->string, item->valueint); - } - } - } - has_mqtt_config_ = true; - } else { - ESP_LOGI(TAG, "No mqtt section found !"); - } - - has_websocket_config_ = false; - cJSON *websocket = cJSON_GetObjectItem(root, "websocket"); - if (cJSON_IsObject(websocket)) { - Settings settings("websocket", true); - cJSON *item = NULL; - cJSON_ArrayForEach(item, websocket) { - if (cJSON_IsString(item)) { - if (settings.GetString(item->string) != item->valuestring) { - settings.SetString(item->string, item->valuestring); - } - } else if (cJSON_IsNumber(item)) { - if (settings.GetInt(item->string) != item->valueint) { - settings.SetInt(item->string, item->valueint); - } - } - } - has_websocket_config_ = true; - } else { - ESP_LOGI(TAG, "No websocket section found!"); - } - - has_server_time_ = false; - cJSON *server_time = cJSON_GetObjectItem(root, "server_time"); - if (cJSON_IsObject(server_time)) { - cJSON *timestamp = cJSON_GetObjectItem(server_time, "timestamp"); - cJSON *timezone_offset = cJSON_GetObjectItem(server_time, "timezone_offset"); - - if (cJSON_IsNumber(timestamp)) { - // 设置系统时间 - struct timeval tv; - double ts = timestamp->valuedouble; - - // 如果有时区偏移,计算本地时间 - if (cJSON_IsNumber(timezone_offset)) { - ts += (timezone_offset->valueint * 60 * 1000); // 转换分钟为毫秒 - } - - tv.tv_sec = (time_t)(ts / 1000); // 转换毫秒为秒 - tv.tv_usec = (suseconds_t)((long long)ts % 1000) * 1000; // 剩余的毫秒转换为微秒 - settimeofday(&tv, NULL); - has_server_time_ = true; - } - } else { - ESP_LOGW(TAG, "No server_time section found!"); - } - - has_new_version_ = false; - cJSON *firmware = cJSON_GetObjectItem(root, "firmware"); - if (cJSON_IsObject(firmware)) { - cJSON *version = cJSON_GetObjectItem(firmware, "version"); - if (cJSON_IsString(version)) { - firmware_version_ = version->valuestring; - } - cJSON *url = cJSON_GetObjectItem(firmware, "url"); - if (cJSON_IsString(url)) { - firmware_url_ = url->valuestring; - } - - if (cJSON_IsString(version) && cJSON_IsString(url)) { - // Check if the version is newer, for example, 0.1.0 is newer than 0.0.1 - has_new_version_ = IsNewVersionAvailable(current_version_, firmware_version_); - if (has_new_version_) { - ESP_LOGI(TAG, "New version available: %s", firmware_version_.c_str()); - } else { - ESP_LOGI(TAG, "Current is the latest version"); - } - // If the force flag is set to 1, the given version is forced to be installed - cJSON *force = cJSON_GetObjectItem(firmware, "force"); - if (cJSON_IsNumber(force) && force->valueint == 1) { - has_new_version_ = true; - } - } - } else { - ESP_LOGW(TAG, "No firmware section found!"); - } - - cJSON_Delete(root); - return ESP_OK; -} - -void Ota::MarkCurrentVersionValid() { - auto partition = esp_ota_get_running_partition(); - if (strcmp(partition->label, "factory") == 0) { - ESP_LOGI(TAG, "Running from factory partition, skipping"); - return; - } - - ESP_LOGI(TAG, "Running partition: %s", partition->label); - esp_ota_img_states_t state; - if (esp_ota_get_state_partition(partition, &state) != ESP_OK) { - ESP_LOGE(TAG, "Failed to get state of partition"); - return; - } - - if (state == ESP_OTA_IMG_PENDING_VERIFY) { - ESP_LOGI(TAG, "Marking firmware as valid"); - esp_ota_mark_app_valid_cancel_rollback(); - } -} - -bool Ota::Upgrade(const std::string& firmware_url, std::function callback) { - ESP_LOGI(TAG, "Upgrading firmware from %s", firmware_url.c_str()); - esp_ota_handle_t update_handle = 0; - auto update_partition = esp_ota_get_next_update_partition(NULL); - if (update_partition == NULL) { - ESP_LOGE(TAG, "Failed to get update partition"); - return false; - } - - ESP_LOGI(TAG, "Writing to partition %s at offset 0x%lx", update_partition->label, update_partition->address); - bool image_header_checked = false; - std::string image_header; - - auto network = Board::GetInstance().GetNetwork(); - auto http = network->CreateHttp(0); - if (!http->Open("GET", firmware_url)) { - ESP_LOGE(TAG, "Failed to open HTTP connection"); - return false; - } - - if (http->GetStatusCode() != 200) { - ESP_LOGE(TAG, "Failed to get firmware, status code: %d", http->GetStatusCode()); - return false; - } - - size_t content_length = http->GetBodyLength(); - if (content_length == 0) { - ESP_LOGE(TAG, "Failed to get content length"); - return false; - } - - char buffer[512]; - size_t total_read = 0, recent_read = 0; - auto last_calc_time = esp_timer_get_time(); - while (true) { - int ret = http->Read(buffer, sizeof(buffer)); - if (ret < 0) { - ESP_LOGE(TAG, "Failed to read HTTP data: %s", esp_err_to_name(ret)); - return false; - } - - // Calculate speed and progress every second - recent_read += ret; - total_read += ret; - if (esp_timer_get_time() - last_calc_time >= 1000000 || ret == 0) { - size_t progress = total_read * 100 / content_length; - ESP_LOGI(TAG, "Progress: %u%% (%u/%u), Speed: %uB/s", progress, total_read, content_length, recent_read); - if (callback) { - callback(progress, recent_read); - } - last_calc_time = esp_timer_get_time(); - recent_read = 0; - } - - if (ret == 0) { - break; - } - - if (!image_header_checked) { - image_header.append(buffer, ret); - if (image_header.size() >= sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { - esp_app_desc_t new_app_info; - memcpy(&new_app_info, image_header.data() + sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t), sizeof(esp_app_desc_t)); - - auto current_version = esp_app_get_description()->version; - ESP_LOGI(TAG, "Current version: %s, New version: %s", current_version, new_app_info.version); - - if (esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle)) { - esp_ota_abort(update_handle); - ESP_LOGE(TAG, "Failed to begin OTA"); - return false; - } - - image_header_checked = true; - std::string().swap(image_header); - } - } - auto err = esp_ota_write(update_handle, buffer, ret); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to write OTA data: %s", esp_err_to_name(err)); - esp_ota_abort(update_handle); - return false; - } - } - http->Close(); - - esp_err_t err = esp_ota_end(update_handle); - if (err != ESP_OK) { - if (err == ESP_ERR_OTA_VALIDATE_FAILED) { - ESP_LOGE(TAG, "Image validation failed, image is corrupted"); - } else { - ESP_LOGE(TAG, "Failed to end OTA: %s", esp_err_to_name(err)); - } - return false; - } - - err = esp_ota_set_boot_partition(update_partition); - if (err != ESP_OK) { - ESP_LOGE(TAG, "Failed to set boot partition: %s", esp_err_to_name(err)); - return false; - } - - ESP_LOGI(TAG, "Firmware upgrade successful"); - return true; -} - -bool Ota::StartUpgrade(std::function callback) { - return Upgrade(firmware_url_, callback); -} - - -std::vector Ota::ParseVersion(const std::string& version) { - std::vector versionNumbers; - std::stringstream ss(version); - std::string segment; - - while (std::getline(ss, segment, '.')) { - versionNumbers.push_back(std::stoi(segment)); - } - - return versionNumbers; -} - -bool Ota::IsNewVersionAvailable(const std::string& currentVersion, const std::string& newVersion) { - std::vector current = ParseVersion(currentVersion); - std::vector newer = ParseVersion(newVersion); - - for (size_t i = 0; i < std::min(current.size(), newer.size()); ++i) { - if (newer[i] > current[i]) { - return true; - } else if (newer[i] < current[i]) { - return false; - } - } - - return newer.size() > current.size(); -} - -std::string Ota::GetActivationPayload() { - if (!has_serial_number_) { - return "{}"; - } - - std::string hmac_hex; -#ifdef SOC_HMAC_SUPPORTED - uint8_t hmac_result[32]; // SHA-256 输出为32字节 - - // 使用Key0计算HMAC - esp_err_t ret = esp_hmac_calculate(HMAC_KEY0, (uint8_t*)activation_challenge_.data(), activation_challenge_.size(), hmac_result); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "HMAC calculation failed: %s", esp_err_to_name(ret)); - return "{}"; - } - - for (size_t i = 0; i < sizeof(hmac_result); i++) { - char buffer[3]; - sprintf(buffer, "%02x", hmac_result[i]); - hmac_hex += buffer; - } -#endif - - cJSON *payload = cJSON_CreateObject(); - cJSON_AddStringToObject(payload, "algorithm", "hmac-sha256"); - cJSON_AddStringToObject(payload, "serial_number", serial_number_.c_str()); - cJSON_AddStringToObject(payload, "challenge", activation_challenge_.c_str()); - cJSON_AddStringToObject(payload, "hmac", hmac_hex.c_str()); - auto json_str = cJSON_PrintUnformatted(payload); - std::string json(json_str); - cJSON_free(json_str); - cJSON_Delete(payload); - - ESP_LOGI(TAG, "Activation payload: %s", json.c_str()); - return json; -} - -esp_err_t Ota::Activate() { - if (!has_activation_challenge_) { - ESP_LOGW(TAG, "No activation challenge found"); - return ESP_FAIL; - } - - std::string url = GetCheckVersionUrl(); - if (url.back() != '/') { - url += "/activate"; - } else { - url += "activate"; - } - - auto http = SetupHttp(); - - std::string data = GetActivationPayload(); - http->SetContent(std::move(data)); - - if (!http->Open("POST", url)) { - ESP_LOGE(TAG, "Failed to open HTTP connection"); - return ESP_FAIL; - } - - auto status_code = http->GetStatusCode(); - if (status_code == 202) { - return ESP_ERR_TIMEOUT; - } - if (status_code != 200) { - ESP_LOGE(TAG, "Failed to activate, code: %d, body: %s", status_code, http->ReadAll().c_str()); - return ESP_FAIL; - } - - ESP_LOGI(TAG, "Activation successful"); - return ESP_OK; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.h deleted file mode 100644 index 1e5d6878..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/ota.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef _OTA_H -#define _OTA_H - -#include -#include - -#include -#include "board.h" - -class Ota { -public: - Ota(); - ~Ota(); - - esp_err_t CheckVersion(); - esp_err_t Activate(); - bool HasActivationChallenge() { return has_activation_challenge_; } - bool HasNewVersion() { return has_new_version_; } - bool HasMqttConfig() { return has_mqtt_config_; } - bool HasWebsocketConfig() { return has_websocket_config_; } - bool HasActivationCode() { return has_activation_code_; } - bool HasServerTime() { return has_server_time_; } - bool StartUpgrade(std::function callback); - static bool Upgrade(const std::string& firmware_url, std::function callback); - void MarkCurrentVersionValid(); - - const std::string& GetFirmwareVersion() const { return firmware_version_; } - const std::string& GetCurrentVersion() const { return current_version_; } - const std::string& GetFirmwareUrl() const { return firmware_url_; } - const std::string& GetActivationMessage() const { return activation_message_; } - const std::string& GetActivationCode() const { return activation_code_; } - std::string GetCheckVersionUrl(); - -private: - std::string activation_message_; - std::string activation_code_; - bool has_new_version_ = false; - bool has_mqtt_config_ = false; - bool has_websocket_config_ = false; - bool has_server_time_ = false; - bool has_activation_code_ = false; - bool has_serial_number_ = false; - bool has_activation_challenge_ = false; - std::string current_version_; - std::string firmware_version_; - std::string firmware_url_; - std::string activation_challenge_; - std::string serial_number_; - int activation_timeout_ms_ = 30000; - - std::function upgrade_callback_; - std::vector ParseVersion(const std::string& version); - bool IsNewVersionAvailable(const std::string& currentVersion, const std::string& newVersion); - std::string GetActivationPayload(); - std::unique_ptr SetupHttp(); -}; - -#endif // _OTA_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.cc deleted file mode 100644 index e2dec435..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.cc +++ /dev/null @@ -1,382 +0,0 @@ -#include "mqtt_protocol.h" -#include "board.h" -#include "application.h" -#include "settings.h" - -#include -#include -#include -#include "assets/lang_config.h" - -#define TAG "MQTT" - -MqttProtocol::MqttProtocol() { - event_group_handle_ = xEventGroupCreate(); - - // Initialize reconnect timer - esp_timer_create_args_t reconnect_timer_args = { - .callback = [](void* arg) { - MqttProtocol* protocol = (MqttProtocol*)arg; - auto& app = Application::GetInstance(); - if (app.GetDeviceState() == kDeviceStateIdle) { - ESP_LOGI(TAG, "Reconnecting to MQTT server"); - auto alive = protocol->alive_; // Capture alive flag - app.Schedule([protocol, alive]() { - if (*alive) { - protocol->StartMqttClient(false); - } - }); - } - }, - .arg = this, - }; - esp_timer_create(&reconnect_timer_args, &reconnect_timer_); -} - -MqttProtocol::~MqttProtocol() { - ESP_LOGI(TAG, "MqttProtocol deinit"); - - // Mark as dead first to prevent any pending scheduled tasks from executing - *alive_ = false; - - if (reconnect_timer_ != nullptr) { - esp_timer_stop(reconnect_timer_); - esp_timer_delete(reconnect_timer_); - } - - udp_.reset(); - mqtt_.reset(); - - if (event_group_handle_ != nullptr) { - vEventGroupDelete(event_group_handle_); - } -} - -bool MqttProtocol::Start() { - return StartMqttClient(false); -} - -bool MqttProtocol::StartMqttClient(bool report_error) { - if (mqtt_ != nullptr) { - ESP_LOGW(TAG, "Mqtt client already started"); - mqtt_.reset(); - } - - Settings settings("mqtt", false); - auto endpoint = settings.GetString("endpoint"); - auto client_id = settings.GetString("client_id"); - auto username = settings.GetString("username"); - auto password = settings.GetString("password"); - int keepalive_interval = settings.GetInt("keepalive", 240); - publish_topic_ = settings.GetString("publish_topic"); - - if (endpoint.empty()) { - ESP_LOGW(TAG, "MQTT endpoint is not specified"); - if (report_error) { - SetError(Lang::Strings::SERVER_NOT_FOUND); - } - return false; - } - - auto network = Board::GetInstance().GetNetwork(); - mqtt_ = network->CreateMqtt(0); - mqtt_->SetKeepAlive(keepalive_interval); - - mqtt_->OnDisconnected([this]() { - if (on_disconnected_ != nullptr) { - on_disconnected_(); - } - ESP_LOGI(TAG, "MQTT disconnected, schedule reconnect in %d seconds", MQTT_RECONNECT_INTERVAL_MS / 1000); - esp_timer_start_once(reconnect_timer_, MQTT_RECONNECT_INTERVAL_MS * 1000); - }); - - mqtt_->OnConnected([this]() { - if (on_connected_ != nullptr) { - on_connected_(); - } - esp_timer_stop(reconnect_timer_); - }); - - mqtt_->OnMessage([this](const std::string& topic, const std::string& payload) { - cJSON* root = cJSON_Parse(payload.c_str()); - if (root == nullptr) { - ESP_LOGE(TAG, "Failed to parse json message %s", payload.c_str()); - return; - } - cJSON* type = cJSON_GetObjectItem(root, "type"); - if (!cJSON_IsString(type)) { - ESP_LOGE(TAG, "Message type is invalid"); - cJSON_Delete(root); - return; - } - - if (strcmp(type->valuestring, "hello") == 0) { - ParseServerHello(root); - } else if (strcmp(type->valuestring, "goodbye") == 0) { - auto session_id = cJSON_GetObjectItem(root, "session_id"); - ESP_LOGI(TAG, "Received goodbye message, session_id: %s", session_id ? session_id->valuestring : "null"); - if (session_id == nullptr || session_id_ == session_id->valuestring) { - auto alive = alive_; // Capture alive flag - Application::GetInstance().Schedule([this, alive]() { - if (*alive) { - CloseAudioChannel(); - } - }); - } - } else if (on_incoming_json_ != nullptr) { - on_incoming_json_(root); - } - cJSON_Delete(root); - last_incoming_time_ = std::chrono::steady_clock::now(); - }); - - ESP_LOGI(TAG, "Connecting to endpoint %s", endpoint.c_str()); - std::string broker_address; - int broker_port = 8883; - size_t pos = endpoint.find(':'); - if (pos != std::string::npos) { - broker_address = endpoint.substr(0, pos); - broker_port = std::stoi(endpoint.substr(pos + 1)); - } else { - broker_address = endpoint; - } - if (!mqtt_->Connect(broker_address, broker_port, client_id, username, password)) { - ESP_LOGE(TAG, "Failed to connect to endpoint, code=%d", mqtt_->GetLastError()); - SetError(Lang::Strings::SERVER_NOT_CONNECTED); - return false; - } - - ESP_LOGI(TAG, "Connected to endpoint"); - return true; -} - -bool MqttProtocol::SendText(const std::string& text) { - if (publish_topic_.empty()) { - return false; - } - if (!mqtt_->Publish(publish_topic_, text)) { - ESP_LOGE(TAG, "Failed to publish message: %s", text.c_str()); - SetError(Lang::Strings::SERVER_ERROR); - return false; - } - return true; -} - -bool MqttProtocol::SendAudio(std::unique_ptr packet) { - std::lock_guard lock(channel_mutex_); - if (udp_ == nullptr) { - return false; - } - - std::string nonce(aes_nonce_); - *(uint16_t*)&nonce[2] = htons(packet->payload.size()); - *(uint32_t*)&nonce[8] = htonl(packet->timestamp); - *(uint32_t*)&nonce[12] = htonl(++local_sequence_); - - std::string encrypted; - encrypted.resize(aes_nonce_.size() + packet->payload.size()); - memcpy(encrypted.data(), nonce.data(), nonce.size()); - - size_t nc_off = 0; - uint8_t stream_block[16] = {0}; - if (mbedtls_aes_crypt_ctr(&aes_ctx_, packet->payload.size(), &nc_off, (uint8_t*)nonce.c_str(), stream_block, - (uint8_t*)packet->payload.data(), (uint8_t*)&encrypted[nonce.size()]) != 0) { - ESP_LOGE(TAG, "Failed to encrypt audio data"); - return false; - } - - return udp_->Send(encrypted) > 0; -} - -void MqttProtocol::CloseAudioChannel() { - { - std::lock_guard lock(channel_mutex_); - udp_.reset(); - } - - std::string message = "{"; - message += "\"session_id\":\"" + session_id_ + "\","; - message += "\"type\":\"goodbye\""; - message += "}"; - SendText(message); - - if (on_audio_channel_closed_ != nullptr) { - on_audio_channel_closed_(); - } -} - -bool MqttProtocol::OpenAudioChannel() { - if (mqtt_ == nullptr || !mqtt_->IsConnected()) { - ESP_LOGI(TAG, "MQTT is not connected, try to connect now"); - if (!StartMqttClient(true)) { - return false; - } - } - - error_occurred_ = false; - session_id_ = ""; - xEventGroupClearBits(event_group_handle_, MQTT_PROTOCOL_SERVER_HELLO_EVENT); - - auto message = GetHelloMessage(); - if (!SendText(message)) { - return false; - } - - // 等待服务器响应 - EventBits_t bits = xEventGroupWaitBits(event_group_handle_, MQTT_PROTOCOL_SERVER_HELLO_EVENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000)); - if (!(bits & MQTT_PROTOCOL_SERVER_HELLO_EVENT)) { - ESP_LOGE(TAG, "Failed to receive server hello"); - SetError(Lang::Strings::SERVER_TIMEOUT); - return false; - } - - std::lock_guard lock(channel_mutex_); - auto network = Board::GetInstance().GetNetwork(); - udp_ = network->CreateUdp(2); - udp_->OnMessage([this](const std::string& data) { - /* - * UDP Encrypted OPUS Packet Format: - * |type 1u|flags 1u|payload_len 2u|ssrc 4u|timestamp 4u|sequence 4u| - * |payload payload_len| - */ - if (data.size() < sizeof(aes_nonce_)) { - ESP_LOGE(TAG, "Invalid audio packet size: %u", data.size()); - return; - } - if (data[0] != 0x01) { - ESP_LOGE(TAG, "Invalid audio packet type: %x", data[0]); - return; - } - uint32_t timestamp = ntohl(*(uint32_t*)&data[8]); - uint32_t sequence = ntohl(*(uint32_t*)&data[12]); - if (sequence < remote_sequence_) { - ESP_LOGW(TAG, "Received audio packet with old sequence: %lu, expected: %lu", sequence, remote_sequence_); - return; - } - if (sequence != remote_sequence_ + 1) { - ESP_LOGW(TAG, "Received audio packet with wrong sequence: %lu, expected: %lu", sequence, remote_sequence_ + 1); - } - - size_t decrypted_size = data.size() - aes_nonce_.size(); - size_t nc_off = 0; - uint8_t stream_block[16] = {0}; - auto nonce = (uint8_t*)data.data(); - auto encrypted = (uint8_t*)data.data() + aes_nonce_.size(); - auto packet = std::make_unique(); - packet->sample_rate = server_sample_rate_; - packet->frame_duration = server_frame_duration_; - packet->timestamp = timestamp; - packet->payload.resize(decrypted_size); - int ret = mbedtls_aes_crypt_ctr(&aes_ctx_, decrypted_size, &nc_off, nonce, stream_block, encrypted, (uint8_t*)packet->payload.data()); - if (ret != 0) { - ESP_LOGE(TAG, "Failed to decrypt audio data, ret: %d", ret); - return; - } - if (on_incoming_audio_ != nullptr) { - on_incoming_audio_(std::move(packet)); - } - remote_sequence_ = sequence; - last_incoming_time_ = std::chrono::steady_clock::now(); - }); - - udp_->Connect(udp_server_, udp_port_); - - if (on_audio_channel_opened_ != nullptr) { - on_audio_channel_opened_(); - } - return true; -} - -std::string MqttProtocol::GetHelloMessage() { - // 发送 hello 消息申请 UDP 通道 - cJSON* root = cJSON_CreateObject(); - cJSON_AddStringToObject(root, "type", "hello"); - cJSON_AddNumberToObject(root, "version", 3); - cJSON_AddStringToObject(root, "transport", "udp"); - cJSON* features = cJSON_CreateObject(); -#if CONFIG_USE_SERVER_AEC - cJSON_AddBoolToObject(features, "aec", true); -#endif - cJSON_AddBoolToObject(features, "mcp", true); - cJSON_AddItemToObject(root, "features", features); - cJSON* audio_params = cJSON_CreateObject(); - cJSON_AddStringToObject(audio_params, "format", "opus"); - cJSON_AddNumberToObject(audio_params, "sample_rate", 16000); - cJSON_AddNumberToObject(audio_params, "channels", 1); - cJSON_AddNumberToObject(audio_params, "frame_duration", OPUS_FRAME_DURATION_MS); - cJSON_AddItemToObject(root, "audio_params", audio_params); - auto json_str = cJSON_PrintUnformatted(root); - std::string message(json_str); - cJSON_free(json_str); - cJSON_Delete(root); - return message; -} - -void MqttProtocol::ParseServerHello(const cJSON* root) { - auto transport = cJSON_GetObjectItem(root, "transport"); - if (transport == nullptr || strcmp(transport->valuestring, "udp") != 0) { - ESP_LOGE(TAG, "Unsupported transport: %s", transport->valuestring); - return; - } - - auto session_id = cJSON_GetObjectItem(root, "session_id"); - if (cJSON_IsString(session_id)) { - session_id_ = session_id->valuestring; - ESP_LOGI(TAG, "Session ID: %s", session_id_.c_str()); - } - - // Get sample rate from hello message - auto audio_params = cJSON_GetObjectItem(root, "audio_params"); - if (cJSON_IsObject(audio_params)) { - auto sample_rate = cJSON_GetObjectItem(audio_params, "sample_rate"); - if (cJSON_IsNumber(sample_rate)) { - server_sample_rate_ = sample_rate->valueint; - } - auto frame_duration = cJSON_GetObjectItem(audio_params, "frame_duration"); - if (cJSON_IsNumber(frame_duration)) { - server_frame_duration_ = frame_duration->valueint; - } - } - - auto udp = cJSON_GetObjectItem(root, "udp"); - if (!cJSON_IsObject(udp)) { - ESP_LOGE(TAG, "UDP is not specified"); - return; - } - udp_server_ = cJSON_GetObjectItem(udp, "server")->valuestring; - udp_port_ = cJSON_GetObjectItem(udp, "port")->valueint; - auto key = cJSON_GetObjectItem(udp, "key")->valuestring; - auto nonce = cJSON_GetObjectItem(udp, "nonce")->valuestring; - - // auto encryption = cJSON_GetObjectItem(udp, "encryption")->valuestring; - // ESP_LOGI(TAG, "UDP server: %s, port: %d, encryption: %s", udp_server_.c_str(), udp_port_, encryption); - aes_nonce_ = DecodeHexString(nonce); - mbedtls_aes_init(&aes_ctx_); - mbedtls_aes_setkey_enc(&aes_ctx_, (const unsigned char*)DecodeHexString(key).c_str(), 128); - local_sequence_ = 0; - remote_sequence_ = 0; - xEventGroupSetBits(event_group_handle_, MQTT_PROTOCOL_SERVER_HELLO_EVENT); -} - -static const char hex_chars[] = "0123456789ABCDEF"; -// 辅助函数,将单个十六进制字符转换为对应的数值 -static inline uint8_t CharToHex(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c >= 'A' && c <= 'F') return c - 'A' + 10; - if (c >= 'a' && c <= 'f') return c - 'a' + 10; - return 0; // 对于无效输入,返回0 -} - -std::string MqttProtocol::DecodeHexString(const std::string& hex_string) { - std::string decoded; - decoded.reserve(hex_string.size() / 2); - for (size_t i = 0; i < hex_string.size(); i += 2) { - char byte = (CharToHex(hex_string[i]) << 4) | CharToHex(hex_string[i + 1]); - decoded.push_back(byte); - } - return decoded; -} - -bool MqttProtocol::IsAudioChannelOpened() const { - return udp_ != nullptr && !error_occurred_ && !IsTimeout(); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.h deleted file mode 100644 index aadb9484..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/mqtt_protocol.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef MQTT_PROTOCOL_H -#define MQTT_PROTOCOL_H - - -#include "protocol.h" -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#define MQTT_PING_INTERVAL_SECONDS 90 -#define MQTT_RECONNECT_INTERVAL_MS 60000 - -#define MQTT_PROTOCOL_SERVER_HELLO_EVENT (1 << 0) - -class MqttProtocol : public Protocol { -public: - MqttProtocol(); - ~MqttProtocol(); - - bool Start() override; - bool SendAudio(std::unique_ptr packet) override; - bool OpenAudioChannel() override; - void CloseAudioChannel() override; - bool IsAudioChannelOpened() const override; - -private: - // Alive flag for safe scheduled callbacks - set to false in destructor - std::shared_ptr> alive_ = std::make_shared>(true); - - EventGroupHandle_t event_group_handle_; - - std::string publish_topic_; - - std::mutex channel_mutex_; - std::unique_ptr mqtt_; - std::unique_ptr udp_; - mbedtls_aes_context aes_ctx_; - std::string aes_nonce_; - std::string udp_server_; - int udp_port_; - uint32_t local_sequence_; - uint32_t remote_sequence_; - esp_timer_handle_t reconnect_timer_; - - bool StartMqttClient(bool report_error=false); - void ParseServerHello(const cJSON* root); - std::string DecodeHexString(const std::string& hex_string); - - bool SendText(const std::string& text) override; - std::string GetHelloMessage(); -}; - - -#endif // MQTT_PROTOCOL_H diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.cc deleted file mode 100644 index 470cc915..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.cc +++ /dev/null @@ -1,90 +0,0 @@ -#include "protocol.h" - -#include - -#define TAG "Protocol" - -void Protocol::OnIncomingJson(std::function callback) { - on_incoming_json_ = callback; -} - -void Protocol::OnIncomingAudio(std::function packet)> callback) { - on_incoming_audio_ = callback; -} - -void Protocol::OnAudioChannelOpened(std::function callback) { - on_audio_channel_opened_ = callback; -} - -void Protocol::OnAudioChannelClosed(std::function callback) { - on_audio_channel_closed_ = callback; -} - -void Protocol::OnNetworkError(std::function callback) { - on_network_error_ = callback; -} - -void Protocol::OnConnected(std::function callback) { - on_connected_ = callback; -} - -void Protocol::OnDisconnected(std::function callback) { - on_disconnected_ = callback; -} - -void Protocol::SetError(const std::string& message) { - error_occurred_ = true; - if (on_network_error_ != nullptr) { - on_network_error_(message); - } -} - -void Protocol::SendAbortSpeaking(AbortReason reason) { - std::string message = "{\"session_id\":\"" + session_id_ + "\",\"type\":\"abort\""; - if (reason == kAbortReasonWakeWordDetected) { - message += ",\"reason\":\"wake_word_detected\""; - } - message += "}"; - SendText(message); -} - -void Protocol::SendWakeWordDetected(const std::string& wake_word) { - std::string json = "{\"session_id\":\"" + session_id_ + - "\",\"type\":\"listen\",\"state\":\"detect\",\"text\":\"" + wake_word + "\"}"; - SendText(json); -} - -void Protocol::SendStartListening(ListeningMode mode) { - std::string message = "{\"session_id\":\"" + session_id_ + "\""; - message += ",\"type\":\"listen\",\"state\":\"start\""; - if (mode == kListeningModeRealtime) { - message += ",\"mode\":\"realtime\""; - } else if (mode == kListeningModeAutoStop) { - message += ",\"mode\":\"auto\""; - } else { - message += ",\"mode\":\"manual\""; - } - message += "}"; - SendText(message); -} - -void Protocol::SendStopListening() { - std::string message = "{\"session_id\":\"" + session_id_ + "\",\"type\":\"listen\",\"state\":\"stop\"}"; - SendText(message); -} - -void Protocol::SendMcpMessage(const std::string& payload) { - std::string message = "{\"session_id\":\"" + session_id_ + "\",\"type\":\"mcp\",\"payload\":" + payload + "}"; - SendText(message); -} - -bool Protocol::IsTimeout() const { - const int kTimeoutSeconds = 120; - auto now = std::chrono::steady_clock::now(); - auto duration = std::chrono::duration_cast(now - last_incoming_time_); - bool timeout = duration.count() > kTimeoutSeconds; - if (timeout) { - ESP_LOGE(TAG, "Channel timeout %ld seconds", (long)duration.count()); - } - return timeout; -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.h deleted file mode 100644 index 17ab3159..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/protocol.h +++ /dev/null @@ -1,98 +0,0 @@ -#ifndef PROTOCOL_H -#define PROTOCOL_H - -#include -#include -#include -#include -#include - -struct AudioStreamPacket { - int sample_rate = 0; - int frame_duration = 0; - uint32_t timestamp = 0; - std::vector payload; -}; - -struct BinaryProtocol2 { - uint16_t version; - uint16_t type; // Message type (0: OPUS, 1: JSON) - uint32_t reserved; // Reserved for future use - uint32_t timestamp; // Timestamp in milliseconds (used for server-side AEC) - uint32_t payload_size; // Payload size in bytes - uint8_t payload[]; // Payload data -} __attribute__((packed)); - -struct BinaryProtocol3 { - uint8_t type; - uint8_t reserved; - uint16_t payload_size; - uint8_t payload[]; -} __attribute__((packed)); - -enum AbortReason { - kAbortReasonNone, - kAbortReasonWakeWordDetected -}; - -enum ListeningMode { - kListeningModeAutoStop, - kListeningModeManualStop, - kListeningModeRealtime // 需要 AEC 支持 -}; - -class Protocol { -public: - virtual ~Protocol() = default; - - inline int server_sample_rate() const { - return server_sample_rate_; - } - inline int server_frame_duration() const { - return server_frame_duration_; - } - inline const std::string& session_id() const { - return session_id_; - } - - void OnIncomingAudio(std::function packet)> callback); - void OnIncomingJson(std::function callback); - void OnAudioChannelOpened(std::function callback); - void OnAudioChannelClosed(std::function callback); - void OnNetworkError(std::function callback); - void OnConnected(std::function callback); - void OnDisconnected(std::function callback); - - virtual bool Start() = 0; - virtual bool OpenAudioChannel() = 0; - virtual void CloseAudioChannel() = 0; - virtual bool IsAudioChannelOpened() const = 0; - virtual bool SendAudio(std::unique_ptr packet) = 0; - virtual void SendWakeWordDetected(const std::string& wake_word); - virtual void SendStartListening(ListeningMode mode); - virtual void SendStopListening(); - virtual void SendAbortSpeaking(AbortReason reason); - virtual void SendMcpMessage(const std::string& message); - -protected: - std::function on_incoming_json_; - std::function packet)> on_incoming_audio_; - std::function on_audio_channel_opened_; - std::function on_audio_channel_closed_; - std::function on_network_error_; - std::function on_connected_; - std::function on_disconnected_; - - int server_sample_rate_ = 24000; - int server_frame_duration_ = 60; - bool error_occurred_ = false; - std::string session_id_; - std::chrono::time_point last_incoming_time_; - - virtual bool SendText(const std::string& text) = 0; - virtual void SetError(const std::string& message); - virtual bool IsTimeout() const; -}; - -#endif // PROTOCOL_H - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.cc deleted file mode 100644 index a8f8cf38..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.cc +++ /dev/null @@ -1,253 +0,0 @@ -#include "websocket_protocol.h" -#include "board.h" -#include "system_info.h" -#include "application.h" -#include "settings.h" - -#include -#include -#include -#include -#include "assets/lang_config.h" - -#define TAG "WS" - -WebsocketProtocol::WebsocketProtocol() { - event_group_handle_ = xEventGroupCreate(); -} - -WebsocketProtocol::~WebsocketProtocol() { - vEventGroupDelete(event_group_handle_); -} - -bool WebsocketProtocol::Start() { - // Only connect to server when audio channel is needed - return true; -} - -bool WebsocketProtocol::SendAudio(std::unique_ptr packet) { - if (websocket_ == nullptr || !websocket_->IsConnected()) { - return false; - } - - if (version_ == 2) { - std::string serialized; - serialized.resize(sizeof(BinaryProtocol2) + packet->payload.size()); - auto bp2 = (BinaryProtocol2*)serialized.data(); - bp2->version = htons(version_); - bp2->type = 0; - bp2->reserved = 0; - bp2->timestamp = htonl(packet->timestamp); - bp2->payload_size = htonl(packet->payload.size()); - memcpy(bp2->payload, packet->payload.data(), packet->payload.size()); - - return websocket_->Send(serialized.data(), serialized.size(), true); - } else if (version_ == 3) { - std::string serialized; - serialized.resize(sizeof(BinaryProtocol3) + packet->payload.size()); - auto bp3 = (BinaryProtocol3*)serialized.data(); - bp3->type = 0; - bp3->reserved = 0; - bp3->payload_size = htons(packet->payload.size()); - memcpy(bp3->payload, packet->payload.data(), packet->payload.size()); - - return websocket_->Send(serialized.data(), serialized.size(), true); - } else { - return websocket_->Send(packet->payload.data(), packet->payload.size(), true); - } -} - -bool WebsocketProtocol::SendText(const std::string& text) { - if (websocket_ == nullptr || !websocket_->IsConnected()) { - return false; - } - - if (!websocket_->Send(text)) { - ESP_LOGE(TAG, "Failed to send text: %s", text.c_str()); - SetError(Lang::Strings::SERVER_ERROR); - return false; - } - - return true; -} - -bool WebsocketProtocol::IsAudioChannelOpened() const { - return websocket_ != nullptr && websocket_->IsConnected() && !error_occurred_ && !IsTimeout(); -} - -void WebsocketProtocol::CloseAudioChannel() { - websocket_.reset(); -} - -bool WebsocketProtocol::OpenAudioChannel() { - Settings settings("websocket", false); - std::string url = settings.GetString("url"); - std::string token = settings.GetString("token"); - int version = settings.GetInt("version"); - if (version != 0) { - version_ = version; - } - - error_occurred_ = false; - - auto network = Board::GetInstance().GetNetwork(); - websocket_ = network->CreateWebSocket(1); - if (websocket_ == nullptr) { - ESP_LOGE(TAG, "Failed to create websocket"); - return false; - } - - if (!token.empty()) { - // If token not has a space, add "Bearer " prefix - if (token.find(" ") == std::string::npos) { - token = "Bearer " + token; - } - websocket_->SetHeader("Authorization", token.c_str()); - } - websocket_->SetHeader("Protocol-Version", std::to_string(version_).c_str()); - websocket_->SetHeader("Device-Id", SystemInfo::GetMacAddress().c_str()); - websocket_->SetHeader("Client-Id", Board::GetInstance().GetUuid().c_str()); - - websocket_->OnData([this](const char* data, size_t len, bool binary) { - if (binary) { - if (on_incoming_audio_ != nullptr) { - if (version_ == 2) { - BinaryProtocol2* bp2 = (BinaryProtocol2*)data; - bp2->version = ntohs(bp2->version); - bp2->type = ntohs(bp2->type); - bp2->timestamp = ntohl(bp2->timestamp); - bp2->payload_size = ntohl(bp2->payload_size); - auto payload = (uint8_t*)bp2->payload; - on_incoming_audio_(std::make_unique(AudioStreamPacket{ - .sample_rate = server_sample_rate_, - .frame_duration = server_frame_duration_, - .timestamp = bp2->timestamp, - .payload = std::vector(payload, payload + bp2->payload_size) - })); - } else if (version_ == 3) { - BinaryProtocol3* bp3 = (BinaryProtocol3*)data; - bp3->type = bp3->type; - bp3->payload_size = ntohs(bp3->payload_size); - auto payload = (uint8_t*)bp3->payload; - on_incoming_audio_(std::make_unique(AudioStreamPacket{ - .sample_rate = server_sample_rate_, - .frame_duration = server_frame_duration_, - .timestamp = 0, - .payload = std::vector(payload, payload + bp3->payload_size) - })); - } else { - on_incoming_audio_(std::make_unique(AudioStreamPacket{ - .sample_rate = server_sample_rate_, - .frame_duration = server_frame_duration_, - .timestamp = 0, - .payload = std::vector((uint8_t*)data, (uint8_t*)data + len) - })); - } - } - } else { - // Parse JSON data - auto root = cJSON_Parse(data); - auto type = cJSON_GetObjectItem(root, "type"); - if (cJSON_IsString(type)) { - if (strcmp(type->valuestring, "hello") == 0) { - ParseServerHello(root); - } else { - if (on_incoming_json_ != nullptr) { - on_incoming_json_(root); - } - } - } else { - ESP_LOGE(TAG, "Missing message type, data: %s", data); - } - cJSON_Delete(root); - } - last_incoming_time_ = std::chrono::steady_clock::now(); - }); - - websocket_->OnDisconnected([this]() { - ESP_LOGI(TAG, "Websocket disconnected"); - if (on_audio_channel_closed_ != nullptr) { - on_audio_channel_closed_(); - } - }); - - ESP_LOGI(TAG, "Connecting to websocket server: %s with version: %d", url.c_str(), version_); - if (!websocket_->Connect(url.c_str())) { - ESP_LOGE(TAG, "Failed to connect to websocket server, code=%d", websocket_->GetLastError()); - SetError(Lang::Strings::SERVER_NOT_CONNECTED); - return false; - } - - // Send hello message to describe the client - auto message = GetHelloMessage(); - if (!SendText(message)) { - return false; - } - - // Wait for server hello - EventBits_t bits = xEventGroupWaitBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT, pdTRUE, pdFALSE, pdMS_TO_TICKS(10000)); - if (!(bits & WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT)) { - ESP_LOGE(TAG, "Failed to receive server hello"); - SetError(Lang::Strings::SERVER_TIMEOUT); - return false; - } - - if (on_audio_channel_opened_ != nullptr) { - on_audio_channel_opened_(); - } - - return true; -} - -std::string WebsocketProtocol::GetHelloMessage() { - // keys: message type, version, audio_params (format, sample_rate, channels) - cJSON* root = cJSON_CreateObject(); - cJSON_AddStringToObject(root, "type", "hello"); - cJSON_AddNumberToObject(root, "version", version_); - cJSON* features = cJSON_CreateObject(); -#if CONFIG_USE_SERVER_AEC - cJSON_AddBoolToObject(features, "aec", true); -#endif - cJSON_AddBoolToObject(features, "mcp", true); - cJSON_AddItemToObject(root, "features", features); - cJSON_AddStringToObject(root, "transport", "websocket"); - cJSON* audio_params = cJSON_CreateObject(); - cJSON_AddStringToObject(audio_params, "format", "opus"); - cJSON_AddNumberToObject(audio_params, "sample_rate", 16000); - cJSON_AddNumberToObject(audio_params, "channels", 1); - cJSON_AddNumberToObject(audio_params, "frame_duration", OPUS_FRAME_DURATION_MS); - cJSON_AddItemToObject(root, "audio_params", audio_params); - auto json_str = cJSON_PrintUnformatted(root); - std::string message(json_str); - cJSON_free(json_str); - cJSON_Delete(root); - return message; -} - -void WebsocketProtocol::ParseServerHello(const cJSON* root) { - auto transport = cJSON_GetObjectItem(root, "transport"); - if (transport == nullptr || strcmp(transport->valuestring, "websocket") != 0) { - ESP_LOGE(TAG, "Unsupported transport: %s", transport->valuestring); - return; - } - - auto session_id = cJSON_GetObjectItem(root, "session_id"); - if (cJSON_IsString(session_id)) { - session_id_ = session_id->valuestring; - ESP_LOGI(TAG, "Session ID: %s", session_id_.c_str()); - } - - auto audio_params = cJSON_GetObjectItem(root, "audio_params"); - if (cJSON_IsObject(audio_params)) { - auto sample_rate = cJSON_GetObjectItem(audio_params, "sample_rate"); - if (cJSON_IsNumber(sample_rate)) { - server_sample_rate_ = sample_rate->valueint; - } - auto frame_duration = cJSON_GetObjectItem(audio_params, "frame_duration"); - if (cJSON_IsNumber(frame_duration)) { - server_frame_duration_ = frame_duration->valueint; - } - } - - xEventGroupSetBits(event_group_handle_, WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.h deleted file mode 100644 index 8c7dd65b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/protocols/websocket_protocol.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _WEBSOCKET_PROTOCOL_H_ -#define _WEBSOCKET_PROTOCOL_H_ - - -#include "protocol.h" - -#include -#include -#include - -#define WEBSOCKET_PROTOCOL_SERVER_HELLO_EVENT (1 << 0) - -class WebsocketProtocol : public Protocol { -public: - WebsocketProtocol(); - ~WebsocketProtocol(); - - bool Start() override; - bool SendAudio(std::unique_ptr packet) override; - bool OpenAudioChannel() override; - void CloseAudioChannel() override; - bool IsAudioChannelOpened() const override; - -private: - EventGroupHandle_t event_group_handle_; - std::unique_ptr websocket_; - int version_ = 1; - - void ParseServerHello(const cJSON* root); - bool SendText(const std::string& text) override; - std::string GetHelloMessage(); -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.cc deleted file mode 100644 index 3b40622b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.cc +++ /dev/null @@ -1,108 +0,0 @@ -#include "settings.h" - -#include -#include - -#define TAG "Settings" - -Settings::Settings(const std::string& ns, bool read_write) : ns_(ns), read_write_(read_write) { - nvs_open(ns.c_str(), read_write_ ? NVS_READWRITE : NVS_READONLY, &nvs_handle_); -} - -Settings::~Settings() { - if (nvs_handle_ != 0) { - if (read_write_ && dirty_) { - ESP_ERROR_CHECK(nvs_commit(nvs_handle_)); - } - nvs_close(nvs_handle_); - } -} - -std::string Settings::GetString(const std::string& key, const std::string& default_value) { - if (nvs_handle_ == 0) { - return default_value; - } - - size_t length = 0; - if (nvs_get_str(nvs_handle_, key.c_str(), nullptr, &length) != ESP_OK) { - return default_value; - } - - std::string value; - value.resize(length); - ESP_ERROR_CHECK(nvs_get_str(nvs_handle_, key.c_str(), value.data(), &length)); - while (!value.empty() && value.back() == '\0') { - value.pop_back(); - } - return value; -} - -void Settings::SetString(const std::string& key, const std::string& value) { - if (read_write_) { - ESP_ERROR_CHECK(nvs_set_str(nvs_handle_, key.c_str(), value.c_str())); - dirty_ = true; - } else { - ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); - } -} - -int32_t Settings::GetInt(const std::string& key, int32_t default_value) { - if (nvs_handle_ == 0) { - return default_value; - } - - int32_t value; - if (nvs_get_i32(nvs_handle_, key.c_str(), &value) != ESP_OK) { - return default_value; - } - return value; -} - -void Settings::SetInt(const std::string& key, int32_t value) { - if (read_write_) { - ESP_ERROR_CHECK(nvs_set_i32(nvs_handle_, key.c_str(), value)); - dirty_ = true; - } else { - ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); - } -} - -bool Settings::GetBool(const std::string& key, bool default_value) { - if (nvs_handle_ == 0) { - return default_value; - } - - uint8_t value; - if (nvs_get_u8(nvs_handle_, key.c_str(), &value) != ESP_OK) { - return default_value; - } - return value != 0; -} - -void Settings::SetBool(const std::string& key, bool value) { - if (read_write_) { - ESP_ERROR_CHECK(nvs_set_u8(nvs_handle_, key.c_str(), value ? 1 : 0)); - dirty_ = true; - } else { - ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); - } -} - -void Settings::EraseKey(const std::string& key) { - if (read_write_) { - auto ret = nvs_erase_key(nvs_handle_, key.c_str()); - if (ret != ESP_ERR_NVS_NOT_FOUND) { - ESP_ERROR_CHECK(ret); - } - } else { - ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); - } -} - -void Settings::EraseAll() { - if (read_write_) { - ESP_ERROR_CHECK(nvs_erase_all(nvs_handle_)); - } else { - ESP_LOGW(TAG, "Namespace %s is not open for writing", ns_.c_str()); - } -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.h deleted file mode 100644 index 7eb596ec..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/settings.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef SETTINGS_H -#define SETTINGS_H - -#include -#include - -class Settings { -public: - Settings(const std::string& ns, bool read_write = false); - ~Settings(); - - std::string GetString(const std::string& key, const std::string& default_value = ""); - void SetString(const std::string& key, const std::string& value); - int32_t GetInt(const std::string& key, int32_t default_value = 0); - void SetInt(const std::string& key, int32_t value); - bool GetBool(const std::string& key, bool default_value = false); - void SetBool(const std::string& key, bool value); - void EraseKey(const std::string& key); - void EraseAll(); - -private: - std::string ns_; - nvs_handle_t nvs_handle_ = 0; - bool read_write_ = false; - bool dirty_ = false; -}; - -#endif diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.cc b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.cc deleted file mode 100644 index 51b00724..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.cc +++ /dev/null @@ -1,151 +0,0 @@ -#include "system_info.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#if CONFIG_IDF_TARGET_ESP32P4 -#include "esp_wifi_remote.h" -#endif - -#define TAG "SystemInfo" - -size_t SystemInfo::GetFlashSize() { - uint32_t flash_size; - if (esp_flash_get_size(NULL, &flash_size) != ESP_OK) { - ESP_LOGE(TAG, "Failed to get flash size"); - return 0; - } - return (size_t)flash_size; -} - -size_t SystemInfo::GetMinimumFreeHeapSize() { - return esp_get_minimum_free_heap_size(); -} - -size_t SystemInfo::GetFreeHeapSize() { - return esp_get_free_heap_size(); -} - -std::string SystemInfo::GetMacAddress() { - uint8_t mac[6]; -#if CONFIG_IDF_TARGET_ESP32P4 - esp_wifi_get_mac(WIFI_IF_STA, mac); -#else - esp_read_mac(mac, ESP_MAC_WIFI_STA); -#endif - char mac_str[18]; - snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return std::string(mac_str); -} - -std::string SystemInfo::GetChipModelName() { - return std::string(CONFIG_IDF_TARGET); -} - -std::string SystemInfo::GetUserAgent() { - auto app_desc = esp_app_get_description(); - auto user_agent = std::string(BOARD_NAME "/") + app_desc->version; - return user_agent; -} - -esp_err_t SystemInfo::PrintTaskCpuUsage(TickType_t xTicksToWait) { - #define ARRAY_SIZE_OFFSET 5 - TaskStatus_t *start_array = NULL, *end_array = NULL; - UBaseType_t start_array_size, end_array_size; - configRUN_TIME_COUNTER_TYPE start_run_time, end_run_time; - esp_err_t ret; - uint32_t total_elapsed_time; - - //Allocate array to store current task states - start_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET; - start_array = (TaskStatus_t*)malloc(sizeof(TaskStatus_t) * start_array_size); - if (start_array == NULL) { - ret = ESP_ERR_NO_MEM; - goto exit; - } - //Get current task states - start_array_size = uxTaskGetSystemState(start_array, start_array_size, &start_run_time); - if (start_array_size == 0) { - ret = ESP_ERR_INVALID_SIZE; - goto exit; - } - - vTaskDelay(xTicksToWait); - - //Allocate array to store tasks states post delay - end_array_size = uxTaskGetNumberOfTasks() + ARRAY_SIZE_OFFSET; - end_array = (TaskStatus_t*)malloc(sizeof(TaskStatus_t) * end_array_size); - if (end_array == NULL) { - ret = ESP_ERR_NO_MEM; - goto exit; - } - //Get post delay task states - end_array_size = uxTaskGetSystemState(end_array, end_array_size, &end_run_time); - if (end_array_size == 0) { - ret = ESP_ERR_INVALID_SIZE; - goto exit; - } - - //Calculate total_elapsed_time in units of run time stats clock period. - total_elapsed_time = (end_run_time - start_run_time); - if (total_elapsed_time == 0) { - ret = ESP_ERR_INVALID_STATE; - goto exit; - } - - printf("| Task | Run Time | Percentage\n"); - //Match each task in start_array to those in the end_array - for (int i = 0; i < start_array_size; i++) { - int k = -1; - for (int j = 0; j < end_array_size; j++) { - if (start_array[i].xHandle == end_array[j].xHandle) { - k = j; - //Mark that task have been matched by overwriting their handles - start_array[i].xHandle = NULL; - end_array[j].xHandle = NULL; - break; - } - } - //Check if matching task found - if (k >= 0) { - uint32_t task_elapsed_time = end_array[k].ulRunTimeCounter - start_array[i].ulRunTimeCounter; - uint32_t percentage_time = (task_elapsed_time * 100UL) / (total_elapsed_time * CONFIG_FREERTOS_NUMBER_OF_CORES); - printf("| %-16s | %8lu | %4lu%%\n", start_array[i].pcTaskName, task_elapsed_time, percentage_time); - } - } - - //Print unmatched tasks - for (int i = 0; i < start_array_size; i++) { - if (start_array[i].xHandle != NULL) { - printf("| %s | Deleted\n", start_array[i].pcTaskName); - } - } - for (int i = 0; i < end_array_size; i++) { - if (end_array[i].xHandle != NULL) { - printf("| %s | Created\n", end_array[i].pcTaskName); - } - } - ret = ESP_OK; - -exit: //Common return path - free(start_array); - free(end_array); - return ret; -} - -void SystemInfo::PrintTaskList() { - char buffer[1000]; - vTaskList(buffer); - ESP_LOGI(TAG, "Task list: \n%s", buffer); -} - -void SystemInfo::PrintHeapStats() { - int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); - int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); - ESP_LOGI(TAG, "free sram: %u minimal sram: %u", free_sram, min_free_sram); -} diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.h b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.h deleted file mode 100644 index a466d712..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/system_info.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _SYSTEM_INFO_H_ -#define _SYSTEM_INFO_H_ - -#include - -#include -#include - -class SystemInfo { -public: - static size_t GetFlashSize(); - static size_t GetMinimumFreeHeapSize(); - static size_t GetFreeHeapSize(); - static std::string GetMacAddress(); - static std::string GetChipModelName(); - static std::string GetUserAgent(); - static esp_err_t PrintTaskCpuUsage(TickType_t xTicksToWait); - static void PrintTaskList(); - static void PrintHeapStats(); -}; - -#endif // _SYSTEM_INFO_H_ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m.csv deleted file mode 100644 index bc3a0e86..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0xF0000, -ota_0, app, ota_0, 0x100000, 6M, -ota_1, app, ota_1, 0x700000, 6M, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_custom_wakeword.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_custom_wakeword.csv deleted file mode 100644 index 868294e5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_custom_wakeword.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0x3f0000, -ota_0, app, ota_0, 0x400000, 6M, -ota_1, app, ota_1, 0xa00000, 6M, \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_echoear.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_echoear.csv deleted file mode 100644 index 543c92ce..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/16m_echoear.csv +++ /dev/null @@ -1,9 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0xF0000, -ota_0, app, ota_0, 0x100000, 5M, -ota_1, app, ota_1, 0x700000, 5M, -assets_A, data, spiffs, , 4000K, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/32m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/32m.csv deleted file mode 100644 index e95eb22f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/32m.csv +++ /dev/null @@ -1,10 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvsfactory, data, nvs, , 200K, -nvs, data, nvs, , 840K, -otadata, data, ota, , 0x2000, -phy_init, data, phy, , 0x1000, -model, data, spiffs, , 0xF0000, -# According to scripts/versions.py, app partition must be aligned to 1MB -ota_0, app, ota_0, 0x200000, 12M, -ota_1, app, ota_1, , 12M, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m.csv deleted file mode 100644 index 101349fe..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m.csv +++ /dev/null @@ -1,7 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0xF0000, -factory, app, factory, 0x100000, 3M, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m_esp-hi.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m_esp-hi.csv deleted file mode 100644 index 90c9c43c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/4m_esp-hi.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0xD0000, -factory, app, factory, 0xe0000, 2200K, -assets_A, data, spiffs, , 700K, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/8m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/8m.csv deleted file mode 100644 index 1e0e9430..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v1/8m.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -model, data, spiffs, 0x10000, 0xF0000, -ota_0, app, ota_0, 0x100000, 0x380000, -ota_1, app, ota_1, 0x480000, 0x380000, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m.csv deleted file mode 100644 index 8af93a35..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -ota_0, app, ota_0, 0x20000, 0x3f0000, -ota_1, app, ota_1, , 0x3f0000, -assets, data, spiffs, 0x800000, 8M diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m_c3.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m_c3.csv deleted file mode 100644 index e4440235..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/16m_c3.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -ota_0, app, ota_0, 0x20000, 0x3f0000, -ota_1, app, ota_1, , 0x3f0000, -assets, data, spiffs, 0x800000, 4000K diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/32m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/32m.csv deleted file mode 100644 index d829cbb9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/32m.csv +++ /dev/null @@ -1,9 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvsfactory, data, nvs, , 200K, -nvs, data, nvs, , 840K, -otadata, data, ota, , 0x2000, -phy_init, data, phy, , 0x1000, -ota_0, app, ota_0, 0x200000, 4M, -ota_1, app, ota_1, 0x600000, 4M, -assets, data, spiffs, 0xA00000, 16M diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/4m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/4m.csv deleted file mode 100644 index 0d2ceae8..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/4m.csv +++ /dev/null @@ -1,7 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 0x270000, -assets, data, spiffs, 0x280000, 0x180000, diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/8m.csv b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/8m.csv deleted file mode 100644 index bae9f150..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/8m.csv +++ /dev/null @@ -1,8 +0,0 @@ -# ESP-IDF Partition Table -# Name, Type, SubType, Offset, Size, Flags -nvs, data, nvs, 0x9000, 0x4000, -otadata, data, ota, 0xd000, 0x2000, -phy_init, data, phy, 0xf000, 0x1000, -ota_0, app, ota_0, 0x20000, 0x2f0000, -ota_1, app, ota_1, , 0x2f0000, -assets, data, spiffs, 0x600000, 2M diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/README.md deleted file mode 100644 index 0b56851e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/partitions/v2/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# Version 2 Partition Table - -This version introduces significant improvements over v1 by adding an `assets` partition to support network-loadable content and optimizing partition layouts for different flash sizes. - -## Key Changes from v1 - -### Major Improvements -1. **Added Assets Partition**: New `assets` partition for network-loadable content -2. **Replaced Model Partition**: The old `model` partition (960KB) is replaced with a larger `assets` partition -3. **Optimized App Partitions**: Reduced application partition sizes to accommodate assets -4. **Enhanced Flexibility**: Support for dynamic content updates without reflashing - -### Assets Partition Features -The `assets` partition stores: -- **Wake word models**: Customizable wake word models that can be loaded from the network -- **Theme files**: Complete theming system including: - - Fonts (text and icon fonts) - - Audio effects and sound files - - Background images and UI elements - - Custom emoji packs - - Language configuration files -- **Dynamic Content**: All content can be updated over-the-air via HTTP downloads - -## Partition Layout Comparison - -### v1 Layout (16MB) -- `nvs`: 16KB (non-volatile storage) -- `otadata`: 8KB (OTA data) -- `phy_init`: 4KB (PHY initialization data) -- `model`: 960KB (model storage - fixed content) -- `ota_0`: 6MB (application partition 0) -- `ota_1`: 6MB (application partition 1) - -### v2 Layout (16MB) -- `nvs`: 16KB (non-volatile storage) -- `otadata`: 8KB (OTA data) -- `phy_init`: 4KB (PHY initialization data) -- `ota_0`: 4MB (application partition 0) -- `ota_1`: 4MB (application partition 1) -- `assets`: 8MB (network-loadable assets) - -## Available Configurations - -### 8MB Flash Devices (`8m.csv`) -- `nvs`: 16KB -- `otadata`: 8KB -- `phy_init`: 4KB -- `ota_0`: 3MB -- `ota_1`: 3MB -- `assets`: 2MB - -### 16MB Flash Devices (`16m.csv`) - Standard -- `nvs`: 16KB -- `otadata`: 8KB -- `phy_init`: 4KB -- `ota_0`: 4MB -- `ota_1`: 4MB -- `assets`: 8MB - -### 16MB Flash Devices (`16m_c3.csv`) - ESP32-C3 Optimized -- `nvs`: 16KB -- `otadata`: 8KB -- `phy_init`: 4KB -- `ota_0`: 4MB -- `ota_1`: 4MB -- `assets`: 4MB (4000K - limited by available mmap pages) - -### 32MB Flash Devices (`32m.csv`) -- `nvsfactory`: 200KB -- `nvs`: 840KB -- `otadata`: 8KB -- `phy_init`: 4KB -- `ota_0`: 4MB -- `ota_1`: 4MB -- `assets`: 16MB - -## Benefits - -1. **Dynamic Content Management**: Users can download and update wake word models, themes, and other assets without reflashing the device -2. **Reduced App Size**: Application partitions are optimized, allowing more space for dynamic content -3. **Enhanced Customization**: Support for custom themes, wake words, and language packs enhances user experience -4. **Network Flexibility**: Assets can be updated independently of the main application firmware -5. **Better Resource Utilization**: Efficient use of flash memory with configurable asset storage -6. **OTA Asset Updates**: Assets can be updated over-the-air via HTTP downloads - -## Technical Details - -- **Partition Type**: Assets partition uses `spiffs` subtype for SPIFFS filesystem compatibility -- **Memory Mapping**: Assets are memory-mapped for efficient access during runtime -- **Checksum Validation**: Built-in integrity checking ensures asset data validity -- **Progressive Download**: Assets can be downloaded progressively with progress tracking -- **Fallback Support**: Graceful fallback to default assets if network updates fail - -## Migration from v1 - -When upgrading from v1 to v2: -1. **Backup Important Data**: Ensure any important data in the old `model` partition is backed up -2. **Flash New Partition Table**: Use the appropriate v2 partition table for your flash size -3. **Download Assets**: The device will automatically download required assets on first boot -4. **Verify Functionality**: Ensure all features work correctly with the new partition layout - -## Usage Notes - -- The `assets` partition size varies by configuration to optimize for different flash sizes -- ESP32-C3 devices use a smaller assets partition (4MB) due to limited available mmap pages in the system -- 32MB devices get the largest assets partition (16MB) for maximum content storage -- All partition tables maintain proper alignment for optimal flash performance \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/LVGLImage.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/LVGLImage.py deleted file mode 100644 index b2ffbb39..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/LVGLImage.py +++ /dev/null @@ -1,1426 +0,0 @@ -#!/usr/bin/env python3 -import os -import logging -import argparse -import subprocess -from os import path -from enum import Enum -from typing import List -from pathlib import Path - -try: - import png -except ImportError: - raise ImportError("Need pypng package, do `pip3 install pypng`") - -try: - import lz4.block -except ImportError: - raise ImportError("Need lz4 package, do `pip3 install lz4`") - - -def uint8_t(val) -> bytes: - return val.to_bytes(1, byteorder='little') - - -def uint16_t(val) -> bytes: - return val.to_bytes(2, byteorder='little') - - -def uint24_t(val) -> bytes: - return val.to_bytes(3, byteorder='little') - - -def uint32_t(val) -> bytes: - try: - return val.to_bytes(4, byteorder='little') - except OverflowError: - raise ParameterError(f"overflow: {hex(val)}") - - -def color_pre_multiply(r, g, b, a, background): - bb = background & 0xff - bg = (background >> 8) & 0xff - br = (background >> 16) & 0xff - - return ((r * a + (255 - a) * br) >> 8, (g * a + (255 - a) * bg) >> 8, - (b * a + (255 - a) * bb) >> 8, a) - - -class Error(Exception): - - def __str__(self): - return self.__class__.__name__ + ': ' + ' '.join(self.args) - - -class FormatError(Error): - """ - Problem with input filename format. - BIN filename does not conform to standard lvgl bin image format - """ - - -class ParameterError(Error): - """ - Parameter for LVGL image not correct - """ - - -class PngQuant: - """ - Compress PNG file to 8bit mode using `pngquant` - """ - - def __init__(self, ncolors=256, dither=True, exec_path="") -> None: - executable = path.join(exec_path, "pngquant") - self.cmd = (f"{executable} {'--nofs' if not dither else ''} " - f"{ncolors} --force - < ") - - def convert(self, filename) -> bytes: - if not os.path.isfile(filename): - raise BaseException(f"file not found: {filename}") - - try: - compressed = subprocess.check_output( - f'{self.cmd} "{str(filename)}"', - stderr=subprocess.STDOUT, - shell=True) - except subprocess.CalledProcessError: - raise BaseException( - "cannot find pngquant tool, install it via " - "`sudo apt install pngquant` for debian " - "or `brew install pngquant` for macintosh " - "For windows, you may need to download pngquant.exe from " - "https://pngquant.org/, and put it in your PATH.") - - return compressed - - -class CompressMethod(Enum): - NONE = 0x00 - RLE = 0x01 - LZ4 = 0x02 - - -class ColorFormat(Enum): - UNKNOWN = 0x00 - RAW = 0x01, - RAW_ALPHA = 0x02, - L8 = 0x06 - I1 = 0x07 - I2 = 0x08 - I4 = 0x09 - I8 = 0x0A - A1 = 0x0B - A2 = 0x0C - A4 = 0x0D - A8 = 0x0E - ARGB8888 = 0x10 - XRGB8888 = 0x11 - RGB565 = 0x12 - ARGB8565 = 0x13 - RGB565A8 = 0x14 - RGB888 = 0x0F - - @property - def bpp(self) -> int: - """ - Return bit per pixel for this cf - """ - cf_map = { - ColorFormat.L8: 8, - ColorFormat.I1: 1, - ColorFormat.I2: 2, - ColorFormat.I4: 4, - ColorFormat.I8: 8, - ColorFormat.A1: 1, - ColorFormat.A2: 2, - ColorFormat.A4: 4, - ColorFormat.A8: 8, - ColorFormat.ARGB8888: 32, - ColorFormat.XRGB8888: 32, - ColorFormat.RGB565: 16, - ColorFormat.RGB565A8: 16, # 16bpp + a8 map - ColorFormat.ARGB8565: 24, - ColorFormat.RGB888: 24, - } - - return cf_map[self] if self in cf_map else 0 - - @property - def ncolors(self) -> int: - """ - Return number of colors in palette if cf is indexed1/2/4/8. - Return zero if cf is not indexed format - """ - - cf_map = { - ColorFormat.I1: 2, - ColorFormat.I2: 4, - ColorFormat.I4: 16, - ColorFormat.I8: 256, - } - return cf_map.get(self, 0) - - @property - def is_indexed(self) -> bool: - """ - Return if cf is indexed color format - """ - return self.ncolors != 0 - - @property - def is_alpha_only(self) -> bool: - return ColorFormat.A1.value <= self.value <= ColorFormat.A8.value - - @property - def has_alpha(self) -> bool: - return self.is_alpha_only or self.is_indexed or self in ( - ColorFormat.ARGB8888, - ColorFormat.XRGB8888, # const alpha: 0xff - ColorFormat.ARGB8565, - ColorFormat.RGB565A8) - - @property - def is_colormap(self) -> bool: - return self in (ColorFormat.ARGB8888, ColorFormat.RGB888, - ColorFormat.XRGB8888, ColorFormat.RGB565A8, - ColorFormat.ARGB8565, ColorFormat.RGB565) - - @property - def is_luma_only(self) -> bool: - return self in (ColorFormat.L8, ) - - -def bit_extend(value, bpp): - """ - Extend value from bpp to 8 bit with interpolation to reduce rounding error. - """ - - if value == 0: - return 0 - - res = value - bpp_now = bpp - while bpp_now < 8: - res |= value << (8 - bpp_now) - bpp_now += bpp - - return res - - -def unpack_colors(data: bytes, cf: ColorFormat, w) -> List: - """ - Unpack lvgl 1/2/4/8/16/32 bpp color to png color: alpha map, grey scale, - or R,G,B,(A) map - """ - ret = [] - bpp = cf.bpp - if bpp == 8: - ret = data - elif bpp == 4: - if cf == ColorFormat.A4: - values = [x * 17 for x in range(16)] - else: - values = [x for x in range(16)] - - for p in data: - for i in range(2): - ret.append(values[(p >> (4 - i * 4)) & 0x0f]) - if len(ret) % w == 0: - break - - elif bpp == 2: - if cf == ColorFormat.A2: - values = [x * 85 for x in range(4)] - else: # must be ColorFormat.I2 - values = [x for x in range(4)] - for p in data: - for i in range(4): - ret.append(values[(p >> (6 - i * 2)) & 0x03]) - if len(ret) % w == 0: - break - elif bpp == 1: - if cf == ColorFormat.A1: - values = [0, 255] - else: - values = [0, 1] - for p in data: - for i in range(8): - ret.append(values[(p >> (7 - i)) & 0x01]) - if len(ret) % w == 0: - break - elif bpp == 16: - # This is RGB565 - pixels = [(data[2 * i + 1] << 8) | data[2 * i] - for i in range(len(data) // 2)] - - for p in pixels: - ret.append(bit_extend((p >> 11) & 0x1f, 5)) # R - ret.append(bit_extend((p >> 5) & 0x3f, 6)) # G - ret.append(bit_extend((p >> 0) & 0x1f, 5)) # B - elif bpp == 24: - if cf == ColorFormat.RGB888: - B = data[0::3] - G = data[1::3] - R = data[2::3] - for r, g, b in zip(R, G, B): - ret += [r, g, b] - elif cf == ColorFormat.RGB565A8: - alpha_size = len(data) // 3 - pixel_alpha = data[-alpha_size:] - pixel_data = data[:-alpha_size] - pixels = [(pixel_data[2 * i + 1] << 8) | pixel_data[2 * i] - for i in range(len(pixel_data) // 2)] - - for a, p in zip(pixel_alpha, pixels): - ret.append(bit_extend((p >> 11) & 0x1f, 5)) # R - ret.append(bit_extend((p >> 5) & 0x3f, 6)) # G - ret.append(bit_extend((p >> 0) & 0x1f, 5)) # B - ret.append(a) - elif cf == ColorFormat.ARGB8565: - L = data[0::3] - H = data[1::3] - A = data[2::3] - - for h, l, a in zip(H, L, A): - p = (h << 8) | (l) - ret.append(bit_extend((p >> 11) & 0x1f, 5)) # R - ret.append(bit_extend((p >> 5) & 0x3f, 6)) # G - ret.append(bit_extend((p >> 0) & 0x1f, 5)) # B - ret.append(a) # A - - elif bpp == 32: - B = data[0::4] - G = data[1::4] - R = data[2::4] - A = data[3::4] - for r, g, b, a in zip(R, G, B, A): - ret += [r, g, b, a] - else: - assert 0 - - return ret - - -def write_c_array_file( - w: int, h: int, - stride: int, - cf: ColorFormat, - filename: str, - premultiplied: bool, - compress: CompressMethod, - data: bytes): - varname = path.basename(filename).split('.')[0] - varname = varname.replace("-", "_") - varname = varname.replace(".", "_") - - flags = "0" - if compress is not CompressMethod.NONE: - flags += " | LV_IMAGE_FLAGS_COMPRESSED" - if premultiplied: - flags += " | LV_IMAGE_FLAGS_PREMULTIPLIED" - - macro = "LV_ATTRIBUTE_" + varname.upper() - header = f''' -#if defined(LV_LVGL_H_INCLUDE_SIMPLE) -#include "lvgl.h" -#elif defined(LV_BUILD_TEST) -#include "../lvgl.h" -#else -#include "lvgl/lvgl.h" -#endif - - -#ifndef LV_ATTRIBUTE_MEM_ALIGN -#define LV_ATTRIBUTE_MEM_ALIGN -#endif - -#ifndef {macro} -#define {macro} -#endif - -static const -LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST {macro} -uint8_t {varname}_map[] = {{ -''' - - ending = f''' -}}; - -const lv_image_dsc_t {varname} = {{ - .header.magic = LV_IMAGE_HEADER_MAGIC, - .header.cf = LV_COLOR_FORMAT_{cf.name}, - .header.flags = {flags}, - .header.w = {w}, - .header.h = {h}, - .header.stride = {stride}, - .data_size = sizeof({varname}_map), - .data = {varname}_map, -}}; - -''' - - def write_binary(f, data, stride): - stride = 16 if stride == 0 else stride - for i, v in enumerate(data): - if i % stride == 0: - f.write("\n ") - f.write(f"0x{v:02x},") - f.write("\n") - - with open(filename, "w+") as f: - f.write(header) - - if compress != CompressMethod.NONE: - write_binary(f, data, 16) - else: - # write palette separately - ncolors = cf.ncolors - if ncolors: - write_binary(f, data[:ncolors * 4], 16) - - write_binary(f, data[ncolors * 4:], stride) - - f.write(ending) - - -class LVGLImageHeader: - - def __init__(self, - cf: ColorFormat = ColorFormat.UNKNOWN, - w: int = 0, - h: int = 0, - stride: int = 0, - align: int = 1, - flags: int = 0): - self.cf = cf - self.flags = flags - self.w = w & 0xffff - self.h = h & 0xffff - if w > 0xffff or h > 0xffff: - raise ParameterError(f"w, h overflow: {w}x{h}") - if align < 1: - # stride align in bytes must be larger than 1 - raise ParameterError(f"Invalid stride align: {align}") - - self.stride = self.stride_align(align) if stride == 0 else stride - - def stride_align(self, align: int) -> int: - stride = self.stride_default - if align == 1: - pass - elif align > 1: - stride = (stride + align - 1) // align - stride *= align - else: - raise ParameterError(f"Invalid stride align: {align}") - - self.stride = stride - return stride - - @property - def stride_default(self) -> int: - return (self.w * self.cf.bpp + 7) // 8 - - @property - def binary(self) -> bytearray: - binary = bytearray() - binary += uint8_t(0x19) # magic number for lvgl version 9 - binary += uint8_t(self.cf.value) - binary += uint16_t(self.flags) # 16bits flags - - binary += uint16_t(self.w) # 16bits width - binary += uint16_t(self.h) # 16bits height - binary += uint16_t(self.stride) # 16bits stride - - binary += uint16_t(0) # 16bits reserved - return binary - - def from_binary(self, data: bytes): - if len(data) < 12: - raise FormatError("invalid header length") - - try: - self.cf = ColorFormat(data[1] & 0x1f) # color format - except ValueError as exc: - raise FormatError(f"invalid color format: {hex(data[0])}") from exc - self.w = int.from_bytes(data[4:6], 'little') - self.h = int.from_bytes(data[6:8], 'little') - self.stride = int.from_bytes(data[8:10], 'little') - return self - - -class LVGLCompressData: - - def __init__(self, - cf: ColorFormat, - method: CompressMethod, - raw_data: bytes = b''): - self.blk_size = (cf.bpp + 7) // 8 - self.compress = method - self.raw_data = raw_data - self.raw_data_len = len(raw_data) - self.compressed = self._compress(raw_data) - - def _compress(self, raw_data: bytes) -> bytearray: - if self.compress == CompressMethod.NONE: - return raw_data - - if self.compress == CompressMethod.RLE: - # RLE compression performs on pixel unit, pad data to pixel unit - pad = b'\x00' * 0 - if self.raw_data_len % self.blk_size: - pad = b'\x00' * (self.blk_size - self.raw_data_len % self.blk_size) - compressed = RLEImage().rle_compress(raw_data + pad, self.blk_size) - elif self.compress == CompressMethod.LZ4: - compressed = lz4.block.compress(raw_data, store_size=False) - else: - raise ParameterError(f"Invalid compress method: {self.compress}") - - self.compressed_len = len(compressed) - - bin = bytearray() - bin += uint32_t(self.compress.value) - bin += uint32_t(self.compressed_len) - bin += uint32_t(self.raw_data_len) - bin += compressed - return bin - - -class LVGLImage: - - def __init__(self, - cf: ColorFormat = ColorFormat.UNKNOWN, - w: int = 0, - h: int = 0, - data: bytes = b'') -> None: - self.stride = 0 # default no valid stride value - self.premultiplied = False - self.rgb565_dither = False - self.set_data(cf, w, h, data) - - def __repr__(self) -> str: - return (f"'LVGL image {self.w}x{self.h}, {self.cf.name}, " - f"{'Pre-multiplied, ' if self.premultiplied else ''}" - f"stride: {self.stride} " - f"(12+{self.data_len})Byte'") - - def adjust_stride(self, stride: int = 0, align: int = 1): - """ - Stride can be set directly, or by stride alignment in bytes - """ - if self.stride == 0: - # stride can only be 0, when LVGLImage is created with empty data - logging.warning("Cannot adjust stride for empty image") - return - - if align >= 1 and stride == 0: - # The header with specified stride alignment - header = LVGLImageHeader(self.cf, self.w, self.h, align=align) - stride = header.stride - elif stride > 0: - pass - else: - raise ParameterError(f"Invalid parameter, align:{align}," - f" stride:{stride}") - - if self.stride == stride: - return # no stride adjustment - - # if current image is empty, no need to do anything - if self.data_len == 0: - self.stride = 0 - return - - current = LVGLImageHeader(self.cf, self.w, self.h, stride=self.stride) - - if stride < current.stride_default: - raise ParameterError(f"Stride is too small:{stride}, " - f"minimal:{current.stride_default}") - - def change_stride(data: bytearray, h, current_stride, new_stride): - data_in = data - data_out = [] # stride adjusted new data - if new_stride < current_stride: # remove padding byte - for i in range(h): - start = i * current_stride - end = start + new_stride - data_out.append(data_in[start:end]) - else: # adding more padding bytes - padding = b'\x00' * (new_stride - current_stride) - for i in range(h): - data_out.append(data_in[i * current_stride:(i + 1) * - current_stride]) - data_out.append(padding) - return b''.join(data_out) - - palette_size = self.cf.ncolors * 4 - data_out = [self.data[:palette_size]] - data_out.append( - change_stride(self.data[palette_size:], self.h, current.stride, - stride)) - - # deal with alpha map for RGB565A8 - if self.cf == ColorFormat.RGB565A8: - logging.warning("handle RGB565A8 alpha map") - a8_stride = self.stride // 2 - a8_map = self.data[-a8_stride * self.h:] - data_out.append( - change_stride(a8_map, self.h, current.stride // 2, - stride // 2)) - - self.stride = stride - self.data = bytearray(b''.join(data_out)) - - def premultiply(self): - """ - Pre-multiply image RGB data with alpha, set corresponding image header flags - """ - if self.premultiplied: - raise ParameterError("Image already pre-multiplied") - - if not self.cf.has_alpha: - raise ParameterError(f"Image has no alpha channel: {self.cf.name}") - - if self.cf.is_indexed: - - def multiply(r, g, b, a): - r, g, b = (r * a) >> 8, (g * a) >> 8, (b * a) >> 8 - return uint8_t(b) + uint8_t(g) + uint8_t(r) + uint8_t(a) - - # process the palette only. - palette_size = self.cf.ncolors * 4 - palette = self.data[:palette_size] - palette = [ - multiply(palette[i], palette[i + 1], palette[i + 2], - palette[i + 3]) for i in range(0, len(palette), 4) - ] - palette = b''.join(palette) - self.data = palette + self.data[palette_size:] - elif self.cf is ColorFormat.ARGB8888: - - def multiply(b, g, r, a): - r, g, b = (r * a) >> 8, (g * a) >> 8, (b * a) >> 8 - return uint32_t((a << 24) | (r << 16) | (g << 8) | (b << 0)) - - line_width = self.w * 4 - for h in range(self.h): - offset = h * self.stride - map = self.data[offset:offset + self.stride] - - processed = b''.join([ - multiply(map[i], map[i + 1], map[i + 2], map[i + 3]) - for i in range(0, line_width, 4) - ]) - self.data[offset:offset + line_width] = processed - elif self.cf is ColorFormat.RGB565A8: - - def multiply(data, a): - r = (data >> 11) & 0x1f - g = (data >> 5) & 0x3f - b = (data >> 0) & 0x1f - - r, g, b = (r * a) // 255, (g * a) // 255, (b * a) // 255 - return uint16_t((r << 11) | (g << 5) | (b << 0)) - - line_width = self.w * 2 - for h in range(self.h): - # alpha map offset for this line - offset = self.h * self.stride + h * (self.stride // 2) - a = self.data[offset:offset + self.stride // 2] - - # RGB map offset - offset = h * self.stride - rgb = self.data[offset:offset + self.stride] - - processed = b''.join([ - multiply((rgb[i + 1] << 8) | rgb[i], a[i // 2]) - for i in range(0, line_width, 2) - ]) - self.data[offset:offset + line_width] = processed - elif self.cf is ColorFormat.ARGB8565: - - def multiply(data, a): - r = (data >> 11) & 0x1f - g = (data >> 5) & 0x3f - b = (data >> 0) & 0x1f - - r, g, b = (r * a) // 255, (g * a) // 255, (b * a) // 255 - return uint24_t((a << 16) | (r << 11) | (g << 5) | (b << 0)) - - line_width = self.w * 3 - for h in range(self.h): - offset = h * self.stride - map = self.data[offset:offset + self.stride] - - processed = b''.join([ - multiply((map[i + 1] << 8) | map[i], map[i + 2]) - for i in range(0, line_width, 3) - ]) - self.data[offset:offset + line_width] = processed - else: - raise ParameterError(f"Not supported yet: {self.cf.name}") - - self.premultiplied = True - - @property - def data_len(self) -> int: - """ - Return data_len in byte of this image, excluding image header - """ - - # palette is always in ARGB format, 4Byte per color - p = self.cf.ncolors * 4 if self.is_indexed and self.w * self.h else 0 - p += self.stride * self.h - if self.cf is ColorFormat.RGB565A8: - a8_stride = self.stride // 2 - p += a8_stride * self.h - return p - - @property - def header(self) -> bytearray: - return LVGLImageHeader(self.cf, self.w, self.h) - - @property - def is_indexed(self): - return self.cf.is_indexed - - def set_data(self, - cf: ColorFormat, - w: int, - h: int, - data: bytes, - stride: int = 0): - """ - Directly set LVGL image parameters - """ - - if w > 0xffff or h > 0xffff: - raise ParameterError(f"w, h overflow: {w}x{h}") - - self.cf = cf - self.w = w - self.h = h - - # if stride is 0, then it's aligned to 1byte by default, - # let image header handle it - self.stride = LVGLImageHeader(cf, w, h, stride, align=1).stride - - if self.data_len != len(data): - raise ParameterError(f"{self} data length error got: {len(data)}, " - f"expect: {self.data_len}, {self}") - - self.data = data - - return self - - def from_data(self, data: bytes): - header = LVGLImageHeader().from_binary(data) - return self.set_data(header.cf, header.w, header.h, - data[len(header.binary):], header.stride) - - def from_bin(self, filename: str): - """ - Read from existing bin file and update image parameters - """ - - if not filename.endswith(".bin"): - raise FormatError("filename not ended with '.bin'") - - with open(filename, "rb") as f: - data = f.read() - return self.from_data(data) - - def _check_ext(self, filename: str, ext): - if not filename.lower().endswith(ext): - raise FormatError(f"filename not ended with {ext}") - - def _check_dir(self, filename: str): - dir = path.dirname(filename) - if dir and not path.exists(dir): - logging.info(f"mkdir of {dir} for {filename}") - os.makedirs(dir) - - def to_bin(self, - filename: str, - compress: CompressMethod = CompressMethod.NONE): - """ - Write this image to file, filename should be ended with '.bin' - """ - self._check_ext(filename, ".bin") - self._check_dir(filename) - - with open(filename, "wb+") as f: - bin = bytearray() - flags = 0 - flags |= 0x08 if compress != CompressMethod.NONE else 0 - flags |= 0x01 if self.premultiplied else 0 - - header = LVGLImageHeader(self.cf, - self.w, - self.h, - self.stride, - flags=flags) - bin += header.binary - compressed = LVGLCompressData(self.cf, compress, self.data) - bin += compressed.compressed - - f.write(bin) - - return self - - def to_c_array(self, - filename: str, - compress: CompressMethod = CompressMethod.NONE): - self._check_ext(filename, ".c") - self._check_dir(filename) - - if compress != CompressMethod.NONE: - data = LVGLCompressData(self.cf, compress, self.data).compressed - else: - data = self.data - write_c_array_file(self.w, self.h, self.stride, self.cf, filename, - self.premultiplied, - compress, data) - - def to_png(self, filename: str): - self._check_ext(filename, ".png") - self._check_dir(filename) - - old_stride = self.stride - self.adjust_stride(align=1) - if self.cf.is_indexed: - data = self.data - # Separate lvgl bin image data to palette and bitmap - # The palette is in format of [(RGBA), (RGBA)...]. - # LVGL palette is in format of B,G,R,A,... - palette = [(data[i * 4 + 2], data[i * 4 + 1], data[i * 4 + 0], - data[i * 4 + 3]) for i in range(self.cf.ncolors)] - - data = data[self.cf.ncolors * 4:] - - encoder = png.Writer(self.w, - self.h, - palette=palette, - bitdepth=self.cf.bpp) - # separate packed data to plain data - data = unpack_colors(data, self.cf, self.w) - elif self.cf.is_alpha_only: - # separate packed data to plain data - transparency = unpack_colors(self.data, self.cf, self.w) - data = [] - for a in transparency: - data += [0, 0, 0, a] - encoder = png.Writer(self.w, self.h, greyscale=False, alpha=True) - elif self.cf == ColorFormat.L8: - # to grayscale - encoder = png.Writer(self.w, - self.h, - bitdepth=self.cf.bpp, - greyscale=True, - alpha=False) - data = self.data - elif self.cf.is_colormap: - encoder = png.Writer(self.w, - self.h, - alpha=self.cf.has_alpha, - greyscale=False) - data = unpack_colors(self.data, self.cf, self.w) - else: - logging.warning(f"missing logic: {self.cf.name}") - return - - with open(filename, "wb") as f: - encoder.write_array(f, data) - - self.adjust_stride(stride=old_stride) - - def from_png(self, - filename: str, - cf: ColorFormat = None, - background: int = 0x00_00_00, - rgb565_dither=False): - """ - Create lvgl image from png file. - If cf is none, used I1/2/4/8 based on palette size - """ - - self.background = background - self.rgb565_dither = rgb565_dither - - if cf is None: # guess cf from filename - # split filename string and match with ColorFormat to check - # which cf to use - names = str(path.basename(filename)).split(".") - for c in names[1:-1]: - if c in ColorFormat.__members__: - cf = ColorFormat[c] - break - - if cf is None or cf.is_indexed: # palette mode - self._png_to_indexed(cf, filename) - elif cf.is_alpha_only: - self._png_to_alpha_only(cf, filename) - elif cf.is_luma_only: - self._png_to_luma_only(cf, filename) - elif cf.is_colormap: - self._png_to_colormap(cf, filename) - else: - logging.warning(f"missing logic: {cf.name}") - - logging.info(f"from png: {filename}, cf: {self.cf.name}") - return self - - def _png_to_indexed(self, cf: ColorFormat, filename: str): - # convert to palette mode - auto_cf = cf is None - - # read the image data to get the metadata - reader = png.Reader(filename=filename) - w, h, rows, metadata = reader.read() - - # to preserve original palette data only convert the image if needed. For this - # check if image has a palette and the requested palette size equals the existing one - if not 'palette' in metadata or not auto_cf and len(metadata['palette']) != 2 ** cf.bpp: - # reread and convert file - reader = png.Reader( - bytes=PngQuant(256 if auto_cf else cf.ncolors).convert(filename)) - w, h, rows, _ = reader.read() - - palette = reader.palette(alpha="force") # always return alpha - - palette_len = len(palette) - if auto_cf: - if palette_len <= 2: - cf = ColorFormat.I1 - elif palette_len <= 4: - cf = ColorFormat.I2 - elif palette_len <= 16: - cf = ColorFormat.I4 - else: - cf = ColorFormat.I8 - - if palette_len != cf.ncolors: - if not auto_cf: - logging.warning( - f"{path.basename(filename)} palette: {palette_len}, " - f"extended to: {cf.ncolors}") - palette += [(255, 255, 255, 0)] * (cf.ncolors - palette_len) - - # Assemble lvgl image palette from PNG palette. - # PNG palette is a list of tuple(R,G,B,A) - - rawdata = bytearray() - for (r, g, b, a) in palette: - rawdata += uint32_t((a << 24) | (r << 16) | (g << 8) | (b << 0)) - - # pack data if not in I8 format - if cf == ColorFormat.I8: - for e in rows: - rawdata += e - else: - for e in png.pack_rows(rows, cf.bpp): - rawdata += e - - self.set_data(cf, w, h, rawdata) - - def _png_to_alpha_only(self, cf: ColorFormat, filename: str): - reader = png.Reader(str(filename)) - w, h, rows, info = reader.asRGBA8() - if not info['alpha']: - raise FormatError(f"{filename} has no alpha channel") - - rawdata = bytearray() - if cf == ColorFormat.A8: - for row in rows: - A = row[3::4] - for e in A: - rawdata += uint8_t(e) - else: - shift = 8 - cf.bpp - mask = 2**cf.bpp - 1 - rows = [[(a >> shift) & mask for a in row[3::4]] for row in rows] - for row in png.pack_rows(rows, cf.bpp): - rawdata += row - - self.set_data(cf, w, h, rawdata) - - def sRGB_to_linear(self, x): - if x < 0.04045: - return x / 12.92 - return pow((x + 0.055) / 1.055, 2.4) - - def linear_to_sRGB(self, y): - if y <= 0.0031308: - return 12.92 * y - return 1.055 * pow(y, 1 / 2.4) - 0.055 - - def _png_to_luma_only(self, cf: ColorFormat, filename: str): - reader = png.Reader(str(filename)) - w, h, rows, info = reader.asRGBA8() - rawdata = bytearray() - for row in rows: - R = row[0::4] - G = row[1::4] - B = row[2::4] - A = row[3::4] - for r, g, b, a in zip(R, G, B, A): - r, g, b, a = color_pre_multiply(r, g, b, a, self.background) - r = self.sRGB_to_linear(r / 255.0) - g = self.sRGB_to_linear(g / 255.0) - b = self.sRGB_to_linear(b / 255.0) - luma = 0.2126 * r + 0.7152 * g + 0.0722 * b - rawdata += uint8_t(int(self.linear_to_sRGB(luma) * 255)) - - self.set_data(ColorFormat.L8, w, h, rawdata) - - def _png_to_colormap(self, cf, filename: str): - - if cf == ColorFormat.ARGB8888: - - def pack(r, g, b, a): - return uint32_t((a << 24) | (r << 16) | (g << 8) | (b << 0)) - elif cf == ColorFormat.XRGB8888: - - def pack(r, g, b, a): - r, g, b, a = color_pre_multiply(r, g, b, a, self.background) - return uint32_t((0xff << 24) | (r << 16) | (g << 8) | (b << 0)) - elif cf == ColorFormat.RGB888: - - def pack(r, g, b, a): - r, g, b, a = color_pre_multiply(r, g, b, a, self.background) - return uint24_t((r << 16) | (g << 8) | (b << 0)) - elif cf == ColorFormat.RGB565: - - def pack(r, g, b, a): - r, g, b, a = color_pre_multiply(r, g, b, a, self.background) - color = (r >> 3) << 11 - color |= (g >> 2) << 5 - color |= (b >> 3) << 0 - return uint16_t(color) - - elif cf == ColorFormat.RGB565A8: - - def pack(r, g, b, a): - color = (r >> 3) << 11 - color |= (g >> 2) << 5 - color |= (b >> 3) << 0 - return uint16_t(color) - elif cf == ColorFormat.ARGB8565: - - def pack(r, g, b, a): - color = (r >> 3) << 11 - color |= (g >> 2) << 5 - color |= (b >> 3) << 0 - return uint24_t((a << 16) | color) - else: - raise FormatError(f"Invalid color format: {cf.name}") - - reader = png.Reader(str(filename)) - w, h, rows, _ = reader.asRGBA8() - rawdata = bytearray() - alpha = bytearray() - for y, row in enumerate(rows): - R = row[0::4] - G = row[1::4] - B = row[2::4] - A = row[3::4] - for x, (r, g, b, a) in enumerate(zip(R, G, B, A)): - if cf == ColorFormat.RGB565A8: - alpha += uint8_t(a) - - if ( - self.rgb565_dither and - cf in (ColorFormat.RGB565, ColorFormat.RGB565A8, ColorFormat.ARGB8565) - ): - treshold_id = ((y & 7) << 3) + (x & 7) - - r = min(r + red_thresh[treshold_id], 0xFF) & 0xF8 - g = min(g + green_thresh[treshold_id], 0xFF) & 0xFC - b = min(b + blue_thresh[treshold_id], 0xFF) & 0xF8 - - rawdata += pack(r, g, b, a) - - if cf == ColorFormat.RGB565A8: - rawdata += alpha - - self.set_data(cf, w, h, rawdata) - - -red_thresh = [ - 1, 7, 3, 5, 0, 8, 2, 6, - 7, 1, 5, 3, 8, 0, 6, 2, - 3, 5, 0, 8, 2, 6, 1, 7, - 5, 3, 8, 0, 6, 2, 7, 1, - 0, 8, 2, 6, 1, 7, 3, 5, - 8, 0, 6, 2, 7, 1, 5, 3, - 2, 6, 1, 7, 3, 5, 0, 8, - 6, 2, 7, 1, 5, 3, 8, 0 -] - -green_thresh = [ - 1, 3, 2, 2, 3, 1, 2, 2, - 2, 2, 0, 4, 2, 2, 4, 0, - 3, 1, 2, 2, 1, 3, 2, 2, - 2, 2, 4, 0, 2, 2, 0, 4, - 1, 3, 2, 2, 3, 1, 2, 2, - 2, 2, 0, 4, 2, 2, 4, 0, - 3, 1, 2, 2, 1, 3, 2, 2, - 2, 2, 4, 0, 2, 2, 0, 4 -] - -blue_thresh = [ - 5, 3, 8, 0, 6, 2, 7, 1, - 3, 5, 0, 8, 2, 6, 1, 7, - 8, 0, 6, 2, 7, 1, 5, 3, - 0, 8, 2, 6, 1, 7, 3, 5, - 6, 2, 7, 1, 5, 3, 8, 0, - 2, 6, 1, 7, 3, 5, 0, 8, - 7, 1, 5, 3, 8, 0, 6, 2, - 1, 7, 3, 5, 0, 8, 2, 6 -] - - -class RLEHeader: - - def __init__(self, blksize: int, len: int): - self.blksize = blksize - self.len = len - - @property - def binary(self): - magic = 0x5aa521e0 - - rle_header = self.blksize - rle_header |= (self.len & 0xffffff) << 4 - - binary = bytearray() - binary.extend(uint32_t(magic)) - binary.extend(uint32_t(rle_header)) - return binary - - -class RLEImage(LVGLImage): - - def __init__(self, - cf: ColorFormat = ColorFormat.UNKNOWN, - w: int = 0, - h: int = 0, - data: bytes = b'') -> None: - super().__init__(cf, w, h, data) - - def to_rle(self, filename: str): - """ - Compress this image to file, filename should be ended with '.rle' - """ - self._check_ext(filename, ".rle") - self._check_dir(filename) - - # compress image data excluding lvgl image header - blksize = (self.cf.bpp + 7) // 8 - compressed = self.rle_compress(self.data, blksize) - with open(filename, "wb+") as f: - header = RLEHeader(blksize, len(self.data)).binary - header.extend(self.header.binary) - f.write(header) - f.write(compressed) - - def rle_compress(self, data: bytearray, blksize: int, threshold=16): - index = 0 - data_len = len(data) - compressed_data = [] - memview = memoryview(data) - while index < data_len: - repeat_cnt = self.get_repeat_count(memview[index:], blksize) - if repeat_cnt == 0: - # done - break - elif repeat_cnt < threshold: - nonrepeat_cnt = self.get_nonrepeat_count( - memview[index:], blksize, threshold) - ctrl_byte = uint8_t(nonrepeat_cnt | 0x80) - compressed_data.append(ctrl_byte) - compressed_data.append(memview[index:index + - nonrepeat_cnt * blksize]) - index += nonrepeat_cnt * blksize - else: - ctrl_byte = uint8_t(repeat_cnt) - compressed_data.append(ctrl_byte) - compressed_data.append(memview[index:index + blksize]) - index += repeat_cnt * blksize - - return b"".join(compressed_data) - - def get_repeat_count(self, data: bytearray, blksize: int): - if len(data) < blksize: - return 0 - - start = data[:blksize] - index = 0 - repeat_cnt = 0 - value = 0 - - while index < len(data): - value = data[index:index + blksize] - - if value == start: - repeat_cnt += 1 - if repeat_cnt == 127: # limit max repeat count to max value of signed char. - break - else: - break - index += blksize - - return repeat_cnt - - def get_nonrepeat_count(self, data: bytearray, blksize: int, threshold): - if len(data) < blksize: - return 0 - - pre_value = data[:blksize] - - index = 0 - nonrepeat_count = 0 - - repeat_cnt = 0 - while True: - value = data[index:index + blksize] - if value == pre_value: - repeat_cnt += 1 - if repeat_cnt > threshold: - # repeat found. - break - else: - pre_value = value - nonrepeat_count += 1 + repeat_cnt - repeat_cnt = 0 - if nonrepeat_count >= 127: # limit max repeat count to max value of signed char. - nonrepeat_count = 127 - break - - index += blksize # move to next position - if index >= len(data): # data end - nonrepeat_count += repeat_cnt - break - - return nonrepeat_count - - -class RAWImage(): - ''' - RAW image is an exception to LVGL image, it has color format of RAW or RAW_ALPHA. - It has same image header as LVGL image, but the data is pure raw data from file. - It does not support stride adjustment etc. features for LVGL image. - It only supports convert an image to C array with RAW or RAW_ALPHA format. - ''' - CF_SUPPORTED = (ColorFormat.RAW, ColorFormat.RAW_ALPHA) - - class NotSupported(NotImplementedError): - pass - - def __init__(self, - cf: ColorFormat = ColorFormat.UNKNOWN, - data: bytes = b'') -> None: - self.cf = cf - self.data = data - - def to_c_array(self, - filename: str): - # Image size is set to zero, to let PNG or JPEG decoder to handle it - # Stride is meaningless for RAW image - write_c_array_file(0, 0, 0, self.cf, filename, - False, CompressMethod.NONE, self.data) - - def from_file(self, - filename: str, - cf: ColorFormat = None): - if cf not in RAWImage.CF_SUPPORTED: - raise RAWImage.NotSupported(f"Invalid color format: {cf.name}") - - with open(filename, "rb") as f: - self.data = f.read() - self.cf = cf - return self - - -class OutputFormat(Enum): - C_ARRAY = "C" - BIN_FILE = "BIN" - PNG_FILE = "PNG" # convert to lvgl image and then to png - - -class PNGConverter: - - def __init__(self, - files: List, - cf: ColorFormat, - ofmt: OutputFormat, - odir: str, - background: int = 0x00, - align: int = 1, - premultiply: bool = False, - compress: CompressMethod = CompressMethod.NONE, - keep_folder=True, - rgb565_dither=False) -> None: - self.files = files - self.cf = cf - self.ofmt = ofmt - self.output = odir - self.pngquant = None - self.keep_folder = keep_folder - self.align = align - self.premultiply = premultiply - self.compress = compress - self.background = background - self.rgb565_dither = rgb565_dither - - def _replace_ext(self, input, ext): - if self.keep_folder: - name, _ = path.splitext(input) - else: - name, _ = path.splitext(path.basename(input)) - output = name + ext - output = path.join(self.output, output) - return output - - def convert(self): - output = [] - for f in self.files: - if self.cf in (ColorFormat.RAW, ColorFormat.RAW_ALPHA): - # Process RAW image explicitly - img = RAWImage().from_file(f, self.cf) - img.to_c_array(self._replace_ext(f, ".c")) - else: - img = LVGLImage().from_png(f, self.cf, background=self.background, rgb565_dither=self.rgb565_dither) - img.adjust_stride(align=self.align) - - if self.premultiply: - img.premultiply() - output.append((f, img)) - if self.ofmt == OutputFormat.BIN_FILE: - img.to_bin(self._replace_ext(f, ".bin"), - compress=self.compress) - elif self.ofmt == OutputFormat.C_ARRAY: - img.to_c_array(self._replace_ext(f, ".c"), - compress=self.compress) - elif self.ofmt == OutputFormat.PNG_FILE: - img.to_png(self._replace_ext(f, ".png")) - - return output - - -def main(): - parser = argparse.ArgumentParser(description='LVGL PNG to bin image tool.') - parser.add_argument('--ofmt', - help="output filename format, C or BIN", - default="BIN", - choices=["C", "BIN", "PNG"]) - parser.add_argument( - '--cf', - help=("bin image color format, use AUTO for automatically " - "choose from I1/2/4/8"), - default="I8", - choices=[ - "L8", "I1", "I2", "I4", "I8", "A1", "A2", "A4", "A8", "ARGB8888", - "XRGB8888", "RGB565", "RGB565A8", "ARGB8565", "RGB888", "AUTO", - "RAW", "RAW_ALPHA" - ]) - - parser.add_argument('--rgb565dither', action='store_true', - help="use dithering to correct banding in gradients", default=False) - - parser.add_argument('--premultiply', action='store_true', - help="pre-multiply color with alpha", default=False) - - parser.add_argument('--compress', - help=("Binary data compress method, default to NONE"), - default="NONE", - choices=["NONE", "RLE", "LZ4"]) - - parser.add_argument('--align', - help="stride alignment in bytes for bin image", - default=1, - type=int, - metavar='byte', - nargs='?') - parser.add_argument('--background', - help="Background color for formats without alpha", - default=0x00_00_00, - type=lambda x: int(x, 0), - metavar='color', - nargs='?') - parser.add_argument('-o', - '--output', - default="./output", - help="Select the output folder, default to ./output") - parser.add_argument('-v', '--verbose', action='store_true') - parser.add_argument( - 'input', help="the filename or folder to be recursively converted") - - args = parser.parse_args() - - if path.isfile(args.input): - files = [args.input] - elif path.isdir(args.input): - files = list(Path(args.input).rglob("*.[pP][nN][gG]")) - else: - raise BaseException(f"invalid input: {args.input}") - - if args.verbose: - logging.basicConfig(level=logging.INFO) - - logging.info(f"options: {args.__dict__}, files:{[str(f) for f in files]}") - - if args.cf == "AUTO": - cf = None - else: - cf = ColorFormat[args.cf] - - ofmt = OutputFormat(args.ofmt) if cf not in ( - ColorFormat.RAW, ColorFormat.RAW_ALPHA) else OutputFormat.C_ARRAY - compress = CompressMethod[args.compress] - - converter = PNGConverter(files, - cf, - ofmt, - args.output, - background=args.background, - align=args.align, - premultiply=args.premultiply, - compress=compress, - keep_folder=False, - rgb565_dither=args.rgb565dither) - output = converter.convert() - for f, img in output: - logging.info(f"len: {img.data_len} for {path.basename(f)} ") - - print(f"done {len(files)} files") - - -def test(): - logging.basicConfig(level=logging.INFO) - f = "pngs/cogwheel.RGB565A8.png" - img = LVGLImage().from_png(f, - cf=ColorFormat.ARGB8565, - background=0xFF_FF_00, - rgb565_dither=True) - img.adjust_stride(align=16) - img.premultiply() - img.to_bin("output/cogwheel.ARGB8565.bin") - img.to_c_array("output/cogwheel-abc.c") # file name is used as c var name - img.to_png("output/cogwheel.ARGB8565.png.png") # convert back to png - - -def test_raw(): - logging.basicConfig(level=logging.INFO) - f = "pngs/cogwheel.RGB565A8.png" - img = RAWImage().from_file(f, - cf=ColorFormat.RAW_ALPHA) - img.to_c_array("output/cogwheel-raw.c") - - -if __name__ == "__main__": - # test() - # test_raw() - main() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/README.md deleted file mode 100644 index 62a02cdb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# LVGL图片转换工具 - -这个目录包含两个用于处理和转换图片为LVGL格式的Python脚本: - -## 1. LVGLImage (LVGLImage.py) - -引用自LVGL[官方repo](https://github.com/lvgl/lvgl)的转换脚本[LVGLImage.py](https://github.com/lvgl/lvgl/blob/master/scripts/LVGLImage.py) - -## 2. LVGL图片转换工具 (lvgl_tools_gui.py) - -调用`LVGLImage.py`,将图片批量转换为LVGL图片格式 -可用于修改小智的默认表情,具体修改教程[在这里](https://www.bilibili.com/video/BV12FQkYeEJ3/) - -### 特性 - -- 图形化操作,界面更友好 -- 支持批量转换图片 -- 自动识别图片格式并选择最佳的颜色格式转换 -- 多分辨率支持 - -### 使用方法 - -创建虚拟环境 -```bash -# 创建 venv -python -m venv venv -# 激活环境 -source venv/bin/activate # Linux/Mac -venv\Scripts\activate # Windows -``` - -安装依赖 -```bash -pip install -r requirements.txt -``` - -运行转换工具 - -```bash -# 激活环境 -source venv/bin/activate # Linux/Mac -venv\Scripts\activate # Windows -# 运行 -python lvgl_tools_gui.py -``` diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/lvgl_tools_gui.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/lvgl_tools_gui.py deleted file mode 100644 index de7c1f24..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/lvgl_tools_gui.py +++ /dev/null @@ -1,253 +0,0 @@ -import tkinter as tk -from tkinter import ttk, filedialog, messagebox -from PIL import Image -import os -import tempfile -import sys -from LVGLImage import LVGLImage, ColorFormat, CompressMethod - -HELP_TEXT = """LVGL图片转换工具使用说明: - -1. 添加文件:点击“添加文件”按钮选择需要转换的图片,支持批量导入 - -2. 移除文件:在列表中选中文件前的复选框“[ ]”(选中后会变成“[√]”),点击“移除选中”可删除选定文件 - -3. 设置分辨率:选择需要的分辨率,如128x128 - 建议根据自己的设备的屏幕分辨率来选择。过大和过小都会影响显示效果。 - -4. 颜色格式:选择“自动识别”会根据图片是否透明自动选择,或手动指定 - 除非你了解这个选项,否则建议使用自动识别,不然可能会出现一些意想不到的问题…… - -5. 压缩方式:选择NONE或RLE压缩 - 除非你了解这个选项,否则建议保持默认NONE不压缩 - -6. 输出目录:设置转换后文件的保存路径 - 默认为程序所在目录下的output文件夹 - -7. 转换:点击“转换全部”或“转换选中”开始转换 -""" - -class ImageConverterApp: - def __init__(self, root): - self.root = root - self.root.title("LVGL图片转换工具") - self.root.geometry("750x650") - - # 初始化变量 - self.output_dir = tk.StringVar(value=os.path.abspath("output")) - self.resolution = tk.StringVar(value="128x128") - self.color_format = tk.StringVar(value="自动识别") - self.compress_method = tk.StringVar(value="NONE") - - # 创建UI组件 - self.create_widgets() - self.redirect_output() - - def create_widgets(self): - # 参数设置框架 - settings_frame = ttk.LabelFrame(self.root, text="转换设置") - settings_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew") - - # 分辨率设置 - ttk.Label(settings_frame, text="分辨率:").grid(row=0, column=0, padx=2) - ttk.Combobox(settings_frame, textvariable=self.resolution, - values=["512x512", "256x256", "128x128", "64x64", "32x32"], width=8).grid(row=0, column=1, padx=2) - - # 颜色格式 - ttk.Label(settings_frame, text="颜色格式:").grid(row=0, column=2, padx=2) - ttk.Combobox(settings_frame, textvariable=self.color_format, - values=["自动识别", "RGB565", "RGB565A8"], width=10).grid(row=0, column=3, padx=2) - - # 压缩方式 - ttk.Label(settings_frame, text="压缩方式:").grid(row=0, column=4, padx=2) - ttk.Combobox(settings_frame, textvariable=self.compress_method, - values=["NONE", "RLE"], width=8).grid(row=0, column=5, padx=2) - - # 文件操作框架 - file_frame = ttk.LabelFrame(self.root, text="选取文件") - file_frame.grid(row=1, column=0, padx=10, pady=5, sticky="nsew") - - # 文件操作按钮 - btn_frame = ttk.Frame(file_frame) - btn_frame.pack(fill=tk.X, pady=2) - ttk.Button(btn_frame, text="添加文件", command=self.select_files).pack(side=tk.LEFT, padx=2) - ttk.Button(btn_frame, text="移除选中", command=self.remove_selected).pack(side=tk.LEFT, padx=2) - ttk.Button(btn_frame, text="清空列表", command=self.clear_files).pack(side=tk.LEFT, padx=2) - - # 文件列表(Treeview) - self.tree = ttk.Treeview(file_frame, columns=("selected", "filename"), - show="headings", height=10) - self.tree.heading("selected", text="选择", anchor=tk.W) - self.tree.heading("filename", text="文件名", anchor=tk.W) - self.tree.column("selected", width=60, anchor=tk.W) - self.tree.column("filename", width=600, anchor=tk.W) - self.tree.pack(fill=tk.BOTH, expand=True) - self.tree.bind("", self.on_tree_click) - - # 输出目录 - output_frame = ttk.LabelFrame(self.root, text="输出目录") - output_frame.grid(row=2, column=0, padx=10, pady=5, sticky="ew") - ttk.Entry(output_frame, textvariable=self.output_dir, width=60).pack(side=tk.LEFT, padx=5) - ttk.Button(output_frame, text="浏览", command=self.select_output_dir).pack(side=tk.RIGHT, padx=5) - - # 转换按钮和帮助按钮 - convert_frame = ttk.Frame(self.root) - convert_frame.grid(row=3, column=0, padx=10, pady=10) - ttk.Button(convert_frame, text="转换全部文件", command=lambda: self.start_conversion(True)).pack(side=tk.LEFT, padx=5) - ttk.Button(convert_frame, text="转换选中文件", command=lambda: self.start_conversion(False)).pack(side=tk.LEFT, padx=5) - ttk.Button(convert_frame, text="帮助", command=self.show_help).pack(side=tk.RIGHT, padx=5) - - # 日志区域(新增清空按钮部分) - log_frame = ttk.LabelFrame(self.root, text="日志") - log_frame.grid(row=4, column=0, padx=10, pady=5, sticky="nsew") - - # 添加按钮框架 - log_btn_frame = ttk.Frame(log_frame) - log_btn_frame.pack(fill=tk.X, side=tk.BOTTOM) - - # 清空日志按钮 - ttk.Button(log_btn_frame, text="清空日志", command=self.clear_log).pack(side=tk.RIGHT, padx=5, pady=2) - - self.log_text = tk.Text(log_frame, height=15) - self.log_text.pack(fill=tk.BOTH, expand=True) - - # 布局配置 - self.root.columnconfigure(0, weight=1) - self.root.rowconfigure(1, weight=1) - self.root.rowconfigure(4, weight=1) - - def clear_log(self): - """清空日志内容""" - self.log_text.delete(1.0, tk.END) - - def show_help(self): - messagebox.showinfo("帮助", HELP_TEXT) - - def redirect_output(self): - class StdoutRedirector: - def __init__(self, text_widget): - self.text_widget = text_widget - self.original_stdout = sys.stdout - - def write(self, message): - self.text_widget.insert(tk.END, message) - self.text_widget.see(tk.END) - self.original_stdout.write(message) - - def flush(self): - self.original_stdout.flush() - - sys.stdout = StdoutRedirector(self.log_text) - - def on_tree_click(self, event): - region = self.tree.identify("region", event.x, event.y) - if region == "cell": - col = self.tree.identify_column(event.x) - item = self.tree.identify_row(event.y) - if col == "#1": # 点击的是选中列 - current_val = self.tree.item(item, "values")[0] - new_val = "[√]" if current_val == "[ ]" else "[ ]" - self.tree.item(item, values=(new_val, self.tree.item(item, "values")[1])) - - def select_output_dir(self): - path = filedialog.askdirectory() - if path: - self.output_dir.set(path) - - def select_files(self): - files = filedialog.askopenfilenames(filetypes=[("图片文件", "*.png;*.jpg;*.jpeg;*.bmp;*.gif")]) - for f in files: - self.tree.insert("", tk.END, values=("[ ]", os.path.basename(f)), tags=(f,)) - - def remove_selected(self): - to_remove = [] - for item in self.tree.get_children(): - if self.tree.item(item, "values")[0] == "[√]": - to_remove.append(item) - for item in reversed(to_remove): - self.tree.delete(item) - - def clear_files(self): - for item in self.tree.get_children(): - self.tree.delete(item) - - def start_conversion(self, convert_all): - input_files = [ - self.tree.item(item, "tags")[0] - for item in self.tree.get_children() - if convert_all or self.tree.item(item, "values")[0] == "[√]" - ] - - if not input_files: - msg = "没有找到可转换的文件" if convert_all else "没有选中任何文件" - messagebox.showwarning("警告", msg) - return - - os.makedirs(self.output_dir.get(), exist_ok=True) - - # 解析转换参数 - width, height = map(int, self.resolution.get().split('x')) - compress = CompressMethod.RLE if self.compress_method.get() == "RLE" else CompressMethod.NONE - - # 执行转换 - self.convert_images(input_files, width, height, compress) - - def convert_images(self, input_files, width, height, compress): - success_count = 0 - total_files = len(input_files) - - for idx, file_path in enumerate(input_files): - try: - print(f"正在处理: {os.path.basename(file_path)}") - - with Image.open(file_path) as img: - # 调整图片大小 - img = img.resize((width, height), Image.Resampling.LANCZOS) - - # 处理颜色格式 - color_format_str = self.color_format.get() - if color_format_str == "自动识别": - # 检测透明通道 - has_alpha = img.mode in ('RGBA', 'LA') or (img.mode == 'P' and 'transparency' in img.info) - if has_alpha: - img = img.convert('RGBA') - cf = ColorFormat.RGB565A8 - else: - img = img.convert('RGB') - cf = ColorFormat.RGB565 - else: - if color_format_str == "RGB565A8": - img = img.convert('RGBA') - cf = ColorFormat.RGB565A8 - else: - img = img.convert('RGB') - cf = ColorFormat.RGB565 - - # 保存调整后的图片 - base_name = os.path.splitext(os.path.basename(file_path))[0] - output_image_path = os.path.join(self.output_dir.get(), f"{base_name}_{width}x{height}.png") - img.save(output_image_path, 'PNG') - - # 创建临时文件 - with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmpfile: - temp_path = tmpfile.name - img.save(temp_path, 'PNG') - - # 转换为LVGL C数组 - lvgl_img = LVGLImage().from_png(temp_path, cf=cf) - output_c_path = os.path.join(self.output_dir.get(), f"{base_name}.c") - lvgl_img.to_c_array(output_c_path, compress=compress) - - success_count += 1 - os.unlink(temp_path) - print(f"成功转换: {base_name}.c\n") - - except Exception as e: - print(f"转换失败: {str(e)}\n") - - print(f"转换完成! 成功 {success_count}/{total_files} 个文件\n") - -if __name__ == "__main__": - root = tk.Tk() - app = ImageConverterApp(root) - root.mainloop() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/requirements.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/requirements.txt deleted file mode 100644 index 5dbc3103..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/Image_Converter/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -lz4==4.4.4 -Pillow==11.3.0 -pypng==0.20220715.0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/demod.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/demod.py deleted file mode 100644 index 89c8196a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/demod.py +++ /dev/null @@ -1,280 +0,0 @@ -""" -实时AFSK解调器 - 基于Goertzel算法 -""" - -import numpy as np -from collections import deque - - -class TraceGoertzel: - """实时Goertzel算法实现""" - - def __init__(self, freq: float, n: int): - """ - 初始化Goertzel算法 - - Args: - freq: 归一化频率 (目标频率/采样频率) - n: 窗口大小 - """ - self.freq = freq - self.n = n - - # 预计算系数 - 与参考代码一致 - self.k = int(freq * n) - self.w = 2.0 * np.pi * freq - self.cw = np.cos(self.w) - self.sw = np.sin(self.w) - self.c = 2.0 * self.cw - - # 初始化状态变量 - 使用deque存储最近两个值 - self.zs = deque([0.0, 0.0], maxlen=2) - - def reset(self): - """重置算法状态""" - self.zs.clear() - self.zs.extend([0.0, 0.0]) - - def __call__(self, xs): - """ - 处理一组采样点 - 与参考代码一致的接口 - - Args: - xs: 采样点序列 - - Returns: - 计算出的振幅 - """ - self.reset() - for x in xs: - z1, z2 = self.zs[-1], self.zs[-2] # Z[-1], Z[-2] - z0 = x + self.c * z1 - z2 # S[n] = x[n] + C * S[n-1] - S[n-2] - self.zs.append(float(z0)) # 更新序列 - return self.amp - - @property - def amp(self) -> float: - """计算当前振幅 - 与参考代码一致""" - z1, z2 = self.zs[-1], self.zs[-2] - ip = self.cw * z1 - z2 - qp = self.sw * z1 - return np.sqrt(ip**2 + qp**2) / (self.n / 2.0) - - -class PairGoertzel: - """双频Goertzel解调器""" - - def __init__(self, f_sample: int, f_space: int, f_mark: int, - bit_rate: int, win_size: int): - """ - 初始化双频解调器 - - Args: - f_sample: 采样频率 - f_space: Space频率 (通常对应0) - f_mark: Mark频率 (通常对应1) - bit_rate: 比特率 - win_size: Goertzel窗口大小 - """ - assert f_sample % bit_rate == 0, "采样频率必须是比特率的整数倍" - - self.Fs = f_sample - self.F0 = f_space - self.F1 = f_mark - self.bit_rate = bit_rate - self.n_per_bit = int(f_sample // bit_rate) # 每个比特的采样点数 - - # 计算归一化频率 - f1 = f_mark / f_sample - f0 = f_space / f_sample - - # 初始化Goertzel算法 - self.g0 = TraceGoertzel(freq=f0, n=win_size) - self.g1 = TraceGoertzel(freq=f1, n=win_size) - - # 输入缓冲区 - self.in_buffer = deque(maxlen=win_size) - self.out_count = 0 - - print(f"PairGoertzel initialized: f0={f0:.6f}, f1={f1:.6f}, win_size={win_size}, n_per_bit={self.n_per_bit}") - - def __call__(self, s: float): - """ - 处理单个采样点 - 与参考代码一致的接口 - - Args: - s: 采样点值 - - Returns: - (amp0, amp1, p1_prob) - 空间频率振幅,标记频率振幅,标记概率 - """ - self.in_buffer.append(s) - self.out_count += 1 - - amp0, amp1, p1_prob = 0, 0, None - - # 每个比特周期输出一次结果 - if self.out_count >= self.n_per_bit: - amp0 = self.g0(self.in_buffer) # 计算space频率振幅 - amp1 = self.g1(self.in_buffer) # 计算mark频率振幅 - p1_prob = amp1 / (amp0 + amp1 + 1e-8) # 计算mark概率 - self.out_count = 0 - - return amp0, amp1, p1_prob - - -class RealTimeAFSKDecoder: - """实时AFSK解码器 - 基于起始帧触发""" - - def __init__(self, f_sample: int = 16000, mark_freq: int = 1800, - space_freq: int = 1500, bitrate: int = 100, - s_goertzel: int = 9, threshold: float = 0.5): - """ - 初始化实时AFSK解码器 - - Args: - f_sample: 采样频率 - mark_freq: Mark频率 - space_freq: Space频率 - bitrate: 比特率 - s_goertzel: Goertzel窗口大小系数 (win_size = f_sample // mark_freq * s_goertzel) - threshold: 判决门限 - """ - self.f_sample = f_sample - self.mark_freq = mark_freq - self.space_freq = space_freq - self.bitrate = bitrate - self.threshold = threshold - - # 计算窗口大小 - 与参考代码一致 - win_size = int(f_sample / mark_freq * s_goertzel) - - # 初始化解调器 - self.demodulator = PairGoertzel(f_sample, space_freq, mark_freq, - bitrate, win_size) - - # 帧定义 - 与参考代码一致 - self.start_bytes = b'\x01\x02' - self.end_bytes = b'\x03\x04' - self.start_bits = "".join(format(int(x), '08b') for x in self.start_bytes) - self.end_bits = "".join(format(int(x), '08b') for x in self.end_bytes) - - # 状态机 - self.state = "idle" # idle / entering - - # 存储解调结果 - self.buffer_prelude:deque = deque(maxlen=len(self.start_bits)) # 判断是否启动 - self.indicators = [] # 存储概率序列 - self.signal_bits = "" # 存储比特序列 - self.text_cache = "" - - # 解码结果 - self.decoded_messages = [] - self.total_bits_received = 0 - - print(f"Decoder initialized: win_size={win_size}") - print(f"Start frame: {self.start_bits} (from {self.start_bytes.hex()})") - print(f"End frame: {self.end_bits} (from {self.end_bytes.hex()})") - - def process_audio(self, samples: np.array) -> str: - """ - 处理音频数据并返回解码文本 - - Args: - audio_data: 音频字节数据 (16-bit PCM) - - Returns: - 新解码的文本 - """ - new_text = "" - # 逐个处理采样点 - for sample in samples: - amp0, amp1, p1_prob = self.demodulator(sample) - # 如果有概率输出,记录并判决 - if p1_prob is not None: - bit = '1' if p1_prob > self.threshold else '0' - match self.state: - case "idle": - self.buffer_prelude.append(bit) - pass - case "entering": - self.buffer_prelude.append(bit) - self.signal_bits += bit - self.total_bits_received += 1 - case _: - pass - self.indicators.append(p1_prob) - - # 检查状态机 - if self.state == "idle" and "".join(self.buffer_prelude) == self.start_bits: - self.state = "entering" - self.text_cache = "" - self.signal_bits = "" # 清空比特序列 - self.buffer_prelude.clear() - elif self.state == "entering" and ("".join(self.buffer_prelude) == self.end_bits or len(self.signal_bits) >= 256): - self.state = "idle" - self.buffer_prelude.clear() - - # 每收集一定数量的比特后尝试解码 - if len(self.signal_bits) >= 8: - text = self._decode_bits_to_text(self.signal_bits) - if len(text) > len(self.text_cache): - new_text = text[len(self.text_cache) - len(text):] - self.text_cache = text - return new_text - - def _decode_bits_to_text(self, bits: str) -> str: - """ - 将比特串解码为文本 - - Args: - bits: 比特串 - - Returns: - 解码出的文本 - """ - if len(bits) < 8: - return "" - - decoded_text = "" - byte_count = len(bits) // 8 - - for i in range(byte_count): - # 提取8位 - byte_bits = bits[i*8:(i+1)*8] - - # 位转字节 - byte_val = int(byte_bits, 2) - - # 尝试解码为ASCII字符 - if 32 <= byte_val <= 126: # 可打印ASCII字符 - decoded_text += chr(byte_val) - elif byte_val == 0: # NULL字符,忽略 - continue - else: - # 非可打印字符pass,以十六进制显示 - pass - # decoded_text += f"\\x{byte_val:02X}" - - return decoded_text - - def clear(self): - """清空解码状态""" - self.indicators = [] - self.signal_bits = "" - self.decoded_messages = [] - self.total_bits_received = 0 - print("解码器状态已清空") - - def get_stats(self) -> dict: - """获取解码统计信息""" - return { - 'prelude_bits': "".join(self.buffer_prelude), - "state": self.state, - 'total_chars': sum(len(msg) for msg in self.text_cache), - 'buffer_bits': len(self.signal_bits), - 'mark_freq': self.mark_freq, - 'space_freq': self.space_freq, - 'bitrate': self.bitrate, - 'threshold': self.threshold, - } diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/graphic.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/graphic.py deleted file mode 100644 index e60cf063..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/graphic.py +++ /dev/null @@ -1,444 +0,0 @@ -import sys -import numpy as np -import asyncio -import wave -from collections import deque -import qasync - -import matplotlib -matplotlib.use('qtagg') - -from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas -from matplotlib.backends.backend_qtagg import NavigationToolbar2QT as NavigationToolbar # noqa: F401 -from matplotlib.figure import Figure - -from PyQt6.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QWidget, - QHBoxLayout, QLineEdit, QPushButton, QLabel, QTextEdit) -from PyQt6.QtCore import QTimer - -# 导入解码器 -from demod import RealTimeAFSKDecoder - - -class UDPServerProtocol(asyncio.DatagramProtocol): - """UDP服务器协议类""" - def __init__(self, data_queue): - self.client_address = None - self.data_queue: deque = data_queue - - def connection_made(self, transport): - self.transport = transport - - def datagram_received(self, data, addr): - # 如果还没有客户端地址,记录第一个连接的客户端 - if self.client_address is None: - self.client_address = addr - print(f"接受来自 {addr} 的连接") - - # 只处理来自已记录客户端的数据 - if addr == self.client_address: - # 将接收到的音频数据添加到队列 - self.data_queue.extend(data) - else: - print(f"忽略来自未知地址 {addr} 的数据") - - -class MatplotlibWidget(QWidget): - def __init__(self, parent=None): - super().__init__(parent) - - # 创建 Matplotlib 的 Figure 对象 - self.figure = Figure() - - # 创建 FigureCanvas 对象,它是 Figure 的 QWidget 容器 - self.canvas = FigureCanvas(self.figure) - - # 创建 Matplotlib 的导航工具栏 - # self.toolbar = NavigationToolbar(self.canvas, self) - self.toolbar = None - - # 创建布局 - layout = QVBoxLayout() - layout.addWidget(self.toolbar) - layout.addWidget(self.canvas) - self.setLayout(layout) - - # 初始化音频数据参数 - self.freq = 16000 # 采样频率 - self.time_window = 20 # 显示时间窗口 - self.wave_data = deque(maxlen=self.freq * self.time_window * 2) # 缓冲队列, 用于分发计算/绘图 - self.signals = deque(maxlen=self.freq * self.time_window) # 双端队列存储信号数据 - - # 创建包含两个子图的画布 - self.ax1 = self.figure.add_subplot(2, 1, 1) - self.ax2 = self.figure.add_subplot(2, 1, 2) - - # 时域子图 - self.ax1.set_title('Real-time Audio Waveform') - self.ax1.set_xlabel('Sample Index') - self.ax1.set_ylabel('Amplitude') - self.line_time, = self.ax1.plot([], []) - self.ax1.grid(True, alpha=0.3) - - # 频域子图 - self.ax2.set_title('Real-time Frequency Spectrum') - self.ax2.set_xlabel('Frequency (Hz)') - self.ax2.set_ylabel('Magnitude') - self.line_freq, = self.ax2.plot([], []) - self.ax2.grid(True, alpha=0.3) - - self.figure.tight_layout() - - # 定时器用于更新图表 - self.timer = QTimer(self) - self.timer.setInterval(100) # 100毫秒更新一次 - self.timer.timeout.connect(self.update_plot) - - # 初始化AFSK解码器 - self.decoder = RealTimeAFSKDecoder( - f_sample=self.freq, - mark_freq=1800, - space_freq=1500, - bitrate=100, - s_goertzel=9, - threshold=0.5 - ) - - # 解码结果回调 - self.decode_callback = None - - def start_plotting(self): - """开始绘图""" - self.timer.start() - - def stop_plotting(self): - """停止绘图""" - self.timer.stop() - - def update_plot(self): - """更新绘图数据""" - if len(self.wave_data) >= 2: - # 进行实时解码 - # 获取最新的音频数据进行解码 - even = len(self.wave_data) // 2 * 2 - print(f"length of wave_data: {len(self.wave_data)}") - drained = [self.wave_data.popleft() for _ in range(even)] - signal = np.frombuffer(bytearray(drained), dtype=' 0: - # 只显示最近的一段数据,避免图表过于密集 - signal = np.array(self.signals) - max_samples = min(len(signal), self.freq * self.time_window) - if len(signal) > max_samples: - signal = signal[-max_samples:] - - # 更新时域图 - x = np.arange(len(signal)) - self.line_time.set_data(x, signal) - - # 自动调整时域坐标轴范围 - if len(signal) > 0: - self.ax1.set_xlim(0, len(signal)) - y_min, y_max = np.min(signal), np.max(signal) - if y_min != y_max: - margin = (y_max - y_min) * 0.1 - self.ax1.set_ylim(y_min - margin, y_max + margin) - else: - self.ax1.set_ylim(-1, 1) - - # 计算频谱(短时离散傅立叶变换) - if len(signal) > 1: - # 计算FFT - fft_signal = np.abs(np.fft.fft(signal)) - frequencies = np.fft.fftfreq(len(signal), 1/self.freq) - - # 只取正频率部分 - positive_freq_idx = frequencies >= 0 - freq_positive = frequencies[positive_freq_idx] - fft_positive = fft_signal[positive_freq_idx] - - # 更新频域图 - self.line_freq.set_data(freq_positive, fft_positive) - - # 自动调整频域坐标轴范围 - if len(fft_positive) > 0: - # 限制频率显示范围到0-4000Hz,避免过于密集 - max_freq_show = min(4000, self.freq // 2) - freq_mask = freq_positive <= max_freq_show - if np.any(freq_mask): - self.ax2.set_xlim(0, max_freq_show) - fft_masked = fft_positive[freq_mask] - if len(fft_masked) > 0: - fft_max = np.max(fft_masked) - if fft_max > 0: - self.ax2.set_ylim(0, fft_max * 1.1) - else: - self.ax2.set_ylim(0, 1) - - self.canvas.draw() - - -class MainWindow(QMainWindow): - def __init__(self): - super().__init__() - self.setWindowTitle("Acoustic Check") - self.setGeometry(100, 100, 1000, 800) - - # 主窗口部件 - main_widget = QWidget() - self.setCentralWidget(main_widget) - - # 主布局 - main_layout = QVBoxLayout(main_widget) - - # 绘图区域 - self.matplotlib_widget = MatplotlibWidget() - main_layout.addWidget(self.matplotlib_widget) - - # 控制面板 - control_panel = QWidget() - control_layout = QHBoxLayout(control_panel) - - # 监听地址和端口输入 - control_layout.addWidget(QLabel("监听地址:")) - self.address_input = QLineEdit("0.0.0.0") - self.address_input.setFixedWidth(120) - control_layout.addWidget(self.address_input) - - control_layout.addWidget(QLabel("端口:")) - self.port_input = QLineEdit("8000") - self.port_input.setFixedWidth(80) - control_layout.addWidget(self.port_input) - - # 监听按钮 - self.listen_button = QPushButton("开始监听") - self.listen_button.clicked.connect(self.toggle_listening) - control_layout.addWidget(self.listen_button) - - # 状态标签 - self.status_label = QLabel("状态: 未连接") - control_layout.addWidget(self.status_label) - - # 数据统计标签 - self.data_label = QLabel("接收数据: 0 bytes") - control_layout.addWidget(self.data_label) - - # 保存按钮 - self.save_button = QPushButton("保存音频") - self.save_button.clicked.connect(self.save_audio) - self.save_button.setEnabled(False) - control_layout.addWidget(self.save_button) - - control_layout.addStretch() # 添加弹性空间 - - main_layout.addWidget(control_panel) - - # 解码显示区域 - decode_panel = QWidget() - decode_layout = QVBoxLayout(decode_panel) - - # 解码标题 - decode_title = QLabel("实时AFSK解码结果:") - decode_title.setStyleSheet("font-weight: bold; font-size: 14px;") - decode_layout.addWidget(decode_title) - - # 解码文本显示 - self.decode_text = QTextEdit() - self.decode_text.setMaximumHeight(150) - self.decode_text.setReadOnly(True) - self.decode_text.setStyleSheet("font-family: 'Courier New', monospace; font-size: 12px;") - decode_layout.addWidget(self.decode_text) - - # 解码控制按钮 - decode_control_layout = QHBoxLayout() - - # 清空按钮 - self.clear_decode_button = QPushButton("清空解码") - self.clear_decode_button.clicked.connect(self.clear_decode_text) - decode_control_layout.addWidget(self.clear_decode_button) - - # 解码统计标签 - self.decode_stats_label = QLabel("解码统计: 0 bits, 0 chars") - decode_control_layout.addWidget(self.decode_stats_label) - - decode_control_layout.addStretch() - decode_layout.addLayout(decode_control_layout) - - main_layout.addWidget(decode_panel) - - # 设置解码回调 - self.matplotlib_widget.decode_callback = self.on_decode_text - - # UDP相关属性 - self.udp_transport = None - self.is_listening = False - - # 数据统计定时器 - self.stats_timer = QTimer(self) - self.stats_timer.setInterval(1000) # 每秒更新一次统计 - self.stats_timer.timeout.connect(self.update_stats) - - def on_decode_text(self, new_text: str): - """解码文本回调""" - if new_text: - # 添加新解码的文本 - current_text = self.decode_text.toPlainText() - updated_text = current_text + new_text - - # 限制文本长度,保留最新的1000个字符 - if len(updated_text) > 1000: - updated_text = updated_text[-1000:] - - self.decode_text.setPlainText(updated_text) - - # 滚动到底部 - cursor = self.decode_text.textCursor() - cursor.movePosition(cursor.MoveOperation.End) - self.decode_text.setTextCursor(cursor) - - def clear_decode_text(self): - """清空解码文本""" - self.decode_text.clear() - if hasattr(self.matplotlib_widget, 'decoder'): - self.matplotlib_widget.decoder.clear() - self.decode_stats_label.setText("解码统计: 0 bits, 0 chars") - - def update_decode_stats(self): - """更新解码统计""" - if hasattr(self.matplotlib_widget, 'decoder'): - stats = self.matplotlib_widget.decoder.get_stats() - stats_text = ( - f"前置: {stats['prelude_bits']} , 已接收{stats['total_chars']} chars, " - f"缓冲: {stats['buffer_bits']} bits, 状态: {stats['state']}" - ) - self.decode_stats_label.setText(stats_text) - - def toggle_listening(self): - """切换监听状态""" - if not self.is_listening: - self.start_listening() - else: - self.stop_listening() - - async def start_listening_async(self): - """异步启动UDP监听""" - try: - address = self.address_input.text().strip() - port = int(self.port_input.text().strip()) - - loop = asyncio.get_running_loop() - self.udp_transport, protocol = await loop.create_datagram_endpoint( - lambda: UDPServerProtocol(self.matplotlib_widget.wave_data), - local_addr=(address, port) - ) - - self.status_label.setText(f"状态: 监听中 ({address}:{port})") - print(f"UDP服务器启动, 监听 {address}:{port}") - - except Exception as e: - self.status_label.setText(f"状态: 启动失败 - {str(e)}") - print(f"UDP服务器启动失败: {e}") - self.is_listening = False - self.listen_button.setText("开始监听") - self.address_input.setEnabled(True) - self.port_input.setEnabled(True) - - def start_listening(self): - """开始监听""" - try: - int(self.port_input.text().strip()) # 验证端口号格式 - except ValueError: - self.status_label.setText("状态: 端口号必须是数字") - return - - self.is_listening = True - self.listen_button.setText("停止监听") - self.address_input.setEnabled(False) - self.port_input.setEnabled(False) - self.save_button.setEnabled(True) - - # 清空数据队列 - self.matplotlib_widget.wave_data.clear() - - # 启动绘图和统计更新 - self.matplotlib_widget.start_plotting() - self.stats_timer.start() - - # 异步启动UDP服务器 - loop = asyncio.get_event_loop() - loop.create_task(self.start_listening_async()) - - def stop_listening(self): - """停止监听""" - self.is_listening = False - self.listen_button.setText("开始监听") - self.address_input.setEnabled(True) - self.port_input.setEnabled(True) - - # 停止UDP服务器 - if self.udp_transport: - self.udp_transport.close() - self.udp_transport = None - - # 停止绘图和统计更新 - self.matplotlib_widget.stop_plotting() - self.matplotlib_widget.wave_data.clear() - self.stats_timer.stop() - - self.status_label.setText("状态: 已停止") - - def update_stats(self): - """更新数据统计""" - data_size = len(self.matplotlib_widget.signals) - self.data_label.setText(f"接收数据: {data_size} 采样") - - # 更新解码统计 - self.update_decode_stats() - - def save_audio(self): - """保存音频数据""" - if len(self.matplotlib_widget.signals) > 0: - try: - signal_data = np.array(self.matplotlib_widget.signals) - - # 保存为WAV文件 - with wave.open("received_audio.wav", "wb") as wf: - wf.setnchannels(1) # 单声道 - wf.setsampwidth(2) # 采样宽度为2字节 - wf.setframerate(self.matplotlib_widget.freq) # 设置采样率 - wf.writeframes(signal_data.tobytes()) # 写入数据 - - self.status_label.setText("状态: 音频已保存为 received_audio.wav") - print("音频已保存为 received_audio.wav") - - except Exception as e: - self.status_label.setText(f"状态: 保存失败 - {str(e)}") - print(f"保存音频失败: {e}") - else: - self.status_label.setText("状态: 没有足够的数据可保存") - - -async def main(): - """异步主函数""" - app = QApplication(sys.argv) - - # 设置异步事件循环 - loop = qasync.QEventLoop(app) - asyncio.set_event_loop(loop) - - window = MainWindow() - window.show() - - try: - with loop: - await loop.run_forever() - except KeyboardInterrupt: - print("程序被用户中断") - finally: - # 确保清理资源 - if window.udp_transport: - window.udp_transport.close() \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/main.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/main.py deleted file mode 100644 index 63ec8497..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/main.py +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env python3 -""" -音频实时监听与绘图系统主程序 -基于Qt GUI + Matplotlib + UDP接收 + AFSK解码字符串 -""" - -import sys -import asyncio -from graphic import main - -if __name__ == '__main__': - try: - asyncio.run(main()) - except KeyboardInterrupt: - print("程序被用户中断") - except Exception as e: - print(f"程序执行出错: {e}") - sys.exit(1) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/readme.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/readme.md deleted file mode 100644 index 9eb9c7c6..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/readme.md +++ /dev/null @@ -1,23 +0,0 @@ -# 声波测试 -该gui用于测试接受小智设备通过`udp`回传的`pcm`转时域/频域, 可以保存窗口长度的声音, 用于判断噪音频率分布和测试声波传输ascii的准确度, - -固件测试需要打开`USE_AUDIO_DEBUGGER`, 并设置好`AUDIO_DEBUG_UDP_SERVER`是本机地址. -声波`demod`可以通过`sonic_wifi_config.html`或者上传至`PinMe`的[小智声波配网](https://iqf7jnhi.pinit.eth.limo)来输出声波测试 - -# 声波解码测试记录 - -> `✓`代表在I2S DIN接收原始PCM信号时就能成功解码, `△`代表需要降噪或额外操作可稳定解码, `X`代表降噪后效果也不好(可能能解部分但非常不稳定)。 -> 个别ADC需要I2C配置阶段做更精细的降噪调整, 由于设备不通用暂只按照boards内提供的config测试 - -| 设备 | ADC | MIC | 效果 | 备注 | -| ---- | ---- | --- | --- | ---- | -| bread-compact | INMP441 | 集成MEMEMIC | ✓ | -| atk-dnesp32s3-box | ES8311 | | ✓ | -| magiclick-2p5 | ES8311 | | ✓ | -| lichuang-dev | ES7210 | | △ | 测试时需要关掉INPUT_REFERENCE -| kevin-box-2 | ES7210 | | △ | 测试时需要关掉INPUT_REFERENCE -| m5stack-core-s3 | ES7210 | | △ | 测试时需要关掉INPUT_REFERENCE -| xmini-c3 | ES8311 | | △ | 需降噪 -| atoms3r-echo-base | ES8311 | | △ | 需降噪 -| atk-dnesp32s3-box0 | ES8311 | | X | 能接收且解码, 但是丢包率很高 -| movecall-moji-esp32s3 | ES8311 | | X | 能接收且解码, 但是丢包率很高 \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/requirements.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/requirements.txt deleted file mode 100644 index 91bc5eca..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/acoustic_check/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -matplotlib==3.10.5 -numpy==2.3.2 -PyQt6==6.9.1 -qasync==0.27.1 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/audio_debug_server.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/audio_debug_server.py deleted file mode 100644 index 872c4905..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/audio_debug_server.py +++ /dev/null @@ -1,54 +0,0 @@ -import socket -import wave -import argparse - - -''' - Create a UDP socket and bind it to the server's IP:8000. - Listen for incoming messages and print them to the console. - Save the audio to a WAV file. -''' -def main(samplerate, channels): - # Create a UDP socket - server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - server_socket.bind(('0.0.0.0', 8000)) - - # Create WAV file with parameters - filename = f"{samplerate}_{channels}.wav" - wav_file = wave.open(filename, "wb") - wav_file.setnchannels(channels) # channels parameter - wav_file.setsampwidth(2) # 2 bytes per sample (16-bit) - wav_file.setframerate(samplerate) # samplerate parameter - - print(f"Start saving audio from 0.0.0.0:8000 to {filename}...") - - try: - while True: - # Receive a message from the client - message, address = server_socket.recvfrom(8000) - - # Write PCM data to WAV file - wav_file.writeframes(message) - - # Print length of the message - print(f"Received {len(message)} bytes from {address}") - - except KeyboardInterrupt: - print("\nStopping recording...") - - finally: - # Close files and socket - wav_file.close() - server_socket.close() - print(f"WAV file '{filename}' saved successfully") - - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='UDP音频数据接收器,保存为WAV文件') - parser.add_argument('--samplerate', '-s', type=int, default=16000, - help='采样率 (默认: 16000)') - parser.add_argument('--channels', '-c', type=int, default=2, - help='声道数 (默认: 2)') - - args = parser.parse_args() - main(args.samplerate, args.channels) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/build_default_assets.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/build_default_assets.py deleted file mode 100644 index 37e4e01d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/build_default_assets.py +++ /dev/null @@ -1,882 +0,0 @@ -#!/usr/bin/env python3 -""" -Build default assets based on configuration - -This script reads configuration from sdkconfig and builds the appropriate assets.bin -for the current board configuration. - -Usage: - ./build_default_assets.py --sdkconfig --builtin_text_font \ - --default_emoji_collection --output -""" - -import argparse -import io -import os -import shutil -import sys -import json -import struct -from datetime import datetime - - -# ============================================================================= -# Pack model functions (from pack_model.py) -# ============================================================================= - -def struct_pack_string(string, max_len=None): - """ - pack string to binary data. - if max_len is None, max_len = len(string) + 1 - else len(string) < max_len, the left will be padded by struct.pack('x') - """ - if max_len == None : - max_len = len(string) - else: - assert len(string) <= max_len - - left_num = max_len - len(string) - out_bytes = None - for char in string: - if out_bytes == None: - out_bytes = struct.pack('b', ord(char)) - else: - out_bytes += struct.pack('b', ord(char)) - for i in range(left_num): - out_bytes += struct.pack('x') - return out_bytes - - -def read_data(filename): - """Read binary data, like index and mndata""" - data = None - with open(filename, "rb") as f: - data = f.read() - return data - - -def pack_models(model_path, out_file="srmodels.bin"): - """ - Pack all models into one binary file by the following format: - { - model_num: int - model1_info: model_info_t - model2_info: model_info_t - ... - model1_index,model1_data,model1_MODEL_INFO - model1_index,model1_data,model1_MODEL_INFO - ... - }model_pack_t - - { - model_name: char[32] - file_number: int - file1_name: char[32] - file1_start: int - file1_len: int - file2_name: char[32] - file2_start: int // data_len = info_start - data_start - file2_len: int - ... - }model_info_t - """ - models = {} - file_num = 0 - model_num = 0 - for root, dirs, _ in os.walk(model_path): - for model_name in dirs: - models[model_name] = {} - model_dir = os.path.join(root, model_name) - model_num += 1 - for _, _, files in os.walk(model_dir): - for file_name in files: - file_num += 1 - file_path = os.path.join(model_dir, file_name) - models[model_name][file_name] = read_data(file_path) - - model_num = len(models) - header_len = 4 + model_num*(32+4) + file_num*(32+4+4) - out_bin = struct.pack('I', model_num) # model number - data_bin = None - for key in models: - model_bin = struct_pack_string(key, 32) # + model name - model_bin += struct.pack('I', len(models[key])) # + file number in this model - - for file_name in models[key]: - model_bin += struct_pack_string(file_name, 32) # + file name - if data_bin == None: - model_bin += struct.pack('I', header_len) - data_bin = models[key][file_name] - model_bin += struct.pack('I', len(models[key][file_name])) - else: - model_bin += struct.pack('I', header_len+len(data_bin)) - data_bin += models[key][file_name] - model_bin += struct.pack('I', len(models[key][file_name])) - - out_bin += model_bin - assert len(out_bin) == header_len - if data_bin != None: - out_bin += data_bin - - out_file = os.path.join(model_path, out_file) - with open(out_file, "wb") as f: - f.write(out_bin) - - -# ============================================================================= -# Build assets functions (from build.py) -# ============================================================================= - -def ensure_dir(directory): - """Ensure directory exists, create if not""" - os.makedirs(directory, exist_ok=True) - - -def copy_file(src, dst): - """Copy file""" - if os.path.exists(src): - shutil.copy2(src, dst) - print(f"Copied: {src} -> {dst}") - return True - else: - print(f"Warning: Source file does not exist: {src}") - return False - - -def copy_directory(src, dst): - """Copy directory""" - if os.path.exists(src): - shutil.copytree(src, dst, dirs_exist_ok=True) - print(f"Copied directory: {src} -> {dst}") - return True - else: - print(f"Warning: Source directory does not exist: {src}") - return False - - -def process_sr_models(wakenet_model_dirs, multinet_model_dirs, build_dir, assets_dir): - """Process SR models (wakenet and multinet) and generate srmodels.bin""" - if not wakenet_model_dirs and not multinet_model_dirs: - return None - - # Create SR models build directory - sr_models_build_dir = os.path.join(build_dir, "srmodels") - if os.path.exists(sr_models_build_dir): - shutil.rmtree(sr_models_build_dir) - os.makedirs(sr_models_build_dir) - - models_processed = 0 - - # Copy wakenet models if available - if wakenet_model_dirs: - for wakenet_model_dir in wakenet_model_dirs: - wakenet_name = os.path.basename(wakenet_model_dir) - wakenet_dst = os.path.join(sr_models_build_dir, wakenet_name) - if copy_directory(wakenet_model_dir, wakenet_dst): - models_processed += 1 - print(f"Added wakenet model: {wakenet_name}") - - # Copy multinet models if available - if multinet_model_dirs: - for multinet_model_dir in multinet_model_dirs: - multinet_name = os.path.basename(multinet_model_dir) - multinet_dst = os.path.join(sr_models_build_dir, multinet_name) - if copy_directory(multinet_model_dir, multinet_dst): - models_processed += 1 - print(f"Added multinet model: {multinet_name}") - - if models_processed == 0: - print("Warning: No SR models were successfully processed") - return None - - # Use pack_models function to generate srmodels.bin - srmodels_output = os.path.join(sr_models_build_dir, "srmodels.bin") - try: - pack_models(sr_models_build_dir, "srmodels.bin") - print(f"Generated: {srmodels_output}") - # Copy srmodels.bin to assets directory - copy_file(srmodels_output, os.path.join(assets_dir, "srmodels.bin")) - return "srmodels.bin" - except Exception as e: - print(f"Error: Failed to generate srmodels.bin: {e}") - return None - - -def process_text_font(text_font_file, assets_dir): - """Process text_font parameter""" - if not text_font_file: - return None - - # Copy input file to build/assets directory - font_filename = os.path.basename(text_font_file) - font_dst = os.path.join(assets_dir, font_filename) - if copy_file(text_font_file, font_dst): - return font_filename - return None - - -def process_emoji_collection(emoji_collection_dir, assets_dir): - """Process emoji_collection parameter""" - if not emoji_collection_dir: - return [] - - emoji_list = [] - - # Copy each image from input directory to build/assets directory - for root, dirs, files in os.walk(emoji_collection_dir): - for file in files: - if file.lower().endswith(('.png', '.gif')): - # Copy file - src_file = os.path.join(root, file) - dst_file = os.path.join(assets_dir, file) - if copy_file(src_file, dst_file): - # Get filename without extension - filename_without_ext = os.path.splitext(file)[0] - - # Add to emoji list - emoji_list.append({ - "name": filename_without_ext, - "file": file - }) - - return emoji_list - - -def process_extra_files(extra_files_dir, assets_dir): - """Process default_assets_extra_files parameter""" - if not extra_files_dir: - return [] - - if not os.path.exists(extra_files_dir): - print(f"Warning: Extra files directory not found: {extra_files_dir}") - return [] - - extra_files_list = [] - - # Copy each file from input directory to build/assets directory - for root, dirs, files in os.walk(extra_files_dir): - for file in files: - # Skip hidden files and directories - if file.startswith('.'): - continue - - # Copy file - src_file = os.path.join(root, file) - dst_file = os.path.join(assets_dir, file) - if copy_file(src_file, dst_file): - extra_files_list.append(file) - - if extra_files_list: - print(f"Processed {len(extra_files_list)} extra files from: {extra_files_dir}") - - return extra_files_list - - -def generate_index_json(assets_dir, srmodels, text_font, emoji_collection, extra_files=None, multinet_model_info=None): - """Generate index.json file""" - index_data = { - "version": 1 - } - - if srmodels: - index_data["srmodels"] = srmodels - - if text_font: - index_data["text_font"] = text_font - - if emoji_collection: - index_data["emoji_collection"] = emoji_collection - - if extra_files: - index_data["extra_files"] = extra_files - - if multinet_model_info: - index_data["multinet_model"] = multinet_model_info - - # Write index.json - index_path = os.path.join(assets_dir, "index.json") - with open(index_path, 'w', encoding='utf-8') as f: - json.dump(index_data, f, indent=4, ensure_ascii=False) - - print(f"Generated: {index_path}") - - -def generate_config_json(build_dir, assets_dir): - """Generate config.json file""" - config_data = { - "include_path": os.path.join(build_dir, "include"), - "assets_path": assets_dir, - "image_file": os.path.join(build_dir, "output", "assets.bin"), - "lvgl_ver": "9.3.0", - "assets_size": "0x400000", - "support_format": ".png, .gif, .jpg, .bin, .json", - "name_length": "32", - "split_height": "0", - "support_qoi": False, - "support_spng": False, - "support_sjpg": False, - "support_sqoi": False, - "support_raw": False, - "support_raw_dither": False, - "support_raw_bgr": False - } - - # Write config.json - config_path = os.path.join(build_dir, "config.json") - with open(config_path, 'w', encoding='utf-8') as f: - json.dump(config_data, f, indent=4, ensure_ascii=False) - - print(f"Generated: {config_path}") - return config_path - - -# ============================================================================= -# Simplified SPIFFS assets generation (from spiffs_assets_gen.py) -# ============================================================================= - -def compute_checksum(data): - checksum = sum(data) & 0xFFFF - return checksum - - -def sort_key(filename): - basename, extension = os.path.splitext(filename) - return extension, basename - - -def pack_assets_simple(target_path, include_path, out_file, assets_path, max_name_len=32): - """ - Simplified version of pack_assets that handles basic file packing - """ - merged_data = bytearray() - file_info_list = [] - skip_files = ['config.json'] - - # Ensure output directory exists - os.makedirs(os.path.dirname(out_file), exist_ok=True) - os.makedirs(include_path, exist_ok=True) - - file_list = sorted(os.listdir(target_path), key=sort_key) - for filename in file_list: - if filename in skip_files: - continue - - file_path = os.path.join(target_path, filename) - if not os.path.isfile(file_path): - continue - - file_name = os.path.basename(file_path) - file_size = os.path.getsize(file_path) - - file_info_list.append((file_name, len(merged_data), file_size, 0, 0)) - # Add 0x5A5A prefix to merged_data - merged_data.extend(b'\x5A' * 2) - - with open(file_path, 'rb') as bin_file: - bin_data = bin_file.read() - - merged_data.extend(bin_data) - - total_files = len(file_info_list) - - mmap_table = bytearray() - for file_name, offset, file_size, width, height in file_info_list: - if len(file_name) > max_name_len: - print(f'Warning: "{file_name}" exceeds {max_name_len} bytes and will be truncated.') - fixed_name = file_name.ljust(max_name_len, '\0')[:max_name_len] - mmap_table.extend(fixed_name.encode('utf-8')) - mmap_table.extend(file_size.to_bytes(4, byteorder='little')) - mmap_table.extend(offset.to_bytes(4, byteorder='little')) - mmap_table.extend(width.to_bytes(2, byteorder='little')) - mmap_table.extend(height.to_bytes(2, byteorder='little')) - - combined_data = mmap_table + merged_data - combined_checksum = compute_checksum(combined_data) - combined_data_length = len(combined_data).to_bytes(4, byteorder='little') - header_data = total_files.to_bytes(4, byteorder='little') + combined_checksum.to_bytes(4, byteorder='little') - final_data = header_data + combined_data_length + combined_data - - with open(out_file, 'wb') as output_bin: - output_bin.write(final_data) - - # Generate header file - current_year = datetime.now().year - asset_name = os.path.basename(assets_path) - header_file_path = os.path.join(include_path, f'mmap_generate_{asset_name}.h') - with open(header_file_path, 'w') as output_header: - output_header.write('/*\n') - output_header.write(' * SPDX-FileCopyrightText: 2022-{} Espressif Systems (Shanghai) CO LTD\n'.format(current_year)) - output_header.write(' *\n') - output_header.write(' * SPDX-License-Identifier: Apache-2.0\n') - output_header.write(' */\n\n') - output_header.write('/**\n') - output_header.write(' * @file\n') - output_header.write(" * @brief This file was generated by esp_mmap_assets, don't modify it\n") - output_header.write(' */\n\n') - output_header.write('#pragma once\n\n') - output_header.write("#include \"esp_mmap_assets.h\"\n\n") - output_header.write(f'#define MMAP_{asset_name.upper()}_FILES {total_files}\n') - output_header.write(f'#define MMAP_{asset_name.upper()}_CHECKSUM 0x{combined_checksum:04X}\n\n') - output_header.write(f'enum MMAP_{asset_name.upper()}_LISTS {{\n') - - for i, (file_name, _, _, _, _) in enumerate(file_info_list): - enum_name = file_name.replace('.', '_') - output_header.write(f' MMAP_{asset_name.upper()}_{enum_name.upper()} = {i}, /*!< {file_name} */\n') - - output_header.write('};\n') - - print(f'All files have been merged into {os.path.basename(out_file)}') - - -# ============================================================================= -# Configuration and main functions -# ============================================================================= - -def read_wakenet_from_sdkconfig(sdkconfig_path): - """ - Read wakenet models from sdkconfig (based on movemodel.py logic) - Returns a list of wakenet model names - """ - if not os.path.exists(sdkconfig_path): - print(f"Warning: sdkconfig file not found: {sdkconfig_path}") - return [] - - models = [] - with io.open(sdkconfig_path, "r") as f: - for label in f: - label = label.strip("\n") - if 'CONFIG_SR_WN' in label and '#' not in label[0]: - if '_NONE' in label: - continue - if '=' in label: - label = label.split("=")[0] - if '_MULTI' in label: - label = label[:-6] - model_name = label.split("_SR_WN_")[-1].lower() - models.append(model_name) - - return models - - -def read_multinet_from_sdkconfig(sdkconfig_path): - """ - Read multinet models from sdkconfig (based on movemodel.py logic) - Returns a list of multinet model names - """ - if not os.path.exists(sdkconfig_path): - print(f"Warning: sdkconfig file not found: {sdkconfig_path}") - return [] - - with io.open(sdkconfig_path, "r") as f: - models_string = '' - for label in f: - label = label.strip("\n") - if 'CONFIG_SR_MN' in label and label[0] != '#': - models_string += label - - models = [] - if "CONFIG_SR_MN_CN_MULTINET3_SINGLE_RECOGNITION" in models_string: - models.append('mn3_cn') - elif "CONFIG_SR_MN_CN_MULTINET4_5_SINGLE_RECOGNITION_QUANT8" in models_string: - models.append('mn4q8_cn') - elif "CONFIG_SR_MN_CN_MULTINET4_5_SINGLE_RECOGNITION" in models_string: - models.append('mn4_cn') - elif "CONFIG_SR_MN_CN_MULTINET5_RECOGNITION_QUANT8" in models_string: - models.append('mn5q8_cn') - elif "CONFIG_SR_MN_CN_MULTINET6_QUANT" in models_string: - models.append('mn6_cn') - elif "CONFIG_SR_MN_CN_MULTINET6_AC_QUANT" in models_string: - models.append('mn6_cn_ac') - elif "CONFIG_SR_MN_CN_MULTINET7_QUANT" in models_string: - models.append('mn7_cn') - elif "CONFIG_SR_MN_CN_MULTINET7_AC_QUANT" in models_string: - models.append('mn7_cn_ac') - - if "CONFIG_SR_MN_EN_MULTINET5_SINGLE_RECOGNITION_QUANT8" in models_string: - models.append('mn5q8_en') - elif "CONFIG_SR_MN_EN_MULTINET5_SINGLE_RECOGNITION" in models_string: - models.append('mn5_en') - elif "CONFIG_SR_MN_EN_MULTINET6_QUANT" in models_string: - models.append('mn6_en') - elif "CONFIG_SR_MN_EN_MULTINET7_QUANT" in models_string: - models.append('mn7_en') - - if "MULTINET6" in models_string or "MULTINET7" in models_string: - models.append('fst') - - return models - - -def read_wake_word_type_from_sdkconfig(sdkconfig_path): - """ - Read wake word type configuration from sdkconfig - Returns a dict with wake word type info - """ - if not os.path.exists(sdkconfig_path): - print(f"Warning: sdkconfig file not found: {sdkconfig_path}") - return { - 'use_esp_wake_word': False, - 'use_afe_wake_word': False, - 'use_custom_wake_word': False, - 'wake_word_disabled': True - } - - config_values = { - 'use_esp_wake_word': False, - 'use_afe_wake_word': False, - 'use_custom_wake_word': False, - 'wake_word_disabled': False - } - - with io.open(sdkconfig_path, "r") as f: - for line in f: - line = line.strip("\n") - if line.startswith('#'): - continue - - # Check for wake word type configuration - if 'CONFIG_USE_ESP_WAKE_WORD=y' in line: - config_values['use_esp_wake_word'] = True - elif 'CONFIG_USE_AFE_WAKE_WORD=y' in line: - config_values['use_afe_wake_word'] = True - elif 'CONFIG_USE_CUSTOM_WAKE_WORD=y' in line: - config_values['use_custom_wake_word'] = True - elif 'CONFIG_WAKE_WORD_DISABLED=y' in line: - config_values['wake_word_disabled'] = True - - return config_values - - -def read_custom_wake_word_from_sdkconfig(sdkconfig_path): - """ - Read custom wake word configuration from sdkconfig - Returns a dict with custom wake word info or None if not configured - """ - if not os.path.exists(sdkconfig_path): - print(f"Warning: sdkconfig file not found: {sdkconfig_path}") - return None - - config_values = {} - with io.open(sdkconfig_path, "r") as f: - for line in f: - line = line.strip("\n") - if line.startswith('#') or '=' not in line: - continue - - # Check for custom wake word configuration - if 'CONFIG_USE_CUSTOM_WAKE_WORD=y' in line: - config_values['use_custom_wake_word'] = True - elif 'CONFIG_CUSTOM_WAKE_WORD=' in line and not line.startswith('#'): - # Extract string value (remove quotes) - value = line.split('=', 1)[1].strip('"') - config_values['wake_word'] = value - elif 'CONFIG_CUSTOM_WAKE_WORD_DISPLAY=' in line and not line.startswith('#'): - # Extract string value (remove quotes) - value = line.split('=', 1)[1].strip('"') - config_values['display'] = value - elif 'CONFIG_CUSTOM_WAKE_WORD_THRESHOLD=' in line and not line.startswith('#'): - # Extract numeric value - value = line.split('=', 1)[1] - try: - config_values['threshold'] = int(value) - except ValueError: - try: - config_values['threshold'] = float(value) - except ValueError: - print(f"Warning: Invalid threshold value: {value}") - config_values['threshold'] = 20 # default (will be converted to 0.2) - - # Return config only if custom wake word is enabled and required fields are present - if (config_values.get('use_custom_wake_word', False) and - 'wake_word' in config_values and - 'display' in config_values and - 'threshold' in config_values): - return { - 'wake_word': config_values['wake_word'], - 'display': config_values['display'], - 'threshold': config_values['threshold'] / 100.0 # Convert to decimal (20 -> 0.2) - } - - return None - - -def get_language_from_multinet_models(multinet_models): - """ - Determine language from multinet model names - Returns 'cn', 'en', or None - """ - if not multinet_models: - return None - - # Check for Chinese models - cn_indicators = ['_cn', 'cn_'] - en_indicators = ['_en', 'en_'] - - has_cn = any(any(indicator in model for indicator in cn_indicators) for model in multinet_models) - has_en = any(any(indicator in model for indicator in en_indicators) for model in multinet_models) - - # If both or neither, default to cn - if has_cn and not has_en: - return 'cn' - elif has_en and not has_cn: - return 'en' - else: - return 'cn' # Default to Chinese - - -def get_wakenet_model_paths(model_names, esp_sr_model_path): - """ - Get the full paths to the wakenet model directories - Returns a list of valid model paths - """ - if not model_names: - return [] - - valid_paths = [] - for model_name in model_names: - wakenet_model_path = os.path.join(esp_sr_model_path, 'wakenet_model', model_name) - if os.path.exists(wakenet_model_path): - valid_paths.append(wakenet_model_path) - else: - print(f"Warning: Wakenet model directory not found: {wakenet_model_path}") - - return valid_paths - - -def get_multinet_model_paths(model_names, esp_sr_model_path): - """ - Get the full paths to the multinet model directories - Returns a list of valid model paths - """ - if not model_names: - return [] - - valid_paths = [] - for model_name in model_names: - multinet_model_path = os.path.join(esp_sr_model_path, 'multinet_model', model_name) - if os.path.exists(multinet_model_path): - valid_paths.append(multinet_model_path) - else: - print(f"Warning: Multinet model directory not found: {multinet_model_path}") - - return valid_paths - - -def get_text_font_path(builtin_text_font, xiaozhi_fonts_path): - """ - Get the text font path if needed - Returns the font file path or None if no font is needed - """ - if not builtin_text_font or 'basic' not in builtin_text_font: - return None - - # Convert from basic to common font name - # e.g., font_puhui_basic_16_4 -> font_puhui_common_16_4.bin - font_name = builtin_text_font.replace('basic', 'common') + '.bin' - font_path = os.path.join(xiaozhi_fonts_path, 'cbin', font_name) - - if os.path.exists(font_path): - return font_path - else: - print(f"Warning: Font file not found: {font_path}") - return None - - -def get_emoji_collection_path(default_emoji_collection, xiaozhi_fonts_path): - """ - Get the emoji collection path if needed - Returns the emoji directory path or None if no emoji collection is needed - """ - if not default_emoji_collection: - return None - - emoji_path = os.path.join(xiaozhi_fonts_path, 'png', default_emoji_collection) - if os.path.exists(emoji_path): - return emoji_path - else: - print(f"Warning: Emoji collection directory not found: {emoji_path}") - return None - - -def build_assets_integrated(wakenet_model_paths, multinet_model_paths, text_font_path, emoji_collection_path, extra_files_path, output_path, multinet_model_info=None): - """ - Build assets using integrated functions (no external dependencies) - """ - # Create temporary build directory - temp_build_dir = os.path.join(os.path.dirname(output_path), "temp_build") - assets_dir = os.path.join(temp_build_dir, "assets") - - try: - # Clean and create directories - if os.path.exists(temp_build_dir): - shutil.rmtree(temp_build_dir) - ensure_dir(temp_build_dir) - ensure_dir(assets_dir) - - print("Starting to build assets...") - - # Process each component - srmodels = process_sr_models(wakenet_model_paths, multinet_model_paths, temp_build_dir, assets_dir) if (wakenet_model_paths or multinet_model_paths) else None - text_font = process_text_font(text_font_path, assets_dir) if text_font_path else None - emoji_collection = process_emoji_collection(emoji_collection_path, assets_dir) if emoji_collection_path else None - extra_files = process_extra_files(extra_files_path, assets_dir) if extra_files_path else None - - # Generate index.json - generate_index_json(assets_dir, srmodels, text_font, emoji_collection, extra_files, multinet_model_info) - - # Generate config.json for packing - config_path = generate_config_json(temp_build_dir, assets_dir) - - # Load config and pack assets - with open(config_path, 'r') as f: - config_data = json.load(f) - - # Use simplified packing function - include_path = config_data['include_path'] - image_file = config_data['image_file'] - pack_assets_simple(assets_dir, include_path, image_file, "assets", int(config_data['name_length'])) - - # Copy final assets.bin to output location - if os.path.exists(image_file): - shutil.copy2(image_file, output_path) - print(f"Successfully generated assets.bin: {output_path}") - - # Show size information - total_size = os.path.getsize(output_path) - print(f"Assets file size: {total_size / 1024:.2f}K ({total_size} bytes)") - - return True - else: - print(f"Error: Generated assets.bin not found: {image_file}") - return False - - except Exception as e: - print(f"Error: Failed to build assets: {e}") - return False - finally: - # Clean up temporary directory - if os.path.exists(temp_build_dir): - shutil.rmtree(temp_build_dir) - - -def main(): - parser = argparse.ArgumentParser(description='Build default assets based on configuration') - parser.add_argument('--sdkconfig', required=True, help='Path to sdkconfig file') - parser.add_argument('--builtin_text_font', help='Builtin text font name (e.g., font_puhui_basic_16_4)') - parser.add_argument('--emoji_collection', help='Default emoji collection name (e.g., emojis_32)') - parser.add_argument('--output', required=True, help='Output path for assets.bin') - parser.add_argument('--esp_sr_model_path', help='Path to ESP-SR model directory') - parser.add_argument('--xiaozhi_fonts_path', help='Path to xiaozhi-fonts component directory') - parser.add_argument('--extra_files', help='Path to extra files directory to be included in assets') - - args = parser.parse_args() - - # Set default paths if not provided - if not args.esp_sr_model_path or not args.xiaozhi_fonts_path: - # Calculate project root from script location - script_dir = os.path.dirname(os.path.abspath(__file__)) - project_root = os.path.dirname(script_dir) - - if not args.esp_sr_model_path: - args.esp_sr_model_path = os.path.join(project_root, "managed_components", "espressif__esp-sr", "model") - - if not args.xiaozhi_fonts_path: - args.xiaozhi_fonts_path = os.path.join(project_root, "components", "xiaozhi-fonts") - - print("Building default assets...") - print(f" sdkconfig: {args.sdkconfig}") - print(f" builtin_text_font: {args.builtin_text_font}") - print(f" emoji_collection: {args.emoji_collection}") - print(f" output: {args.output}") - - # Read wake word type configuration from sdkconfig - wake_word_config = read_wake_word_type_from_sdkconfig(args.sdkconfig) - - # Read SR models from sdkconfig - wakenet_model_names = read_wakenet_from_sdkconfig(args.sdkconfig) - multinet_model_names = read_multinet_from_sdkconfig(args.sdkconfig) - - # Apply wake word logic to decide which models to package - wakenet_model_paths = [] - multinet_model_paths = [] - - # 1. Only package wakenet models if USE_ESP_WAKE_WORD=y or USE_AFE_WAKE_WORD=y - if wake_word_config['use_esp_wake_word'] or wake_word_config['use_afe_wake_word']: - wakenet_model_paths = get_wakenet_model_paths(wakenet_model_names, args.esp_sr_model_path) - elif wakenet_model_names: - print(f" Note: Found wakenet models {wakenet_model_names} but wake word type is not ESP/AFE, skipping") - - # 2. Error check: if USE_CUSTOM_WAKE_WORD=y but no multinet models selected, report error - if wake_word_config['use_custom_wake_word'] and not multinet_model_names: - print("Error: USE_CUSTOM_WAKE_WORD is enabled but no multinet models are selected in sdkconfig") - print("Please select appropriate CONFIG_SR_MN_* options in menuconfig, or disable USE_CUSTOM_WAKE_WORD") - sys.exit(1) - - # 3. Only package multinet models if USE_CUSTOM_WAKE_WORD=y - if wake_word_config['use_custom_wake_word']: - multinet_model_paths = get_multinet_model_paths(multinet_model_names, args.esp_sr_model_path) - elif multinet_model_names: - print(f" Note: Found multinet models {multinet_model_names} but USE_CUSTOM_WAKE_WORD is disabled, skipping") - - # Print model information (only for models that will actually be packaged) - if wakenet_model_paths: - print(f" wakenet models: {', '.join(wakenet_model_names)} (will be packaged)") - if multinet_model_paths: - print(f" multinet models: {', '.join(multinet_model_names)} (will be packaged)") - - # Get text font path if needed - text_font_path = get_text_font_path(args.builtin_text_font, args.xiaozhi_fonts_path) - - # Get emoji collection path if needed - emoji_collection_path = get_emoji_collection_path(args.emoji_collection, args.xiaozhi_fonts_path) - - # Get extra files path if provided - extra_files_path = args.extra_files - - # Read custom wake word configuration - custom_wake_word_config = read_custom_wake_word_from_sdkconfig(args.sdkconfig) - multinet_model_info = None - - if custom_wake_word_config and multinet_model_paths: - # Determine language from multinet models - language = get_language_from_multinet_models(multinet_model_names) - - # Build multinet_model info structure - multinet_model_info = { - "language": language, - "duration": 3000, # Default duration in ms - "threshold": custom_wake_word_config['threshold'], - "commands": [ - { - "command": custom_wake_word_config['wake_word'], - "text": custom_wake_word_config['display'], - "action": "wake" - } - ] - } - print(f" custom wake word: {custom_wake_word_config['wake_word']} ({custom_wake_word_config['display']})") - print(f" wake word language: {language}") - print(f" wake word threshold: {custom_wake_word_config['threshold']}") - - # Check if we have anything to build - if not wakenet_model_paths and not multinet_model_paths and not text_font_path and not emoji_collection_path and not extra_files_path and not multinet_model_info: - print("Warning: No assets to build (no SR models, text font, emoji collection, extra files, or custom wake word)") - # Create an empty assets.bin file - os.makedirs(os.path.dirname(args.output), exist_ok=True) - with open(args.output, 'wb') as f: - pass # Create empty file - print(f"Created empty assets.bin: {args.output}") - return - - # Build the assets - success = build_assets_integrated(wakenet_model_paths, multinet_model_paths, text_font_path, emoji_collection_path, - extra_files_path, args.output, multinet_model_info) - - if not success: - sys.exit(1) - - print("Build completed successfully!") - - -if __name__ == "__main__": - main() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/download_github_runs.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/download_github_runs.py deleted file mode 100644 index cd812179..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/download_github_runs.py +++ /dev/null @@ -1,264 +0,0 @@ -#!/usr/bin/env python3 -""" -Download GitHub Actions artifacts and rename them with version numbers. - -Usage: - python download_github_runs.py 2.0.4 https://github.com/78/xiaozhi-esp32/actions/runs/18866246016 -""" - -import argparse -import os -import re -import sys -import zipfile -from pathlib import Path -from urllib.parse import urlparse - -import requests -from dotenv import load_dotenv - - -def parse_github_run_url(url: str) -> tuple[str, str, str]: - """ - Parse GitHub Actions run URL to extract owner, repo, and run_id. - - Args: - url: GitHub Actions run URL - - Returns: - Tuple of (owner, repo, run_id) - """ - # Example: https://github.com/78/xiaozhi-esp32/actions/runs/18866246016 - pattern = r'github\.com/([^/]+)/([^/]+)/actions/runs/(\d+)' - match = re.search(pattern, url) - - if not match: - raise ValueError(f"Invalid GitHub Actions URL: {url}") - - owner, repo, run_id = match.groups() - return owner, repo, run_id - - -def get_artifacts(owner: str, repo: str, run_id: str, token: str) -> list[dict]: - """ - Get all artifacts for a specific workflow run (with pagination support). - - Args: - owner: Repository owner - repo: Repository name - run_id: Workflow run ID - token: GitHub personal access token - - Returns: - List of artifact dictionaries - """ - headers = { - "Authorization": f"Bearer {token}", - "Accept": "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28" - } - - all_artifacts = [] - page = 1 - per_page = 100 # Maximum allowed by GitHub API - - while True: - url = f"https://api.github.com/repos/{owner}/{repo}/actions/runs/{run_id}/artifacts" - params = { - "page": page, - "per_page": per_page - } - - response = requests.get(url, headers=headers, params=params) - response.raise_for_status() - - data = response.json() - artifacts = data.get("artifacts", []) - - if not artifacts: - break - - all_artifacts.extend(artifacts) - - # Check if there are more pages - total_count = data.get("total_count", 0) - if len(all_artifacts) >= total_count: - break - - page += 1 - - return all_artifacts - - -def download_artifact(artifact_url: str, token: str, output_path: Path) -> None: - """ - Download an artifact from GitHub. - - Args: - artifact_url: Artifact download URL - token: GitHub personal access token - output_path: Path to save the downloaded artifact - """ - headers = { - "Authorization": f"Bearer {token}", - "Accept": "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28" - } - - response = requests.get(artifact_url, headers=headers, stream=True) - response.raise_for_status() - - # Create parent directory if it doesn't exist - output_path.parent.mkdir(parents=True, exist_ok=True) - - # Download the file - with open(output_path, 'wb') as f: - for chunk in response.iter_content(chunk_size=8192): - if chunk: - f.write(chunk) - - -def rename_artifact(original_name: str, version: str) -> str: - """ - Rename artifact according to the specified rules. - - Rules: - - Remove "xiaozhi_" prefix - - Remove hash suffix (underscore followed by hex string) - - Add version prefix (e.g., "v2.0.4_") - - Change extension to .zip - - Example: - xiaozhi_atk-dnesp32s3-box0_43ef2f4e7f0957dc62ec7d628ac2819d226127b8.bin - -> v2.0.4_atk-dnesp32s3-box0.zip - - Args: - original_name: Original artifact name - version: Version string (e.g., "2.0.4") - - Returns: - New filename - """ - # Remove "xiaozhi_" prefix - name = original_name - if name.startswith("xiaozhi_"): - name = name[len("xiaozhi_"):] - - # Remove extension - name_without_ext = os.path.splitext(name)[0] - - # Remove hash suffix (pattern: underscore followed by 40+ hex characters) - # This matches Git commit hashes and similar identifiers - name_without_hash = re.sub(r'_[a-f0-9]{40,}$', '', name_without_ext) - - # Add version prefix and .zip extension - new_name = f"v{version}_{name_without_hash}.zip" - - return new_name - - -def main(): - """Main function to download and rename GitHub Actions artifacts.""" - parser = argparse.ArgumentParser( - description="Download GitHub Actions artifacts and rename them with version numbers." - ) - parser.add_argument( - "version", - help="Version number (e.g., 2.0.4)" - ) - parser.add_argument( - "url", - help="GitHub Actions run URL (e.g., https://github.com/owner/repo/actions/runs/12345)" - ) - parser.add_argument( - "--output-dir", - default="../releases", - help="Output directory for downloaded artifacts (default: ../releases)" - ) - - args = parser.parse_args() - - # Load GitHub token from .env file - load_dotenv() - github_token = os.getenv("GITHUB_TOKEN") - - if not github_token: - print("Error: GITHUB_TOKEN not found in environment variables.", file=sys.stderr) - print("Please create a .env file with GITHUB_TOKEN=your_token_here", file=sys.stderr) - sys.exit(1) - - try: - # Parse the GitHub URL - owner, repo, run_id = parse_github_run_url(args.url) - print(f"Repository: {owner}/{repo}") - print(f"Run ID: {run_id}") - print(f"Version: {args.version}") - print() - - # Get artifacts - print("Fetching artifacts...") - artifacts = get_artifacts(owner, repo, run_id, github_token) - - if not artifacts: - print("No artifacts found for this run.") - return - - print(f"Found {len(artifacts)} artifact(s):") - for artifact in artifacts: - print(f" - {artifact['name']}") - print() - - # Create output directory - output_dir = Path(args.output_dir) - output_dir.mkdir(parents=True, exist_ok=True) - - # Download and rename each artifact - downloaded_count = 0 - skipped_count = 0 - - for artifact in artifacts: - original_name = artifact['name'] - new_name = rename_artifact(original_name, args.version) - final_path = output_dir / new_name - - # Check if file already exists - if final_path.exists(): - print(f"Skipping (already exists): {original_name}") - print(f" -> {new_name}") - print(f" File: {final_path}") - print() - skipped_count += 1 - continue - - print(f"Downloading: {original_name}") - print(f" -> {new_name}") - - # Download to temporary path first - temp_path = output_dir / f"{original_name}.zip" - download_artifact( - artifact['archive_download_url'], - github_token, - temp_path - ) - - # Rename to final name - temp_path.rename(final_path) - - print(f" Saved to: {final_path}") - print() - downloaded_count += 1 - - print(f"Summary:") - print(f" Downloaded: {downloaded_count} artifact(s)") - print(f" Skipped: {skipped_count} artifact(s)") - print(f" Total: {len(artifacts)} artifact(s)") - print(f" Output directory: {output_dir.absolute()}") - - except Exception as e: - print(f"Error: {e}", file=sys.stderr) - sys.exit(1) - - -if __name__ == "__main__": - main() - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/gen_lang.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/gen_lang.py deleted file mode 100644 index 81c0326e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/gen_lang.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 -import argparse -import json -import os - -HEADER_TEMPLATE = """// Auto-generated language config -// Language: {lang_code} with en-US fallback -#pragma once - -#include - -#ifndef {lang_code_for_font} - #define {lang_code_for_font} // 預設語言 -#endif - -namespace Lang {{ - // 语言元数据 - constexpr const char* CODE = "{lang_code}"; - - // 字符串资源 (en-US as fallback for missing keys) - namespace Strings {{ -{strings} - }} - - // 音效资源 (en-US as fallback for missing audio files) - namespace Sounds {{ -{sounds} - }} -}} -""" - -def load_base_language(assets_dir): - """加载 en-US 基准语言数据""" - base_lang_path = os.path.join(assets_dir, 'locales', 'en-US', 'language.json') - if os.path.exists(base_lang_path): - try: - with open(base_lang_path, 'r', encoding='utf-8') as f: - base_data = json.load(f) - print(f"Loaded base language en-US with {len(base_data.get('strings', {}))} strings") - return base_data - except json.JSONDecodeError as e: - print(f"Warning: Failed to parse en-US language file: {e}") - else: - print("Warning: en-US base language file not found, fallback mechanism disabled") - return {'strings': {}} - -def get_sound_files(directory): - """获取目录中的音效文件列表""" - if not os.path.exists(directory): - return [] - return [f for f in os.listdir(directory) if f.endswith('.ogg')] - -def generate_header(lang_code, output_path): - # 从输出路径推导项目结构 - # output_path 通常是 main/assets/lang_config.h - main_dir = os.path.dirname(output_path) # main/assets - if os.path.basename(main_dir) == 'assets': - main_dir = os.path.dirname(main_dir) # main - project_dir = os.path.dirname(main_dir) # 项目根目录 - assets_dir = os.path.join(main_dir, 'assets') - - # 构建语言JSON文件路径 - input_path = os.path.join(assets_dir, 'locales', lang_code, 'language.json') - - print(f"Processing language: {lang_code}") - print(f"Input file path: {input_path}") - print(f"Output file path: {output_path}") - - if not os.path.exists(input_path): - raise FileNotFoundError(f"Language file not found: {input_path}") - - with open(input_path, 'r', encoding='utf-8') as f: - data = json.load(f) - - # 验证数据结构 - if 'language' not in data or 'strings' not in data: - raise ValueError("Invalid JSON structure") - - # 加载 en-US 基准语言数据 - base_data = load_base_language(assets_dir) - - # 合并字符串:以 en-US 为基准,用户语言覆盖 - base_strings = base_data.get('strings', {}) - user_strings = data['strings'] - merged_strings = base_strings.copy() - merged_strings.update(user_strings) - - # 统计信息 - base_count = len(base_strings) - user_count = len(user_strings) - total_count = len(merged_strings) - fallback_count = total_count - user_count - - print(f"Language {lang_code} string statistics:") - print(f" - Base language (en-US): {base_count} strings") - print(f" - User language: {user_count} strings") - print(f" - Total: {total_count} strings") - if fallback_count > 0: - print(f" - Fallback to en-US: {fallback_count} strings") - - # 生成字符串常量 - strings = [] - sounds = [] - for key, value in merged_strings.items(): - value = value.replace('"', '\\"') - strings.append(f' constexpr const char* {key.upper()} = "{value}";') - - # 收集音效文件:以 en-US 为基准,用户语言覆盖 - current_lang_dir = os.path.join(assets_dir, 'locales', lang_code) - base_lang_dir = os.path.join(assets_dir, 'locales', 'en-US') - common_dir = os.path.join(assets_dir, 'common') - - # 获取所有可能的音效文件 - base_sounds = get_sound_files(base_lang_dir) - current_sounds = get_sound_files(current_lang_dir) - common_sounds = get_sound_files(common_dir) - - # 合并音效文件列表:用户语言覆盖基准语言 - all_sound_files = set(base_sounds) - all_sound_files.update(current_sounds) - - # 音效统计信息 - base_sound_count = len(base_sounds) - user_sound_count = len(current_sounds) - common_sound_count = len(common_sounds) - sound_fallback_count = len(set(base_sounds) - set(current_sounds)) - - print(f"Language {lang_code} sound statistics:") - print(f" - Base language (en-US): {base_sound_count} sounds") - print(f" - User language: {user_sound_count} sounds") - print(f" - Common sounds: {common_sound_count} sounds") - if sound_fallback_count > 0: - print(f" - Sound fallback to en-US: {sound_fallback_count} sounds") - - # 生成语言特定音效常量 - for file in sorted(all_sound_files): - base_name = os.path.splitext(file)[0] - # 优先使用当前语言的音效,如果不存在则回退到 en-US - if file in current_sounds: - sound_lang = lang_code.replace('-', '_').lower() - else: - sound_lang = 'en_us' - - sounds.append(f''' - extern const char ogg_{base_name}_start[] asm("_binary_{base_name}_ogg_start"); - extern const char ogg_{base_name}_end[] asm("_binary_{base_name}_ogg_end"); - static const std::string_view OGG_{base_name.upper()} {{ - static_cast(ogg_{base_name}_start), - static_cast(ogg_{base_name}_end - ogg_{base_name}_start) - }};''') - - # 生成公共音效常量 - for file in sorted(common_sounds): - base_name = os.path.splitext(file)[0] - sounds.append(f''' - extern const char ogg_{base_name}_start[] asm("_binary_{base_name}_ogg_start"); - extern const char ogg_{base_name}_end[] asm("_binary_{base_name}_ogg_end"); - static const std::string_view OGG_{base_name.upper()} {{ - static_cast(ogg_{base_name}_start), - static_cast(ogg_{base_name}_end - ogg_{base_name}_start) - }};''') - - # 填充模板 - content = HEADER_TEMPLATE.format( - lang_code=lang_code, - lang_code_for_font=lang_code.replace('-', '_').lower(), - strings="\n".join(sorted(strings)), - sounds="\n".join(sorted(sounds)) - ) - - # 写入文件 - os.makedirs(os.path.dirname(output_path), exist_ok=True) - with open(output_path, 'w', encoding='utf-8') as f: - f.write(content) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="Generate language configuration header file with en-US fallback") - parser.add_argument("--language", required=True, help="Language code (e.g: zh-CN, en-US, ja-JP)") - parser.add_argument("--output", required=True, help="Output header file path") - args = parser.parse_args() - - try: - generate_header(args.language, args.output) - print(f"Successfully generated language config file: {args.output}") - except Exception as e: - print(f"Error: {e}") - exit(1) \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/mp3_to_ogg.sh b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/mp3_to_ogg.sh deleted file mode 100644 index 2cb870ad..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/mp3_to_ogg.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -# mp3_to_ogg.sh -ffmpeg -i $1 -c:a libopus -b:a 16k -ac 1 -ar 16000 -frame_duration 60 $2 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/README.md deleted file mode 100644 index eecbe42d..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# ogg_covertor 小智AI OGG 音效批量转换器 - -本脚本为OGG批量转换工具,支持将输入的音频文件转换为小智可使用的OGG格式 - -基于Python第三方库 `ffmpeg-python` 实现,**需要** `ffmpeg` 环境 - -可前往[此处](https://ffmpeg.org/download.html)下载对应你自己系统的ffmpeg发行版,并添加到环境变量或者放在脚本所在目录 - -支持OGG和音频之间的互转,响度调节等功能 - -# 创建并激活虚拟环境 - -```bash -# 创建虚拟环境 -python -m venv venv -# 激活虚拟环境 -source venv/bin/activate # Mac/Linux -venv\Scripts\activate # Windows -``` -# 下载FFmpeg -前往[此处](https://ffmpeg.org/download.html)下载ffmpeg - -根据你当前的系统下载对应的版本,并将`ffmpeg`的可执行文件放置在脚本所在目录或者添加可执行文件所在目录到环境变量 - -# 安装依赖 -请在虚拟环境中执行 - -```bash -pip install ffmpeg-python -``` - -# 运行脚本 -```bash -python ogg_covertor.py -``` - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/xiaozhi_ogg_converter.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/xiaozhi_ogg_converter.py deleted file mode 100644 index 5c3ddb29..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/ogg_converter/xiaozhi_ogg_converter.py +++ /dev/null @@ -1,230 +0,0 @@ -import tkinter as tk -from tkinter import ttk, filedialog, messagebox -import os -import threading -import sys -import ffmpeg - -class AudioConverterApp: - def __init__(self, master): - self.master = master - master.title("小智AI OGG音频批量转换工具") - master.geometry("680x600") # 调整窗口高度 - - # 初始化变量 - self.mode = tk.StringVar(value="audio_to_ogg") - self.output_dir = tk.StringVar() - self.output_dir.set(os.path.abspath("output")) - self.enable_loudnorm = tk.BooleanVar(value=True) - self.target_lufs = tk.DoubleVar(value=-16.0) - - # 创建UI组件 - self.create_widgets() - self.redirect_output() - - def create_widgets(self): - # 模式选择 - mode_frame = ttk.LabelFrame(self.master, text="转换模式") - mode_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew") - - ttk.Radiobutton(mode_frame, text="音频转到OGG", variable=self.mode, - value="audio_to_ogg", command=self.toggle_settings, - width=12).grid(row=0, column=0, padx=5) - ttk.Radiobutton(mode_frame, text="OGG转回音频", variable=self.mode, - value="ogg_to_audio", command=self.toggle_settings, - width=12).grid(row=0, column=1, padx=5) - - # 响度设置 - self.loudnorm_frame = ttk.Frame(self.master) - self.loudnorm_frame.grid(row=1, column=0, padx=10, pady=5, sticky="ew") - - ttk.Checkbutton(self.loudnorm_frame, text="启用响度调整", - variable=self.enable_loudnorm, width=15 - ).grid(row=0, column=0, padx=2) - ttk.Entry(self.loudnorm_frame, textvariable=self.target_lufs, - width=6).grid(row=0, column=1, padx=2) - ttk.Label(self.loudnorm_frame, text="LUFS").grid(row=0, column=2, padx=2) - - # 文件选择 - file_frame = ttk.LabelFrame(self.master, text="输入文件") - file_frame.grid(row=2, column=0, padx=10, pady=5, sticky="nsew") - - # 文件操作按钮 - ttk.Button(file_frame, text="选择文件", command=self.select_files, - width=12).grid(row=0, column=0, padx=5, pady=2) - ttk.Button(file_frame, text="移除选中", command=self.remove_selected, - width=12).grid(row=0, column=1, padx=5, pady=2) - ttk.Button(file_frame, text="清空列表", command=self.clear_files, - width=12).grid(row=0, column=2, padx=5, pady=2) - - # 文件列表(使用Treeview) - self.tree = ttk.Treeview(file_frame, columns=("selected", "filename"), - show="headings", height=8) - self.tree.heading("selected", text="选中", anchor=tk.W) - self.tree.heading("filename", text="文件名", anchor=tk.W) - self.tree.column("selected", width=60, anchor=tk.W) - self.tree.column("filename", width=600, anchor=tk.W) - self.tree.grid(row=1, column=0, columnspan=3, sticky="nsew", padx=5, pady=2) - self.tree.bind("", self.on_tree_click) - - # 输出目录 - output_frame = ttk.LabelFrame(self.master, text="输出目录") - output_frame.grid(row=3, column=0, padx=10, pady=5, sticky="ew") - - ttk.Entry(output_frame, textvariable=self.output_dir, width=60 - ).grid(row=0, column=0, padx=5, sticky="ew") - ttk.Button(output_frame, text="浏览", command=self.select_output_dir, - width=8).grid(row=0, column=1, padx=5) - - # 转换按钮区域 - button_frame = ttk.Frame(self.master) - button_frame.grid(row=4, column=0, padx=10, pady=10, sticky="ew") - - ttk.Button(button_frame, text="转换全部文件", command=lambda: self.start_conversion(True), - width=15).pack(side=tk.LEFT, padx=5) - ttk.Button(button_frame, text="转换选中文件", command=lambda: self.start_conversion(False), - width=15).pack(side=tk.LEFT, padx=5) - - # 日志区域 - log_frame = ttk.LabelFrame(self.master, text="日志") - log_frame.grid(row=5, column=0, padx=10, pady=5, sticky="nsew") - - self.log_text = tk.Text(log_frame, height=14, width=80) - self.log_text.pack(fill=tk.BOTH, expand=True) - - # 配置布局权重 - self.master.columnconfigure(0, weight=1) - self.master.rowconfigure(2, weight=1) - self.master.rowconfigure(5, weight=3) - file_frame.columnconfigure(0, weight=1) - file_frame.rowconfigure(1, weight=1) - - def toggle_settings(self): - if self.mode.get() == "audio_to_ogg": - self.loudnorm_frame.grid() - else: - self.loudnorm_frame.grid_remove() - - def select_files(self): - file_types = [ - ("音频文件", "*.wav *.mogg *.ogg *.flac") if self.mode.get() == "audio_to_ogg" - else ("ogg文件", "*.ogg") - ] - - files = filedialog.askopenfilenames(filetypes=file_types) - for f in files: - self.tree.insert("", tk.END, values=("[ ]", os.path.basename(f)), tags=(f,)) - - def on_tree_click(self, event): - """处理复选框点击事件""" - region = self.tree.identify("region", event.x, event.y) - if region == "cell": - col = self.tree.identify_column(event.x) - item = self.tree.identify_row(event.y) - if col == "#1": # 点击的是选中列 - current_val = self.tree.item(item, "values")[0] - new_val = "[√]" if current_val == "[ ]" else "[ ]" - self.tree.item(item, values=(new_val, self.tree.item(item, "values")[1])) - - def remove_selected(self): - """移除选中的文件""" - to_remove = [] - for item in self.tree.get_children(): - if self.tree.item(item, "values")[0] == "[√]": - to_remove.append(item) - for item in reversed(to_remove): - self.tree.delete(item) - - def clear_files(self): - """清空所有文件""" - for item in self.tree.get_children(): - self.tree.delete(item) - - def select_output_dir(self): - path = filedialog.askdirectory() - if path: - self.output_dir.set(path) - - def redirect_output(self): - class StdoutRedirector: - def __init__(self, text_widget): - self.text_widget = text_widget - self.original_stdout = sys.stdout - - def write(self, message): - self.text_widget.insert(tk.END, message) - self.text_widget.see(tk.END) - self.original_stdout.write(message) - - def flush(self): - self.original_stdout.flush() - - sys.stdout = StdoutRedirector(self.log_text) - - def start_conversion(self, convert_all): - """开始转换""" - input_files = [] - for item in self.tree.get_children(): - if convert_all or self.tree.item(item, "values")[0] == "[√]": - input_files.append(self.tree.item(item, "tags")[0]) - - if not input_files: - msg = "没有找到可转换的文件" if convert_all else "没有选中任何文件" - messagebox.showwarning("警告", msg) - return - - os.makedirs(self.output_dir.get(), exist_ok=True) - - try: - if self.mode.get() == "audio_to_ogg": - target_lufs = self.target_lufs.get() if self.enable_loudnorm.get() else None - thread = threading.Thread(target=self.convert_audio_to_ogg, args=(target_lufs, input_files)) - else: - thread = threading.Thread(target=self.convert_ogg_to_audio, args=(input_files,)) - - thread.start() - except Exception as e: - print(f"转换初始化失败: {str(e)}") - - def convert_audio_to_ogg(self, target_lufs, input_files): - """音频转到ogg转换逻辑""" - for input_path in input_files: - try: - filename = os.path.basename(input_path) - base_name = os.path.splitext(filename)[0] - output_path = os.path.join(self.output_dir.get(), f"{base_name}.ogg") - - print(f"正在转换: {filename}") - ( - ffmpeg - .input(input_path) - .output(output_path, acodec='libopus', audio_bitrate='16k', ac=1, ar=16000, frame_duration=60) - .run(overwrite_output=True) - ) - print(f"转换成功: {filename}\n") - except Exception as e: - print(f"转换失败: {str(e)}\n") - - def convert_ogg_to_audio(self, input_files): - """ogg转回音频转换逻辑""" - for input_path in input_files: - try: - filename = os.path.basename(input_path) - base_name = os.path.splitext(filename)[0] - output_path = os.path.join(self.output_dir.get(), f"{base_name}.ogg") - - print(f"正在转换: {filename}") - ( - ffmpeg - .input(input_path) - .output(output_path, acodec='libopus', audio_bitrate='16k', ac=1, ar=16000, frame_duration=60) - .run(overwrite_output=True) - ) - print(f"转换成功: {filename}\n") - except Exception as e: - print(f"转换失败: {str(e)}\n") - -if __name__ == "__main__": - root = tk.Tk() - app = AudioConverterApp(root) - root.mainloop() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/README.md deleted file mode 100644 index 0ee279cb..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/README.md +++ /dev/null @@ -1,95 +0,0 @@ -# P3音频格式转换与播放工具 - -这个目录包含两个用于处理P3格式音频文件的Python脚本: - -## 1. 音频转换工具 (convert_audio_to_p3.py) - -将普通音频文件转换为P3格式(4字节header + Opus数据包的流式结构)并进行响度标准化。 - -### 使用方法 - -```bash -python convert_audio_to_p3.py <输入音频文件> <输出P3文件> [-l LUFS] [-d] -``` - -其中,可选选项 `-l` 用于指定响度标准化的目标响度,默认为 -16 LUFS;可选选项 `-d` 可以禁用响度标准化。 - -如果输入的音频文件符合下面的任一条件,建议使用 `-d` 禁用响度标准化: -- 音频过短 -- 音频已经调整过响度 -- 音频来自默认 TTS (小智当前使用的 TTS 的默认响度已是 -16 LUFS) - -例如: -```bash -python convert_audio_to_p3.py input.mp3 output.p3 -``` - -## 2. P3音频播放工具 (play_p3.py) - -播放P3格式的音频文件。 - -### 特性 - -- 解码并播放P3格式的音频文件 -- 在播放结束或用户中断时应用淡出效果,避免破音 -- 支持通过命令行参数指定要播放的文件 - -### 使用方法 - -```bash -python play_p3.py -``` - -例如: -```bash -python play_p3.py output.p3 -``` - -## 3. 音频转回工具 (convert_p3_to_audio.py) - -将P3格式转换回普通音频文件。 - -### 使用方法 - -```bash -python convert_p3_to_audio.py <输入P3文件> <输出音频文件> -``` - -输出音频文件需要有扩展名。 - -例如: -```bash -python convert_p3_to_audio.py input.p3 output.wav -``` -## 4. 音频/P3批量转换工具 - -一个图形化的工具,支持批量转换音频到P3,P3到音频 - -![](./img/img.png) - -### 使用方法: -```bash -python batch_convert_gui.py -``` - -## 依赖安装 - -在使用这些脚本前,请确保安装了所需的Python库: - -```bash -pip install librosa opuslib numpy tqdm sounddevice pyloudnorm soundfile -``` - -或者使用提供的requirements.txt文件: - -```bash -pip install -r requirements.txt -``` - -## P3格式说明 - -P3格式是一种简单的流式音频格式,结构如下: -- 每个音频帧由一个4字节的头部和一个Opus编码的数据包组成 -- 头部格式:[1字节类型, 1字节保留, 2字节长度] -- 采样率固定为16000Hz,单声道 -- 每帧时长为60ms \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/batch_convert_gui.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/batch_convert_gui.py deleted file mode 100644 index 8555e55b..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/batch_convert_gui.py +++ /dev/null @@ -1,221 +0,0 @@ -import tkinter as tk -from tkinter import ttk, filedialog, messagebox -import os -import threading -import sys -from convert_audio_to_p3 import encode_audio_to_opus -from convert_p3_to_audio import decode_p3_to_audio - -class AudioConverterApp: - def __init__(self, master): - self.master = master - master.title("音频/P3 批量转换工具") - master.geometry("680x600") # 调整窗口高度 - - # 初始化变量 - self.mode = tk.StringVar(value="audio_to_p3") - self.output_dir = tk.StringVar() - self.output_dir.set(os.path.abspath("output")) - self.enable_loudnorm = tk.BooleanVar(value=True) - self.target_lufs = tk.DoubleVar(value=-16.0) - - # 创建UI组件 - self.create_widgets() - self.redirect_output() - - def create_widgets(self): - # 模式选择 - mode_frame = ttk.LabelFrame(self.master, text="转换模式") - mode_frame.grid(row=0, column=0, padx=10, pady=5, sticky="ew") - - ttk.Radiobutton(mode_frame, text="音频转P3", variable=self.mode, - value="audio_to_p3", command=self.toggle_settings, - width=12).grid(row=0, column=0, padx=5) - ttk.Radiobutton(mode_frame, text="P3转音频", variable=self.mode, - value="p3_to_audio", command=self.toggle_settings, - width=12).grid(row=0, column=1, padx=5) - - # 响度设置 - self.loudnorm_frame = ttk.Frame(self.master) - self.loudnorm_frame.grid(row=1, column=0, padx=10, pady=5, sticky="ew") - - ttk.Checkbutton(self.loudnorm_frame, text="启用响度调整", - variable=self.enable_loudnorm, width=15 - ).grid(row=0, column=0, padx=2) - ttk.Entry(self.loudnorm_frame, textvariable=self.target_lufs, - width=6).grid(row=0, column=1, padx=2) - ttk.Label(self.loudnorm_frame, text="LUFS").grid(row=0, column=2, padx=2) - - # 文件选择 - file_frame = ttk.LabelFrame(self.master, text="输入文件") - file_frame.grid(row=2, column=0, padx=10, pady=5, sticky="nsew") - - # 文件操作按钮 - ttk.Button(file_frame, text="选择文件", command=self.select_files, - width=12).grid(row=0, column=0, padx=5, pady=2) - ttk.Button(file_frame, text="移除选中", command=self.remove_selected, - width=12).grid(row=0, column=1, padx=5, pady=2) - ttk.Button(file_frame, text="清空列表", command=self.clear_files, - width=12).grid(row=0, column=2, padx=5, pady=2) - - # 文件列表(使用Treeview) - self.tree = ttk.Treeview(file_frame, columns=("selected", "filename"), - show="headings", height=8) - self.tree.heading("selected", text="选中", anchor=tk.W) - self.tree.heading("filename", text="文件名", anchor=tk.W) - self.tree.column("selected", width=60, anchor=tk.W) - self.tree.column("filename", width=600, anchor=tk.W) - self.tree.grid(row=1, column=0, columnspan=3, sticky="nsew", padx=5, pady=2) - self.tree.bind("", self.on_tree_click) - - # 输出目录 - output_frame = ttk.LabelFrame(self.master, text="输出目录") - output_frame.grid(row=3, column=0, padx=10, pady=5, sticky="ew") - - ttk.Entry(output_frame, textvariable=self.output_dir, width=60 - ).grid(row=0, column=0, padx=5, sticky="ew") - ttk.Button(output_frame, text="浏览", command=self.select_output_dir, - width=8).grid(row=0, column=1, padx=5) - - # 转换按钮区域 - button_frame = ttk.Frame(self.master) - button_frame.grid(row=4, column=0, padx=10, pady=10, sticky="ew") - - ttk.Button(button_frame, text="转换全部文件", command=lambda: self.start_conversion(True), - width=15).pack(side=tk.LEFT, padx=5) - ttk.Button(button_frame, text="转换选中文件", command=lambda: self.start_conversion(False), - width=15).pack(side=tk.LEFT, padx=5) - - # 日志区域 - log_frame = ttk.LabelFrame(self.master, text="日志") - log_frame.grid(row=5, column=0, padx=10, pady=5, sticky="nsew") - - self.log_text = tk.Text(log_frame, height=14, width=80) - self.log_text.pack(fill=tk.BOTH, expand=True) - - # 配置布局权重 - self.master.columnconfigure(0, weight=1) - self.master.rowconfigure(2, weight=1) - self.master.rowconfigure(5, weight=3) - file_frame.columnconfigure(0, weight=1) - file_frame.rowconfigure(1, weight=1) - - def toggle_settings(self): - if self.mode.get() == "audio_to_p3": - self.loudnorm_frame.grid() - else: - self.loudnorm_frame.grid_remove() - - def select_files(self): - file_types = [ - ("音频文件", "*.wav *.mp3 *.ogg *.flac") if self.mode.get() == "audio_to_p3" - else ("P3文件", "*.p3") - ] - - files = filedialog.askopenfilenames(filetypes=file_types) - for f in files: - self.tree.insert("", tk.END, values=("[ ]", os.path.basename(f)), tags=(f,)) - - def on_tree_click(self, event): - """处理复选框点击事件""" - region = self.tree.identify("region", event.x, event.y) - if region == "cell": - col = self.tree.identify_column(event.x) - item = self.tree.identify_row(event.y) - if col == "#1": # 点击的是选中列 - current_val = self.tree.item(item, "values")[0] - new_val = "[√]" if current_val == "[ ]" else "[ ]" - self.tree.item(item, values=(new_val, self.tree.item(item, "values")[1])) - - def remove_selected(self): - """移除选中的文件""" - to_remove = [] - for item in self.tree.get_children(): - if self.tree.item(item, "values")[0] == "[√]": - to_remove.append(item) - for item in reversed(to_remove): - self.tree.delete(item) - - def clear_files(self): - """清空所有文件""" - for item in self.tree.get_children(): - self.tree.delete(item) - - def select_output_dir(self): - path = filedialog.askdirectory() - if path: - self.output_dir.set(path) - - def redirect_output(self): - class StdoutRedirector: - def __init__(self, text_widget): - self.text_widget = text_widget - self.original_stdout = sys.stdout - - def write(self, message): - self.text_widget.insert(tk.END, message) - self.text_widget.see(tk.END) - self.original_stdout.write(message) - - def flush(self): - self.original_stdout.flush() - - sys.stdout = StdoutRedirector(self.log_text) - - def start_conversion(self, convert_all): - """开始转换""" - input_files = [] - for item in self.tree.get_children(): - if convert_all or self.tree.item(item, "values")[0] == "[√]": - input_files.append(self.tree.item(item, "tags")[0]) - - if not input_files: - msg = "没有找到可转换的文件" if convert_all else "没有选中任何文件" - messagebox.showwarning("警告", msg) - return - - os.makedirs(self.output_dir.get(), exist_ok=True) - - try: - if self.mode.get() == "audio_to_p3": - target_lufs = self.target_lufs.get() if self.enable_loudnorm.get() else None - thread = threading.Thread(target=self.convert_audio_to_p3, args=(target_lufs, input_files)) - else: - thread = threading.Thread(target=self.convert_p3_to_audio, args=(input_files,)) - - thread.start() - except Exception as e: - print(f"转换初始化失败: {str(e)}") - - def convert_audio_to_p3(self, target_lufs, input_files): - """音频转P3转换逻辑""" - for input_path in input_files: - try: - filename = os.path.basename(input_path) - base_name = os.path.splitext(filename)[0] - output_path = os.path.join(self.output_dir.get(), f"{base_name}.p3") - - print(f"正在转换: {filename}") - encode_audio_to_opus(input_path, output_path, target_lufs) - print(f"转换成功: {filename}\n") - except Exception as e: - print(f"转换失败: {str(e)}\n") - - def convert_p3_to_audio(self, input_files): - """P3转音频转换逻辑""" - for input_path in input_files: - try: - filename = os.path.basename(input_path) - base_name = os.path.splitext(filename)[0] - output_path = os.path.join(self.output_dir.get(), f"{base_name}.wav") - - print(f"正在转换: {filename}") - decode_p3_to_audio(input_path, output_path) - print(f"转换成功: {filename}\n") - except Exception as e: - print(f"转换失败: {str(e)}\n") - -if __name__ == "__main__": - root = tk.Tk() - app = AudioConverterApp(root) - root.mainloop() \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_audio_to_p3.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_audio_to_p3.py deleted file mode 100644 index 519d6620..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_audio_to_p3.py +++ /dev/null @@ -1,62 +0,0 @@ -# convert audio files to protocol v3 stream -import librosa -import opuslib -import struct -import sys -import tqdm -import numpy as np -import argparse -import pyloudnorm as pyln - -def encode_audio_to_opus(input_file, output_file, target_lufs=None): - # Load audio file using librosa - audio, sample_rate = librosa.load(input_file, sr=None, mono=False, dtype=np.float32) - - # Convert to mono if stereo - if audio.ndim == 2: - audio = librosa.to_mono(audio) - - if target_lufs is not None: - print("Note: Automatic loudness adjustment is enabled, which may cause", file=sys.stderr) - print(" audio distortion. If the input audio has already been ", file=sys.stderr) - print(" loudness-adjusted or if the input audio is TTS audio, ", file=sys.stderr) - print(" please use the `-d` parameter to disable loudness adjustment.", file=sys.stderr) - meter = pyln.Meter(sample_rate) - current_loudness = meter.integrated_loudness(audio) - audio = pyln.normalize.loudness(audio, current_loudness, target_lufs) - print(f"Adjusted loudness: {current_loudness:.1f} LUFS -> {target_lufs} LUFS") - - # Convert sample rate to 16000Hz if necessary - target_sample_rate = 16000 - if sample_rate != target_sample_rate: - audio = librosa.resample(audio, orig_sr=sample_rate, target_sr=target_sample_rate) - sample_rate = target_sample_rate - - # Convert audio data back to int16 after processing - audio = (audio * 32767).astype(np.int16) - - # Initialize Opus encoder - encoder = opuslib.Encoder(sample_rate, 1, opuslib.APPLICATION_AUDIO) - - # Encode and save - with open(output_file, 'wb') as f: - duration = 60 # 60ms per frame - frame_size = int(sample_rate * duration / 1000) - for i in tqdm.tqdm(range(0, len(audio) - frame_size, frame_size)): - frame = audio[i:i + frame_size] - opus_data = encoder.encode(frame.tobytes(), frame_size=frame_size) - packet = struct.pack('>BBH', 0, 0, len(opus_data)) + opus_data - f.write(packet) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description='Convert audio to Opus with loudness normalization') - parser.add_argument('input_file', help='Input audio file') - parser.add_argument('output_file', help='Output .opus file') - parser.add_argument('-l', '--lufs', type=float, default=-16.0, - help='Target loudness in LUFS (default: -16)') - parser.add_argument('-d', '--disable-loudnorm', action='store_true', - help='Disable loudness normalization') - args = parser.parse_args() - - target_lufs = None if args.disable_loudnorm else args.lufs - encode_audio_to_opus(args.input_file, args.output_file, target_lufs) \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_p3_to_audio.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_p3_to_audio.py deleted file mode 100644 index f870b01c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/convert_p3_to_audio.py +++ /dev/null @@ -1,51 +0,0 @@ -import struct -import sys -import opuslib -import numpy as np -from tqdm import tqdm -import soundfile as sf - - -def decode_p3_to_audio(input_file, output_file): - sample_rate = 16000 - channels = 1 - decoder = opuslib.Decoder(sample_rate, channels) - - pcm_frames = [] - frame_size = int(sample_rate * 60 / 1000) - - with open(input_file, "rb") as f: - f.seek(0, 2) - total_size = f.tell() - f.seek(0) - - with tqdm(total=total_size, unit="B", unit_scale=True) as pbar: - while True: - header = f.read(4) - if not header or len(header) < 4: - break - - pkt_type, reserved, opus_len = struct.unpack(">BBH", header) - opus_data = f.read(opus_len) - if len(opus_data) != opus_len: - break - - pcm = decoder.decode(opus_data, frame_size) - pcm_frames.append(np.frombuffer(pcm, dtype=np.int16)) - - pbar.update(4 + opus_len) - - if not pcm_frames: - raise ValueError("No valid audio data found") - - pcm_data = np.concatenate(pcm_frames) - - sf.write(output_file, pcm_data, sample_rate, subtype="PCM_16") - - -if __name__ == "__main__": - if len(sys.argv) != 3: - print("Usage: python convert_p3_to_audio.py ") - sys.exit(1) - - decode_p3_to_audio(sys.argv[1], sys.argv[2]) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/img/img.png b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/img/img.png deleted file mode 100644 index 7ee34ee5e01f1ad6c234e6e15cb0ccf5e61a0938..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144945 zcmZs@by!>9(l%U*6)O(Ki#rr|C{`Q-B)AlJcP~zH3+@yM!QG*_6?ZT0?*4Ml_r2G7 zp7VSE$hER_WzSwSYt}t8_nPD#NL&U67Roz_xYWSgecHm?2utjg1cv_oMg@)+ zj3`EB1RVt&ZWRxPBxYwgG6gbSxP+(Oq&Qj-)vw#;miz35k$45^g{!VebTMuYr?FNu z)01ac(@~JT=W(5OX=$nL#J=+ntOAuMG}-f-Z-^VGt%A>Hk_lKCO)i8avISU~cY^>O zpo#QD3@TYT6v$Ap?#2&T(x5C)PfQ8>mfu-c#b{YasG#^!7Oe7`s%X|)PtnmO=p)24 zpI0&UJ#=VD<<(BX_ZwJtp6*~`i-=~i_+4gW2%bWD$gf14Hcd4(H3*QwN2p8MAP_8@ zGeAMh2rDJ!r9;FsnLKAvJGVqHuTso3FbGpdgZ?&2ZMkUk2$g~{v+qptA&ot}SXhQ| z=CIgp_g$tFJKjOEfg~Fuuw(Dr=P>u+bd^Iv?K~IjyM8R?%m)~*L{VI|Bh#d)FT)*` z=W7Tr_s{E|$M7Gyo9~)CD$?EZ0~0@e+AG7h8EWXfyNx0(D^LpG*PeTM4B!W($6P=5QYpSa7%$Jav(a0py+vd>^&Qi>M z`BT_i;H@pc(;r`hI}PyGg{MYq>-m-WuwQL{N(Wo(;GOi{W3Y@(N9!;9v0n&!RQC3o zY9hb&Og-=X65$SU)Xsy>XRX-u1aYlzc$yC{D)trQb0uRHQ)3f-FUA=q$oI2bh_Eo- zJyaLrUID9hhIpeL_3bg?=eh5288|%%fylUoWjhaTC4c+Wg1W9xbd3KJ?&?o*f7-Py z2q#v+lLgC)a93AX12l`TZb`rnq_YG&R{>30fkP_6idN~Aq7!gHzRM@dOT zdE|~%HjzYdLF0b2c`DZK#wba2aeJy`8$Qz~RFl#5VqHO%mK;IJ6%IfOL#)S=LJ z&$E35h|93ONQ$)h@?Z+~WaPorsT5?#Tp6i6m8l#M80S$+SxAPc<)6lE5HL&qQOd&t zV-*CaFgj~!LQrd>X1^$25i_H5hc!{r4u9FPDVv$wrD*G=x!s8@WnyP%zvAZQ=RY_c ze`J;lT~v$YV|>2u&2aGf_$S+_$DM<7;Y&sMVYo*xFLT(TcJa(SbS9)pYfLTSH4^$O zPL8sTEFKHn-r0V7tcJdr-V>oO)YVH{8<>|VTi~mRakIF%K)6HQ$3{HCN&f$vd{h>5Q#wAeN?;mPR|FKa#c z6A95QgX76zAE%0qmJUv>?$zlc4@?g=t_#}g%*>8I7A#u1MWOxnbRyr6@Z5wt5^3?R z&7Ke|pY)|^{$38P3b_L4HTiz0ndgsFAP)v+o{3)*Ib2@t9~fv(9_h{EbC_tVI^Sw* z-lO>X{q1-zUARI?#%7I+OAc=f_39U~=-syiTAU z-RNi?ec{0pj}6b#*W$JtwbEhr-m~&HZuQ`6mzIxC^GVwtP6v=B99!E%hSQE}PwD3! zZQ|@a=5oRAMHArKF{_9WJ!ELC)HkW|{=xP7ZZLzdV&@d@T;{yB%9tF>%J_8s;#eY-VZ%t!@@IG>wdfYp(v_N^zyUrF!^gQp#ni1H{uX zH+okw>}+MaTITy6t$@TNfnl$kM=5={PzB#n+HV@3HPKew!tC2flK{{=Lf^vmn7=XN z)bBM*{?HkR1CQl{#r7tb-P8P%RifG8NQDwfi|~Th%1N0J-VSQPP+j}Yq8eYzq4+)& z0|>eu*CPv?Q6ggG34!`W&cQ>so7UB%&2-Ie6nqKP@fWq9Qt6%AJt|OUd7Oz3Hr$~V zqGp!O6~O+a-xqc3m#0Y%R~wi(Q#)hmO$Baq9IbIPo@dcWzEL;}qky~m4;H_eU?|lZB3upAS|I}5kZzYrxMYGCT%53}S zTpP8rsC4{$p(S;%3>~;r8+w(tnmtmcnb&3{PgDS@b5fT20GlT>Y`^0tl-`8P-Oxxf z4oAHRyqBGYtZccGiP)6b0ezy^jjMBP$cmO>uIu{2&ym)L*%DqJ$6^XmYG`ppW*f^A zh(%pZbm!n)=~z$#q@)df=LlOSc43y(;FZ6CLIqaww#8K|A|pA<5zi>oW7%b~}t;=KVnSL-El`DT*A zL5n@&w1liU$&K9Y*7MHv#zb;Rq#|AMPb2!CMK6vOT77lhx#YFE?vB)DY%-!C0im*+ibeZJ&*K_q zOHq?C4N$A(AU%ES!>9nAX;4s5>%}DY<&Y}qPu-^%0naqpSKVAt_Bj=m2^Jn$e7aY) zv9Hwhri68KasK#0dv#c~VZf?q!}fS+nP-P>vx!y#O4lBEveFc~gcwCZBM^NSvF>cO zQqVK}k(fPG|rMzzhXUj#@pm!DxT&*bI_;>J-bKO-o9j|6IDEUaJLM9v8q zh=CTIiu1n{SOq0jSy`FNm_|0{dlqL(y$e%=?6G7%1bC4)Cl~5vd5TiU>;KSy8N!?E z1+)3d;A=fjY2l4(=djWqpgw!a<(78XX)47Chd7x^!fP+QFSCRLSp*D!S5*(k28u;K zw>n&-iOJRWt~5JTne=cEZ@_`?j%F4rR)0(YF~B_O=tEF*t%hD)saiz8gzpf-(c>Cd^$9eg*2`st?KKpS6-?uz|0Ur;lOJ8 z6;wXUxiN*z_a2@*&JT&0#GFmgyA62 z;nD?iQ3zv->>(LwxYgCuP~2R6f6EpJSlHIG-q2zA4816M&*Ph^!X`&3ORs)t`gC)v zbhW=$GEH;5T%SH6-iMv-Q=rGw#;NSGc`A#nqnst6>|nG2@Lfn21B|4Su%Ci=hj4)W znbEb=K)jAeHr|HLHV<{zmvijhe0B#b0j$Hs%~~txU^6|>k9AtQI|qqXNMcO5D|%+p zp}pJ!ak31L1Bpnz$e-P;c*2pPc_kXXnT!m&fafk~g&*Cuj+%!WB*>jTLz#hh4j9J) zEToXOKISN`#Lbw%I`+OP*p*#oH)DYOY4X)vdKsdG{1FNST{8mnmIjD&_>3y=1mksk z7iPBOL5Fh}%U$6_ac{trJeXvyJ;Pohgzy&7d$E~XSh&>!CyDCc7vemPjvz4qdZ}j*yD6bi|U?0cjA0EB}I~W`OqxiyaAOb8|_a^^ZI}_|DB@kgoOZ&469A ztlIB6jJ>Xv#Y`v;&@k9iAIS_7=~Hwt3IMfcgZf0!YD$e4&YrZcg}LlrSU+n{2V5jo z_z4$#?$mYX_nDLs)p8f`n- z_n~e6f=9r3b=af=P*C{mY(G@ae9?l*5}z#k=q>>yx0ZWJsh{`rL$B~9=d)+M=|v>H z=`H4z=?7(}{jOg2;WUJdFC*53KrwII@*J!Q7_^C733pd<28OK2B}9cWvs8rgFQxAH ziIy$OfP0?XIm8JJ^7V*s_t@`;IUy1jyE#Me>#owrQZN1*^_pVO@z%ZqQcEmDT#4QT zdW`$iK0r?%j(tOFEI_o7$Y;??XcL{^MTokZKKtu!e8GL`f!rwcwwSM>VqQBrs^<_>FkTW%$tip74F8>NF1xPK|OGRdwDhs0i$!p|G zj_{n0nE0t}6!?ii-EWA9yUm=lePdJvx1nsz+-PDAch1&GPt~jUAeGI!`9pF$od{G9 zgu*bz!VCwxmb_=QvIjyQhr}GyjbZm-X9T#1nr%RH`D)LO^4AYJrW%|<+=&WMDmH3a zJhESTNBoEC(NG+T>ymA1ZS58xePpPn=UfUcWT=@Eygl5t-Jw%Y*qeZ|6Vm$Ry`cOO zl%sVvWc8+TTwAVRrPrJu|MD&7{;v2rAY*-W$&15!>kK&tIX?$0cTg@ZGW<;|Hzfi; z+WL{7XZwX_5c!6yRNH$-!pJTl0Qc3lFg{(q@>t25h{-<4!DOg0vm);_m%%DMYoa=D z_m?adkUH}x)-q~|BD}%Wn%))nik2J4aD!Zjrk3?PROQBB96(&nR0hjP53}MS!q28$ zRsLr2k%Wzba^`y14{fE|$zPyH3b<%195aW3Y58-2MP+t2BR`hn0%{a!{Kvkz3^(YB ztO@`;Qf=DbHNpUqACpJQPHfw*sNOv56IiS^u>uG_&OXIzDvi-`&`DNn?N{Q9=Gzz*=o&j%?aol%CUtJ0BzNN2?BUpybRBg{gwP1hAY=G z*@3D-RYh&{XT_+z<4oP#lmQ}(T&%a~Q5?Uh8lS_y!>R;8RxUILc0e_9*%vA5VF~r= zte^g15WcWI&kBn(-1oL4M4#NBJ~BM(Di^j6VF7n;a4#=sj*Ly)bzQiMwm|Aas?V;V ziqnD|hT*`O;f~T0^_5d1Spf#AU+$tN{K$mwY2ON@6Kbx*-E?IDh>1=TgaQ>z@@Yco zy|in?W53+DFhORh661R9ZHjEQ!O<3PxR~l&fkS(9*3cBeYteuu#N?F**+JzAX1_iL zG_y*U{oX_iXF+mj;2?>K?>K$lCP)nDUYN4WDM7Iut(CKP3sHd(D$$wg68ckC z?^90zvJsAO{tqm(Oj&*u5SC)q5a)C1K2NLMkn^={ttgd2jp&|EGr6pRC?K2+Mfc!D z+3iq#$?b6AIOJ9ZJc}e7aiP8po2(&vwAf6PonGq6JmgnZ>A|RiU_hs8f+QURrq;L} zRrj73JmqWOF%Dt{ujMECQ%a| zB#s??@?`~hH3#%_YRP+!`I?UL@WgXe)lSQaDDz>@P~ZfXR=<$NHB`*7|zxWuA2y z(v&+4#Zg5%@Q|aX>eY@`9GzdEv=;)~cZ|2vK$#jo9)n{2(1fwcWZcj)y^S zQE+my)HhEAGsP^^g?QFRJlqjPIg!5MB@`5}WD^>*B4DLa4Ai(-C-SU97q8#Mnx_Ao zt~tE@Z$sYoibgrP;^(@#!XY7@nXDDiT=s#iLcEFYxy13J^7C_!qfxu-eu~@mfth(0 z2?$)0TUTVLBYV=o!cQBf{v01r{E(Eln zww-@0iq76j*KgIt5VoLrR=?32^lCPuP=UjNus8Lq4f8#YqNSm23N(Zm29V* zF!K4`2v)SUb-8ZGfgH!hXI~-s@YLO&>xGtF)s~N6N1|RWgH`;8 zN|KD=Q6YsCXmz?foAHK2-fHYcRO90xykj*LnbR$ z+6#CqI@-_BYBGFkb+AkFF;A*E7KHFUa^Z+)^AjTws083x;7x(M_^2XYzt zfujA>%H%GJHCMOWv}9h2+cAx@f*@wq3F0f#4eU7t z9h=cZ7&hQF3r{dp9=akIae>#`K+tuMiaNjaNNvdjDb%v>rFo+aS|!e2LKuBrjOXOd z@~xQfe(14MGn*F_T!w3=fvaAT%5NLOy((S3ZhP6n_pHfbB&k`D^2&H6gZib`&usIZ(ZM8yee_5v+UfjGyRA3VS zRRKHYVZ+Ep8~|p4h8q^6W4rlOR<*8_?JNSDLaWkhYFgnAeSHVZPaYu*Or?4v>b6g6 zl8=`8(FZ14M9k26F1wE((Y#9ZJ-jt$%~_RnaSt7;6R80B9|RvQN#-xi;FM=8nck_9 zA(;P5u5RVdqOq@jqo&%2;lq;foeDlO^=UE9@@hEfT0fYm18k#jlUU(fST_L;*R3(A zGN11%rb18d4>gIpxtIo3kf}QA)nz9OW5oQ~SVPW0d zzLZ)>Ikx-#ikY(D>syddRZ4#~T!UHy?`_BHxPDt5HiIM=GCVB{qqZ*__*~`KK+3Yg z!!wbuC4Fj|ayH&oKn|k@;Rm(o%!g}}-6)^Z+Db+=b$J3lX=M{%BnaTz;0$rw+Cz<}|L;rmn#0xGcCr!{# zFq~E&1%a4Fp=aRl{TF53yrYNIwj zr!WtFz@AlAhJu}ZQGFJ#mgaW{*mUc73Kn~2Ztzv#vH4+f-;fwglMK~2{mtbCXB~mM z-tGzHB_b643TCBrNww(?YbBK5ZE-v#D>me7?Ltdam5z22m(ip1COwY6&&t3|fz5+M z|C-b^*>p?=l`T>3YzxWcdIl!;Nom=-Uk)v5?oiPbri6c5!|q?!K=!C?9s}%;@7Hdb z7Krs&?g+Ic)aG=e`W@JYaN?DS;)UJnQy)EstnpZ{A4iC5-glZWa#r^uP|Fs;CnXJe zPfi@Y?!eBz`h-_%<5#&y@|3&cnU^0M?=I?V+>OF}vU&zCX|;_1!K-zp4N z_6}?V%MxI@@c?NwL#?gJ*d6V?ZLe3G+cJt<#QY;KMoG>o&w`tQ8TKH?0tj@?NJ@+K zKR*BO)z1+TzaDy~%hLNIvNb~sJrn{C_Vi0RZ0x~@-6aLf+1Q&efhTSeHtj6@i;8H^ z&(C$9&8U~$hz-iFyIVP`_-sEi;P7r99LU()Z>qq9?vl_oF1K4+??Vx+@M))^-kp=R zuqTvR2G@zBjRG3FZXO1rGvNYdN@v@f5qH|@lJeCErKNx+?YznDSiIz)lbxiDb?7#p zQGavcISBSe_Zh#l^@lCrPzQF{jYf>27qoO+)K{$h?k55Xwj0B|qBwRgIcMh{MgDUK zoPPKOHxoF+1esKHycy?ifAl1K>~eM32*4+O(SvKK>sBo28XJq*+Y`?aa7?K&bLlDZ z`cm3}#yyK{kDOzYEG+n?5T*QFV4?N#{gS%f-?N|6T`j^xJqF^Rrmj$D&kz4^FTkf) z+owSNmx!YK*Kgy5mGaB|FMc=nf(tQ8W8R(G4Nc<%-;gXOdNM>tR!Kseyp8$vX&ZXx zI#9Z`Jq-#5M6un{qC_N(u=nKp*W2f*q^h5v0Y@RIT^&YNi}hFes$)0qdM{wmQa2wq zShIBsJ5NTWJrsn=eRq8-Km5((S7@fmlK-cNS33&vQ?l+KABAfxE8KkE^49-aY3cX( za97$ddLD4SH7GlwLBKg=kSP`0dgwyEhXCX1f_$339PxWCtoc$TU2VRNjSVr&1JawP z<``_+G6yoQBpCl3HJEx^&U5r%QlW*s5~b_I`rUVK#~(-a!fEr40pDCM3VnuzNBad5 zcKlFo754&o=yf#OBALA^FxP&uHYjBdRDMRZ?y2wWxzypWO?Rx3x=#0P1@1G|ki~*Y&rMcMzfWEz_oh6oBX@Z4;4H?h(Qh#{V`dzH>RC!5kR$hR+ zma393jlR@*`}o=3T|eMi$l=cr1wB2y+pQYh>*>d4g!>7da+SeOy8p7owD$W4IzLvS zppAv#OL4J6^|>UGanm4dA4`(U!l%%~clhky&6Bm7JbIswWvB0*dJ0J?oO?fhByGr9 zaEf93gWD4jFU=r;Pb~OkUcNM#)JDSy%-;}XQ7 zmW6nN;&9Oc$EI)mrG8M}wj%J(ou#KYEMaKaDU@8 zrX&H|(I2`RO=8jbU%2+R%ehP!GiR6~&cAf$d)Kp9|5gQ3di*+u8Kw7;v0zU$*|c7$ z+!C)RUg%uqD3;i1+?*_gFYBpq^F~~Fbfdm2UywgU{y2LtO8>&&nd*z;-tfrQ?s=>_ zd)y|SSU_@<#9tkcJ)t3BU}6(2n;hKL6(U;kI*bh~G)~q#sY|&(q~FSB&2k89XL2Tf z%SJB!)AccwNt&#C{^JWA4<05nvdR`&4WA9qyM7o}_NM$h9XZ!;{F)0*=0PEhiHRCi z*|g`s(U*l8Lm%-)`WlxOG0h`O$OW?gOU=(noFCrcTj=f&?3=3bP1Ub%zFuB1M9to# zbfI;`iuP1}7Ib7$&eVrTnjcGjlC#J7V)q0x2pV|WSPJ1x1Q5~F;IAmg5t%^u0hTKt zqv3={ZD5Y=g@&D75%A~_kpd^FhTE>pk-F6Jf1an48#VBv3G@BK=h z+oI^e(r&JA-`kc-E2>*|Z!^o%JeJ*i>~@tCp&GcyQH}Wzbc*a5U{5T4f(=ghG<|@C*+jl5!O0f*7wlY^}(3ro-iJ^uBmY=h;sHz!2 z+jMa&JE^rSy5toZzz`tR@$|dC&5RElQ%Z3f=|=Y^*QJuy)^?Q>>8!wq%&T6>6Fq(Z zl*91oI|5h2v*JH;FG4Jsw}kHL=r~;Ret2X=@`;{NQ>!rU6KUV-jKBw2tg(=40a?*% zAE}emCI1tnCq7|6VeQc^jKd|cZ5BKif9<|p=qhZ}iV{qbuj%@j_Wbp(Xgv0%^x<;$ ziNZ3uw@@-?yT&8BF>nc3Uw#*v@y##H{=Oq&i;vy<}(C z)z%X3HzQ84wcks(>;4ka`uiu)EX|A8pe&45SSSGp#ZQY*Ty0*_Q46hL`%J1)0C03J zNBwYQQ7%D^<+D$v?&dSx<+IZC>c8r2wHcZo!ORl1vA}6TXwcB!J1!u_UTCxa0cYoe zF{0wB?H}F_M1zr&lj|XKO27bSd*5pI!hybhL(tUJga9ds^#=zR7YWZ1FMcp}y}D<{ zxORFxYTxbYp#zE>wl3G^-JU4$CAj#}s4{oQQ-L}Nf?YzYMVInCRv#Y0ZuP+qTVpon zlgxwdPBd->FP*cLyNx(jQEhEP(P!44GQ~%yqAVjSFh=3mSacg_Q%~488L}!48avhaO@6+(u$rzjQbf)~taim&; z{Io}<)j?1Jh_pFAKr7`?G*#&z&H@ek@hxApOwGtjn>S0$0(=NR(*VW*ZsbKrM;GvX zO;B)Ea+a{r5Z3>6( zX3A#>M~n8|KE(Tl9Gt3V9NdyRrS->_O;T9ST2M&0J|GV7+U|7xePuJ=dv{{HhI9Dz z9pmJr(|zYj%6ZFUR_|~W@@FoUge`3KSj#@!jF^aCzkinV(41$T{YaP4i zy-U{<=Z-Z~g98ZK=yuJhBwy{;@G`VtiOvr`2iUe`I%Hzs+YDLXxOfGu->!Cw`v_J< zP++1OzVeV&zMQHCq3QKVg%Rvk*j2+%&R}zQd%vA!H24QCQb=xrLCG zi6Po?OZt60_VW|tp^K*8|HD7NO2W_dGnRM-Gwi%q?^3)N3x>0I3GObryKIe@7}Iut z_9tyzoR9VP7U);X*!mkRJ^HQBo{Qy&mznSoN#N4d;({}J{?D9d7tDx$_suly(FG%~ zg{xh)SsUTN?z5_^0sh}$b9gqzmB#1Mm#f1mEF~+s$aR+5{d0-Z)J|*z*u9loyeyI} zNkc=1^K*kE&1V84MH73jg%HKTem+cR+Rf9(1Q;8iGfU&(s4_yAdByg%8^o4qeR3L# zxM@fYad<;-zfj6MbVS0(#?57mcekjDe~XHIH)5eAHs74L47k6nAATjx7Rge6PTSO@ zE>8ykcj+7d)dUF$1Ta55IN>O@<6&JqsE&CpbeGYXv%n`jp|Jc*bjjy7F)y$JP zV&%JQ9f>>Y*3spY)|SzNGwP?F5H{kFTcu=&uriZ;(`=M6-fQOLFP8@K$ zdZoB9%J{(DBE+L6QoxEN8G3vAx_o6}cjK}m>MOVfy^qxHa6B1XxZ2F=NIq7qon zHhGzbLA6~<=`vtoSb{h9_-DyY=l^yf8l$e(ki#&U*Q1+#(M=HM+!j11g^2rL@$SyzNGmhrayM8Y)H)LYHvjk9GM`LVN59Ki4j3?4+E#)?~$(wkW;v zJ+pu=a*I(dfd)QHlMCJP%SUuwuC``NWL|vUG$aZ&Cs)4a$hV&TPR!KNIC65O$GQ$R z_7kk_NF(mz&1d+zM6aeRvm83gd{d5ph6N|rV$@D(*4G&iTr~d~WuZZD8v}G*0l>A< zJ3{K>sQtCziM4#^S&NjQ6N0~+#hcr?x=Nt0fBsEp(=4v1U;AGb;31x?1li)(Urwyc zLTwXfE#xM7BR?q~061xQWe%<`lGzIBuoI!Yxek3<#7BcWrBM1zA;HS(O1fF{!S!{j z-e0+vgpr|$iLqsHW;6+@sS;uV$mr_3<$7Ys;c&VwyqIDyk{ zQ0w^Tp*cW z4QlVN1=f((*9~iW2(+7{TJfJ>z5M^Qxug!4VQs~@c*)>ts68^k>6?mVeFiiQ@k;OV6)wvxIhrD2xq@w<@Sdz;BRrg~zWhYNHb~DI~(Z5pZRA zneMvvVy*TqiduA0@&7~5-%S6SdqfWbbQk{*dg@~j2b$fmzA4RO3S8cKPFxE-H@9h3 zV(J@5_4}>dWtNb_F0lv#*PtmX?%>3G{F`R`{|P@xIvfKFq`lNb6r54KJzXdNf+V+n zRmbF5=iv!eT&p_y&X4J;o8st)uOsT+uOI8o9~MKaTtfZ$P=xn`k%dLJ^cug3&BTlrn~Y3R zCxb|_y}XfM)5vk5dBN#07ep9^!1kAdf?{BBkX)%WXonUB1w~Lu$YL6TIZMq4HBYap znV_b@LN~8?9VJ9T!Pn8Hci5(7W=^}ilZc;Mwzt|3FDaNDe+{Sc@mn1m6VWYLaZ=si zKK$Y3`%TxC;aot(XkVGNRls#K+Mn5;ZJ2h!xJbuvHxxy~iYtB<7SY}g9lb`Du&-ZO z*o!r!Ue&fhb@A7`yyNMt-lQNuJ+Xw(YKWT-9A-nh$zy ze+Ke1_?lxxV#1|VjE1P_H&AKoZB4R=%a&JXvcI}5b(zCHOg1=u@qyL-nt-P6R`pQL zNP1unq`kS^31D14KL+xf=Y0_I$;wyX7~gm9>FLRt;osbY^mTR;GI}ZTFLOknC|m#v z3Su!F;)4zr(W^;M^ys`13%PtYYTaLe1+u266>WX}dzVj1-v=%j^PlW%B3iUUoI7TJnNFAl| zZs3l`jUKnKRo0}UH{fyTym1=z>2)QoHUiHO8jnT)Ro0(dyeGSRJlaAPJ36H<%NZD zS^Hu6$*?cXk5ffXUq~eUz9Ig?BFPl<>~Xz$ZOgn(-e&V11U@|Q|J^jtZxEvA&jj^DAzoYHHX^N>GTTs;-XejpI$hPS>nqO^US6-x{Xo;Rs0}nyp-ea+ED? z#ZXRtT*s9E{%9M?bemI>SXcvp zYJ2*=MIxO`25^Yx+Z9>Gl8tOLT#j&V8EgMvr12-Dev1g#6X9b3!M5+d10`?lUk}4{ zY6_FDaK->xQ9M!vy}L70G|-Jq`(4faLZn`vv9&=aQn?w<$Txy;b{6|BL~R~!JXe*7zoCJKkw5X) zF143+g0F{v(dg7T_?(ZOV-)!|Noe0|j%1mmkkv+r+~QSM&G&|}L@a;2{;E?hQ+j#O z-Z8^-^0HjY3>X+JD6Up4O8?gCG*w(&Jio9oQEQ?4ye5_sMg^z-Rzl8|>r&Fw z%e*#elsUS(vPc3mcYCr$E+>TSYDf`rZ0qNjAeC6x7P!VbH8kIUOMirO+*FqUOUKk%j~j@9uz7kMz_LS?T<TBozWlKSF9^QBzftC>fMlEsuvuD`s`_kq(B z?NCfgT`tiQaruZ@xi1*&VaZg@w&)h?aG{94Ek6` z`(3cFJ-hy_Q3&~R(DX=f>=Bz;;oUi=Z76-j9xg-HI_mR+H&2xHXaao)Q>G@Tp^@Ti zGPJTnLPnOYVujho$j+|PL0zek&JCG45M$JY4~_~r@R^;;`n?orf&Et=`)fjK=eCI7 z?ssS6a6NPm&kY>YTcyo0{GzjMVf<;>ezt>EmaD4yUOQF1nuB;)VRQwfjVW{|sVSzg z)!(=JAs5efkG#(GxN=3awbmBF34!pWC$<{eW{&4wBE*Z}pK2?lWFkD?Y3~`V&h|&T z(W7$I8SOF#Bub(%`wPY;Y>m77rideM4Yz8mYSpyA)8l}-(+4<0=g)Up=h4!|dHiUX z)A@}KwSALpae(Lhg!S1<+uPT15=EBdJ9g)c!{SMJ z$ewqL=NAC1DR>b#)S>IOvbN(8(_vMT9d#o7y zeM4@UBwy#_{m?~<(2N!Rvy)w`y9cqivge%bH0CBJuI#Q}zwiPJ!%()AA1Q9@;6S#< zbOgh!KvvFB;JdfC;OiiM#s#U=gUC06g zM5RDHI!tXxm#|Mb=ICerUc>j-V{jLwe#tyi;l2d{XMh*YmZTzesxRx8F`uxH!YkU| z2dik>3s=VGH2;Z2939_|di=yY4ZnTTalgK=be~SVfz2_YsbOGY7g(3cftor}6mw(n zozY)DYx{Y_aQxfZ0`@{ z$M9)6o_p7wId9UBgr070%)D>52}W-`GwkqVax>cysz2j%DJq5_V>d8uwXymdDgZxI z>OG~Y+bVCCCV9Ouus`)QK{(7t_u%6+GO@Jp{>T_U>N`8v`aWi7XOk)RhIGF5-^OT; z(Pime<7|c?PU+};W<{xf+1?CYHJ*`CU+$APoOm*DH=~YEvIs8FDihiKH7xzvw;M(9 zW}-s}#XH5Tu>E&}(B)%ir;_H)riW{$`WNf(gp5WfhU-2f=R>@mFC^)_SiTwKAk6V1 z5$1HSspaY%6Wg|vB0Cgn*Y(`eCqtCv;6BRWd8g#C$kA_yb4jjQmOc1n#ywcr1cQFb zb$2edp~->N+<4`jR!iwiG*JcU0t*k_r%VFGNuXflqD&GVIRx(>w37MmO#WA!!;s{^^6z|HF#yO35dOTr z-&#!`FRsopF!AX<;I5^(sUlqf{l+|?q9l#DEV^5L^3HXP%a<2J&hus6O?4{@qeIcLv(B2xLak~ylK*x67`4Ta8GJ+3m%6K)R?|80C&SpN{*6gsm zyIKT1xb6>8GPCox@4MC8J!eI!!#Y@!$|rN5Y-Q(6rXSB<;4QkL7Y6z`1TcsU{9bT* zs@(HxUq}>vh~3q^UBpOhng5&>=)@5(-RK>TEye0!zr^q&m?fe3+dd1$EI7%lD&DhqrcF6sl?smTI5ubRD0n(K4&AZw{n_qX61FXiGFr? zklBM5E~er7D2ahP_WL7hs}+Wg%3S5f;q#LdjX$c&*#MfEkA~4A+~fM%B8;vzLlx2F zr$%G)m?0m)luBrIC1Vm9_V#Vjp7Zs|Wu_J3(FZ__bs3J<_ z##KVY-QN}@{?)?5f=WV{ocswDlOTtUDFB?2$WVD*2)3h4^Wg4UWe<#m2t74FqvEq_ z=Y*{)NpyM49(tYu%|yuQSXNtEAbAVdy;7xm zZOO1@Cq|!37BJSbzOK1O9&ZJQ=7&sWi}W(gJUj1AC9~-&km{F}IXGN&bgH9^t;?FDFBuQ1${`v46@L_d&>n{QY5oNf=W3bTQvrlu0}JBKAv zl(vWY`--z8L(w&qc)tB1R#;;Zc8^uCRf98gEi;|zlaAL~9?Zlh-OQZ0hav4@*xCoU zzPw;(KUXF{C$lDy*psPdxyPE39)%!oWNdi&dYth2cII#Ygzj` zAQy>E7Zjn2))Cls^lE8j29BIzrvIEe00`cLv4E^hs7R?CZ98ya4GY4RPB3~O{D!%a zKfB0LZ5W(88;dF{BwAO2R!GV$DF^GXq0*6If02`hZ|BFi{~y4J*igx$!H+_igr&K7 z*!0=AS^k!o9L&v;Sm)Pl;Nl|SplRkI;DDNbQn?#%gN&GDM|=45GJQ*;FX5m<14ar zWvM4sf`?QzKZh_eRn=aQH?En}Fr^Giqkkcd8j9rY*>|z~V$>^>w;4ZRfApvjGpfi?Js10%Ii>}h&Q_g=l$ z*FDFp?&*$aC;hieeH`)rhg8HC)eC=2DRT1uuN0#t($78pG%U8;B3#SwK{5;@UT)tGnKc>#d?4*g`v0w%IKnXVZRkg&BlWy8-1l57ay_R_f*?`*_fUO z?mIe+zH}aWJ=}=|@1W3GOTbJL>aE|8jahsr4R4U7%KC!7>z&4ZuZ1bM>$9H&VH5|@ z4k^e|3o?d}MtsiU8Z{jc(sMcyiYW|f${rHvo!Vg6Oa@ZU4kOnM;k5o}(KnlF+=w`e zF(L=)45C4(S>~}Zz2vh5_P7AnEdb^%@!`b*-ju zLJKG$^hanM1b)CK$mje7S~U_ZJBLEvzAF6BBbhgokk%G`pfJh#3_RuBd4Ym zW0T(ZgucN&gg6&3uHW(yR(tNkrc*cv<-fyFeqv3GIMz`vC)&PVlXW9EWT;qMN&A*j ztFzdYX@b!)1ZAZ@sLMPziNrDx>sZ|Ezu#TP{ETZW-uZI8Z4R|(Al$&?2Dq89!Ikla zD1}QfWsno)E7<(KYZT##9F{0{%MO~*J$;b4Jw#x6;~jessd4HdAvq(*ar^d{EN^Kj znh6RS7W-pLC>@CXe{0w~OV*#%djh1F4=9c$@&Mwf!S%?FoOvIi$kHcvRq~I0>$Bqm z?2Y)Mnf1ndhx0C6DT?)aCVNdEykn4KQ+Ysmi;J-ul5UA~h=z(!())$ctVi8W1rau1 zl6PJD9OQ+4W7s z9cF+7)kc%!9wI6#!xkzyq|}UMYqdS(n>WlkHZFjss~}crxjnut@g;pZQaYT8I;-CRwmBnMv1L@8nF38)>yGP62k(fq)ZYI%3B;6xN$BV zR1BNIhHy^9mbD@f>I<6eR5-0sLdUH9jNHjqf1^U=^|x_Z8F*37SWR3Bwqh$3EpA#- zfG+>o0_@SkyK|h8NPjx+xb2ZNci&y1RN-^H46pL{?azd!6+E&=9jpSEa=6PzhSI3v z6eWd%X?u(m1t&(==4*i>b2?EakLQ<_AJgNbtBhWKk9q9jggz%bmrwvRa8P*h3#iY2NhmmsY24?eU!y`AIL zt#sKs@sqVwzfHoAnO<~}y z>Uf?d*PUVP=N6Ecx3|3=3);N_gT72cM^5tK*hlVDHfmR*9e-y>m_?34aUjZeL3a^z ziqH|^i`w-@Qb^WzJnPu{A(OhTU|-Xql`%z-DRX!F z6@TzH$z5az_o-22Us>R2Q;5x~3(uZw3XCWi-mD@Dm5wa1iHkl_Ry+AzW6MIo;Dc(j zoYZp~v)-Dx%e0sW&jgj(eeeLa32dlz=uQP-G3jSI~gvIP9jIhLod~bU!u~dgrw9s{>%~na3(j&*H z*c(bgnD7z`mMHLV7q7YvFtj*_FeY?hgaUvbftt7v>@+knA`P1)dSslZM0*O>-?Tfm zOIeVMkMY=Y&@YZ$JQv{>j4~jkEw4yBdyGZ3-j|$Is7_siH!$BqT&uQvZG2YK!t;lb zZ1sJ$Tn37NxvxY}Pm_0v9 zB|eryGnhvqW$}%nALqL417YKPZ)PYXAt62B-YhOHZSCv?m04eC%S7IonVDe`63Tx5 z94OR*DD}PX>XfhDTVtHqZr>vq9a>n=&YZ+y|8wu-pp&0gLvDPw|=5b1= zzd)~bGi6e|weOoW_WkAuy!>)PAgBMjDgJBEw9x)wUB;zpVm(u^s29pofUZDyig5dGNs?{VcdeJC4gtpI zWsbP`aYwf+{qK5@%utr}g5X&Ig$lu_Y?SP9RQPzYF_rU(3F||3pv}h7!u_qN%g)`T z*`jeK!EfY=Qi`b>HmUa*OZ76fR;K4p^Z)R;B{rOY$Q$$97yo{5M7&nECb7?p@;zYS zYTTdI>Bc4^JP|pOO&@@k(qlVGynoT1E0VKDL~SZ)~*`5^hv9IdibzXSS6m>-eV2D{<%KocNuOK;e{{c^etWSW#rbKD_$_ZON{P2QF~F<4QES08Y0)%Et7s>)#q?D6bkiRZvASoJr3dxZ5rI<`pu>{4m)XNh z>3VwUzScBqyLu~h%cwM6&}hNR*hE%J;+X=Q@=uG_YHz@L4f!5KbV;v^OfD4z34x9PkVVB@4Kfy~YH#O$=RXjC6xHpf$CQRoVBqAs#m z(wgj`qKQGTG6thQ@VDeEx+3Roo>q|8r5fF3gari?Uia^AKjfW&{2-n9*gJ9Uh4x)D zAN{)ElT26k{VM7Ma4USGVEmBO!eD|Z`$ER1#T(jQ%KKgPK+74zd5qxJEDJc;onc*5xcTdm7`FSH=QUXi9 z+*NpFWE}#t$Wj}fQd!an zAv0xP!j;?2hqK}Ec)%t(S&4x_(ngFi|MNAl>AjrKAJVp*fm5es9jBG3(VhkH*9MdsT5oi zuimp0jz1_1(tIH0ZXnl~7*`{>Q7O%6@&E9O_(X1{RO9eP zOpwDs#^{7}By7y3GuJ_vyd*>g+_Ju)nRLzb-pG*0X+}z<#3k_Ys1a~Www4}na0bUP zjQWYEma44yPXD26Iz~al0kzN&qw+=SAJ$sjAK8|1aU)X%9O+nn2VzZT*D>FJ76}#B z=w>$S1m8b3ct1psIf^=499uE9!W~{05;q04`1ag6s9bA_lxK>2en@L4XYiA>>w*}Ali4W z$p@&gPQ=mu>@;MJN%2mS6F{`P>dgN|tKL^;HZt<*XcYgukI%l24$o^}tG7m2SlE26 zmOyJ;6M2Cqg8|DAWxLL7JNYAjf6Op0vsyma)(jNei*9_HiQeJeQT+2O$DY0~KP8rt zZ0$^Bvbqe`mzx~7cXk%U!9ibAHZ`)v;2!r?FQ%Vff@*5<21kTO@CDB4A4On8+ zk45Y%`J;xtf9&C=F-Dh`vKud^+tb$z_kd?d6y$nyz&TCF-U&%b5-v7OBz}H0u0nba zg;`@zvKJ_q%jmMW-LX#F^5M@|pmBxaCV(>0>zt~QsT`9PdUc2OaK#RV%+wSx0+8`E7L=qfmROm7K9Y&qPIGq32V;^C->7ZlluuX9-NyIsK|B~-t6Y;;y z;de=9*W-6sa|__Km=x1FKd<5NzozZmLd7rO9C^a$>NTHuTHl>~ z?m_p^ABg{X=_LR4Ag#VnM6qr%)5DjmJ$+XoTiRG74Y=VyM*Kg;_2d64QnXnrV0Gi_g+q9l^9oc)yGqyz(gtP%QrvptCUK)ZE4hYgZx z#?n;$FL|M|59f-A0#kn;!aegm6MmAA0n$a6G3@=16##TFaDIods<~A1GttBXsxWFr zEF%(M{zrMaoqe7l358S;DYaj*Kz&tu{D0{zRD>339yU>V$F{fk!sGe(2Ai0g%FIf6Y-xGg5Jx>uV-NvH&E~2OrXVM7Axl_p@sjqbrQJ! z{5?TJqMVy2(0}B}wo}o{S(zUFKfO6XqVco5)F2%ZRLz%U(8l@WoBwnfnhKcrpkb?# zVfV2AX}r0!PlVIsa_NCpQIPr;kjU3`{NIZB3~WW5hXs#XfcoV!@<^Y14WNSLo9qbu zuOPbXhCqVH4bKOqXtX#HwZrY|fY)XbADF@+nR;r4h<#+xJ1XaYY1yeUkkM;ty4RV9+X zp=6=4<;zeA(JEsSrgjM*|9rukB8L|#@wlHLk=yh|J8A6So-T5LNRxH4`g$m?$}ERh z=xa1Dm2#=UH(srVS&2e3y^!#6XLr{WL%mvu4*0fsd0D5rrskw0MubxE^B+e8mZH#P z9jrcH!tU^@dbIiMBO_k zad(FJ;caozUv32?<#wAVCIT`18pElsR(10{va`FpwKeTv@upoHLW(p3=bP_7@7Pzdh&a@h=ze z(RRg9v(XcRuZdi4^_S6|t1+LU(@7_?n_ccy1+~`nX7P^H3!>Ma0$>$2&<+jR)r7XS ztF%hLCcZLki1P7(luC$c7v##kE*Yp4h=fABI@n%TSKsPRxbJ9pIz)V8Z8Bem0pSq^ zLg*Okml+~VD~p^PTWBW7e)bvmnYQ#V(27FS-J;SGGB>jaFVD5?B&~WRdt1gRJB?4NX%3NyvWRQr|^N};PBB$v3e64}CE!dP#bk7hE zWP|O!rAjTvuVt1*9F{Za4Hc0U{D6h;^DT|T8;fVMX=T9hE#SE>l$wF8(XPGM@rqu0 zExWS{-1O+1k~8-PV9zc6qO3-u$b(5B*Bx7UsvqOubH16xodVc7ph+kbbmp8ogD-ooc-pXN_)4r z$z{}QsqoR>4Cca=zW@E{*hmSRsA%HF75xxO1l|;SwfS|;_fR~A7AD;$?!_7kW`?f= z>2UnQCchs;2E$Ls#V3|!LrRXh-ETY@7LP=VeKqtvDyd=yU!axcJe{561jR&A(a&&j z8(YVy5}#)CDBkYUyPjjazk~LXULd7orp{ zd3{RdCIq3v!%EZA0;m7MApQ$&dJC_RL}J zo6U}$Z#274*cu%p%!m@7b_3tKP*E5_F0vf}?-EZ46TbXClmw9H!C}GY5`6I2G z*Z1sSZY_!5*6wAW)`2jKy(*KwOkp>%i*#=GGiDTg+Vdaqpg7G31KBN zA)(Cm{^$M0Gfa;!bZeT0l}3GrF30@RI`E(j9VF0n)~>?i(4fG`#^`s{1xZbgD~(G+ z2wAg>wWYhI2rtg->@t`l6yVFaP4zAGFsLe4rghc0v5IXpaQCT8ZxTuB*?$BGynyuCnfP38*d?zEb{ z_4t7=zVhZIr=O?7K0Vc$!&V`GSzap@Op|Tp`hj2-GOw>&e+Qm(159KA11! zhV}fM;8Bt!0HDQEj;`DsTPR&d<~SJbtkMOQf2gLpq=~M%3JGG+bV~medwYI}!iaSB zJ2PuMRn}%#n#-FdRv%rxP^JRP$OGy8iahU~d-qDE$2PymE?s9ktjsR6AKO2A0*>s` zGpv#-y*Bt<`hH1qr&RLsZWK>%kg5h*GB!_kD9VcIFda9{@R}g}9WXVBiXf@R3;CYS z%HKbJH)2znO{e7LKWoNVQz$_AO0m|umL&p&nCfZZg% z&W3A^`F< zY0(o!e68tb%@I2}^s5AJHA9KKGcG;_3)QE&?6B-*Kf ztGTz>QK}CS>QBb#WxWD(_BO%;@;&9rtBn=}JTVs48Iejb{q_4<-`AIIU;V%wbt_=h z&0UrfYEEVpe(Ef6V#(keJ1u2UUS2u)TEw>gWlX}R_iS@8R82RQfQTH#BPor zViK`5S`ehqW^u{fs|wEbtsxam3kGZuoDJTA-t8aLb6t8d4zE(OLsBhQu=HZ^T8EGGfAXAIkhH&k|< z+GU>M`G+`OWSz4`e>a_Yx^)vact4$Gp*R=rXZcBG(K~!;U#a$JC8B@TU`(3Krt4jB zd9i}=UM8w@Xz?d%7(^}NzSJ_Yi{8_iF3n=x9tR2 z;YMXFspyF0wrlD>_%-l*FVCRqdP--G3p-;j#Y~T1(WF);!bzpSPKfT@kx{O+*3+K2 zwa4*89WQn^7JYiZyHE%mv-l2BInY#aF~SQE#FP1+k6CrZV|w78WctMEsSO)oFdKz9 zt@zO~BW(H@%vADzpZ88zMNJz% zs+rbl^a=8+WnSNrGS81;zP7kSCl&JTPRxdXJ~7kkvh0eR)xM_%@LAN&sYqf;Ubt6K&1*SS(J zeeWv}7zHbZaN1+A(yy9z7KNm^2=zik(mquDcj90_=OQIV`Nb&4CoUs=fg5 zfrGrF4`C(|+PE^&HuC0L`S6J_Vo0_`Vxg32qYPM0NnS)5>Gt-{oxJvMDli1a3arSR zLwS7eFWxQeMesDXYAPQD8G#~c=TSr4jZVuAp;@llSbZw5-aYoHcheRhgcXj&tx1zhmaX!C(d7!J-Q~^U znVvxUuU@*mZfux60j|r>yjTUJ+quLx93&5L`WT2k6J^)IpkY&>rAW=>Fi1_~5PJa* zB{Jy*()*k_aDP6Q8CaZsop<_l>!1E-^e5oH@dQo@`#i#`Z4I9;ugzyg#jdv2aU^ku zOtWg2QlhJ_`9j#Q;t!`Ov?A4;!U}&;GE#<#vknX$bA<6u;G(MzJ7rceaB4|I5BjHp z9-IaqlfyUO=Gz2;H+D;T^}EJpY}DbwXC$JpW->S+2bkt78v0-Lyh)?W0$${Nn8c@w zE9shF-WKcQu^GUg3c_9>k5XFAeKSi04 z6er%BFQSROPHu4^zqP(tyIJPrScv;GLw9!288D{_U4gYV5;nU9RV^gw)x0vK*|%fA zjrQn(B0R3>NFcFAcKT-OL{d8q-n0}ZsV6&AvV1#d$)xI)3ndtBsSleDiHeLk;Xy=> zBr}%sul<~%=W0`74j5pMg4)M~YxOduQe24`!g&VXbbgMktQT}LmK+>nLWB+Lj*vql zR#_kN8W~^9HT`Ol#FM2|$zLOKY8Wsob1^wZk>iXBneJ;JFhMx1#+{-$`bP>|yOyX{ zNi_yf73pohAFN9}-y4!<|NOLdC$YMs6JnNiAkyOT?XJc1J)ZI#T`km-2AkdJiiQ|V zL||V+^1kb-N^o1ITxwzJLz%;%zzw(6ZolXVmudyUmpmi%c^CGTa~AeYhF_Ov^5LJ{ z_Y8%eciACX0DDA52fN&)A{aFf$a>~!BH0G>Y}wa-QiSP?5eMoX`nbVz-TlQD?6DHJ zrEpIv{F}|S={Zsmvh~rvA&&1W(z7rPIY3k1&PFh+gD)&4Jla87JF!4lTe(bKaIwKc zzQ^*7s%o=O)hC9&2mmF+W=Vsv(Pa(?+o@-`bwzDn&YUkJAV}HMK>w6*KB=AzA-p0cdD`C2Y(4a~3eHgxJX}uTn zPvwMjlH#=nN8m+CtAhq&=J?zl!B=;9=)Oo%5|T#q1OfvYAfGP=IL6FkwvDW=jcnpq ze+qWR`S4+?sueh_>vopvU4COf{%pr1vS*!jMQcd$FIwM)_A&RF3k2vHqVn0zYx6ag-W_MG)2M56i6Mt z^4*rE3&cjf{g$5JWdZc^5`N9k9z-oPGVuOb;ZgnmtD%aN0(?m_#%VM1-EO`Z1ZP#j z_t$}9ZH`qR>ZXgW5%{u)VqfkqW;9h*LqQwHoo_jSNP|?z`XZf&Sh4hrxLp7Z0iE+K zgp_h}^M|67xYkX33s5AOqS$cF^9vkZ?quktikrQQi^P4Cagz*im_5(#;r3gEj}_&J zOIjt5=jPEFB6jh6Y;cmz?e%*3_)U?LF{pVsK^RFDlJg-IWH|#;LuwF1+r$K?NLaUA zi9GxJ$}jV#?Fcg)U&OUNdDCSW3k%a}faDASG@{^Ql?J6xd^hHzjWrMg6&6{CgCys_ zb4SBJf4m2+J|E^!A*tTZ-0qz638hOGrKGo=}xWNXt!}5j|Svdo`w(gKDxF=VbW0oo(Gp>q7P!8$Q~WN z!WiiQCVerjMkLWfDRPftf)Y_!7U8NA9a9 zhWTW$YxEZyn*hLvA+#)y#Dlff_z2inFN3*exOEf$@SY8^Toa)}-c}FVwF%zPVj~O! zzSpq_H%@Az9{21rLP;*--Ofz!-bI*;^67+@7S*a~2@@jW&aikSytW?D+H3aJPVR`z zEtBVf{TJXc&rp;g!n{4rXn)4&9~RgUa=G6eH^#-X+p`;(B!WDdx6VtmFzubGM#@ zB?!X!xvQ=2wYZMMKH*^THc^fDWl@o>MDUgpi?8BOcyq!Oc_lsyjp$V*e)@NzG4+Qa zV2mM1#5w!>gSb5GKJkfoW#KGIX%1a8oAnqz&YA3n++zMjF`W{y`n$F+BTTg_O3S?75^M*$t%GA3c}F%S0=a9RU!`$sD=GE}UXI zz(OZ@4s)e345V`x4zn`-eQL7L#q+`UmS~(rrrX%D7rcNZ8FF>o0ZpUrq_FP(stl~p zQ!7kb2IpC3i@n=}1xuiSSMg<{0~PUGJ2U9~s8ZoFO&2T7F6B9;t`S<}BbU6`6(hz|(Cc(m-Pf6S_I1?buo%w4!iLvNoC? z?#o_<8duw!G5FW$fh-G`gBs{}%-CIAGZf&3U#dxw4-H*>f4K4VNx8zJk8V;nIiG8N z6yad}N#n|VhWRHu?#HhJ&ErOX<}}=NgC3ge9puT!6DGD1CF=}6q*-xpr_?XuC&A429B499=L z?NgQQ9FW6+7eMfL!GY_x7^?6*?Fn^~{vZIaf3x$+tEIl-TzOyq{Xh8hNI*nAc4fPM zk5Nb(&`lk8Nv_~%6@DKi+EfA_)kY7X$6XzKpoL8-8^KY!C4tH)uNv*#9{Rs!gNGKuau^Vp=XKj0W&{~mMOD>QQKYnBp zDR@X+k97P3{K?<7`blyj85kk?Qga6f&epnV4#X8uX)>T?0^ln+*sKx3-}odu$4;=i z?f;|yCh~Kt!nkn>*YJ>6dJDE_3UoD zgHnrj-8qM@?JvT4h?MDl&vb}mLjeUf0(#U=@oNohG>7D$;^jNMLVPw!iO#M_YJzKb z%C+D;lm5==t&ii<+=%4AyKk{VECbdgOA5yrR7U&!D!bR%Pow}4XK@Ec<51g6X-DId zI_zFi&jCD-@jNnplVBfq^?yN}`t5JIh2gyKhc^UjQWtYEGZtCqx@lvrz4#NDZk z4LQErK>&+eEnnseA}~dbZ2Oqk@`1~TCw2>)57S;+>E|TF(-n_z8quU?oZbE_vG+7} zPJ;Xd`oZ`oo01fFk#Hk*@^LaWB(%#so2mRSv<_SKj&9K1v=vqpfo9sj`9^!Q<)PT1 z=bK0I(@kI3hWucrfI#87O8a~D&8Oz6%h=Uxb8Klr-(<1ElDEYvPv;j@3hHHF;;AIm z2^J@r$)lUc?FBlf;$syXdL6+O5W2ps5{`~bAEx}@+2BxG8_qRvk`QrY##D%{l$0sC zr_f11A>s1SZK-rXXs0jaXepiPB<*+p0XUP`Wv@fY28<6K)^b!138Xdmak@ObO*zxF z!jy=rywp4md)k?eX2^tMBpVkSu=wo2H`obrM|(IqzHaZ=s8tIWb9;UXSLX`?OO#cH zhQS7t%_`acYy|EJS()BR2hgtrtMiB(awI8yvtGM})vuV*_sG9&em+__>e-t5{H&uT zd!TkdVsNGypK>*X+8$ogl{+o`&0q_$m=+s_UBS*~;8uXkfv=@>vPZFt+5)hyt^Huq^6w;` z%6k3V;<(J;YOsl8Fq#N=8)M0unL5NBvu$`fo}?A1U&Z?dNDHm^_-2}NLe&LAxEZ!W zE>O-hYm-EwaKpy7DP)Xr;)lCD9^~}XwYA3BOPTj121HHhJIVIIo}OuRIpYQfZsuj7 z*^M+-QTF7_wS8BGw6NE!SLR7SqQfWBt)S+V<7oK?4IZZpr2c6SoauT+6t#QD?NP|i z)5{Bo=`7v^KPJy0sdarO*J3@y} zw^U7s5vSYPm@R2%KKWB9x8;3G?4Z8NBCC(aTavCDbJF{XLE^4R3j*Ev0!-zuQi|tR z)#4}3sX>9JFvVbj{?V=MI}TgPXr?+)343h)4MuyK@2}eZ_GLjQmIrj1r3}+0+>Yw| zTEZx_#q-~S;Pa31x}+E;hovW_brO>&K{ieo!OQZpDGlF+TXYHR*R-ecrl(*lluP*> zjQkE!r7@i?mO9>a4cF8#aRs86$s)=>+2Rp{m3Sc#;;`@U6uxe}*MTtRy}!NX zntg4Iq>GIK3>ibCzYB7cbC#VGGVgxy?Vzv={E6QtzKN=dpF7#~T`w=NrA4e;Y+KFMd4U z=e2Q3PAV{!z~wiv&}=TGGEhEn-_&&t+7$5EqK6W3@e3U{sye2OF)e$g;F!t7^Tx@DPo5=Q=YK0G+*R+I`WGmm~ z#;`!(t4fE>WR|2akQAjxEF~MUwZ3X(od12d<-m+73ZTZ8XMdN>I?Cxpks~44tj_%Q zmNNh&Y74`Wa5_;X+5QId$gHg;}wUBZjLTNZ)5huj>l*a9~4GKiL4pZf7>$bL~z} ztnRFWkOLQ@9NexP+Ee+mI0rUE9qs$Rq(y3%`w@vFl3|`$2%jUJ+Gq#B`wbbV>y9Mo zVQKo*Q_1V$4Q?@ics9^a>k}D{)lU)f#3yWc8e0ggG0xjlCgb>kFhJzMKwyVVog+aA z-}-=R-Lrhb+%|kQ=Qxz;{5J_;;|E=0P^}D$a2h$XsmxJeX1UijdwwBpiVja*b#D9R zpolp=FsfPU$aiL4BIb4yd~Lfca@eJh$GI;%b;Q*#OpzCw))PPUlV75HTuy9&al2~v z&CJZP;p0@6+wBTx;1TZS*O7l%((N23h?q!yy11Qet!DDKoP5Ip;pt8`^4+FG+|Jq3=fTz~_^uinPHT8pk-6?zPvS`tdH$x?BTUTekTT5t2=7P^4)^nr&>vCyu z!rE6pTO?b?3$x!?Rmb{X34*Me6eVqT&K2T&e$V@0fpnQD>2#s`#4pw|7l}9EZ1w1vp#?RJD4Hi<}qAb$0)wxN$Aeto5w{2IMtqgE+ z{Fr;MW+O1Tb2h`x)FAolRxM+vcRWk;xkm?Qlvn-t*{8+Hmlr>QsRnjk7@3YT84^$e zZ5)5f)v6fRnSgZH99%MUxw)X_l;QrzW({ZR&-hcE1u@t)i3ig-mBzP1o9t}o*QHV! z9xDgjPVeN4o41TeALPmCt?8%rbvv^;6v-cN@~mDVIy+?;LyrqJ7WnkOuK|pNQCYsE zYGgFUWMj>Bg{}?g9EfiVl~MEZ*Tkw3{tk9W;Ew$cM=%>~0xfs4<=UUFh(<6>^cq}x zWSCIRRs9B1vF&?Ye1yJM53%uYf+p9Gjk^;Z(>Y6`HT1Z1U_##NnN`?tDdWZL0ME?5ROpX}`&`=F;Z_gAUVz?EG+ zJ)M`WE5?)%GHEmg^&0YYYnHG#DRij{3Udx8rS+xUeV(e0xI=iGV}H}Vq8X6O7<-pc za~$dlbXKEBaM}6h;4;ur&HaWBO-lneJ!6Ka`1>|3_KU;V_O908gd(}%N`(B5{MXNF z2?KVt&bP-mpD)Y4MlKNP5eG2xrT;Lng?UMV4PxXD?yX6ops*6%k(E+oZe8KvDY|4y zLp3%bs9=|)9gi}vWoqE)31DM{iUI3$(iR4%wE2kn9rRA!VK|BdUvC^*k zReh59QNBt2QkBkbW@B?VI9xp-zAcOXmML{;h$Aiy!LkgUTVv&(99#WzRKfub9yM6t z5o`XExXxTx$KH81@o;b^$duU~s65`|Pc|Y|&O7mPcS4VwZypFw&CQ)otTtbCX}!Id zGBnO*z@}ZfyO*n6G|7X_!^>N2R~f%J*Z}4|;E)?e?nzcMZB(v^uidfLKt+?1Ad zpxpMtL0x4?R=iR}x}PTjS&M3FDuSoU6X@tbx7iZ~SF-TgrT{;^ZSs%^P{R0YjEb#h zl*iLE*U^qf^+N7G#+00U4haE)lK_GKzNv{uad>!+jx=~i<5k2&ctwYS$3Wb1h~0_- zC%nzLUR~R*JX$%uM=S}y)j1~L7!V1cF_K@=rp$^P{)N}~#$<{9EBjhfH0{{u_7*IH z!jb5v^*Wqzf2kYS|tCJ{?`?-05D)r{grN7Usr-3L=}k33U829--B$-eB-_UMwAlT zMY2UWp{inZtF%2Jtv(igd#VGiq|n;(X=rH7Seh*6k2WwYrw$_~PMT9tQxDkWPA06f zSDY^EQAjfV9WW%l{cHH)Cggm8GEmArgH;KN&_+_mOcOj0VPIiTvSpHd-mTVsiD3k9VPq6 zF8?IIfT+kceuti(KmuWf3Q{5E(`>qcNQ#jErRcce5=3ssMw68yiGee$^En3D|NpcnpLz4XxN1w{ zKr)hu-me&yD~{;zvcW%TIgy1AfB9>TMD`)Lu;iu1)&~l>aX~dF^Z(Ku6lY`9;+$gE zuGWH4!~agfOY!G5@GpF_nifg~3i5ADKl9tl$Nqmc^I=*1hK=s|j`abvNAh*Vk1kDz z!FV$gW8JQ$>pPc}G}%}WY@~YllKj~kd|ph_uAfA1-^nhw+q5LbzoFfKx<;e(U#`KX zjiib-urG6VrmQB z(XPisA^0ZOIS)nX-e3&8zL`sY)T!gMs2$dMSZA?TyUB=X(NKP2BKtqS$xRJ~?uu$8 za|v=ui%11?5{3)38GgwxP*4&ZjSOH^_xe)EYddAzW+3zMc&?YR+n)}S`(#ultoiVZ z>+NW95MO*0Oq(H}T51~vnD8`Z{pw@?<%#TY8DVV72Ska;S;@utT~o}>6xA1Pt68S* z;ONL4Kk|{^o!Sv0%0#U$&1{?wi! zMtX}@n$rGLO_J{SMwyxU-JV^)O(;+z4|ze{w%pW%PRbS;L4$wE;6 zL7u3LRM*na5*NXhd8bDIW&1XWcg9LDayWa{t*K?>>}YJEqusEtX_w;&oJIXQ7y7fG zy)?~*G|Lw8W95Q3D&BlJx{^;a-k$c=Ap4F%wLjz9FqHAUydovkT=$I>NvsMX9@)Lv zohRi*{fcbMxfTrmC9j@|EJ@8c&PP3yd|Zb@DRZ9kMtiZB?jNm>;JF-RP45^ z6<(Q_EHy&zG3#xl=iuZJ&18b1ADENoTw}(&WTaw;oCUUN1aB7_@II@mz7rA(Dil~P z(v^zR{;xs)(gM>!4bYq#`nl3S&MAD=n<^!7QzALCt{P>nKk?M$`>k|Sa_R+@$XQE3 zy!H3CrgU_eI4-a!&!xY_66FDvKsM`eJqHy{w<@n{Z(ztv*byIvA)4)ZV8Hx%FW5|} zL~BY~0J|rP@HVE8H;U;#?77H~NBvCdmTEP*m3-^i=VkRluwyzPBz1<0?ql2!8BU8S z)(D`X72WsB*tPXc2Fkwsj{v8qKE?OT?RwS9-E*v#YuVYmm{Ae<;&J z@soF3Z-;Pza42q7pIz5H9d`fItUDs>khgT5b`I>1zG;J@5kAXX>yk$jncMF9HP##I zAU$G*EGqWt2F@f79^Y1Tu7@&iBB;hTp7bHo8ZssM#qu zvwL6*)5;)FdM#>J4PEFP#{y378q_^(Xp$v7$UFBE!wQcmpyzAy?CAtBog89o%Lp1x z;Etx=6Rt5u^mXxvLTnZH!U~`Z_jadly;vh{exa=q(%YIIKr-1@RzVfFIdNxPdq!FK z?p4>3Hi+c{E7<8LFzWUGvHG&iK*r!;d++XW&$+akg95mRn6z4#7QLz|YdPlG_;_!2 zKo}#o>`#WOOZkQNrRI!<*Zx1=D}D})=ZZ={k#cWxgA3YJZ@Q_vZDhRkAfvyf$ln5P{W_a0ATzn9V0#oH#7Xs&cyLb#sAdc6RBR8J^T9`sH>+uihh^#pLlBz-*$TGJK8 z=gAY~bff?z9=S%Rr~f->g62c@I)%h;Zs^9b#5jZ`@dqJbp@P8JW#(p zwD;~AelqS!(}@#~&2i#K2EFMS<3sUbc=KKUbGJsN>RF&u=nCZ5SRk0}b5IuLULHMP z1KqMlj!2@F@4K@C3<);p8fLX-q0ZdfIr8;uFFjv75_>^}i}jurx4f>ptS4h>;oenY zoJ%l5hh1ymGsoQN_BAWYL8i6aCD^YPWhz_cRb^9P&9Xb8G6`)#ZE*F0SklGDFnH@q zuA(`n?h%cMU&A2Aw$4Cieqe1+$NmZpC=-f{`?E>%mh?+YztU%S{TG2!{wDsRs=pcY zzXG?;3`QW>QprcA843}xf@~-N_^9xnz~)(W&Q$-ycMB=BF-<`SJ+oM61S001t^(r> z-*z|5wPpvqE9Yb~!D*+^WOi^~0FmA!?{t9;MQ$Ja^@Bdf1Luucyid#+7WMh=8{BUG zn~ep8=IM{;Uf5xVY7u!^cj4B;K7l@>eD}c|tpqNG3vICYF0OTAL3B*tJK>FEBT)*I z3da%Xv@^p-8zaB-9E7{}0S?tF?5c|OGsh&6 z(iq@*F6oV^y+_Mi0Xd#RTF9_oU>7(B36zRw@<)$aDu{es(pkumh@+6 zwZvI*>hYo+>>Cz-95OwYjAhh;KAM99fG^lxI^Ra?%LSvz0Z61 z?tR{`?lHQ0jasw5s#)`!mdOQ+n#2^%ShosSi6P`7`DMLF28X4FD!fSWMAGt!nLi;S zT!gYh{Sz*MI#UR=W2fPS1grOL*QK(QuZ4C6j>2ZM@5GnRw7QhY7H4zjUD_;5oy;$C z*co%k9J>ec*~uY*1aQJzFbOwXozE7PY6VY!>R}a&>$0q5MXa#1j^_GGBoXhi5?~b3 z))d=G6A3TGclkJ5z~{E};jVb;Bvq|6}Ex^Ua9_0URP z61(ROpn`Q%Tcqu7gG7P zDp}g+|4p(4D=WVhGIdcgW?%GukGoReF6;@ZjV)S`B84+y%}JzDoAA}; zbHfs=FL4MP9m#q%(w!%=!S!0F-7f5aEGSdQ9W(TN>3Lb{DK5&<;2A-c{wgI?*;T6$Y-{9Vd+SVQw%2e|E)@&F8aF4d@?%av6`P?$7~#yH{w<{L%P7{K0?rhdh%XK9aIhmyZUeB%>z(H5c(|x$+aWfDd zA9IxVz8}S9W<~-GYOoWU{}`E4#KmQbHZCV0^YNJ>*iM@GC6EyC9|VUtq4+ISu&K|G z#NPc&#Rx#zG;|Z9me|};j^6**FT$Jie{nQ;+&}AmluM)K*V51vEB}X1_`hGeE3sk( zoXbUwJ^y+81Al+V^-D)o-Vr+yLn6Lu9XFw7T)f*5QrVUn4g0T=-|V!Y!N66uSxWtf z`UY=B0r$_%(*k!r3;7C>iD+flbJ)Au|24-drOjYSAUl{Liq};ApTMpEOKI5tl~u|2 z;t~-dpV&0<<>24&`ex_-_wTi^RFvsH-pjQvEf_$hSX4KX~TR>PDBh1Y%;l!RB|$^MHlG6-6*xMv^}AJ#og@ z2+i-B>dV6L^>S^Yt8UXZc#_q(%cbo$Pokg=aQ-KXX|yP-%{I>KQ0`wjhA!VZt1S_Y zjErKyOXVggio*9q z3+BX?NIl#4Ht_0Cvm44srZZ^rJ1pX~gp{qiP;k~*!WR@5uUzDoX}8o$-?U*Ry}W(? zxMx6!k8jzPEtyJ36%Lo6_OV4aX(5UB^`;ebLE^}_a6@*_8D(Mi?^RMNdpV+rn2(MT zP|-^;rV~L}h$* zAxh0PGI+E?OTX;pn8`^%hKMYn|00jqPh+6FQj@ zuySyg4K-;n6cxvw97d@Y_W_PZ!ZkY`BHK^XN*wG2DyQY;Z3cpuVuHS|1X6C`%IUG! zTfkN=&Q!LVU{4o3u`%zTdiU?D_3CK(Ndj~)rMmdFFNkdJxipHNvjKs_MZL#4J$Kjq zDNm|aSR_a0EgY?F`Lmn~!VlEvDC|#I=mP=IoLl%|VnLQoEoU#-86y0TB2PONqGtu7 zl~j+{vnGtOmf{qUa_!pnhgH|G{2L~K4DYB4FYJ0v)78-NsWXJQn0cK}PFD@P}0Uy0+-E|IFnXqEWln;Tox zVRsKIB~Ms|o;^+Ac>+dq_edy-Mxq8}v}`nUD-!AHhitsJ-GR5>3#s|biCE;ZwB_^? z1Uio7t#y|=VvLc?(&60DZV^8w@638)V=hr}Zi!sB!O1-T@ZGsUK#AFLh&f{ck^a^Y zg$DlB=d(8FgEx?x>?A9mQdKi~>m%s1b}_QxeRQtGY1%WqV==v{#Qa+O)wBFEl-s7G zJ8_H1!f9TsuFbxNi}cAz|JX;T!_{c)@V3q59v{!Tg<+<(_xnmCAg9>Gqv+M)o-adW zO#zYm*boIf>eWoR)5&_uw^ltyT9f{m*6g4@;vK{VzuQyKGd8*9rszk<1957Ha5@f) zfYL>V-(i{!uNM|0Jt`I1yczcGJ#&86hZyc6(VfkO{%;Ebu1v%QItQH*-$VXBtUUEP zf0xN+SAlFhpCrJ{X#0oZuWLkpwO+ZhTAZQu$^Cz1X8nsrkqa8=aoD|wlFJo2cV~W~ z$vxH`4R;cpaRfB3dCV~9nboytIA)|ilgbeti z4OmdL!SnH5XPQ>TQculKG{CsN=#$WbMy~F~)b(i}szesyF_(c67RA zq_9s43JU$a_7|~f)MA>c8;Z|~#>T3us^B8qeYNIE`$Maqx!XSge&`sO@*3Z2w{*{6 zc=>*X?F&GOfTOSx_`yx~4xW6n9}e2jIS;&DYCYe$r8hJQ#hQ$6J+ufcoeU3m)sD81 zL9bm*H%(_W2)xmj9W=F;GDb5g=T69%-JLkgwP8!_7|N-kfimWRwp7DIpeq#dI?d)r zX6fkOQCnm@=FEGTxCC2vjTgmmBG`#l5qCuM@ORI3Ss06IY4I=e^yo% zhm<92qKmxuhaFMZJegmx`_12@Dna2g5;<+P4*e0ghGxBCfYU!7O8E*T%TT&atUZ)5 zzXq&vfo(7`BT>-4HM~4wLRXyqgM-*}Q-g!Bo}R-}gnxjKpXW4$e#nwR9J3c?$*{os zfQYNFd3`(QB0G_&VRPcDgYgAuJd$ppq)NSlO6e^su&E=?RQA|{- zi>GbuD3|X=cTs=0I=eFCP0&RulLxY;-}XBSixM21MpdV{+5LK6H?H5QJ16W{-WySa8vF9SCis=Vi|lOCas*8 zYG>~xCdBiI_cmhH@^uTQ9NuxS@S%}F!_|&~WdvQo*N?9b*Xr%pa+e|?JHMFe8FF{| zCi+dr=i@#K!?r%R>7uE)64vP`<2cSraQpiA*&pFZt6|&XUe9pUUL#@cIv2UePkgdf zyu&kGZczgiYs$P3_i|`_eXai8X>^mh!v4o(Lqzs~ZLh`eK7-3WDItM|VK+~XQ|b_e zL)By@+pw%+7he>tj8_7Tr|@LYQ&7RKjSl?d4B{xtu#wr}I(KWs^cE>}e!`}Uv0%%0 zacCt^x4OTw7N$y*?^tnsxl%Oz5`O6YGb18&PrP5SkyckYVuJz3^;7?b(#Q|XfZnoR zUR$y*f>Mcin+{w8yI8{o__9?*)8A_y5!R-HrtQZD_SOvc z)l%c#CZDXnjvuL3loxCq%^;Lr6w>(i5O?77Y&plWbr_`T&h6`dE*bLE+>WWYMNV(B zGB6kA9*8cLTujh|=Xdw}q~>~xq(MrsE*Iq~v`XcTZJ@TyM~lkHA(wn0mV>Ok~!=cAm<3Ucwyj@+e{ ztFLyL5A>V!@wZ0N3{pnsAgLPr0t?8}{k>oD_sfx5xDsN&Cld{)K~qz82veb^{OC#Em zENjQRi-&b38}042f#I+t-?&AYgI;J%i$2b{NwHcxCFC_&XQ9;8-*ohd0ep#LDR!Mt zMzGFed@}NF0u~&(@WppT3Ef+3 zJQ)ow|2$MisYRA4ceUdc=5Y|qE51`#=A^wncn~^4;FYFJfBr zsQjW~j&cm?(`Yi_uAzAQ8QKY>($2+@V@YMMKYw%FsaHRF zjn0N`_`p-Dt>GsMnN*=f8uUJq0G@VV%=r5{?qanPRc8cr>@8?4zQL_>`i0?ARO-*8;X7tU zq@XsQaSs%)yreLdA|=KpIXnt*6&v0uCtd6WKCgT_+Yh8OA>2a4j$!qRF0E$iQyKXU z34j82MbwXx@vOy)cd(-;AU<|+D$JeZN^hK3ntuhTEAf#A-yGcfE~RZtjDO63+@GZ= zsbmP)qcd#$H(<NC%rMhf(Wz8J%b_P*$bR@7pEMxV2qC%d|zkPy6YkrZ@TRNoPnC)!5 zTX$wxqh{x!h7+rBm4fd~RuY_aBlQ-&WU4)c=;gOG$<{pcVK&sbB8@vbmbup5Yt?QU z*w`~ZA0~1VG{F6fy#b{DH-$!Kg(diMu1o~7a}^{*sd z0K2;94)I(ln~vtxW72b#R8Pw%BFZDz)_VWrXU>Z+_&iPmmldgwfjLx=0ikLYur#{}6o1PMew z=XNgB>9JbOP#!~iZe&O4z?(apZS?X&pt$Vay^H32XujMNazWGg`ic~BrVV{jccb3H z6*xKRWODx?hk95hLZX&eTLaLw)Jm`~-+t7TfOH0w)|7;Pu{(gGGRYVVD8L*`s|h+g zc|di)Cm5t@glaGg)SLS5;c6~32qSu3*Hm{~+&}|2ooh1_`$qE2SZgkmaRwaP3o@5L zG%d+8Oxi$U;eSL|g*BZ}KZ$SqhB0_geoxdQzD!1V><{lQF@$?*wM=ZA2oXJ!^%#Y) z&st47QM7J6Hje>c=F6`?)jHq)x-S4~EDKH$CE=$|<=wd5y{SNRI^j$S3VPOE z@V>=McaFR|q=y1#db(0(4^0L^hP(5-VU^Q^N-e>#*(CkI{vi{g_p$3scQu4Qe$S{)(GpN^8$9N~0kF{VV>F!qmW46J6)*E|}K zM}i^>eXBhlVL>}b=Q28HKvIzX3BPI2B>(jlIe!{UQ=cw+U(oKSYl4;8(<2nO(Mvwt z3%K^DPl>Fs-s>7J=fBC+Y~$KHHktMc>|M@R#zu~$`q<8J=8N1Q5TO%aPUJhP_}81p zK50wNyFRH)bj=oGDnomgq_J5O5a6}yz?HSJB)Prxkja0AMF=MN{g{5SAd2R|fYp&t z(cl@CbF+0+5!ODm#KURPKv2h+ULQX=T&avLhV812n4}{``8ABTj(V|4IU&KI6VKbm zczLeg;8uLMA6{&=3|JJ_h6kI7*)kR?8Fke!O!$pWBwA)%)(M|8wa0nOp`Gmj5a(p| z)t0}FAX}}o;JrJl{t7CbFJO+4_-f$UK1J)nw7+2M_U=2|LpJ(&?w#Y4L9c0rL~y$e zF;i|pn90$z+k-8)?#d-E~De`VKm z%GvjE`B(h0oERG~0-gkl<@xW6zG-NNfG__q7QnZ!0At3#0!p=mHw}pE$MJyaf1Gv4 zAC5bN{u=@D=TmT`Ra;4S)hJ@SJS%bHjAp&^MBq|}l!F6S;|!B`Wblv4_`r5TpS$C& zqukyE7yo>%g}Uo(UIH10ujLxiAVRLG1`(xW_Ui$iOriBB(h0GwU87qcHY;8sD_NKc z=d_tzNB-a@%g{FNA?7{}MnfX%rs7QwaH|$=OqV4sbyoI>%YF+d&@L~GXy;g9 z)dx}e1}iYizCi(bPk!a)Ac*DsK*o^v_`NY))K|Rp#|g{=oX8`;BrKfua(GKjw#=dl z4`di>`9KcTyMD7D)ckDJxwvp5jwmOg0xX=pWMe6@=*PkDnV8ZEwAJm2i`R8~nk$xy zmt1TSx9s9ASugpjdp&DZP-G{t7E%+*^gEib`)Uy*qRI~n2}g*VI4sjXQA&52alRAu z`5g~-)@l(wg5WSxX?nw_Yc5<>4rvcijE6}x+2(a5TW!#HjM>ggA3$DV>RQ?4R%ZA? zs2$0QZ%?qA@$Ay^51DT@sxoF({BH!_YbYwCjCQNU3^TULw2^Ax3WJUo$i9JypXv>y zO!Nh{{N$M#WAUURqNrHaxh74Gx2FpPll~%3RgW+Yc{WHWbH!EXxgP88oc0nf{iVxS z4*cBP+cS)*G>5WP#*;ODV~j4Qnq9%o%cVUNglgFqb2pAXj6M|U7i=cap887C@*SKt z?5~<`*l<*a_s~(3hXbA(^i!oL0_&&8IxIrYSyOU)rb0I8UrWx#sPSIjStk z76RcX=n*(KLvoRZVrEc-`SbxQtFBsgf@XF&B%t^?s+8h=vl-9XTeBj z3!BF?Gjnswa~7<+Z?snz3~}pz`f7f%S)COAW$yB`o3!{sfKR~J!@#^T1i_piC>Y`< z7ZvpCjc*(j9ur3U@$1c&iQ0>d0V4Q9PcxSgo*R`Tew6g+Rc0Xvn-USF$pc532lAkW zfwg^%g9nS*+b795;MM}B9g+npMHk(MDu`OLC47Y=o z?WbTb^a6rSZAlvLggadIax51~GUYO<@gzbVked>zdw%;$%GpsEmk+iWR_9<28SBvu z?=KV947->lofGDkW@m((+vqLgsfbQz#5V-(-P;j&;kMg;-`^>@R9chtODhpars6}* zLySD;hTzh-@6Ykp6m>ai6ccKbXq1bl8R-_J+$~HbNfW!n!RK>RGq?;fq{P&(0WdSU8lgbFC+X&CuDHPx`VKKPO7(Wuj17(++sCgpH(k{RAi=B}0TT zzwUjweUI1=LSjc#PMrActdH+|)(lc$+t>Yax67C(go1vsDIl7a?Bf2x|19D$b`^s%`foUBmXPCGH##htUq!*OHNir0p|I za9bRr?{)#vb>&>y`J-K%*+|^#ThEMIy5+r{lLKf~W>Se1x|_ozD=9M|dTl)IDQxQ?S@oC+-2quZ3Y@|BF_>6fb#`0Ww*PjY>N9TFgU#~xQzrUiLMj70rTbE|Lvr-04(DaFt(M!J=Heh5( zC0GOV6jyRo^mLVs2U5WKH-p&1ieZYNhc#Z4t?eq~z*D|%uR&z58Ma`4UBs`G9h7Hp z4;(Vp!*o8Oi)YUo{A3Z!Ql?BL0`izibW3dJ0AccpPo`>4COsP!Sj@p0%C)pEi;EU^ ze>&1sn&yAgyKfEm29zOYduJ~A&TdavAx1;*fh%nZ{Yd*H$m`2nl*VhuaE?UY6pNiD z;m#}wyu7YD>h<>b$c*YQVYSlXN?!66-CkvhiC37Y_X63Ab}namxKk|E86a8SYnH5+ zvqNT|_W*BkT*Vq_vg!U~DXf6Y`WLy|4S9e8HeUH zCDWl&uqGgHy_Vz$E-l-qrWZT4Wqiyj66?wqF{$Xm*fh{ZqsA)|U_$6#ree&}Se6&a z>55xNk64yhfFZ{Z44b%Hi;YrCzV9WcBN|_DCo!LCXP#{M{zx4&w6)P?65XCDE~y~- z-q|*&$iZNWH_A@5V-_;`)Np1~)NxO})pFn5U?G7-DL0o$9Tbs5`q{2J<3lgeOr0 zJ*iZQg(Q;qsP`+DUU#-KWk|%M;qkCDBN?hpg2ode1&~&n4ZpjRtbf{y8Xxm=29?Sw z@163$4`u{t1Ri)Q&f*RH)DZ*S5)3ItLr)iF!D5;fZeSjhy~-x5%6l_g=AkOPE`;{a zqCox)Cy09v{4P+i24WuP_2b~n>+;Fiy2EdsC5u%R z4_RHS(SlM#+&QveWn~5ul(J5RI(2D0C!Vn?)ZZkiH2r+<-Ecyp#o|iLyJy$Z^s8g< ze{yaeFQgPfdd{vBT2)&yj1QK`?e<4iT4~fru!_xu4mZjx5y?pwzTM(X#p`yYO)qZL z>7&}cI-d<3f0gzb!|v!z$q7pty#}T~v6PARxHBQ?oFPCZDwg&S6m1jQDa;7GGTdTL z2a6>O1VzL@rJ}M0ZBBW(ahm3+3^3a}5++TYMw>tIXN0R6xLozE@J10@DqbSY+0)S_ zF5b{Ry5dV$M@7P2%43hYVUrd<+C$aV!U*|%KB6#cZc#HF>MwhFGhxx;CzPXj5XxBU z2#BUbGSbS1e0e#rcX$O|J=T#N(UPrFH=pyFc;e0uNk*9XmT?2iS`?NPbQr{0jmXfi zti{$x@uU{AgxrclY<~_2IvEXQkpj2${6!yMFsi6etM zn}Hd<9345=wr(+WB{%!lwcoD9^N&TxLmaXAT7jRCM3wH>p=>N=8n{RD_tYA1q=LZO zkCV?Qa7#`Zx8DSvx7^@hqeMRE9t}Jay@`w>)HgrP7urWpKymqV(TCJCi*Y#9WCSRf za@f(NN(WFU9z!b@XW{dK&;xCw$aRYa&XhvS{G6{);PTA#1f? z6juk=zl32y*+}R77#Pmm<$a#9+)QwfIn3XRSkg`|WX>*7)HK?nX$wG_53GFQc-5=T z;AJR-yecK???zig+|isy5rOtUE;dauCX5bQ{#D!?u^b~Idrx`K6nur=IyLtvxbiFa zBZni0=OE{whlgqn_dEnP>$kyzg|y9hOgUj(z$w1QmP<|Dw`Us(*m`zLp`hEYyper^ zlpYij31V_D?l3lu_sgC|cLFBWfhJ2-zZumg>IIFsZ~2_flFpGiO#AzBi3x%AQ`L4h zWtU7wg?3&bbg$Gq4C}Usy~Ohw1yTV0-_91bIJMmvEbqVoeD)frS2|?whn*H|&}^N% zidR98K+j6u(C~Dge2O@Cga00XM=z|`9S}33)R}xP%6+2%_Y6BU**3-HZY>dR+}7a-7KZjiya+E-Yw3OHnRcRELhvi7PstV zV&3T6xCD7im4F{r=G~)$iAh`rQM|JG13!8{GnRU)%*>K;s<@Gb$Ql|S%KF$pCNvnn zmTt>)nA4BLwQwv6fz0oN2oL1VzQ@9naKz^J?yd#q3+e?0VQOc!-H_vJ&@s{xMnMD>1%1Xypq zdR={AR&wm%4a}*PuUu}p;eBXYz?wkFOnK#E?%gGQLOLjBPutGAM7fAq@772bt;c)9 zA>MB=aiceO(EyhhOl`!-s+v<-tIubNm0&=dZ845y4fSF-LbvTG! z2MVFu;ER1wGee`T_7GN=UMgoJB(JwpD7SN*3|b@0;cC{0Hl2#MeX;$@h(4G8_vt0Z zOeqD=99@bs=*IqwDFYuA-jAZ(+GT7-x`TAL?s-V-jXB?Wwkv;V@6nbNji>#p&`Cz_ zu}rSU@-O?5qOH8`gIW>;8I;%YF`L$*yHdpy=I#OTHfN(Mt<^mS84@}{v--!QynN@x zm#HiqUv}`|W-I-MgD%3Xh9R}Jh#;g6S%iD zsfy|_BnfOiJLL6%3wUPF56+b7`Lx)ehG37jvUEM^fHjG@(+tSY)$<+u%|~m#t?kBP z{OG#&#BzcQZniO&&ihj3&a>04ty;N0b}+4z%IuBmXXC>DeaEG;%k^D%M!@^Rf>iP| z)JWFfU`ofWi$zLzxdN%`?YHm9EVipuEVqXQdVwQBcqcB|b#tAq#a7?&{~)Y8FgifC z?YB>8Z*aCRQN*au>zpF;k4+9jrY?K1SHJ&>iiAbCD_zOTsZmN@-auF5hPFpT>(7z` z6!}o6k-c@#6@sAz>%7x?sZE2i!R3Nq=cghy^(7K3C z!1j7|qBT^tl1fw^k<+HN|x&EZ!IvF}(rCie6*(l)?$BfpDc5p$zY<W1cm)2k(4bH#xA>icLuIvsj_yrYa%D zd<}GF(R$8mTw`&@Id$oKBDfi88^5j?)?BX4s>Kh$)Qu`*u z?mCi|9M6=yu(Fhurv?^8)+&-$qMJ?_B$nDcKM3RlbEZoaMi7`Ubv!i~aBp`Hj)o@Y z?fH(r@%i{Pw{T(7R5Ri_XYe*;p^MsjmCqIU4K{>8YSM{*CU%T^#eO}U2BK8X-6Nce zk|E7uHpAyx_;*{wD-UsKw9hBg#h^O+bzmpl9u{mK=5jbFPq-S~%WCrlENj}M- zFYg+W*|FKs7h~|6?Ue(R;-h=?Ne4@Mm&mgZQydFSsiwJ92a1E4C-6ji+N5D1P3oYP zE#~$KYQdC|rB!(5lWV1h4K}x}W&g8V-(OzB6JL{C4ctRo$=ya|j^&Z=iXEq0cV$gj z9V*uOXRBT;4J|3{%P`*1Z z9H+MY^D7C`Et%^4Fy5ufIVB6jo)hs88f$J`BHN?ieVXiRd!IL)t!y7Vz#G|&>8CtZ z?8@R7LOGRveyn}dI7>wXMGO1ZpdD;boy5q!Q+n%ee7a??k>a*fIrh5P29?A#*BH@rOJjK;PZ2ZWjP? zT_FHRVea!30TUB)lR8{_`fC5WsKAm|!@%fM$eFm%$HzyAE_;X84AG-lz*oFCRCHAP z>#uA!oa~h}+Xa_h4s0_*FCgx#zuq*cOIDc8{XT573C0D>|M;s5`EJB4 z;oM{P+x4Fspzn4~4HqOzmF8sS8r3CtiVdtG58n%rwDT3bD z)R_7H1Z{v%5l#7VFZ87_Olp5_SMZbl?ywZD+Q{`;@TQNPpz}t?$C0?X+x+_x4T_Gd zruh=+W0FwB`AEDs3yr_eXz1WY?nlKr^CajC=Mz~#e3Rvy+o!!5NOT4ZT5X@)qeM?# z^DoJOTqn4PRHeZcm)ysc8HMiT+mg&yE8)ZmC-oV?L9S{kccR+<0`PF+J|whvvlb1| z%*sE0C4We3-t!~-vb_sw+4`(`RT~!H`+i=IOT5^7@ptG@5*>o*e7*VX=G2t@*AgOi zS2Rp|Lp?mH;bEmC+&bMjdrQ024@o$h)F6)fvm#ycJM zdY->z-NrUba^pV((ldt!ZW|Mm;PZMoU9xX@kw5`Sc1-ee{eOM=0tW~2zaR1$0^p%} zfF1*sL_0D;0aR2dsE_~q;Z_fypekRf`2t^CL@Ndx68sytOl&1c_yqbNgTR0B16y+7 z=XBL=h_JaVhi#S`3MX}mEqDu${(l40{~FltPviT|8kB#=n|JrWllgmU-6XO(bN&`@ z&qJy&Pd0W36y%BSiU{65d?xWvXzY<@o&WU)U*J}4ArJ~7wD8l@RrBlpE$&~2hXxw0 z@OW4YPG^g3muur4uR% zgwk?BT~~$yT_C42RAu9zrHY+GaAk`A=+W^1SirwzM)pNs*Z=r}Ec?sz=FM;q`d|kc zlnVSO1>Gj_;i_u{@cgeu`1qY(ut6ViFvR!7#_af{N9_?#`k<$roaHIJ{X1N-}1%(=CfB@uS?{Gv2xgu5wvC!BvfwY0Q8 z3uA0HfP0FRKBLcZ!*nqTx&290if6K7_i+7Y_tRUrT3SFp(s!$Rv-*3EWh}aFX8gNd z{0N+g8Ha}Qg;XTH>x%)IG5eQamDNpoVYhbEWbwlai)K?LiQji?5w_&mF_p0(am|xC zFbTu2TGP@Tm?gA%BCGQVOQx&P<@o0zqAkx$1LMQ78zAaSK9&|1l@wNFH2pd-8Fe=u zmiuJCI#NVDU&l8RnY9sBycdP-PBNG6!3$!(T1pb>759@Y6!1Z!W*%52*mj-xx#XYf z^@oQDA9}7z2Or!bwA&wO@Qt4yyJI@JTTpJ+*T@&NCY!4QXZagUxc_qx^H}{Qq}Pr| zL!%vjU%JOx`;9dvL1R|@AqhUfz$Ed`N}wtfGOpwX-jZ*s8-#V>U#B%Ig# zBX=X3XBJ{3;d^ZP1SOK{qH|s^(7%9OIaX$<(OH_=D?57DRYRr8C7O7y9p!2~d#Wq= zPenS=&~cvUzke;E3Tz7fm#i)i(ZB}_tK)jx(10&5)#EI7(T0*BS?ZL*7|GeKV()g@ zc15c&XqeXvG>+Q}gOb}>=eH{p&Pm|z*FF)C`}u<=rWw^jcbf+-MA&>3ne~f*_Cb}= zQ4fummsgdW=#O69?avbi%55`T45;`jxj7@l!&^Usqdf9`w*v(4%=gPHQP-WoOCwD| zd5^*U10_a;ib8E{&nyi)td;j@1GJnei90ODL2yqoirf9Z%#!yr5u{wI8qLOAj(utl zC$_in|6&2+ii7IB23%j7S<;5si2uCKie|juIh(wAhyAhQUv8Z3emgrIiP=%C!$LY% z9#s8_m?aqDRm4qu?6#9L3C^<=#G*}^IKB&6L@yNumsJYj#~BQlS+kdyVh&l-{=Gc0 zpIyx8*cPd@t>-CbDHEY9q`b#At~zA{&^a7KGr zAi4gUmM^<0dpx=9X7#d>1C!P|e5ETc^BLJrd?o$?mVIzo)gY;Y4p)S zm}GgrWYb@A1o)E$oRFr`eY|_>`sCR~m~4S^aC0?opAe`h=qpZQGKsM7%NEpN-Fa~H zv-0Thz!|B$pSI`arH{ua)J}+ZSLi-6pzy-CKbQl>D(x;`?Tmnl{e7S!p3aTkQY1U- z?vGkYHz0am&~NV2PB8Vei1s0II}bHpWC(HM+|!U#s*$DTl+U3$m%E9f^y>J1=86Wf z2XgVRo?FjG{xiHM#k>sMXx$AgTC9KRp=Q{>H!jyRt`d$3#nEcp@ zjJ&0|DG$@}geSzS6smX0GilolzAn86eK&9&GaShsxb>;v9jD49;j}`#F+KazxumYi zLE2X+lrh2>uT@9C6M~X!u0kvO4Hv)*hn@%bFYV@+{`Vd=ycagghK)ubV&5X7dkSCc z@1z}l)K_4E?R8Nwer$7^BFzs~pLkKi8f*Q;B+XU=q&nRtcUoFXIa{r%Q^<*9FOYcn z*?yz8)tOTdri8~zQM$a>L&`)SFCnQ* zHsSC)AG1`-mGpag)_upaB=MLjS4?UjCo!d$X48&xt7l8Y411omppz+KZ&JHb9*;LF zmhBTTvV#|$vxmaE3#GMo{l&6BM!4s5-#OUQmsD|;;MOUG$QF~ZzI`fosW7~~&f_bf`kA5&yk0F!)+{_dN5u~WGH3^CSRs3I<#?38K`6_=4Kp19ECbw&+E3+~= zZ}5v0DS-IrRrzFXevjC#M+LUreA8EM>d5{*+slC?7pMlC5&Z-4d2jB>y1s=gX-gD{ zRh1I!GdnxlG3{h+(vtfnr@cCM%`GjKUtP^R-1Dcaef0O)e+-n7cnAu9zLLeERFT~l z6BFwT8k4%ONGH8C#L+)A?4`$CIhB1L^rP=I?dh`Db~E8(7JJ?~%4vCNyA?JuNf zH1Rbgn7vn0iS6c3ul0V?A0Y^MBL8VFduiK&g6;Y6Gj|M9{7=7A4(_jh z6!ToOhuGgXLuadrPWKSbEVKg-e66=G;HaHnGh(9}6CK8IXAC4HJvcU$@33 z{BY&Vm_688Dn9T1BPwgA64yNyo9>ksXc&v4tQhtVYKppLZd<&0Sdi9Ci6UbsOjdn0 z<2RtOMXpeyQ2^{w&b zUQXPAEj<#{3Ssnrnjs~>|2lBTQ=iCdtGnKqAA_*7ng{)X!*1+wQ zRww>=EHRk`shITR=ey_Cp`;A~D_%|s+1TAu$%(LkucVHVDSerIzcKA1E_m#6H=iH-CmWAGqBq|{T$E4%tHrj?c^~p@6S0%nJW9ZKG-Yu0Ja~`np3d@ooqiGya^* zrnuV0>pXvlx3q{ZP*Y=vK$`aAToB)&oOLVBr~YVTM`=O4;`0`RGA|OFWf~)UU-;Us z;Pot6?cd`gxZQ=X%|3ChX8(GS21) zS4<)?9T-JIRQ&#Hf6l?aN5wE?Ks2%pr$Eb|G0_c0#5I~ID9y(Khf zd6c*h+rHF=!ap#ltQq;c1^GV?if$pazbX?0W|ho?v2g^yN79qnQcL(G?68yOnT9W2MJlN8FbI1ROu6GR1tP9#kPbRA=f|Cd4q5Z?Sn`j3}zSv7waQrHA<{BQ6zZ)M@;PvFa%giCZy2wMgog(Q=%}MxcSPMw_Nx(DsfaV@EFdSEM^CR+S-{ey zXdnW-buuhB6^a_2bK}aF41~-M`G0)P{|GWEq5rgbPgOa=^>mir<8`n3*$${r1;Tp~ zpTaw_Jt+6PN&bJK20isO=X-wnBluhv83IIIm@7|{W&D8C9{T~|Ty9d$t=5b{w zl0oLXAesLy2TA1_xrb8ge@U}b@Sj4Q5m<(uP2^EP^uDP4`F?CRHYC3z{zi26e@lYM z_n#GlEyk)${90ys8Lc~l`R0l?CI0`oBK7b5zwrJ}!s7b3!0~pZ5R1Mc4Bt8W|9PD} zPN4ro4dR&v*xZHsH)`ikhkW~R`d5}OR8t?9-`!@rXG?7qc!U@J)eKMuyQaWdlT%b7q zM>Sv(MpFzH!`gC-B-hgcdaQml3X7)0DE5zf;Hp%CJ`eV>IMdH?K%Z3uEGRn-DAZy8E-Qsfc|Lt4})LGqRx-d`y|L%EO2^V0oHLHzIkd|^x~ z_&$7}dii=64j>a2t0qZ?i2exLyf}91f;xMuCRJQv!h8UORf~;fmK;_2KT&SbOU@|67p<6ySM0QzMg zVS0|rNS#_i>#EY&&cJ<3wFVjH1t*$UFIcX_0@;H(M2OHeig&1y7R&?gG#IvZ|L*tn{$3)zPuFv6fPNm}Oh>+cv8S&^=MyTC6@y)NEv-o^b3h)0Dmv z{l*lt=!&uGYU*UjNA-+_g(*lXJk8|Hwtim#4>{Mzi>CwWx260P>)F|1SQ~=mghy=8 z?zS_>|E@?pf?M~zw&+~_`LXrn7Wz9(tfmhi77Gg2%eh{hzIEAX*rbU#Srf>#$$La; z!i+X-6!JStlbOnHEMYv+DCU8qsDg3}{Th)O3(yRM-BHDvT~4uSL3bm0s#)Q`c|m>U z&kW=H5I3Nb_@(!my1Fu^DCy6l38bmaGtsYENTkJ>t35wf@=>cg;GC#Ye?fn%h2x=m zlDJH$Dz65ho|ur*_W!O`HKHGt11;5F(Wyum1Ibh+{1_Qpu`K1-j4m< zx%H6ba}0`PNezHuC<)?T@@YBV4(Ye`R$kpw;N(vrVab@qlKT8dxvqug#{x6zpmfak z>qSwr*HknQH)Re}OpWtuKBHRHIB%}GX22nlzY2X=%+&57>VDuqBc<*aNBfd2*^jE% z9nPYn1#b(U{Zg6+-V?ygljYgT{OZ^nH&13*tG0i2*hlbBl{8ybaZ^Y%+6qPnishI% zDcylFPd819bBii|J=S zZoi+cdrG3B&h9Kc%lZe)E@Sl89L{r$#S-HS|RP_7B6MZXfD4Ctw?sQNUimFUDziwipz{P6$_PHKu1nsJh* zL`19rE+B>+#%j5Nh}L{gdn|47$N|RVeGrwf6<1*6RI@E-jv+Os#MbBc%Y#{httKS4 zGsb?H6aK^K9ozW6V6ytmh3cknR`-(p8Pg%gt)G@&`umJU+b557ztrG&)8;8uVF7Q5qQb_LYG0eQw;Q)ekSI2Kxx@$TYP$ z^?Jb&J^Gh%e^0rr|@?DVY6nC%|a;jf~P$rn81^DvSb zF&(ve(oAKh!W^Ys=1hk2dY}U4KiFa`*I71J$5JKmn4Yw>*!~=&FZ1f@CIR(IQiX)# z;GSC?_AuD%4$lSau(5+S>i((HUfLi~B*EjlI~#boqCX9{+-2U;k>X03%1J5asZ}{v z*vyQ^#!hnQlk7G4))^?wwP(NzpRXy%X?64~lPQbwo7d^JgT{ko|XgQ+Jkt*?u{*?N%ZBdqGlP*pNCtT*v}4F<{X zz@+0-AKn!aTxl@}xo*Y%e@u?jGd?4n7b;CuEKlZ8EI=U)AJ#uqAJVU>1-2<9o+%-? z)e+Xwe&aZgNA;w9FAk4^s^qK9Bmr-p4pxWV*3l*lIrI8E8}?}V)72~s`dOtcDZu5) z(m-%sSL3Tqe56TxRPN*DiMn*`l^~e$^U11HJt=qtjM3)0itwRDw0;0iv^MpM{|<3u zkxNKvaE=%-e{0cm%^{L4QS-w=EUc=CZ+?`k0JeK9smQasw||W+O{%5I=4iyZc85@X z=dieM)@WyJmsO15Z?adBC0#|_m0MHgWuJI6nb7ya5o}gy$KYcF>DQfV`XEkk0Z;8i=?%{HXzJS3*0|c$4Ig=)Y+Xk*a0@Ulk?{5Ajdsh zb#e7y?{luRckeuovSB$1oNnca9Bqv%LQRP6=U*i)ubOCwe*BO`ek!VwJxGzGyZ z37j=X;fw;f!3QUAhT~8E<1MUoEGRrZBKxh6r#y$F4d16#^K0`<^P0yEuBjncPn7i* zu9uRTzV4zXnU)D;U20{`q_SbOpYuntv!sY+ldg}io~Ft1kMyA4sc|?_?_vR9kf&PH z1Qnv(7iPBZ*`-3;^&-;l>G4kx79b7M)jC|iXF@ah#2>84#30KLuV~OIAt0gr;mQcj zc~K*xAn;bTaq6Q3B@dAvC_dwxp0 zzpt#}6-k!}vQ|+^vE1E+S`~^1(`uiWsg3;gByKD-W8Ovz$6)a1Ub$E3VGQSWL@4Di zn88i!oS9GBJ~g)G`PV4IOwnPl&wuV#cK@XXuPmIxbjmtLCCvaETB}SF(eJLA>sK&3nf}QFUcXyFBLGrq6*P;D#S)?36W-DZF(dDG z-3T6c<%?*dSEk5wJ1BCf>IrKu6`v-2CVS}6_8puVv3SP3`^>K=h0k_?zo;N>*ui_- zn4(t=IVM`#JiXl0ONqAR%1|@>h4`N>|Iu#K5NHj@3uv$QBj~Lj9m>NC$AZfH>%3jY z3STs$C7*DwOey~$R>@0hc6jsUvc9&6n0fTSZD@ok_xl(V7Wg;a%Obo8UjE6ekGQ`6 z(q9Wgv$pRc=a{g59a^CpLtuB*-|jZewJ_PeUZ^t6ro+26z+eV^wmypcVipV)8_Kml zaKC3Mk7(1-#4{0vg(IllEp)V$N$^o=4bfPy9V%bE3)R#r=4M#e{#|V!uh1dDZ#Ri zK~{m##?2w?L9Fhg$!Pg(i+cRCIBk^L#V0Ce^j>VKKH%Fxz={^?j-Z63UQe7f48W$^ z>85UzpWi0l(Sg$0osuRVHzBUs;T{wI7nP5XuXc74EgOjpm|04NLHA@p_qu#E&A8&L z`yt3GvH@_5aJ>*)3_aro_=1X@Kb=p!OshmXQehjp7eRs9)#-Sa71Y(SB+F(n&EAl& zF>x`8x>HRv`0Tq#mG+=Ca-eJ zT#-9Ejd3TGnJR|HENVn1@k%R&2MW<|I67X;eG^*O1!xo`Vkeeo7MZITN1-SrxfgHA zM_v1o{I_?_rOjz89J!R~%K8RW(J}lqpgMDqaX}L=SV4_hhmKrxK1dDrmzndqF$|r3 zafM3)nb>l8eObrldN-KJFp5&`H`7OnnS$zAhUCPvYx(iuL`=Q(5x3bXccq6c9mO~o zunrA0K)uibTvjkOTBT?w?Ipj9&4Pmwbrs`=L|m-U$x?H1)?6m(k+4c)>K)Y+{`Jj@ zA!ccjuu?C^&@r*hLumzvQH5HKV58t}T^lPW;J-Bp>V>7Q8nZf#4R^>znu(`_*AS($ z76&+VeBc3a((|bD-QQP9Bg?C`rYA5cWrkMU7-Y05<;)5)T;kJ?YLTjJ!9i5Rax;=y zJnL!uj3;z#R31PoV+dQjv5e*>S6y-DT2#;;mUhs8)^hu!J^6F1BLCFT#8K&ruTtV1FR7t#-OvHJDe(tTD@`9|_B3yhNswG{1BUU2T{dzN2R> zXN#d(a^A9_17JyIs<|~xRSVlHCJOw79xzg4F-s53n5OUfGm-_7`Nbt0DMylEsZ1`E zko`qN)7s!rocl^dp|AC;@ZKYgI*@eO(Pj8F;iT+cmM=bxh9a}gGwE|7qr(r8eiv56 z<1m(94YK&4hs%Qpxmq3;>hvPY$$&7J3`H93y!Qg`Z|;V_fPZqu?CDw{Hz*l)O_cMo z$^GR3rnq~jr(x?EY0HN7z)^yL)K`n zjx38Gs!%Lt)}sn=^Ll>oWfnD=?)EA4H&;w4En>3j1WfX%j}GzjWkmkGtfh>_hqO|h zdNBg6pb<%?7-%UH+S1-PE5Q|pfBOSdDlc*TBq>G@&(nSZkI449V7UjB4V0w$HnGFG zW_y8BWZx}l6Ld_>dq<;eig8V0mUq%F53A>5z-W176YlPRpsM`o*?L#oID=P+iu+0l z`sIh&aEW7qAga@pvRZTiO_)+d<)Vp+9V>B`?KONOS%u+rVsLl$Gpbe`%(|G}oA8wl zT%+Xz%3T}0w0LFYtEfNwf)I6T!=a6E5QwkkT$l#7$}m2PHv7AZR;60&9pJG9O`T6#xcskw0Xr;#j7bS;!qz(ElyJ`BslH> zQhd=ck1~uuS4u!|@R-zWZWZhPD(RIUPCy|d`lA%+p->Xo8rjuK*ySXP$BjGl1~OC{ ziS&FP$XFStA6@-?k0DNmiH(_+hTtXQKMkoTBbR~C`7rz=D5R2)f;NiCC^)g`Y_q|s z71~i5-ODL)_D@N6$y?Hcn5lBj$OS6Q%ZfkbwMyMtvLu#g1Sa8jmrCz$25V+*bvfJ>8 z+|=A}eOTaTS{?MrHC!B9MpaFgy;m=iE$}dj#<6K7^$22gI4HueXNS|4KFdI<(IGRm z=yQvWU6{AwQ)%%?8dPE;Aw9bJ!@fM8c;zT@%?8B;@edC$TDwKgSBp%YPS8 z64bahGLh!A>Bl1{Pf|tR2Z>QebdDPXzuj7H#-Gz&hW-i4dVJ5mbR<{nqm0-D3V3^OR{$1q* z;#ZM7nAPcN@1H`Sl_=_LGs(F!`R^{!fg$(|?%|LnZRG0`Rt3hSBAc*o#yn~2o-6m< z2DFkR^&ix5{P(6(5S7u;R^kv6=mE#o_8NO-1@3_n_%8WkN*oxzBTjOMyu0-*#sxpUnBVi75s=jJWJr7L5a#5pE_QQs`dh_5gxm2PTwXbx9&~*!w&fJJS zLaN$IlM$gohE6^$f4stMOM~SeMkVD`2n`)A1smxfQAZAQL`a(qvenJacpy@zjxRh1 zTDn;2?I4vGMkG&lLZ(DwL_un3W{wcdjBwPBOeG=bp{DxJJVRC5Y z8*ANmX=EeBTV@#>#DgBa5hE&8SJulvo&ny!9_$1_MynCsw?0ic(k)Z9i? zDI4J?5jxtvO7ak}93C>^NL@|5>~PDD?~K5cC&4o6K?qz%HF_3DTSCI3U`YHiNp6Rv zb-PHg+dMh~Y3BB-wR5q(-8oHZNgDmp3Io^&#|aqb4LC7&Y99I3q@hh@7@s$EFtAA4 z5Z&){xS>YqE9a0(^oT=q&(GZ;TS zj6$ajN1 zw#FVI|A`vbi0jyJV;Ci~#S+9QC0i>MDvpm3q3CX5s-9=PsOrY#_(4j(xynOXwoxU1 zh@EXlqCT7>D?Tl^B`<94_qirKG69vwot(s&ck{hwW>D@#)ccM|pnSEgL zlPU_OxVR#TbNhZJNHi4840Z4pdzWV@m>qd9Yh|Q_tQN=QnaszAh^R}reLx7MAU2Q| z=f~^+D@b1Eb&Nwe{VelO{HNll#u%2Oa|2*hJ#UJxH3PLIw-{c45?CPjliBl zPv#nf;pbmZm0`<+M^%_jV9j}U*!=wC4Dj8gIU1}#X{shpQFnQFH@W-b2t5Q2g(&Ub z`MP>_lb^IXUeY9&8wAn%VAd_$C=}Ci7rQ zS-0y_Cpo2T%Dn39BOpHpv|M$Nj6{I8XB1M{GByn+1SGk{f(a$vh@n92k;*#7P(w;p zNz`%&@}rb(0SHlKb(4`&PE1MgOux1zGVjU(8mcgRvz$Hith89;jk$D!k9DTK|7Ji{ zBzJ8iX`@2fw7Y#au(6QJ&)V2M?w)A0A z|LuvAFO`26{vy^Ir^>QtQ;rIZkzSd)5mTAKOQgquRbwtRgh55-|6As0Y#&xh6G-_z zF&yjlvBq-p5kj+laaeyHC0(rS-gkCFAd7eb&LMV;AX!e7RnXk`7b1b2WuVFOK#!c! zKYoeE)a*n{oAe*j+ZRWwSWOSHtHxBve+oi;^4lP9hf2ENB(uNdU4W%U{I-l}(l;K>Uc)0_HR-zYYiD2k4 z#=JKMU#wjoWz>LXvVz?oq2FEVjgK6UDQx=pB-SHSRfL}NjPBn7U#Hcswvo+*B?d#l zgzr=o`6(7(x<9Ju$3_xTMH`)7CF9b{_@A5vZB5MT%$CeZ<5~jFN7MeqDu~bZOAZc$oN4ZIW_4e!Qz-((YM>Udr&0FcLz3Mt!|)JgJ~EB8 zbI1~c3!KY9hZwnIotKIP{FTv)vUA2zK_?v;>}9L4m9QYA$-U-1f=IVM`{fvwysrbdL7` zON**?&mvt((upzH!J>_S90Y?5V)8bsl4g zwSNmg3UQ?<|D1}D$4Ts4H?-UYr1{(2HdLDbG&N@}!aaGO4~d-Q9UU+&p=QR$_3@6+ zj6TjxH~TrSaJ+lVSC1;B8kUH4Xoimi=m^1PkzU z6b0D)?!lw${HFj;an4fN#3}WRwO{4zXfu#=@p2b5uEU6V`gL;?%Ve>s-XlCsU0dE_ zoL~&*k7;=HDEkj6CN3V9eJ3-J#f;Ml1--#jz2wX?c6`dCA;T#3{I0)am-q7;A!*w+ zE{zWsAsESF)yQtCGjqv{mq+gFyj@E~4xXk^&uZn2*2;1*bsS&DtD;adLcb(lA31q?IZ)5(zq^zhG z3>;G`-St7;`(Z%Y%#Derr$K3;HLc?3?F@q6O`y6S(zkh2jYl3LIi#M0C;pukZtnj6 zGT%S;wUSbJ9a2?2d327>O%Dt+MkY(VoZ{8MGc%4q75)NdfT`%~8U#}l?BDHQs910< zR2T@23GWxP8fD?RL=a~(quzUMw7YP#dG3N}KX*bYe4_llI!wiejMvW^frt$_OV5Ib z2hEMw^zclD0jNpd>v6nm72;A&?3sNBz^N=MPUAXtM4dy^<214b)P`}<(I_m_U_j1kgT{@mfMjA=!mX=v(Kk215yo@)Uak6ZL(-$Qr~+VGFmM5rnE z(XXm+pR{FGUx}4iTlyQ%*w;6moNIsXKCi*|acdAkja3>q`Ad;3Db;eX!g{X#Zzkah zLPN*eU@to)u)R3qeHtXcqgg4mAzbX>GMEiTDJY+2$gWHzZFTHI(JU9gj(C%jxQYAq zvIU7itcmv_)P-JonDZ=RS2@b$1k$PGXQ!@`)QUi#iJ;#?G1agJ3+!*b)Yf2qfFK>r zfySZ=TGdbXuoZ%c{dfumDd^vP_;;gPygs-{3g+Y79CTdJkR_{sy=eQQbcNJBAV((b zY$3J6AcbvKulFi8g`B2o_SPIYw6#s)Rlyo5Cduon_Z1y)U3gm6&al>raPWs5^9sq+ zst+?%iwz6L(^#1~$yA*wd6c%T424~|KSGPJ{jugk-S*TJjB zr_$(wyXRzJBgXVwD|>t9;mW8hzho7k-mJ>$W4%_lkPI}}6_5ZS;-wjEq868neh-;S zI{9Y%-kS@SXspd*oGVED1&f^M-w>$QEOA_~2r@cQdU}?55T(p4Il6?|m3@^iQE?D% zgL(94)|y8N)pQRbM3JLb7c%y5YOyrTHpA+;$TQ5vMZ2f8;~UYMyrn-9>c5BC3bQ<= z2PfMplTXV)R2r~kJ5;Bt>&eYBQ%o{MCdm`QN`^qwQktX?$M5+(#ftlERE(WFJpJqP zdI{oYGvIEUHyD?PvVGXN{%zF<$#iD=B%|ao$N;1z-NGVtQ+|3B;Yv8+40g4S3|i%Z zsn({h!?2m8Wn|zx-0!g?_Esb0fvD^&Yt??H^m6_<>+;dq-w(zwD(=CmJZ}|A(p*_* zzSe>A7d^D}QN29O^X}@pQ1GSBe>*F*vBRUuw}0^A_HDdwd{+47uQF@>;oOl- zfN*(fbXuS=M|mcKn$ANO%MicFbfv)q%N~*(P?^6l{-{jn)63|y1gctxaogBaw7;K? zwU>;?mod!3NsqG`Wl~z$YPxd3rXe|rTH3#^yslVQ_?OfnmwjZN&hdlq+%#!~$AM3| z0yx(4=S5mf2Z!6Ed2NP={;!2->CEKuvavDirOW+-7Q?x`R}KY&&8PVOoO7>VfK^8P z*`CX%Ut)k$Z`yHKcEMY=FW0w*d~JjlH<@+C3QW!sUs&!R#e@6oC@~o~0Vrz!I3NgN zFkBvlb_==TxTwgD?>(Mk^Lnqn$O6(@!LX0ykdm#rOK-|~+0{TG$cU6F{fH#TU#Yjeg+j`ML$O4P6xaWhS_24B;pnNbO0@ z&$455T2CpR1I983h{3g!g^4-mA+d1{kSjXcqtY^h_j_s)uegeHDDO{31AVT#C;a6+ zYyCPhoS|bD2NaE8DQrq^ASw%!cwuu%HWPG1=Jkwrt~PG35xe6jCrU zUau}#>6;*4CD^AqQOqAA^k&-x4ST|VM<+=H$LH{Yy&H%J;E8{9`S1p)CK;oR$$Fj> z*mJ#-AElkY7IFHs{v4G>!^ddK@z`}yP(eY(%&Ul{Q zEUL#J1gA@jV`J&n5Vxcixhw!V?=)@-6%8{zP3O=H?pzwC$hqr%oPi~7)P)sO5qU9MZoUoW_;P-W4YSWz{VW7(@9{g=|2n7ZTR z*RxkQplP`|e}xK(gD|5KYh~z@&N^t8gaYpt@FE^dpPQSm^c6~Vo5&oNKTiqS{#7}c;ro~JU8pM)FZxGiGh zCfAmaPgwGv`RBUXilZ2S+|VclJhEM zJ+0DnX+(6`6J6{mE$Sq`-LsfGiYBQq+tlRBf$!O5*uyR-+O_tR`=aMs-h7GK$^|=` z0cGXIj-qY>Y844IV>*wGH`x5hvYxd=vug_&O%dt+ZpHfbW8VoS|L%ShT`1<*{MNxR zWYZ}l29JsNm3^zDKf>Aj$5&-nOP=rirJmW{hu^r zQ%m(bIy@Z5VxI4@2)R{h5h)rkho)*~Av(MdsnN@sXmH8?t=GMHa(GEOz$bmg@+FVZ z;uqfrj0W=~hsN=VFe?W6Yv_3@du(dFZOxRC7?FgtOF6$Jw1uap{|xDUgs-k`CEp*_ zIY;51q!<~tCkF^~LOE@X#Dg}BgUF!`MIHXgL0chqn`@b<0Qu~#iD3s(De;oqDl9D- zTf6Tiiw$&qIRg5G4hFIu3@Sf7wpngWH~|G6?{_ZazK$qAIz4A<@)xU*dz8rDc-hzp zI8WKFnGVYT+6puS9t8!P9sCfsaUegnI2dehZpg8(x_RU4Ohi^1=lgj^QC7$wK~?b4 zlP6?9UW{ne+_Ps3KyZRlvd9u8y%G(TLTvGvI*MSLg1}sfbDI|AXjly|pOhL$`->z? zIweda1EDpE$=uj9A;oHE;2O>BBf51JwZ5qsSIV}%Fd3)k)<%=?w6v@la+a?H5YK@J z-X3vyJ8I$u;XvjOsYAfeKmRN>M(w39)+%Mv>;rjRo&gn{UpbGGJcyt0g zhqvI0Z+i=~#uqv)Ykeg`KhkOtaAzDwjG#YuA#!m^o>fjXRjSK2ibddFJY4lvo_Yi+ zDzQ=vOz(aM8hi6CbSOcpn+`@mG&DPAcW5!>aT?(&QUe!Y3|eo-e9-4W1*AFNDkhd4 z?D+F?0pgf05&U#e2R&g%fd}3+ zi%wG+(+YV0&oH!R@Tk!-8!Cn-xnx7V?4BBn7!*mh=1ZKg>gPTmkI9&`aCq}lswVjN zH!3xGy1EVQD${>{YQ%E;c}OFWxz=3RNjr!XnLCB?`UU?@U6g7P;Zz|w*neZ>Ip`j+ z*r{aV#yGId$gMCk$rW^Vj=0b>puLUqDAeb8uNGb zloQQBS|kk9NjcGWkx`cZ@6xHMbEk-QM2hT(kortV72$j-`Dni2DT3lTYKF5PhJIeY zxzgB7CqdKQUu5)U+DUw{{PBGtGD^Rhfc*vHd`i;^2QxKBae;7Y@PrmIy!xahNlk62 z|H6w>0Ci-UNZ4Tombs#0B?_a}Vg0PK(a(98h0(J?MYl@$4bH_r%HK^cqO03vM54x= z{}kPt#kmfWlR^vS-85nI#*olL%DGSW5gTl~WV~fq?gn8WHL|+8e3w7~lPbs(>STY( zYgWTC{eb48o12rUs3X8*qvP5fx&~uGbI{dTa zgQ$RoYKz0scVZjqxp*jcNG>iYjOp=%*#VGV{|Vss`5={59`CXYIliumIlCXbs_XsK zTA;~Ck7mJFf7=7N3N^Wu;b)ij-Ulol9M9Pv15fuy1=bwPRF^|+tWI81l@7U zIn~zoB%ijoEET`G{`4G=6kj1TfJ!R?*o`6J@6(zk3j>Zivi_oo%t}&db9FSs6I304 z`m%)XMz7@M`QR#k<~znsSu>U{gWSkm($Bue8iQwi+|L~8I7|D;&vA5i3BCl!)-= z@knxg3ziN{eEWh^=vKYl2ZBRWJ2lgGkmf|v<=B+N-nf+|d@ua=EP|YIqsTh@U45O( zxuPu7>aGSIWOH44%(HA(uW)m}YxYZCP4tu<>t*#4ix$RHvukm1#vSrKfbq4?RM7Nj zOEhCL;iFn>*Wh%PF_wIFd~4tr#hHWO-jFrU&vLYr1(+scpt6cS9Q_$GDUG&|PqWre z#rmbncja#uUv=g4{ka`@ot|B>AkAOhYXf!Z^s|d8aaIj9HsXxUy+6l37DU0>@+Diwjl-{!&^ zomN4qe7`}H8-c;{Xtk7c+J;75w&`Ym78<)7YGzmk1QTddfd|p%!$_wld1;pH;|3q)Hbj2jg<6+f>UAvXQh$>PXO{ zE8Fn1Z9%wMQ98+jq-e(e?g5pt2zvI>^ZDw|o^eq9g~t6BoGmryq6=eJf3zs_#BsZEfl#g?oh+Zgv7QLpr)C7#u_L!wK`Sm?F@w zo#8zC&LwcZVVLfIPo^-e*lhDOv>U9FGk`EkYXPhMU%Fa%Ffu;2F{x6%Da%_{`&{jP zwTojPFgX4>)%~qA{nrAw4NWBDilGvj!$U0YWyWi>h zvV#(~>9GV{FN0PLG~P`Sb(0D#nzjBI>IrFdw{PEG&*n@Sr{3Ne7q#%hckZHFgrkn0hf4=jphImU2E+#zhpj%x8SZdRsCj>v=} z!?jwc=ea|KZ7zhN;!tMAaWuM_9cDqvTnga@T>YU$2-~|Zt#ur!wc_KyxYQ+&7g1T# zQxNafpx;;Oot}+rgEL;BsvWTc40FlrM~5}8^m=EK=7^~UZ%GFxw%uvJu=mOr!HUQa zZ=AF84&V7{gdbN~9=1J0$>+y?kFnYYFb@B<@_3Y*_k2f#YYS2)*0=Kd=W?yjeD6!H zTsk>qhH=1$N97ISX<{vv11R6F&-yHiR=83=?#*q23ol62Qj^;nDLQ51Kz?$`yJjo$ z7{>cS>l#`MXQy{7M0+-|_eQHE$DSzXaT#6*OYD1Xo|icKJ#i_ku!%9V?Ijc6~+MKEhRyY<)WYO=+k)SKQ zsSUpk_J5NPhcaCm{a1#v%Ph7^GMI0448s@w6d)bsIm?4dzHZ4JGWkqT+&#xR6a_dI5&sbW$+|p8C zZyI}VkwQpzKZO*7#V9d+ek9}0=ShLxRWKF%?th$7;r_RO<$FD^pT90ceSfrasRvmc z9P2kJV?Ev7j@ad%plLGNV{SLTYSfD(JP7lZ1%Izj`NGS0x^DzeNVea#Up_t6*#>S~ zgV8>ZvBAN8JlVnayXJItQ;bRJgSBHAZKviL??kO~`PdhWJc{G->R%q~nuAHw8DXUX zlTNvvxVt}0lY_V6f9@m)oZZQowS6=}?g2B!m_*0Jygf3a&H!@UvEZP9xGHk&41KW2 z#hi~l#xL_EqJFEo+mMMo z0|T%6xbV4;E;QNWPBQ@l)=l04L(9{Pz0Wff0 z=*v1s$%@Z2XueR+Z}zW1Tf`vcQhIrBTb+oGgIBjllO9;Pr7vuz?}r87NC zsdC{2CoYK7;Nl%tvZtP53ollkGXta$dQ!0IacWB!DrJ^bPS@v{T~v;&(ko)`j;28# z6CuDSGFaVSEjchT0VVqwfbcAyDP9(>!uILWwIN!>@5HD;-pWI}|riRh}Ql-o>+X2&gooGHqxqaLrYv#~Och(LaF zBMq@IbJwfz>Zt-mY0-~WnIyt=;&OYy3J;6ob5(((m zSrR8@)_t+|>#Pkp2f{L=&Jr@Uk{NryMNoJ1W;HMF!TtjreqKJ&HX)8Wr2-8hM)ds7 z&%2Q~dc8W>9EkFkCQ%I^Rv|~y@rdaA^qk`K5`^3&&0x~}xqN{=W1tn{_49>zFlePc zV5nZ&G4qg6iXJn!z|f;JdfVQ~KPv3Z<@kKH*Kaz8_X>+HVg7QrpjFo!Vl)vaO1xI2z%Q+sgpp3o0kYCwHS>Ho6)cF|Pxu0W)_@R+WYIVtZ|TzVlz#D$|ZSODrv>{b5})pxUPqu+1ux z{IHHH8|WwU?Pn^Fsa5sO*HORo*fG*|VOEv=7@PIQBZ$BRa<=gOn(Zl#GjRjztsW^UA82 z;3zeEkZEyBjm}ew_$#QU$iO7=b(%RF93B0@QkRDoNCqN0L=R`7Pqh&cw)0nXRrk1)|SkRZe)i zyINNJ@2Bc>WmFLl?F(}5#2CE!P;@2TIam30hYy^aSnVD5S`Z*qyzDZKjTEUabXTXZ zwG7uLeXgjKStJQei)<{ryOXzZD^Io%sbC((A_3Pbk}Ee z9&jVzld0t-Ir)MW@P?1hfmd^*?bS^=EdFHUZdZq5J4QQ8&!sVf4%h5hoSFS2LnF20 zBwEhDW3G(mMMgmZq8g%J>0{#}Wzh^Hg$Dg}V*6oW6Z59UAa4`*H{EhC)LNva>srcA zu)AgGZll{GJFtEPV(W>K08ehwAIl4R9AA)atFMh7QFWFQPYXwx4n`~rx#c+ukaVx# zXMpmjYQM&PyUkiT;OgK&0tsRG^ehUuE zKWx2ocx2DoHT;{I*tTt(lVqZfI`+i2olI=oww;b`+qUgw-kkG3&pGdRUEiPk>fY70 zci&ZY*Q&MdMR=y`1lwTI;91Kw7(S+bzJQyeK^2z`bvOFRlwfi@1_)_-b~Q?me%k10 zi%6oKY_uJ)CGX)!5MWycZDJX#I>fl}qD4${+UclAa5h6OmrpZU7i8f&oDRor0 zFD2+_l}$Y{>k`0Ii;&wth_0-w!-a`)Hq$+2F?C`I2hnu#`P;|<<-Y*pxn@4g(fXTl zQJ$bc^k*#;11Yl4_iBcwRQ6|KX12JvarqC}x6zKI$^hEIg1d)xuAwNfml|y%7X=zwTH|U=|&16{+V8iPA5Eash>gi4D?k4-Isq zp~Dx*T3elHvqG8pfu}SYR-whbIoiwj&BA0<&rI1M<%c&oIJwxRhN;oA5T|n8KfEu^ zfCe0P2a1!E&GUYnCH*ngc=fejmopRh8%T)t6)Xt%Ype2U4oeflpe zlN3@RXllCLbC{c1A@pYY>G&(ynkI_zE=OaGsj&KeE6VDH;Fau*Mrum>R5?%ere8gRV!taj%W<-@V(hDhN6RUx02*QlVe5)?dPHL@9MRFq!{WaWb_yGa zn*=;X56a_XK3b$|R2cvmo)LLpOjspxis0}vCZQJI1huF6?F%x~DbrrkdU)BITQ<90 z^kIMNpvVkhC= zl*n6*&9#NMlgW;dbYyfFJj0A|^>lk5g{7YrXo6X));!uX>P((w&$^XbQKVQGa*VNkn}cNK$br~j%X5A z@g>8n7tcF?prxi|vl|n2wnpH7?hzMAyHH`MX0j8VAFx40uw_a(@p7Z+1E z%KplK6%8s`)M0+cJf%vS9}f8Y^Yo2028bmV+FiNv0JOd>T07iHh-}e+*0U&mzdJH? zu;>gZn;3F&>B(4eu3C6q@h0kj%t;eH(xfgk+skdGB6Jz3Rc{#2aAnCsNr0)FjT|3S zRxH9CZYaZ2De7Cr>(!u{w(B1&oA{mN3NChFCMowt_6LQRCBp`NXt}~XDJD`WX+SWZ9X*tJOf^2Q4!pQ zCsM+@DVAH2Zat0Ku4HlmR(aF=(uew|(SbNQ^Jhyzx|272d~q7cHl=?iIt^4UnO}X5YjOhvV0)i{6CV%gPnm>f{nR9nk9y5CZZf&JaUm8D-#yD?r$VO z?%BcQ;*(Uf2>FiIa2x!HU99;TB}w(rKt^d6JGtEc)vq(S2ElQT=wI`;#)IV0C4*-z zKtiK~Pun_u)$dGoR*M7H5mUJbMh$+Q? z9Y^gUkR4x(nOWV}!~Ni#s&(-44e6ZYB)Vg}_5~XalcvLBgcPT_<>7C?uMPL%7?6i! zwSOYQrfCEip4+kyHSyT3IKt7gGHo0fOP1qRSfu=>h%1GwfBswRvUnqpuS4j)Sf3t= z3-$zIYO4W=#h^~u1y%s@!ca55!~f0!u4n3#gVA1E_f)n(?sleacx|;w5(Vg5iM&}{ zz4sl7TyFB-ji-X{I#`b~B9ZCj{)GAEjGBqy;!7QkiCyx`HXV)KIx5Qd%ZL$#XGJ2z zz_^c$RK>>kiS!M5YXCOA`u{kHA;9PeW{Y-?_9)rlixZrrzI6kTF}b}b0i*l2-SjKt zsF{IZp==sWQ)VFWYjI6?O*IW;1rmCP|G2h_US8hWH^<-`pNFN zl%_7vfRC^)X@{}fW)0WrzeOpX_ynPlkqJ{2^TP}AEU@P1{W)GN``1H?rv_UDiAvU= zn=(iV2g&Om4Edt(JQP<4f~1tbJJ_rU;>S{^`&kO_YRQokVkXp3vQvq!#unZCjq1nS zZsg>&OKAv>&G1OrDnO4=#D_|Qm48_2?kw`-cUeX@5oWqO#|hJj7ODUjRio;)gk#$$ zm8Onj=*vNv3rfL!IwfEZhXTh{^;MqI)Of0UEMXL$Mlu z$ur{S?-O^K20 z?{?RxMnHem7skLwLq&R`%e5s4oGqxL)bSukb>L6>BLa~{h2|+g6W_#bNhQ38Wjj3F z;h9xYRocCy!WaHXZuhg$_?HJ`JL9jKow}?!bMZ9KOUdMYED8cC^@LTI;tRqbpAi>; z5$);7OCvlgM%Ef#4>(*qJx@~jO*zz+2EkbT*?TAEm5&nlMTdO%UudL{ly#gck|%kS z??CN=y&rlJ9p(Xi1P#=C04Ze@kKRgZWRbbB?YEuFpH4ckN702k6=T#HijuO7?C7^; zW~yi$^gg|Q#Tee4QnvQ;3N0~TDhl8Wmwew+ki)O<{!0V)>jYB_fx)XnvY#0^8mhPZ zu;SVjI^%(7ze!87z!h)zSxbH2TplW7xmnBo{N^b8)V)QA&`Z;32;HZB)rtgaZs$pI zO*tUnZ+YiNP(Bf~`3dJ8b7N-1KC`m= z%!*Mw+2)7Idq@F8$I7J!8q2Y?l|`Asi5IHy0mQ|w@|0S6yDhiCq2Gu$80c(uXH}_Z zwc96`e|)?l?}sjtQ)Gc=Y&1CYH@g-luth*pIcXM{M8~}D2iq?N3`(H_P@s60;5gS% z4{_8ie%Xa4D0Rqj${BAKw#*&!xAQeJiYH8XjeeEFdLql4wfaV#Y=Q^cBqyZKW9Cay z5hne|K34z*lb3c7H(mMG3JtegJ@2g(w5kS1lI@!_p41dY-2wOwd=|HMiRxlvY@wl+ zK=Q8=NufF-Y}3-yav}qsDo#$~)DH2ymHTe#hTZj2c@`x+KVJg*?bQ`bA62hUcWB-Y5Rw^rH$s7@~QKu}dnz{XHts*h+g zaldB}^F@KtH0C9nBg@TK0ikb0@O(36Cz?ay6xXSpQB-OkByW{;^MpY0iys%yiPRnDecg8 z5!sKl6;nnsVDkycjyw(m68>@iAFdKA#pzVSG7xZPOzc-fVE->%6%bl_dPXk{>sxa$ z^WQLm1F%Fd)g^y)_D0V{?cR+w=&!}UP8Q9c(^zzbMySzk%v=Zv4|l%du>AIvTXqm~ zu8#(5Ls4^+n~KYPg2F&@RDXNvShf$)c4B$c*~y_$EuqQ~k@1hy;7L+4cxi^Fu_2Dl zOCr2ggNBJROcxf-MbTJ&=2cLXF!%^U!A|PWjn|9lj?WfUP+(FKx0UdO*eV&fx#jD@ z3BZfcePKtH>&Q4(T8qDpT8BrGGa5xT9X_8SbuXBJ`BIGKNC6)mod#QU%=k!L zj-NAr$In0LH(`lwb83qxOAvUnBUtbnkT!9iVNZGw1!vS1P#Z{Te{BjTl82UHs}M71 zNiJ`4SVf*%&Rhy&X3-zH5PPeWeSCW(({#1Hg#Km{i5CgLeJGW!P2@XPQ}ZL^ixtq^ zy}0mtL!`GCpxu*Rz+*v)Dl!aVysKr5)E-YE97M8JSCgkPRbPv&zUA3vBwJ3zf?B;# z0Qal+IaOI^WdNV(Keo(>N>rf8tOg$PTOUlK@}ET)-p|zY&?dURw$_y7vVKM>H1saD zfc=QJ5s*`R(O^XbQx-y0Np8>!Pqy94DR80&A9@m$UP`uKZ-|O8KN2#kM3bZAbB!5( z?T{aLxHD|Al^(f>7Ttkq!{}i|BpzRhC44WO8j>fbw+iD?VC~54%p*P-nu&#v(g%84NboQ1Sz)sm*4Yy|nSx zHngzb5?KeFpwGFnC;G*ONz^eZ78T<8Swb%;cb9b&6yNSL*f@r2p2SGP^A8MZ&nGXZ z_A~gAMihvz12?{1PAyxX+E{qpMK%W>Yu0)i$Ptwg=aljm(o1H*hZ@U1hdV*bD&5MP zF&4d~uhdYd`5QytqPrBNr)PQh*k#PBkEo9O2Z?4r({X3%T&73@{?1G=lxQ8_<|Ym$ z@2a^n#qyW-GUcT5%D{31r<0_$JW&*re${cy57#E`PEDUk*`&4jl5)_+hMu?JiLV)) z91&x4du5jB41|Aki&*Ev?^&06P4?me$`{qJ{=ntx@r9Ir=TBwreW`MEPy_g2wcPdl z6}3ac@8%sllZ9@`1q@2a6BSb#qYd!C6eXZm-bzSvK;MncCA-sR?wVe-Cq&Bhi~WrvZN zK_iynjuX)rlfRdhg|op`(hSA@o}6L6!Es#XS6grc@-ozdm_hT?3X2RwfsCr|RUZUX z=lIZ%hW*@H`z|E4l#^h0Q>E1V?O3d11Rsb;W_nLS&`;sO zBq`>WZ0IeBKGC{1=y*i{|E)3OWqoXLZ%uN1vIW8|{L(vFsty3OS^@1`t>tQ{EkWzl zql-xMNk#WFv;O)kY;2*7fNB0}ft|S2|GXf7KGiQIb39LAlwq2#Qm_wKarp-8t{e)+;-eVXGSm2micBx;%KH6S1c_Q+Fa5pL#J zjc>F+x7vbdP1dX1D30Lyo6Ho(ZF+7Auv74>H7Mo$$rG~+khslB)aShpd=}1EDy1T- z&8G$b3=CT&q zx~iCjf|Uw~wN=9iVn3Gn)I!iM4PQT)tc5$K*7jX_X|A6FU~?h#$2rJu(R{cH2h0UmNfOJc&dvLjv&KP`DsT$aMliHD z^O{f|hKCt7Dv5v#9pQ_SfIyyQL9Edk-GLZ7+nDW~I0bIp^{|FpH7L)U_WZvA7l7$! zE(M^KP$jD^i&jf17-b|{;6#vm$fcQAErWYGoOofJ92$l966_E)`S1Zsg92`?d-(=~ zJ%|g~t1Rmr9VcJM> zS5YUA*f}UE4E{)f9tpsqTW8h`os8*{qBvJ^w|Lg5+B5ydvV>~ID2^`@m7E?o8;Ewz z=3Bp`LNc4pDz!w20V@#@V%-~6I1@(PNRN`cu^dCCgyxtiKfMw*5;uNe3yTbq>$CrS zq%sG}OB*_JJP&2Mo!0F!ZHhG|ETEm!nETVJ%duXQO$`5>4b6< z@{|j~AW*_YpLNM2`W$icpK&+8^+IH85$8uFf46xXWB8H$HGcz$g~)$|(#Lb3BTnF5 zU6YoA*;K9z3|5O`g-&ZS8)ICklL(a}<#iVp$HjzH%h+hYF*2B zB%kbBhP}a_n7Gz3#9M_E0@dx-!GJ@ez8RUx;8-yRtbmu#>_u^uHknaN>Jy=W;f|?s z)vP*aB^ZZLBzhJn5XHSbU^^{A0C^o^77J=*;KG^VK9$T!8fL~M5T4E>2R9yF`!@WF zfHFA2rE5T6CUfZ%=51`f`(IPwItY5?_{RT-hl@|N{O3N)ZEN}Yh!S`+f@EE6eRO07 zTw{C6loZYF}YT#kg)JWX4-ee=xGzvWmIrj8n3Y)ZJM}9O;qoa z*RFgdNK0JTsJrPmb=v1vt4P`bC2CUX`qM9(y@TTv2*tVk(^-GXqMV)-6b=O2+n+{g zfhy%N`L^*1Ze|Nn-rU@=&7vBqWedzp!GbyM z-su8y%a~D<1?P??kEo4WVJZ}K>-2ogce^RFCaQHxb~khoQx-$PU^{_~Ofh7zrKk!Y zt1K$&!`XQ;v6%_cT#N;Oq?RaQa-(pdQ{p7qI`m!MtZborB^dT6>h(~g2n5s90|ufJ zv@Tg3nK61J{M3AkCC>tjiHq1&e{PG(`V;IQsef55YmZJy7_G%1o(n54tmIC43UR8GbxwC+MVvK--xZZ45j8y5Q(tjE?;xC{VD^##q z3dggW_ZOlY^=ngV)eI%jSqz0I16AuVZy!=>)B?@}Sq$w@EZ+DIIys0HEBPtM&(8O> zPv3tLjP#!>&)vu!ZEwjp=3P8d(Yxd9GwC$NfYlg>v+T9{8z55Sq<|) zZ}&YO+AuNa)oMwMOk^ku4sX5w>J3$?)`Yvm2%Yq`y2hl56Wv^9$eR9Sp^i$kZLJG5JUl521!Sj@*NyUsE4q9pL)`Rqc|g$X zuKGNtjvRbd^*n}{u!xB3`!alDG-KzBmd@Ido*pJNe4}o{OI+U;q>hK*+W1)8{7WEj zKp=9ts-9BYZhX%_TZLAsi-11_IDnLaABp7rJi~cE7`0GFJN7)(1ueox_)#qvOH z`pxl!xzZ%UK8;4C`NG*;lWfn?5=DUh)vnMY?IRV)wJc49MEA#G!>s-j>9 zzT%W8&aQ;JYm`$tX3f#N$fY z<_XtVM^AGuEI|i9XR0Bm%j+m75&X2IiOyH`9_h2j%tc^ZohKvvR{G90y;Erk7EaiU zsSEk>YEeVl#P3%gz@)dtOB{?&Im<=D8N=frq4MOuo|}W?f@|P}66dxFOEh}w?k+d_ zhh1~DgY$w!5#dw5d9k5IZdtzK zLCh=Q(_%&KoHmoeDxUUpy(2sW7D2z~#^P51c@C#!Ee&fee4oMY<+<)|NTk+diR=VL zqp5uUFe^iIQxt{ioBX6=(rD(;^dMq`&++h$4p%T%Z%9{L_Q@WHJqKL^)Q83SC!=SD zEA4;Bx+>JySYM^t&&A=Y@Y$~MCEaYx!Qry~0Y+!!>K~>=y&tCWfw58Q)8F`Ep~mEm zLTLecXK?pDL0NlmJ8dC?pac3l2h)uXd5N{X-57vk0at`cKe7&S~=Iy1Sz_HEcsM3$TH zmJ#=`G6yC&nG2}q5es?cOrcsFlc%}*v+ke9bPbm4kcl6>OeQjT%;am#)($Q--{r5S zo0inA>=nQeRhx46?lt?9EXCV8`A_62LdvIh5Y zjJw9&X#^dvnx*g2!0YV|8rdTrz;VikT&h~J%2#jRWUE$=QV@XHy}~zAiFT&zj8FG` zXuZ`wI%K2E`4b$R%IA$Wh9FLQXEQKO_@gu)mhHAV#i#BZg`c@O+Ft(z3_`9eve8i; z216+izHKlOpEKmqV(ib&M#2yBdj5D!#NMCJ#4$L* z7M%m329O3v7WUNH9B^P6+6+lb(q?H}zE=)9?}q~jW9Yr|H(=v7=D>9*Nn1$u=H{#Xh3sNE2DzD&tx{S-6`{CmcjEtKP9% zYOFz`7LT?0rm;>z9e3|xn;O+~pGq&%;o0`9d$syQCawC4SYFFArK z5OhUDcu&KeN*9*16#{B(y5*#Kt-C?;syvT>qnf-^FT9K?N;>mNX7IevnhIV1L3ww+ z$AY5)+hX&GL09C<$OMdek8$k+ulZRXb$WL z`FD}te6)Wy>+v!>YEAYs030naSkJ(P$a|cPdDoIE3}<_#B*vTzuL=(5t74YC>Eiau zTpQASJ5=qS-|_Qi>=Yapke&C4rC=9NHiFA2yuH>IYb7-kHL<2 zw8fA{Rvh5Eh(E;x)Q*o3@T3GVm%DMo-cFpo8XfHWa*2Z>n=zFDdIJ@XO9R=9Rc%RI zt4~GlRtKncQGfj$)J5It54tq=1pTgXGL!D`zQCT{F{s1c+ujGmf!B};xl?63;R&IJ z@A#8HUdEX~ezak0_K6=(u}DfuBq*3Xqlm%!5s_rie^h^--tKC~SYxz5HJ;|2<&gMV zqbCmwaOK%`^}y9soyc2}BSt%~kHWSBD3*4|C*Xr96rmpxw~yvCIi5nK_*QsRVfg)k z3)#Q^BFLQFhf=CVAmQ{53|Vu%JjXF+(_-n@;t|OB>z%diuY_Q11Tl4f8N|4yLYGA; z?Nh;SwOZNNP#AEWN=ioz#Ndt26%&-OF}NDf5EWYFdB^1528Z}T~h-L-%SbiE|SRHN@jg0Tzmt%}}tO#}ym6Ww+94)6{ zkEh!wl)sqI`3xAQp*b9-p5=%_=Hgkz7P@dl6w6YUSb>?*( zFJ9n^&5uP1&;=A;q%r^1;#l}eCn^VMMzrgecWhY}8s4`KxFvYvS zhc+oYQ&ek+`$_sqUj!6?`2d>_6iEF_E*a8Q-aWny6T|7X$uDMcIES7*_z2<-e!Ee3 z#%x0(@#1BRG~4X@;m_kGEF19?Dm)EQZ)WfpoKaW7)6;<)ALz#z<58YO`ai8tZ$W9P zJk~I~%fA#Hzw^|CmrMJxtc2_cQORxaPq(;k=PTsJ9fwE(4oBjPOO$Z<`08^P&1cF2 ze_|QKL5Gr&V>6E!am7TO+$iRu(To#h?JHQ=&6dSVky8r^JH}#(RHLArO2y`Ny1JX! z1Zr>3L=nDl>9StR6wg(A8LTGxBnIa_-=h6{SN!kD-*)=Cn zR0YP!U_RL(imUFuE^%uCraX6|bM0oP!)L%Ytc>k1(=H4or|j*}fjZ{%&*^7Lup<0v ztJ*Vm{N?a91A!r(GA7qGU|`AYyXP-J(l&N54z9eXN zY+3)>uMF+UW|?C9R!bjuC!3LLM%ZQlO9SSwBJ8n;hQkL6bds?FRcFF&Baoq=HM~}D z5jmTNH^fj!VC!@n?l)?p z>axhN-tDbzWbV}!M$E1~Qk1xw&s>D&8=m#tZ`jfn&ff!T#?0@ZQ%4??LX%}o$(Cn4 z^a%H|3h7oh?5@^=b~wzX#qLJUNt_}?*z<89lUjGoR?HrG%wC+edMe!)SM|SKVN_}I$dNG zGWq@jiduZ-_Xaf9CpkGdL`qAWF%s&Ljp0o#R>LHK4tj>nYc|_=t5MIjPrtxBd6?;M zQAll})lmH-0873TM}TER|IG+C6oZ-@z*b}*7^h^fF%{yb8XCb)6uVE9tV4h5bPlM7 z=;X4fs`0q}p2V;@G~(x0GNCN{oAa7U)=!E-aCGTRqU$$2)qaH}cM$C_`-T)|^?(f- z;?{hyjSd4XjfLn})Tvv&YMqlC8SPU{ZznjJ8+MxiqBPy*|IRboocQBz@*yFeuRfk& z$~2G>oXSHZ?yMX^Lc5hnhUNPik0VS}${u7cu^V3oRUr z``xK*{}@1*j*Hv>tf1X9SsaMAs5qPUe+kaARo;6xDupSpAx=*#&n}mcL++)0tWXMRiowxVVegI*`YWDr^~Lx;mRTLOkaX(vl@! zaj;VV(gV65P2<+zt(7*N5?kkK7+J6036ABJe}YG=4Q>tmjl~R| zy99DO&0DzEP}UafutW!AHk7CGe~_LVwf)kKH9gWu5ZOB~CUgO=^M9a_

    GwO;3O!8)a0uCqU-WAPj}_`8b@3|e=8!CnI_zN@ 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 N*K;WS^0SV2{tZ+{{*wRz diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/p3_gui_player.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/p3_gui_player.py deleted file mode 100644 index 3bbc8a3a..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/p3_gui_player.py +++ /dev/null @@ -1,241 +0,0 @@ -import tkinter as tk -from tkinter import filedialog, messagebox -import threading -import time -import opuslib -import struct -import numpy as np -import sounddevice as sd -import os - - -def play_p3_file(input_file, stop_event=None, pause_event=None): - """ - 播放p3格式的音频文件 - p3格式: [1字节类型, 1字节保留, 2字节长度, Opus数据] - """ - # 初始化Opus解码器 - sample_rate = 16000 # 采样率固定为16000Hz - channels = 1 # 单声道 - decoder = opuslib.Decoder(sample_rate, channels) - - # 帧大小 (60ms) - frame_size = int(sample_rate * 60 / 1000) - - # 打开音频流 - stream = sd.OutputStream( - samplerate=sample_rate, - channels=channels, - dtype='int16' - ) - stream.start() - - try: - with open(input_file, 'rb') as f: - print(f"正在播放: {input_file}") - - while True: - if stop_event and stop_event.is_set(): - break - - if pause_event and pause_event.is_set(): - time.sleep(0.1) - continue - - # 读取头部 (4字节) - header = f.read(4) - if not header or len(header) < 4: - break - - # 解析头部 - packet_type, reserved, data_len = struct.unpack('>BBH', header) - - # 读取Opus数据 - opus_data = f.read(data_len) - if not opus_data or len(opus_data) < data_len: - break - - # 解码Opus数据 - pcm_data = decoder.decode(opus_data, frame_size) - - # 将字节转换为numpy数组 - audio_array = np.frombuffer(pcm_data, dtype=np.int16) - - # 播放音频 - stream.write(audio_array) - - except KeyboardInterrupt: - print("\n播放已停止") - finally: - stream.stop() - stream.close() - print("播放完成") - - -class P3PlayerApp: - def __init__(self, root): - self.root = root - self.root.title("P3 文件简易播放器") - self.root.geometry("500x400") - - self.playlist = [] - self.current_index = 0 - self.is_playing = False - self.is_paused = False - self.stop_event = threading.Event() - self.pause_event = threading.Event() - self.loop_playback = tk.BooleanVar(value=False) # 循环播放复选框的状态 - - # 创建界面组件 - self.create_widgets() - - def create_widgets(self): - # 播放列表 - self.playlist_label = tk.Label(self.root, text="播放列表:") - self.playlist_label.pack(pady=5) - - self.playlist_frame = tk.Frame(self.root) - self.playlist_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5) - - self.playlist_listbox = tk.Listbox(self.playlist_frame, selectmode=tk.SINGLE) - self.playlist_listbox.pack(fill=tk.BOTH, expand=True) - - # 复选框和移除按钮 - self.checkbox_frame = tk.Frame(self.root) - self.checkbox_frame.pack(pady=5) - - self.remove_button = tk.Button(self.checkbox_frame, text="移除文件", command=self.remove_files) - self.remove_button.pack(side=tk.LEFT, padx=5) - - # 循环播放复选框 - self.loop_checkbox = tk.Checkbutton(self.checkbox_frame, text="循环播放", variable=self.loop_playback) - self.loop_checkbox.pack(side=tk.LEFT, padx=5) - - # 控制按钮 - self.control_frame = tk.Frame(self.root) - self.control_frame.pack(pady=10) - - self.add_button = tk.Button(self.control_frame, text="添加文件", command=self.add_file) - self.add_button.grid(row=0, column=0, padx=5) - - self.play_button = tk.Button(self.control_frame, text="播放", command=self.play) - self.play_button.grid(row=0, column=1, padx=5) - - self.pause_button = tk.Button(self.control_frame, text="暂停", command=self.pause) - self.pause_button.grid(row=0, column=2, padx=5) - - self.stop_button = tk.Button(self.control_frame, text="停止", command=self.stop) - self.stop_button.grid(row=0, column=3, padx=5) - - # 状态标签 - self.status_label = tk.Label(self.root, text="未在播放", fg="blue") - self.status_label.pack(pady=10) - - def add_file(self): - files = filedialog.askopenfilenames(filetypes=[("P3 文件", "*.p3")]) - if files: - self.playlist.extend(files) - self.update_playlist() - - def update_playlist(self): - self.playlist_listbox.delete(0, tk.END) - for file in self.playlist: - self.playlist_listbox.insert(tk.END, os.path.basename(file)) # 仅显示文件名 - - def update_status(self, status_text, color="blue"): - """更新状态标签的内容""" - self.status_label.config(text=status_text, fg=color) - - def play(self): - if not self.playlist: - messagebox.showwarning("警告", "播放列表为空!") - return - - if self.is_paused: - self.is_paused = False - self.pause_event.clear() - self.update_status(f"正在播放:{os.path.basename(self.playlist[self.current_index])}", "green") - return - - if self.is_playing: - return - - self.is_playing = True - self.stop_event.clear() - self.pause_event.clear() - self.current_index = self.playlist_listbox.curselection()[0] if self.playlist_listbox.curselection() else 0 - self.play_thread = threading.Thread(target=self.play_audio, daemon=True) - self.play_thread.start() - self.update_status(f"正在播放:{os.path.basename(self.playlist[self.current_index])}", "green") - - def play_audio(self): - while True: - if self.stop_event.is_set(): - break - - if self.pause_event.is_set(): - time.sleep(0.1) - continue - - # 检查当前索引是否有效 - if self.current_index >= len(self.playlist): - if self.loop_playback.get(): # 如果勾选了循环播放 - self.current_index = 0 # 回到第一首 - else: - break # 否则停止播放 - - file = self.playlist[self.current_index] - self.playlist_listbox.selection_clear(0, tk.END) - self.playlist_listbox.selection_set(self.current_index) - self.playlist_listbox.activate(self.current_index) - self.update_status(f"正在播放:{os.path.basename(self.playlist[self.current_index])}", "green") - play_p3_file(file, self.stop_event, self.pause_event) - - if self.stop_event.is_set(): - break - - if not self.loop_playback.get(): # 如果没有勾选循环播放 - break # 播放完当前文件后停止 - - self.current_index += 1 - if self.current_index >= len(self.playlist): - if self.loop_playback.get(): # 如果勾选了循环播放 - self.current_index = 0 # 回到第一首 - - self.is_playing = False - self.is_paused = False - self.update_status("播放已停止", "red") - - def pause(self): - if self.is_playing: - self.is_paused = not self.is_paused - if self.is_paused: - self.pause_event.set() - self.update_status("播放已暂停", "orange") - else: - self.pause_event.clear() - self.update_status(f"正在播放:{os.path.basename(self.playlist[self.current_index])}", "green") - - def stop(self): - if self.is_playing or self.is_paused: - self.is_playing = False - self.is_paused = False - self.stop_event.set() - self.pause_event.clear() - self.update_status("播放已停止", "red") - - def remove_files(self): - selected_indices = self.playlist_listbox.curselection() - if not selected_indices: - messagebox.showwarning("警告", "请先选择要移除的文件!") - return - - for index in reversed(selected_indices): - self.playlist.pop(index) - self.update_playlist() - - -if __name__ == "__main__": - root = tk.Tk() - app = P3PlayerApp(root) - root.mainloop() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/play_p3.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/play_p3.py deleted file mode 100644 index 3c9ec815..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/play_p3.py +++ /dev/null @@ -1,71 +0,0 @@ -# 播放p3格式的音频文件 -import opuslib -import struct -import numpy as np -import sounddevice as sd -import argparse - -def play_p3_file(input_file): - """ - 播放p3格式的音频文件 - p3格式: [1字节类型, 1字节保留, 2字节长度, Opus数据] - """ - # 初始化Opus解码器 - sample_rate = 16000 # 采样率固定为16000Hz - channels = 1 # 单声道 - decoder = opuslib.Decoder(sample_rate, channels) - - # 帧大小 (60ms) - frame_size = int(sample_rate * 60 / 1000) - - # 打开音频流 - stream = sd.OutputStream( - samplerate=sample_rate, - channels=channels, - dtype='int16' - ) - stream.start() - - try: - with open(input_file, 'rb') as f: - print(f"正在播放: {input_file}") - - while True: - # 读取头部 (4字节) - header = f.read(4) - if not header or len(header) < 4: - break - - # 解析头部 - packet_type, reserved, data_len = struct.unpack('>BBH', header) - - # 读取Opus数据 - opus_data = f.read(data_len) - if not opus_data or len(opus_data) < data_len: - break - - # 解码Opus数据 - pcm_data = decoder.decode(opus_data, frame_size) - - # 将字节转换为numpy数组 - audio_array = np.frombuffer(pcm_data, dtype=np.int16) - - # 播放音频 - stream.write(audio_array) - - except KeyboardInterrupt: - print("\n播放已停止") - finally: - stream.stop() - stream.close() - print("播放完成") - -def main(): - parser = argparse.ArgumentParser(description='播放p3格式的音频文件') - parser.add_argument('input_file', help='输入的p3文件路径') - args = parser.parse_args() - - play_p3_file(args.input_file) - -if __name__ == "__main__": - main() diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/requirements.txt b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/requirements.txt deleted file mode 100644 index d76d4cd5..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/p3_tools/requirements.txt +++ /dev/null @@ -1,7 +0,0 @@ -librosa>=0.9.2 -opuslib>=3.0.1 -numpy>=1.20.0 -tqdm>=4.62.0 -sounddevice>=0.4.4 -pyloudnorm>=0.1.1 -soundfile>=0.13.1 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/release.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/release.py deleted file mode 100644 index 35e99140..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/release.py +++ /dev/null @@ -1,305 +0,0 @@ -import sys -import os -import json -import zipfile -import argparse -from pathlib import Path -from typing import Optional - -# Switch to project root directory -os.chdir(Path(__file__).resolve().parent.parent) - -################################################################################ -# Common utility functions -################################################################################ - -def get_board_type_from_compile_commands() -> Optional[str]: - """Parse the current compiled BOARD_TYPE from build/compile_commands.json""" - compile_file = Path("build/compile_commands.json") - if not compile_file.exists(): - return None - with compile_file.open() as f: - data = json.load(f) - for item in data: - if not item["file"].endswith("main.cc"): - continue - cmd = item["command"] - if "-DBOARD_TYPE=\\\"" in cmd: - return cmd.split("-DBOARD_TYPE=\\\"")[1].split("\\\"")[0].strip() - return None - - -def get_project_version() -> Optional[str]: - """Read set(PROJECT_VER "x.y.z") from root CMakeLists.txt""" - with Path("CMakeLists.txt").open() as f: - for line in f: - if line.startswith("set(PROJECT_VER"): - return line.split("\"")[1] - return None - - -def merge_bin() -> None: - if os.system("idf.py merge-bin") != 0: - print("merge-bin failed", file=sys.stderr) - sys.exit(1) - - -def zip_bin(name: str, version: str) -> None: - """Zip build/merged-binary.bin to releases/v{version}_{name}.zip""" - out_dir = Path("releases") - out_dir.mkdir(exist_ok=True) - output_path = out_dir / f"v{version}_{name}.zip" - - if output_path.exists(): - output_path.unlink() - - with zipfile.ZipFile(output_path, "w", compression=zipfile.ZIP_DEFLATED) as zipf: - zipf.write("build/merged-binary.bin", arcname="merged-binary.bin") - print(f"zip bin to {output_path} done") - -################################################################################ -# board / variant related functions -################################################################################ - -_BOARDS_DIR = Path("main/boards") - - -def _collect_variants(config_filename: str = "config.json") -> list[dict[str, str]]: - """Traverse all boards under main/boards, collect variant information. - - Return example: - [{"board": "bread-compact-ml307", "name": "bread-compact-ml307"}, ...] - """ - variants: list[dict[str, str]] = [] - for board_path in _BOARDS_DIR.iterdir(): - if not board_path.is_dir(): - continue - if board_path.name == "common": - continue - cfg_path = board_path / config_filename - if not cfg_path.exists(): - print(f"[WARN] {cfg_path} does not exist, skip", file=sys.stderr) - continue - try: - with cfg_path.open() as f: - cfg = json.load(f) - for build in cfg.get("builds", []): - variants.append({"board": board_path.name, "name": build["name"]}) - except Exception as e: - print(f"[ERROR] 解析 {cfg_path} 失败: {e}", file=sys.stderr) - return variants - - -def _parse_board_config_map() -> dict[str, str]: - """Build the mapping of CONFIG_BOARD_TYPE_xxx and board_type from main/CMakeLists.txt""" - cmake_file = Path("main/CMakeLists.txt") - mapping: dict[str, str] = {} - lines = cmake_file.read_text(encoding="utf-8").splitlines() - for idx, line in enumerate(lines): - if "if(CONFIG_BOARD_TYPE_" in line: - config_name = line.strip().split("if(")[1].split(")")[0] - if idx + 1 < len(lines): - next_line = lines[idx + 1].strip() - if next_line.startswith("set(BOARD_TYPE"): - board_type = next_line.split('"')[1] - mapping[config_name] = board_type - return mapping - - -def _find_board_config(board_type: str) -> Optional[str]: - """Find the corresponding CONFIG_BOARD_TYPE_xxx for the given board_type""" - for config, b_type in _parse_board_config_map().items(): - if b_type == board_type: - return config - return None - - -# Kconfig "select" entries are not automatically applied when we simply append -# sdkconfig lines from config.json, so add the required dependencies here to -# mimic menuconfig behaviour. -_AUTO_SELECT_RULES: dict[str, list[str]] = { - "CONFIG_USE_ESP_BLUFI_WIFI_PROVISIONING": [ - "CONFIG_BT_ENABLED=y", - "CONFIG_BT_BLUEDROID_ENABLED=y", - "CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y", - "CONFIG_BT_BLE_50_FEATURES_SUPPORTED=n", - "CONFIG_BT_BLE_BLUFI_ENABLE=y", - "CONFIG_MBEDTLS_DHM_C=y", - ], -} - - -def _apply_auto_selects(sdkconfig_append: list[str]) -> list[str]: - """Apply hardcoded auto-select rules to sdkconfig_append.""" - items: list[str] = [] - existing_keys: set[str] = set() - - def _append_if_missing(entry: str) -> None: - key = entry.split("=", 1)[0] - if key not in existing_keys: - items.append(entry) - existing_keys.add(key) - - # Preserve original order while tracking keys - for entry in sdkconfig_append: - _append_if_missing(entry) - - # Apply auto-select rules - for key, deps in _AUTO_SELECT_RULES.items(): - for entry in sdkconfig_append: - name, _, value = entry.partition("=") - if name == key and value.lower().startswith("y"): - for dep in deps: - _append_if_missing(dep) - break - - return items - -################################################################################ -# Check board_type in CMakeLists -################################################################################ - -def _board_type_exists(board_type: str) -> bool: - cmake_file = Path("main/CMakeLists.txt") - pattern = f'set(BOARD_TYPE "{board_type}")' - return pattern in cmake_file.read_text(encoding="utf-8") - -################################################################################ -# Compile implementation -################################################################################ - -def release(board_type: str, config_filename: str = "config.json", *, filter_name: Optional[str] = None) -> None: - """Compile and package all/specified variants of the specified board_type - - Args: - board_type: directory name under main/boards - config_filename: config.json name (default: config.json) - filter_name: if specified, only compile the build["name"] that matches - """ - cfg_path = _BOARDS_DIR / board_type / config_filename - if not cfg_path.exists(): - print(f"[WARN] {cfg_path} 不存在,跳过 {board_type}") - return - - project_version = get_project_version() - print(f"Project Version: {project_version} ({cfg_path})") - - with cfg_path.open() as f: - cfg = json.load(f) - target = cfg["target"] - - builds = cfg.get("builds", []) - if filter_name: - builds = [b for b in builds if b["name"] == filter_name] - if not builds: - print(f"[ERROR] 未在 {board_type} 的 {config_filename} 中找到变体 {filter_name}", file=sys.stderr) - sys.exit(1) - - for build in builds: - name = build["name"] - if not name.startswith(board_type): - raise ValueError(f"build.name {name} 必须以 {board_type} 开头") - - output_path = Path("releases") / f"v{project_version}_{name}.zip" - if output_path.exists(): - print(f"跳过 {name} 因为 {output_path} 已存在") - continue - - # Process sdkconfig_append - board_type_config = _find_board_config(board_type) - sdkconfig_append = [f"{board_type_config}=y"] - sdkconfig_append.extend(build.get("sdkconfig_append", [])) - sdkconfig_append = _apply_auto_selects(sdkconfig_append) - - print("-" * 80) - print(f"name: {name}") - print(f"target: {target}") - for item in sdkconfig_append: - print(f"sdkconfig_append: {item}") - - os.environ.pop("IDF_TARGET", None) - - # Call set-target - if os.system(f"idf.py set-target {target}") != 0: - print("set-target failed", file=sys.stderr) - sys.exit(1) - - # Append sdkconfig - with Path("sdkconfig").open("a") as f: - f.write("\n") - f.write("# Append by release.py\n") - for append in sdkconfig_append: - f.write(f"{append}\n") - # Build with macro BOARD_NAME defined to name - if os.system(f"idf.py -DBOARD_NAME={name} -DBOARD_TYPE={board_type} build") != 0: - print("build failed") - sys.exit(1) - - # merge-bin - merge_bin() - - # Zip - zip_bin(name, project_version) - -################################################################################ -# CLI entry -################################################################################ - -if __name__ == "__main__": - parser = argparse.ArgumentParser() - parser.add_argument("board", nargs="?", default=None, help="板子类型或 all") - parser.add_argument("-c", "--config", default="config.json", help="指定 config 文件名,默认 config.json") - parser.add_argument("--list-boards", action="store_true", help="列出所有支持的 board 及变体列表") - parser.add_argument("--json", action="store_true", help="配合 --list-boards,JSON 格式输出") - parser.add_argument("--name", help="指定变体名称,仅编译匹配的变体") - - args = parser.parse_args() - - # List mode - if args.list_boards: - variants = _collect_variants(config_filename=args.config) - if args.json: - print(json.dumps(variants)) - else: - for v in variants: - print(f"{v['board']}: {v['name']}") - sys.exit(0) - - # Current directory firmware packaging mode - if args.board is None: - merge_bin() - curr_board_type = get_board_type_from_compile_commands() - if curr_board_type is None: - print("未能从 compile_commands.json 解析 board_type", file=sys.stderr) - sys.exit(1) - project_ver = get_project_version() - zip_bin(curr_board_type, project_ver) - sys.exit(0) - - # Compile mode - board_type_input: str = args.board - name_filter: str | None = args.name - - # Check board_type in CMakeLists - if board_type_input != "all" and not _board_type_exists(board_type_input): - print(f"[ERROR] main/CMakeLists.txt 中未找到 board_type {board_type_input}", file=sys.stderr) - sys.exit(1) - - variants_all = _collect_variants(config_filename=args.config) - - # Filter board_type list - target_board_types: set[str] - if board_type_input == "all": - target_board_types = {v["board"] for v in variants_all} - else: - target_board_types = {board_type_input} - - for bt in sorted(target_board_types): - if not _board_type_exists(bt): - print(f"[ERROR] main/CMakeLists.txt 中未找到 board_type {bt}", file=sys.stderr) - sys.exit(1) - cfg_path = _BOARDS_DIR / bt / args.config - if bt == board_type_input and not cfg_path.exists(): - print(f"开发板 {bt} 未定义 {args.config} 配置文件,跳过") - sys.exit(0) - release(bt, config_filename=args.config, filter_name=name_filter if bt == board_type_input else None) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/sonic_wifi_config.html b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/sonic_wifi_config.html deleted file mode 100644 index b5c50933..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/sonic_wifi_config.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - 小智声波配网 - - - - -

    -

    📶 小智声波配网

    - - - - - - -
    - -
    - - - - -
    - - - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/README.md b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/README.md deleted file mode 100644 index 9cd0f924..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/README.md +++ /dev/null @@ -1,110 +0,0 @@ -# SPIFFS Assets Builder - -这个脚本用于构建 ESP32 项目的 SPIFFS 资源分区,将各种资源文件打包成可在设备上使用的格式。 - -## 功能特性 - -- 处理唤醒网络模型 (WakeNet Model) -- 集成文本字体文件 -- 处理表情符号图片集合 -- 自动生成资源索引文件 -- 打包生成最终的 `assets.bin` 文件 - -## 依赖要求 - -- Python 3.6+ -- 相关资源文件 - -## 使用方法 - -### 基本语法 - -```bash -./build.py --wakenet_model \ - --text_font \ - --emoji_collection -``` - -### 参数说明 - -| 参数 | 类型 | 必需 | 说明 | -|------|------|------|------| -| `--wakenet_model` | 目录路径 | 否 | 唤醒网络模型目录路径 | -| `--text_font` | 文件路径 | 否 | 文本字体文件路径 | -| `--emoji_collection` | 目录路径 | 否 | 表情符号图片集合目录路径 | - -### 使用示例 - -```bash -# 完整参数示例 -./build.py \ - --wakenet_model ../../managed_components/espressif__esp-sr/model/wakenet_model/wn9_nihaoxiaozhi_tts \ - --text_font ../../components/xiaozhi-fonts/build/font_puhui_common_20_4.bin \ - --emoji_collection ../../components/xiaozhi-fonts/build/emojis_64/ - -# 仅处理字体文件 -./build.py --text_font ../../components/xiaozhi-fonts/build/font_puhui_common_20_4.bin - -# 仅处理表情符号 -./build.py --emoji_collection ../../components/xiaozhi-fonts/build/emojis_64/ -``` - -## 工作流程 - -1. **创建构建目录结构** - - `build/` - 主构建目录 - - `build/assets/` - 资源文件目录 - - `build/output/` - 输出文件目录 - -2. **处理唤醒网络模型** - - 复制模型文件到构建目录 - - 使用 `pack_model.py` 生成 `srmodels.bin` - - 将生成的模型文件复制到资源目录 - -3. **处理文本字体** - - 复制字体文件到资源目录 - - 支持 `.bin` 格式的字体文件 - -4. **处理表情符号集合** - - 扫描指定目录中的图片文件 - - 支持 `.png` 和 `.gif` 格式 - - 自动生成表情符号索引 - -5. **生成配置文件** - - `index.json` - 资源索引文件 - - `config.json` - 构建配置文件 - -6. **打包最终资源** - - 使用 `spiffs_assets_gen.py` 生成 `assets.bin` - - 复制到构建根目录 - -## 输出文件 - -构建完成后,会在 `build/` 目录下生成以下文件: - -- `assets/` - 所有资源文件 -- `assets.bin` - 最终的 SPIFFS 资源文件 -- `config.json` - 构建配置 -- `output/` - 中间输出文件 - -## 支持的资源格式 - -- **模型文件**: `.bin` (通过 pack_model.py 处理) -- **字体文件**: `.bin` -- **图片文件**: `.png`, `.gif` -- **配置文件**: `.json` - -## 错误处理 - -脚本包含完善的错误处理机制: - -- 检查源文件/目录是否存在 -- 验证子进程执行结果 -- 提供详细的错误信息和警告 - -## 注意事项 - -1. 确保所有依赖的 Python 脚本都在同一目录下 -2. 资源文件路径使用绝对路径或相对于脚本目录的路径 -3. 构建过程会清理之前的构建文件 -4. 生成的 `assets.bin` 文件大小受 SPIFFS 分区大小限制 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build.py deleted file mode 100644 index 47069d23..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build.py +++ /dev/null @@ -1,400 +0,0 @@ -#!/usr/bin/env python3 -""" -Build the spiffs assets partition - -Usage: - ./build.py --wakenet_model \ - --text_font \ - --emoji_collection - -Example: - ./build.py --wakenet_model ../../managed_components/espressif__esp-sr/model/wakenet_model/wn9_nihaoxiaozhi_tts \ - --text_font ../../components/xiaozhi-fonts/build/font_puhui_common_20_4.bin \ - --emoji_collection ../../components/xiaozhi-fonts/build/emojis_64/ -""" - -import os -import sys -import shutil -import argparse -import subprocess -import json -from pathlib import Path - - -def ensure_dir(directory): - """Ensure directory exists, create if not""" - os.makedirs(directory, exist_ok=True) - - -def copy_file(src, dst): - """Copy file""" - if os.path.exists(src): - shutil.copy2(src, dst) - print(f"Copied: {src} -> {dst}") - else: - print(f"Warning: Source file does not exist: {src}") - - -def copy_directory(src, dst): - """Copy directory""" - if os.path.exists(src): - shutil.copytree(src, dst, dirs_exist_ok=True) - print(f"Copied directory: {src} -> {dst}") - else: - print(f"Warning: Source directory does not exist: {src}") - - -def process_wakenet_model(wakenet_model_dir, build_dir, assets_dir): - """Process wakenet_model parameter""" - if not wakenet_model_dir: - return None - - # Copy input directory to build directory - wakenet_build_dir = os.path.join(build_dir, "wakenet_model") - if os.path.exists(wakenet_build_dir): - shutil.rmtree(wakenet_build_dir) - copy_directory(wakenet_model_dir, os.path.join(wakenet_build_dir, os.path.basename(wakenet_model_dir))) - - # Use pack_model.py to generate srmodels.bin - srmodels_output = os.path.join(wakenet_build_dir, "srmodels.bin") - try: - subprocess.run([ - sys.executable, "pack_model.py", - "-m", wakenet_build_dir, - "-o", "srmodels.bin" - ], check=True, cwd=os.path.dirname(__file__)) - print(f"Generated: {srmodels_output}") - # Copy srmodels.bin to assets directory - copy_file(srmodels_output, os.path.join(assets_dir, "srmodels.bin")) - return "srmodels.bin" - except subprocess.CalledProcessError as e: - print(f"Error: Failed to generate srmodels.bin: {e}") - return None - - -def process_text_font(text_font_file, assets_dir): - """Process text_font parameter""" - if not text_font_file: - return None - - # Copy input file to build/assets directory - font_filename = os.path.basename(text_font_file) - font_dst = os.path.join(assets_dir, font_filename) - copy_file(text_font_file, font_dst) - - return font_filename - - -def process_emoji_collection(emoji_collection_dir, assets_dir): - """Process emoji_collection parameter""" - if not emoji_collection_dir: - return [] - - emoji_list = [] - - # Copy each image from input directory to build/assets directory - for root, dirs, files in os.walk(emoji_collection_dir): - for file in files: - if file.lower().endswith(('.png', '.gif')): - # Copy file - src_file = os.path.join(root, file) - dst_file = os.path.join(assets_dir, file) - copy_file(src_file, dst_file) - - # Get filename without extension - filename_without_ext = os.path.splitext(file)[0] - - # Add to emoji list - emoji_list.append({ - "name": filename_without_ext, - "file": file - }) - - return emoji_list - -def load_emoji_config(emoji_collection_dir): - """Load emoji config from config.json file""" - config_path = os.path.join(emoji_collection_dir, "emote.json") - if not os.path.exists(config_path): - print(f"Warning: Config file not found: {config_path}") - return {} - - try: - with open(config_path, 'r', encoding='utf-8') as f: - config_data = json.load(f) - - # Convert list format to dict for easy lookup - config_dict = {} - for item in config_data: - if "emote" in item: - config_dict[item["emote"]] = item - - return config_dict - except Exception as e: - print(f"Error loading config file {config_path}: {e}") - return {} - -def process_board_emoji_collection(emoji_collection_dir, target_board_dir, assets_dir): - """Process emoji_collection parameter""" - if not emoji_collection_dir: - return [] - - emoji_config = load_emoji_config(target_board_dir) - print(f"Loaded emoji config with {len(emoji_config)} entries") - - emoji_list = [] - - for emote_name, config in emoji_config.items(): - - if "src" not in config: - print(f"Error: No src field found for emote '{emote_name}' in config") - continue - - eaf_file_path = os.path.join(emoji_collection_dir, config["src"]) - file_exists = os.path.exists(eaf_file_path) - - if not file_exists: - print(f"Warning: EAF file not found for emote '{emote_name}': {eaf_file_path}") - else: - # Copy eaf file to assets directory - copy_file(eaf_file_path, os.path.join(assets_dir, config["src"])) - - # Create emoji entry with src as file (merge file and src) - emoji_entry = { - "name": emote_name, - "file": config["src"] # Use src as the actual file - } - - eaf_properties = {} - - if not file_exists: - eaf_properties["lack"] = True - - if "loop" in config: - eaf_properties["loop"] = config["loop"] - - if "fps" in config: - eaf_properties["fps"] = config["fps"] - - if eaf_properties: - emoji_entry["eaf"] = eaf_properties - - status = "MISSING" if not file_exists else "OK" - eaf_info = emoji_entry.get('eaf', {}) - print(f"emote '{emote_name}': file='{emoji_entry['file']}', status={status}, lack={eaf_info.get('lack', False)}, loop={eaf_info.get('loop', 'none')}, fps={eaf_info.get('fps', 'none')}") - - emoji_list.append(emoji_entry) - - print(f"Successfully processed {len(emoji_list)} emotes from config") - return emoji_list - -def process_board_icon_collection(icon_collection_dir, assets_dir): - """Process emoji_collection parameter""" - if not icon_collection_dir: - return [] - - icon_list = [] - - for root, dirs, files in os.walk(icon_collection_dir): - for file in files: - if file.lower().endswith(('.bin')) or file.lower() == 'listen.eaf': - src_file = os.path.join(root, file) - dst_file = os.path.join(assets_dir, file) - copy_file(src_file, dst_file) - - filename_without_ext = os.path.splitext(file)[0] - - icon_list.append({ - "name": filename_without_ext, - "file": file - }) - - return icon_list -def process_board_layout(layout_json_file, assets_dir): - """Process layout_json parameter""" - if not layout_json_file: - print(f"Warning: Layout json file not provided") - return [] - - print(f"Processing layout_json: {layout_json_file}") - print(f"assets_dir: {assets_dir}") - - if os.path.isdir(layout_json_file): - layout_json_path = os.path.join(layout_json_file, "layout.json") - if not os.path.exists(layout_json_path): - print(f"Warning: layout.json not found in directory: {layout_json_file}") - return [] - layout_json_file = layout_json_path - elif not os.path.isfile(layout_json_file): - print(f"Warning: Layout json file not found: {layout_json_file}") - return [] - - try: - with open(layout_json_file, 'r', encoding='utf-8') as f: - layout_data = json.load(f) - - # Layout data is now directly an array, no need to get "layout" key - layout_items = layout_data if isinstance(layout_data, list) else layout_data.get("layout", []) - - processed_layout = [] - for item in layout_items: - processed_item = { - "name": item.get("name", ""), - "align": item.get("align", ""), - "x": item.get("x", 0), - "y": item.get("y", 0) - } - - if "width" in item: - processed_item["width"] = item["width"] - if "height" in item: - processed_item["height"] = item["height"] - - processed_layout.append(processed_item) - - print(f"Processed {len(processed_layout)} layout elements") - return processed_layout - - except Exception as e: - print(f"Error reading/processing layout.json: {e}") - return [] - -def process_board_collection(target_board_dir, res_path, assets_dir): - """Process board collection - merge icon, emoji, and layout processing""" - - # Process all collections - if os.path.exists(res_path) and os.path.exists(target_board_dir): - emoji_collection = process_board_emoji_collection(res_path, target_board_dir, assets_dir) - icon_collection = process_board_icon_collection(res_path, assets_dir) - layout_json = process_board_layout(target_board_dir, assets_dir) - else: - print(f"Warning: EAF directory not found: {res_path} or {target_board_dir}") - emoji_collection = [] - icon_collection = [] - layout_json = [] - - return emoji_collection, icon_collection, layout_json - -def generate_index_json(assets_dir, srmodels, text_font, emoji_collection, icon_collection, layout_json): - """Generate index.json file""" - index_data = { - "version": 1 - } - - if srmodels: - index_data["srmodels"] = srmodels - - if text_font: - index_data["text_font"] = text_font - - if emoji_collection: - index_data["emoji_collection"] = emoji_collection - - if icon_collection: - index_data["icon_collection"] = icon_collection - - if layout_json: - index_data["layout"] = layout_json - - # Write index.json - index_path = os.path.join(assets_dir, "index.json") - with open(index_path, 'w', encoding='utf-8') as f: - json.dump(index_data, f, indent=4, ensure_ascii=False) - - print(f"Generated: {index_path}") - - -def generate_config_json(build_dir, assets_dir): - """Generate config.json file""" - # Get absolute path of current working directory - workspace_dir = os.path.abspath(os.path.join(os.path.dirname(__file__))) - - config_data = { - "include_path": os.path.join(workspace_dir, "build/include"), - "assets_path": os.path.join(workspace_dir, "build/assets"), - "image_file": os.path.join(workspace_dir, "build/output/assets.bin"), - "lvgl_ver": "9.3.0", - "assets_size": "0x400000", - "support_format": ".png, .gif, .jpg, .bin, .json, .eaf", - "name_length": "32", - "split_height": "0", - "support_qoi": False, - "support_spng": False, - "support_sjpg": False, - "support_sqoi": False, - "support_raw": False, - "support_raw_dither": False, - "support_raw_bgr": False - } - - # Write config.json - config_path = os.path.join(build_dir, "config.json") - with open(config_path, 'w', encoding='utf-8') as f: - json.dump(config_data, f, indent=4, ensure_ascii=False) - - print(f"Generated: {config_path}") - return config_path - - -def main(): - parser = argparse.ArgumentParser(description='Build the spiffs assets partition') - parser.add_argument('--wakenet_model', help='Path to wakenet model directory') - parser.add_argument('--text_font', help='Path to text font file') - parser.add_argument('--emoji_collection', help='Path to emoji collection directory') - - parser.add_argument('--res_path', help='Path to res directory') - parser.add_argument('--target_board', help='Path to target board directory') - - args = parser.parse_args() - - # Get script directory - script_dir = os.path.dirname(os.path.abspath(__file__)) - - # Set directory paths - build_dir = os.path.join(script_dir, "build") - assets_dir = os.path.join(build_dir, "assets") - if os.path.exists(assets_dir): - shutil.rmtree(assets_dir) - - # Ensure directories exist - ensure_dir(build_dir) - ensure_dir(assets_dir) - - print("Starting to build SPIFFS assets partition...") - - # Process each parameter - srmodels = process_wakenet_model(args.wakenet_model, build_dir, assets_dir) - text_font = process_text_font(args.text_font, assets_dir) - - if(args.target_board): - emoji_collection, icon_collection, layout_json = process_board_collection(args.target_board, args.res_path, assets_dir) - else: - emoji_collection = process_emoji_collection(args.emoji_collection, assets_dir) - icon_collection = [] - layout_json = [] - - # Generate index.json - generate_index_json(assets_dir, srmodels, text_font, emoji_collection, icon_collection, layout_json) - - # Generate config.json - config_path = generate_config_json(build_dir, assets_dir) - - # Use spiffs_assets_gen.py to package final build/assets.bin - try: - subprocess.run([ - sys.executable, "spiffs_assets_gen.py", - "--config", config_path - ], check=True, cwd=script_dir) - print("Successfully packaged assets.bin") - except subprocess.CalledProcessError as e: - print(f"Error: Failed to package assets.bin: {e}") - sys.exit(1) - - # Copy build/output/assets.bin to build/assets.bin - shutil.copy(os.path.join(build_dir, "output", "assets.bin"), os.path.join(build_dir, "assets.bin")) - print("Build completed!") - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build_all.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build_all.py deleted file mode 100644 index e812f8d0..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/build_all.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python3 -""" -Build multiple spiffs assets partitions with different parameter combinations - -This script calls build.py with different combinations of: -- wakenet_models -- text_fonts -- emoji_collections - -And generates assets.bin files with names like: -wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-emojis_32.bin -""" - -import os -import sys -import shutil -import subprocess -import argparse -from pathlib import Path - - -def ensure_dir(directory): - """Ensure directory exists, create if not""" - os.makedirs(directory, exist_ok=True) - - -def get_file_path(base_dir, filename): - """Get full path for a file, handling 'none' case""" - if filename == "none": - return None - return os.path.join(base_dir, f"{filename}.bin" if not filename.startswith("emojis_") else filename) - - -def build_assets(wakenet_model, text_font, emoji_collection, target_board, build_dir, final_dir): - """Build assets.bin using build.py with given parameters""" - - # Prepare arguments for build.py - cmd = [sys.executable, "build.py"] - - if wakenet_model != "none": - wakenet_path = os.path.join("../../managed_components/espressif__esp-sr/model/wakenet_model", wakenet_model) - cmd.extend(["--wakenet_model", wakenet_path]) - - if text_font != "none": - text_font_path = os.path.join("../../components/78__xiaozhi-fonts/cbin", f"{text_font}.bin") - cmd.extend(["--text_font", text_font_path]) - - if emoji_collection != "none": - emoji_path = os.path.join("../../components/xiaozhi-fonts/build", emoji_collection) - cmd.extend(["--emoji_collection", emoji_path]) - - if target_board != "none": - res_path = os.path.join("../../managed_components/espressif2022__esp_emote_gfx/emoji_large", "") - cmd.extend(["--res_path", res_path]) - - target_board_path = os.path.join("../../main/boards/", f"{target_board}") - cmd.extend(["--target_board", target_board_path]) - - print(f"\n正在构建: {wakenet_model}-{text_font}-{emoji_collection}-{target_board}") - print(f"执行命令: {' '.join(cmd)}") - - try: - # Run build.py - result = subprocess.run(cmd, check=True, cwd=os.path.dirname(__file__)) - - # Generate output filename - if(target_board != "none"): - output_name = f"{wakenet_model}-{text_font}-{target_board}.bin" - else: - output_name = f"{wakenet_model}-{text_font}-{emoji_collection}.bin" - - # Copy generated assets.bin to final directory with new name - src_path = os.path.join(build_dir, "assets.bin") - dst_path = os.path.join(final_dir, output_name) - - if os.path.exists(src_path): - shutil.copy2(src_path, dst_path) - print(f"✓ 成功生成: {output_name}") - return True - else: - print(f"✗ 错误: 未找到生成的 assets.bin 文件") - return False - - except subprocess.CalledProcessError as e: - print(f"✗ 构建失败: {e}") - return False - except Exception as e: - print(f"✗ 未知错误: {e}") - return False - - -def main(): - # Parse command line arguments - parser = argparse.ArgumentParser(description='构建多个 SPIFFS assets 分区') - parser.add_argument('--mode', - choices=['emoji_collections', 'emoji_target_boards'], - default='emoji_collections', - help='选择运行模式: emoji_collections 或 emoji_target_boards (默认: emoji_collections)') - - args = parser.parse_args() - - # Configuration - wakenet_models = [ - "none", - "wn9_nihaoxiaozhi_tts", - "wn9s_nihaoxiaozhi" - ] - - text_fonts = [ - "none", - "font_puhui_common_14_1", - "font_puhui_common_16_4", - "font_puhui_common_20_4", - "font_puhui_common_30_4", - ] - - emoji_collections = [ - "none", - "emojis_32", - "emojis_64", - ] - - emoji_target_boards = [ - "esp-box-3", - "echoear", - ] - - # Get script directory - script_dir = os.path.dirname(os.path.abspath(__file__)) - - # Set directory paths - build_dir = os.path.join(script_dir, "build") - final_dir = os.path.join(build_dir, "final") - - # Ensure directories exist - ensure_dir(build_dir) - ensure_dir(final_dir) - - print("开始构建多个 SPIFFS assets 分区...") - print(f"运行模式: {args.mode}") - print(f"输出目录: {final_dir}") - - # Track successful builds - successful_builds = 0 - - if args.mode == 'emoji_collections': - # Calculate total combinations for emoji_collections mode - total_combinations = len(wakenet_models) * len(text_fonts) * len(emoji_collections) - - # Build all combinations with emoji_collections - for wakenet_model in wakenet_models: - for text_font in text_fonts: - for emoji_collection in emoji_collections: - if build_assets(wakenet_model, text_font, emoji_collection, "none", build_dir, final_dir): - successful_builds += 1 - - elif args.mode == 'emoji_target_boards': - # Calculate total combinations for emoji_target_boards mode - total_combinations = len(wakenet_models) * len(text_fonts) * len(emoji_target_boards) - - # Build all combinations with emoji_target_boards - for wakenet_model in wakenet_models: - for text_font in text_fonts: - for emoji_target_board in emoji_target_boards: - if build_assets(wakenet_model, text_font, "none", emoji_target_board, build_dir, final_dir): - successful_builds += 1 - - print(f"\n构建完成!") - print(f"成功构建: {successful_builds}/{total_combinations}") - print(f"输出文件位置: {final_dir}") - - # List generated files - if os.path.exists(final_dir): - files = [f for f in os.listdir(final_dir) if f.endswith('.bin')] - if files: - print("\n生成的文件:") - for file in sorted(files): - file_size = os.path.getsize(os.path.join(final_dir, file)) - print(f" {file} ({file_size:,} bytes)") - else: - print("\n未找到生成的 .bin 文件") - - -if __name__ == "__main__": - main() - - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/pack_model.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/pack_model.py deleted file mode 100644 index 1fc85aa9..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/pack_model.py +++ /dev/null @@ -1,123 +0,0 @@ -import os -import struct -import argparse - - -def struct_pack_string(string, max_len=None): - """ - pack string to binary data. - if max_len is None, max_len = len(string) + 1 - else len(string) < max_len, the left will be padded by struct.pack('x') - - string: input python string - max_len: output - """ - - if max_len == None : - max_len = len(string) - else: - assert len(string) <= max_len - - left_num = max_len - len(string) - out_bytes = None - for char in string: - if out_bytes == None: - out_bytes = struct.pack('b', ord(char)) - else: - out_bytes += struct.pack('b', ord(char)) - for i in range(left_num): - out_bytes += struct.pack('x') - return out_bytes - -def read_data(filename): - """ - Read binary data, like index and mndata - """ - data = None - with open(filename, "rb") as f: - data = f.read() - return data - -def pack_models(model_path, out_file="srmodels.bin"): - """ - Pack all models into one binary file by the following format: - { - model_num: int - model1_info: model_info_t - model2_info: model_info_t - ... - model1_index,model1_data,model1_MODEL_INFO - model1_index,model1_data,model1_MODEL_INFO - ... - }model_pack_t - - { - model_name: char[32] - file_number: int - file1_name: char[32] - file1_start: int - file1_len: int - file2_name: char[32] - file2_start: int // data_len = info_start - data_start - file2_len: int - ... - }model_info_t - - model_path: the path of models - out_file: the ouput binary filename - """ - - models = {} - file_num = 0 - model_num = 0 - for root, dirs, _ in os.walk(model_path): - for model_name in dirs: - models[model_name] = {} - model_dir = os.path.join(root, model_name) - model_num += 1 - for _, _, files in os.walk(model_dir): - for file_name in files: - file_num += 1 - file_path = os.path.join(model_dir, file_name) - models[model_name][file_name] = read_data(file_path) - - model_num = len(models) - header_len = 4 + model_num*(32+4) + file_num*(32+4+4) - out_bin = struct.pack('I', model_num) # model number - data_bin = None - for key in models: - model_bin = struct_pack_string(key, 32) # + model name - model_bin += struct.pack('I', len(models[key])) # + file number in this model - - for file_name in models[key]: - model_bin += struct_pack_string(file_name, 32) # + file name - if data_bin == None: - model_bin += struct.pack('I', header_len) - data_bin = models[key][file_name] - model_bin += struct.pack('I', len(models[key][file_name])) - # print(file_name, header_len, len(models[key][file_name]), len(data_bin)) - else: - model_bin += struct.pack('I', header_len+len(data_bin)) - # print(file_name, header_len+len(data_bin), len(models[key][file_name])) - data_bin += models[key][file_name] - model_bin += struct.pack('I', len(models[key][file_name])) - - out_bin += model_bin - assert len(out_bin) == header_len - if data_bin != None: - out_bin += data_bin - - out_file = os.path.join(model_path, out_file) - with open(out_file, "wb") as f: - f.write(out_bin) - - -if __name__ == "__main__": - # input parameter - parser = argparse.ArgumentParser(description='Model package tool') - parser.add_argument('-m', '--model_path', help="the path of model files") - parser.add_argument('-o', '--out_file', default="srmodels.bin", help="the path of binary file") - args = parser.parse_args() - - # convert(args.model_path, args.out_file) - pack_models(model_path=args.model_path, out_file=args.out_file) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/spiffs_assets_gen.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/spiffs_assets_gen.py deleted file mode 100644 index e07aaaaf..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/spiffs_assets/spiffs_assets_gen.py +++ /dev/null @@ -1,647 +0,0 @@ -# SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Apache-2.0 -import io -import os -import argparse -import json -import shutil -import math -import sys -import time -import numpy as np -import importlib -import subprocess -import urllib.request - -from PIL import Image -from datetime import datetime -from dataclasses import dataclass -from typing import List -from pathlib import Path -from packaging import version - -sys.dont_write_bytecode = True - -GREEN = '\033[1;32m' -RED = '\033[1;31m' -RESET = '\033[0m' - -@dataclass -class AssetCopyConfig: - assets_path: str - target_path: str - spng_enable: bool - sjpg_enable: bool - qoi_enable: bool - sqoi_enable: bool - row_enable: bool - support_format: List[str] - split_height: int - -@dataclass -class PackModelsConfig: - target_path: str - include_path: str - image_file: str - assets_path: str - name_length: int - -def generate_header_filename(path): - asset_name = os.path.basename(path) - - header_filename = f'mmap_generate_{asset_name}.h' - return header_filename - -def compute_checksum(data): - checksum = sum(data) & 0xFFFF - return checksum - -def sort_key(filename): - basename, extension = os.path.splitext(filename) - return extension, basename - -def download_v8_script(convert_path): - """ - Ensure that the lvgl_image_converter repository is present at the specified path. - If not, clone the repository. Then, checkout to a specific commit. - - Parameters: - - convert_path (str): The directory path where lvgl_image_converter should be located. - """ - - # Check if convert_path is not empty - if convert_path: - # If the directory does not exist, create it and clone the repository - if not os.path.exists(convert_path): - os.makedirs(convert_path, exist_ok=True) - try: - subprocess.run( - ['git', 'clone', 'https://github.com/W-Mai/lvgl_image_converter.git', convert_path], - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - check=True - ) - except subprocess.CalledProcessError as e: - print(f'Git clone failed: {e}') - sys.exit(1) - - # Checkout to the specific commit - try: - subprocess.run( - ['git', 'checkout', '9174634e9dcc1b21a63668969406897aad650f35'], - cwd=convert_path, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - check=True - ) - except subprocess.CalledProcessError as e: - print(f'Failed to checkout to the specific commit: {e}') - sys.exit(1) - else: - print('Error: convert_path is NULL') - sys.exit(1) - -def download_v9_script(url: str, destination: str) -> None: - """ - Download a Python script from a URL to a local destination. - - Parameters: - - url (str): URL to download the script from. - - destination (str): Local path to save the downloaded script. - - Raises: - - Exception: If the download fails. - """ - file_path = Path(destination) - - # Check if the file already exists - if file_path.exists(): - if file_path.is_file(): - return - - try: - # Create the parent directories if they do not exist - file_path.parent.mkdir(parents=True, exist_ok=True) - - # Open the URL and retrieve the data - with urllib.request.urlopen(url) as response, open(file_path, 'wb') as out_file: - data = response.read() # Read the entire response - out_file.write(data) # Write data to the local file - - except urllib.error.HTTPError as e: - print(f'HTTP Error: {e.code} - {e.reason} when accessing {url}') - sys.exit(1) - except urllib.error.URLError as e: - print(f'URL Error: {e.reason} when accessing {url}') - sys.exit(1) - except Exception as e: - print(f'An unexpected error occurred: {e}') - sys.exit(1) - -def split_image(im, block_size, input_dir, ext, convert_to_qoi): - """Splits the image into blocks based on the block size.""" - width, height = im.size - - if block_size: - splits = math.ceil(height / block_size) - else: - splits = 1 - - for i in range(splits): - if i < splits - 1: - crop = im.crop((0, i * block_size, width, (i + 1) * block_size)) - else: - crop = im.crop((0, i * block_size, width, height)) - - output_path = os.path.join(input_dir, str(i) + ext) - crop.save(output_path, quality=100) - - qoi_module = importlib.import_module('qoi-conv.qoi') - Qoi = qoi_module.Qoi - replace_extension = qoi_module.replace_extension - - if convert_to_qoi: - with Image.open(output_path) as img: - if img.mode != 'RGBA': - img = img.convert('RGBA') - - img_data = np.asarray(img) - out_path = qoi_module.replace_extension(output_path, 'qoi') - new_image = qoi_module.Qoi().save(out_path, img_data) - os.remove(output_path) - - - return width, height, splits - -def create_header(width, height, splits, split_height, lenbuf, ext): - """Creates the header for the output file based on the format.""" - header = bytearray() - - if ext.lower() == '.jpg': - header += bytearray('_SJPG__'.encode('UTF-8')) - elif ext.lower() == '.png': - header += bytearray('_SPNG__'.encode('UTF-8')) - elif ext.lower() == '.qoi': - header += bytearray('_SQOI__'.encode('UTF-8')) - - # 6 BYTES VERSION - header += bytearray(('\x00V1.00\x00').encode('UTF-8')) - - # WIDTH 2 BYTES - header += width.to_bytes(2, byteorder='little') - - # HEIGHT 2 BYTES - header += height.to_bytes(2, byteorder='little') - - # NUMBER OF ITEMS 2 BYTES - header += splits.to_bytes(2, byteorder='little') - - # SPLIT HEIGHT 2 BYTES - header += split_height.to_bytes(2, byteorder='little') - - for item_len in lenbuf: - # LENGTH 2 BYTES - header += item_len.to_bytes(2, byteorder='little') - - return header - -def save_image(output_file_path, header, split_data): - """Saves the image with the constructed header and split data.""" - with open(output_file_path, 'wb') as f: - if header is not None: - f.write(header + split_data) - else: - f.write(split_data) - -def handle_lvgl_version_v9(input_file: str, input_dir: str, - input_filename: str, convert_path: str) -> None: - """ - Handle conversion for LVGL versions greater than 9.0. - - Parameters: - - input_file (str): Path to the input image file. - - input_dir (str): Directory of the input file. - - input_filename (str): Name of the input file. - - convert_path (str): Path for conversion scripts and outputs. - """ - - convert_file = os.path.join(convert_path, 'LVGLImage.py') - lvgl_image_url = 'https://raw.githubusercontent.com/lvgl/lvgl/master/scripts/LVGLImage.py' - - download_v9_script(url=lvgl_image_url, destination=convert_file) - lvgl_script = Path(convert_file) - - cmd = [ - 'python', - str(lvgl_script), - '--ofmt', 'BIN', - '--cf', config_data['support_raw_cf'], - '--compress', 'NONE', - '--output', str(input_dir), - input_file - ] - - try: - result = subprocess.run( - cmd, - check=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True - ) - print(f'Completed {input_filename} -> BIN') - except subprocess.CalledProcessError as e: - print('An error occurred while executing LVGLImage.py:') - print(e.stderr) - sys.exit(e.returncode) - -def handle_lvgl_version_v8(input_file: str, input_dir: str, input_filename: str, convert_path: str) -> None: - """ - Handle conversion for supported LVGL versions (<= 9.0). - - Parameters: - - input_file (str): Path to the input image file. - - input_dir (str): Directory of the input file. - - input_filename (str): Name of the input file. - - convert_path (str): Path for conversion scripts and outputs. - """ - - download_v8_script(convert_path=convert_path) - - if convert_path not in sys.path: - sys.path.append(convert_path) - - try: - import lv_img_conv - except ImportError as e: - print(f"Failed to import 'lv_img_conv' from '{convert_path}': {e}") - sys.exit(1) - - try: - lv_img_conv.conv_one_file( - root=Path(input_dir), - filepath=Path(input_file), - f=config_data['support_raw_ff'], - cf=config_data['support_raw_cf'], - ff='BIN', - dither=config_data['support_raw_dither'], - bgr_mode=config_data['support_raw_bgr'], - ) - print(f'Completed {input_filename} -> BIN') - except KeyError as e: - print(f'Missing configuration key: {e}') - sys.exit(1) - except Exception as e: - print(f'An error occurred during conversion: {e}') - sys.exit(1) - -def process_image(input_file, height_str, output_extension, convert_to_qoi=False): - """Main function to process the image and save it as .sjpg, .spng, or .sqoi.""" - try: - SPLIT_HEIGHT = int(height_str) - if SPLIT_HEIGHT < 0: - raise ValueError('Height must be a positive integer') - except ValueError as e: - print('Error: Height must be a positive integer') - sys.exit(1) - - input_dir, input_filename = os.path.split(input_file) - base_filename, ext = os.path.splitext(input_filename) - OUTPUT_FILE_NAME = base_filename - - try: - im = Image.open(input_file) - except Exception as e: - print('Error:', e) - sys.exit(0) - - width, height, splits = split_image(im, SPLIT_HEIGHT, input_dir, ext, convert_to_qoi) - - split_data = bytearray() - lenbuf = [] - - if convert_to_qoi: - ext = '.qoi' - - for i in range(splits): - with open(os.path.join(input_dir, str(i) + ext), 'rb') as f: - a = f.read() - split_data += a - lenbuf.append(len(a)) - os.remove(os.path.join(input_dir, str(i) + ext)) - - header = None - if splits == 1 and convert_to_qoi: - output_file_path = os.path.join(input_dir, OUTPUT_FILE_NAME + ext) - else: - header = create_header(width, height, splits, SPLIT_HEIGHT, lenbuf, ext) - output_file_path = os.path.join(input_dir, OUTPUT_FILE_NAME + output_extension) - - save_image(output_file_path, header, split_data) - - print('Completed', input_filename, '->', os.path.basename(output_file_path)) - -def convert_image_to_qoi(input_file, height_str): - process_image(input_file, height_str, '.sqoi', convert_to_qoi=True) - -def convert_image_to_simg(input_file, height_str): - input_dir, input_filename = os.path.split(input_file) - _, ext = os.path.splitext(input_filename) - output_extension = '.sjpg' if ext.lower() == '.jpg' else '.spng' - process_image(input_file, height_str, output_extension, convert_to_qoi=False) - -def convert_image_to_raw(input_file: str) -> None: - """ - Convert an image to raw binary format compatible with LVGL. - - Parameters: - - input_file (str): Path to the input image file. - - Raises: - - FileNotFoundError: If required scripts are not found. - - subprocess.CalledProcessError: If the external conversion script fails. - - KeyError: If required keys are missing in config_data. - """ - input_dir, input_filename = os.path.split(input_file) - _, ext = os.path.splitext(input_filename) - convert_path = os.path.join(os.path.dirname(input_file), 'lvgl_image_converter') - lvgl_ver_str = config_data.get('lvgl_ver', '9.0.0') - - try: - lvgl_version = version.parse(lvgl_ver_str) - except version.InvalidVersion: - print(f'Invalid LVGL version format: {lvgl_ver_str}') - sys.exit(1) - - if lvgl_version >= version.parse('9.0.0'): - handle_lvgl_version_v9( - input_file=input_file, - input_dir=input_dir, - input_filename=input_filename, - convert_path=convert_path - ) - else: - handle_lvgl_version_v8( - input_file=input_file, - input_dir=input_dir, - input_filename=input_filename, - convert_path=convert_path - ) - -def pack_assets(config: PackModelsConfig): - """ - Pack models based on the provided configuration. - """ - - target_path = config.target_path - assets_include_path = config.include_path - out_file = config.image_file - assets_path = config.assets_path - max_name_len = config.name_length - - merged_data = bytearray() - file_info_list = [] - skip_files = ['config.json', 'lvgl_image_converter'] - - file_list = sorted(os.listdir(target_path), key=sort_key) - for filename in file_list: - if filename in skip_files: - continue - - file_path = os.path.join(target_path, filename) - file_name = os.path.basename(file_path) - file_size = os.path.getsize(file_path) - - try: - img = Image.open(file_path) - width, height = img.size - except Exception as e: - # print("Error:", e) - _, file_extension = os.path.splitext(file_path) - if file_extension.lower() in ['.sjpg', '.spng', '.sqoi']: - offset = 14 - with open(file_path, 'rb') as f: - f.seek(offset) - width_bytes = f.read(2) - height_bytes = f.read(2) - width = int.from_bytes(width_bytes, byteorder='little') - height = int.from_bytes(height_bytes, byteorder='little') - else: - width, height = 0, 0 - - file_info_list.append((file_name, len(merged_data), file_size, width, height)) - # Add 0x5A5A prefix to merged_data - merged_data.extend(b'\x5A' * 2) - - with open(file_path, 'rb') as bin_file: - bin_data = bin_file.read() - - merged_data.extend(bin_data) - - total_files = len(file_info_list) - - mmap_table = bytearray() - for file_name, offset, file_size, width, height in file_info_list: - if len(file_name) > int(max_name_len): - print(f'\033[1;33mWarn:\033[0m "{file_name}" exceeds {max_name_len} bytes and will be truncated.') - fixed_name = file_name.ljust(int(max_name_len), '\0')[:int(max_name_len)] - mmap_table.extend(fixed_name.encode('utf-8')) - mmap_table.extend(file_size.to_bytes(4, byteorder='little')) - mmap_table.extend(offset.to_bytes(4, byteorder='little')) - mmap_table.extend(width.to_bytes(2, byteorder='little')) - mmap_table.extend(height.to_bytes(2, byteorder='little')) - - combined_data = mmap_table + merged_data - combined_checksum = compute_checksum(combined_data) - combined_data_length = len(combined_data).to_bytes(4, byteorder='little') - header_data = total_files.to_bytes(4, byteorder='little') + combined_checksum.to_bytes(4, byteorder='little') - final_data = header_data + combined_data_length + combined_data - - with open(out_file, 'wb') as output_bin: - output_bin.write(final_data) - - os.makedirs(assets_include_path, exist_ok=True) - current_year = datetime.now().year - - asset_name = os.path.basename(assets_path) - file_path = os.path.join(assets_include_path, f'mmap_generate_{asset_name}.h') - with open(file_path, 'w') as output_header: - output_header.write('/*\n') - output_header.write(' * SPDX-FileCopyrightText: 2022-{} Espressif Systems (Shanghai) CO LTD\n'.format(current_year)) - output_header.write(' *\n') - output_header.write(' * SPDX-License-Identifier: Apache-2.0\n') - output_header.write(' */\n\n') - output_header.write('/**\n') - output_header.write(' * @file\n') - output_header.write(" * @brief This file was generated by esp_mmap_assets, don't modify it\n") - output_header.write(' */\n\n') - output_header.write('#pragma once\n\n') - output_header.write("#include \"esp_mmap_assets.h\"\n\n") - output_header.write(f'#define MMAP_{asset_name.upper()}_FILES {total_files}\n') - output_header.write(f'#define MMAP_{asset_name.upper()}_CHECKSUM 0x{combined_checksum:04X}\n\n') - output_header.write(f'enum MMAP_{asset_name.upper()}_LISTS {{\n') - - for i, (file_name, _, _, _, _) in enumerate(file_info_list): - enum_name = file_name.replace('.', '_') - output_header.write(f' MMAP_{asset_name.upper()}_{enum_name.upper()} = {i}, /*!< {file_name} */\n') - - output_header.write('};\n') - - print(f'All bin files have been merged into {os.path.basename(out_file)}') - -def copy_assets(config: AssetCopyConfig): - """ - Copy assets to target_path based on the provided configuration. - """ - format_tuple = tuple(config.support_format) - assets_path = config.assets_path - target_path = config.target_path - - for filename in os.listdir(assets_path): - if any(filename.endswith(suffix) for suffix in format_tuple): - source_file = os.path.join(assets_path, filename) - target_file = os.path.join(target_path, filename) - shutil.copyfile(source_file, target_file) - - conversion_map = { - '.jpg': [ - (config.sjpg_enable, convert_image_to_simg), - (config.qoi_enable, convert_image_to_qoi), - ], - '.png': [ - (config.spng_enable, convert_image_to_simg), - (config.qoi_enable, convert_image_to_qoi), - ], - } - - file_ext = os.path.splitext(filename)[1].lower() - conversions = conversion_map.get(file_ext, []) - converted = False - - for enable_flag, convert_func in conversions: - if enable_flag: - convert_func(target_file, config.split_height) - os.remove(target_file) - converted = True - break - - if not converted and config.row_enable: - convert_image_to_raw(target_file) - os.remove(target_file) - else: - print(f'No match found for file: {filename}, format_tuple: {format_tuple}') - -def process_assets_build(config_data): - assets_path = config_data['assets_path'] - image_file = config_data['image_file'] - target_path = os.path.dirname(image_file) - include_path = config_data['include_path'] - name_length = config_data['name_length'] - split_height = config_data['split_height'] - support_format = [fmt.strip() for fmt in config_data['support_format'].split(',')] - - copy_config = AssetCopyConfig( - assets_path=assets_path, - target_path=target_path, - spng_enable=config_data['support_spng'], - sjpg_enable=config_data['support_sjpg'], - qoi_enable=config_data['support_qoi'], - sqoi_enable=config_data['support_sqoi'], - row_enable=config_data['support_raw'], - support_format=support_format, - split_height=split_height - ) - - pack_config = PackModelsConfig( - target_path=target_path, - include_path=include_path, - image_file=image_file, - assets_path=assets_path, - name_length=name_length - ) - - print('--support_format:', support_format) - - if '.jpg' in support_format or '.png' in support_format: - print('--support_spng:', copy_config.spng_enable) - print('--support_sjpg:', copy_config.sjpg_enable) - print('--support_qoi:', copy_config.qoi_enable) - print('--support_raw:', copy_config.row_enable) - - if copy_config.sqoi_enable: - print('--support_sqoi:', copy_config.sqoi_enable) - if copy_config.spng_enable or copy_config.sjpg_enable or copy_config.sqoi_enable: - print('--split_height:', copy_config.split_height) - if copy_config.row_enable: - print('--lvgl_version:', config_data['lvgl_ver']) - - if not os.path.exists(target_path): - os.makedirs(target_path, exist_ok=True) - for filename in os.listdir(target_path): - file_path = os.path.join(target_path, filename) - if os.path.isfile(file_path) or os.path.islink(file_path): - os.unlink(file_path) - elif os.path.isdir(file_path): - shutil.rmtree(file_path) - - copy_assets(copy_config) - pack_assets(pack_config) - - total_size = os.path.getsize(os.path.join(target_path, image_file)) - recommended_size = math.ceil(total_size / 1024) - partition_size = math.ceil(int(config_data['assets_size'], 16)) - - print(f'{"Total size:":<30} {GREEN}{total_size / 1024:>8.2f}K ({total_size}){RESET}') - print(f'{"Partition size:":<30} {GREEN}{partition_size / 1024:>8.2f}K ({partition_size}){RESET}') - - if int(config_data['assets_size'], 16) <= total_size: - print(f'Recommended partition size: {GREEN}{recommended_size}K{RESET}') - print(f'{RED}Error:Binary size exceeds partition size.{RESET}') - sys.exit(1) - -def process_assets_merge(config_data): - app_bin_path = config_data['app_bin_path'] - image_file = config_data['image_file'] - target_path = os.path.dirname(image_file) - - combined_bin_path = os.path.join(target_path, 'combined.bin') - append_bin_path = os.path.join(target_path, image_file) - - app_size = os.path.getsize(app_bin_path) - asset_size = os.path.getsize(append_bin_path) - total_size = asset_size + app_size - recommended_size = math.ceil(total_size / 1024) - partition_size = math.ceil(int(config_data['assets_size'], 16)) - - print(f'{"Asset size:":<30} {GREEN}{asset_size / 1024:>8.2f}K ({asset_size}){RESET}') - print(f'{"App size:":<30} {GREEN}{app_size / 1024:>8.2f}K ({app_size}){RESET}') - print(f'{"Total size:":<30} {GREEN}{total_size / 1024:>8.2f}K ({total_size}){RESET}') - print(f'{"Partition size:":<30} {GREEN}{partition_size / 1024:>8.2f}K ({partition_size}){RESET}') - - if total_size > partition_size: - print(f'Recommended partition size: {GREEN}{recommended_size}K{RESET}') - print(f'{RED}Error:Binary size exceeds partition size.{RESET}') - sys.exit(1) - - with open(combined_bin_path, 'wb') as combined_bin: - with open(app_bin_path, 'rb') as app_bin: - combined_bin.write(app_bin.read()) - with open(append_bin_path, 'rb') as img_bin: - combined_bin.write(img_bin.read()) - - shutil.move(combined_bin_path, app_bin_path) - print(f'Append bin created: {os.path.basename(app_bin_path)}') - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Move and Pack assets.') - parser.add_argument('--config', required=True, help='Path to the configuration file') - parser.add_argument('--merge', action='store_true', help='Merge assets with app binary') - args = parser.parse_args() - - with open(args.config, 'r') as f: - config_data = json.load(f) - - if args.merge: - process_assets_merge(config_data) - else: - process_assets_build(config_data) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/versions.py b/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/versions.py deleted file mode 100644 index ac9472c3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/scripts/versions.py +++ /dev/null @@ -1,250 +0,0 @@ -#! /usr/bin/env python3 -from dotenv import load_dotenv -load_dotenv() - -import os -import struct -import zipfile -import oss2 -import json -import requests -from requests.exceptions import RequestException - -# 切换到项目根目录 -os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - -def get_chip_id_string(chip_id): - return { - 0x0000: "esp32", - 0x0002: "esp32s2", - 0x0005: "esp32c3", - 0x0009: "esp32s3", - 0x000C: "esp32c2", - 0x000D: "esp32c6", - 0x0010: "esp32h2", - 0x0011: "esp32c5", - 0x0012: "esp32p4", - 0x0017: "esp32c5", - }[chip_id] - -def get_flash_size(flash_size): - MB = 1024 * 1024 - return { - 0x00: 1 * MB, - 0x01: 2 * MB, - 0x02: 4 * MB, - 0x03: 8 * MB, - 0x04: 16 * MB, - 0x05: 32 * MB, - 0x06: 64 * MB, - 0x07: 128 * MB, - }[flash_size] - -def get_app_desc(data): - magic = struct.unpack("> 4) - chip_id = get_chip_id_string(app_data[0xC]) - # get segments - segment_count = app_data[0x1] - segments = [] - offset = 0x18 - image_size = 0x18 - for i in range(segment_count): - segment_size = struct.unpack("

    DN3pMYloGq=5ne>Z9^(9t7==HCIxx&bVE3tb8n>mOVEjL|pn1ck|?%tzC8= zE`{9LRP<(myO?x3rt*U_tt@fT3ft#s+^lLHQ+4wS(Quwfgt^DL5bDe8K5yihUBLMIR$&Ei2?I+l*N$sk$TeJiM-9eMQh`nv@-3b z1t+h}T$)+itt{)Mq37Md_Y?yTx^a!SSM!}5@0|RR8;15xJj5ESZD5GiY~!y%miJcv z#xjSGu*nl)pX5zq12UPzjiqefwHMJhC7TF_xP-tdxApw&#Qe=6N30mgWGY!UpDwC~ z!2RSq4o{A%8iLT%TR!hUA@K{%N{F|qzU}@(094n2CPsCuXV2-r@XRLZV5!d_!~a@r z*6XA?*rb#De2*HN)j>1hCNi`0=SR98o^~h=$Cshix>a}LqoV>sOG(Kd2hGqt zm+r>sWPLqBIsX*ZLmZd*4ise9pJar6L_B=_Qwm-(rwTO5CI2v;K4v=F816;yJvxbj z6i&E5M8)fqZGGevdt!t=XIk&{i=$LM0Z>y-u_d{yx)-w{gt65{Q3Lm<-)jHK+||%e z8e9?nrE*{^!kzuC@b2x-`rg^!@{+5OQ`=JoV@Uz>f8j-#mA=0zsi^W(D}B;zUF4b+ mD^XHxbJp75Sc#VE3TmaDg4z|Kbnf7w^b8Uu<$Sfe()T}z>Op$| diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/6.ogg deleted file mode 100644 index 8ef182aa9cf4c6b045c0e90f89345ff31ae260f3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/8.ogg deleted file mode 100644 index 4533f5087d8f8ed84c7ee5b9d71dfcff718b316b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2521 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/activation.ogg deleted file mode 100644 index 4c780fa71277297e94c856ea139a12304096d672..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10223 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/err_pin.ogg deleted file mode 100644 index ee2dd69b31fdb9fe56fdbf93fc0456394b74a404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3467 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/language.json deleted file mode 100644 index 5c56f48f..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "sk-SK" - }, - "strings": { - "WARNING": "Upozornenie", - "INFO": "Informácie", - "ERROR": "Chyba", - "VERSION": "Verzia ", - "LOADING_PROTOCOL": "Prihlasovanie...", - "INITIALIZING": "Inicializácia...", - "PIN_ERROR": "Vložte SIM kartu", - "REG_ERROR": "Nie je možné pristúpiť k sieti, skontrolujte stav SIM karty", - "DETECTING_MODULE": "Zisťovanie modulu...", - "REGISTERING_NETWORK": "Čakanie na sieť...", - "CHECKING_NEW_VERSION": "Kontrola novej verzie...", - "CHECK_NEW_VERSION_FAILED": "Kontrola novej verzie zlyhala, opakuje sa o %d sekúnd: %s", - "SWITCH_TO_WIFI_NETWORK": "Prepínanie na Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Prepínanie na 4G...", - "STANDBY": "Pohotovostný režim", - "CONNECT_TO": "Pripojenie k ", - "CONNECTING": "Pripája sa...", - "CONNECTION_SUCCESSFUL": "Pripojenie úspešné", - "CONNECTED_TO": "Pripojené k ", - "LISTENING": "Načúvanie...", - "SPEAKING": "Hovorenie...", - "SERVER_NOT_FOUND": "Hľadanie dostupnej služby", - "SERVER_NOT_CONNECTED": "Nie je možné pripojiť sa k službe, skúste to neskôr", - "SERVER_TIMEOUT": "Časový limit čakania na odpoveď vypršal", - "SERVER_ERROR": "Odosielanie zlyhalo, skontrolujte sieť", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Konfiguračná URL: ", - "WIFI_CONFIG_MODE": "Režim konfigurácie Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "Vstup do režimu konfigurácie Wi-Fi...", - "SCANNING_WIFI": "Skenovanie Wi-Fi...", - "NEW_VERSION": "Nová verzia ", - "OTA_UPGRADE": "OTA aktualizácia", - "UPGRADING": "Systém sa aktualizuje...", - "UPGRADE_FAILED": "Aktualizácia zlyhala", - "ACTIVATION": "Aktivácia", - "BATTERY_LOW": "Slabá batéria", - "BATTERY_CHARGING": "Nabíjanie", - "BATTERY_FULL": "Batéria plná", - "BATTERY_NEED_CHARGE": "Slabá batéria, nabite ju", - "VOLUME": "Hlasitosť ", - "MUTED": "Stíšené", - "MAX_VOLUME": "Maximálna hlasitosť", - "RTC_MODE_OFF": "AEC vypnuté", - "RTC_MODE_ON": "AEC zapnuté", - "PLEASE_WAIT": "Počkajte prosím...", - "FOUND_NEW_ASSETS": "Nájdené nové zdroje: %s", - "DOWNLOAD_ASSETS_FAILED": "Sťahovanie zdrojov zlyhalo", - "LOADING_ASSETS": "Načítavanie zdrojov...", - "HELLO_MY_FRIEND": "Ahoj, môj priateľ!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/upgrade.ogg deleted file mode 100644 index ce12dbf58ac9906129878fbc79917ccb5bdaba16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3417 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/welcome.ogg deleted file mode 100644 index 05b8cad57bf1e090664e3a93a01452bc781e3e32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2630 zcmY+F2{c=28^;B)6KkrLh%NEeZp2nws+QVG>|;>D5W5nk*4RgjB57-DT1BpD+&E6LXIUZ#88Fbp>T5 zr87d5c6kMQ24TEHb!eU^%~RH-naWUq-|IoNjsGOpe@)|PahCY3sf=;$L!N*TkC4c~ z&#6TBxt~AwyS4 zPMGJNdf_X+g4KDQ)s&1hmY{3;7hH*2t6^+@maBt=efR5nGfE+ORi<%=Oji2z7w5Hc z;AO_^<724!s6kQ39pQ}Q&|!XVmS?2{Jk}+%tv;pFYdn(M=mC{V2e^y z+HT<2er*1hv?8)|FboNm|Mi4pzY7GBmyTZ33w(46>WRi=i_-n)%VZGQy}``N$f50p zBtm~Q0N5A48#|LoKcPVs+cXm&!o>#++RzHZ$;+J&L4okf8B3IkzLESSmC|e=&#`n0H80So>>KQCCC1i#sVuOMGj^#HdEM5Xe4jL@Y5RUY(&bYAm zjv<-%DyeuxFrW2_zs6Y95?W^~A)~*G>D)D-M;p`N*XB7*0u$mvZ}E#fhJkwG|y?hMid} zSpX-T0?kiZ^ikzP=*SY|qTX29jz)%z15d}Qqsz5!w*<$S9Q zYZZd(>f%k~H%l;C<0DISx$X}~({1)n7m)FN1z0=`)}p41RP6Snv?oUGKwM-9)`2(R z0Y4P{-rrjBe@_oOP}>%c5uRwqNQnd`2{rtnCxTY`$^LKVeyq1NT=cgguq3 zjbIx4nMoy>v2Sjp^|QJGIx6tECP+s8X+NV)0N?TSW0gN3_k6ocvagjcVe#T{RrGSW z!&fH{$dRGr1Kxv|E5(&l?E@=Z2R@%Tcav){fP&#jwXFRvLBT3C-?0@)jHA`$`|?{Mt%Qpj#ziKQ)rd*G%9iD_$i2=zmCiWn1d+sJ*hKxSG&gv5 z?+lstrqZn}Og-LJ{zBWyL{6Hsq_z>oo1yIMOT-cYG_q4)E z*`jkYMOExMwjx?&XceWJi=#x4vawsYy9$`?r2r-#cc=H8Hm}s(g)R<;T@`z=$|9xo zYPt1I?@$h8wz>AU|CMX5w*0*vl@_1nW_RjNwhMBzGZR4Kx8H7An%JVs==@?GH%?&6 zQbCsnAYJOK$GvXxRNZnqnXB+Nq7(gkF+!wlogh^TW(Aj+iNDF@`gkWn&!URmIg>}2 z=m;j|hWRxsIBS6*mZY1REWFX(nq))xv4?9aahPM?3a0QMTX^~VylzOROqOzr7tqy!wn|$% zGs>kc^^Xlp%e}<&H|y6WereFcr4IUN0}66V`J=E5t?Z1udzsJ8WXQ=w!~Uba$M%I1 zE(t@kE=!#^5jWUYn+;C#^impQx)Q^Z&F=4!(v6=R-k5Va@zqFV_H3NQjK&jsc%$Fx z9ec=$)}p@Ley{~(ch9+%@{>R~)9uhe$UJC&Z3DO;96L}v>NikDvec)YQn5!~+!3h^_uTo*CnX&t~~Q|<;XtY&n(IOtD`HE6((}hO@HG|fG)^E?miaiWY~mqOb29b=tXvx| zU73Rp*RruqB|YQ0uKEEx4aMSx1wd-d zsW%P!-O(3`_7lDw{7GnmwsPA~0#i6YuEpQJGFI3I4jd12+%X?XQW<}O4CP8ushbiJ zcnrue%jNF%!Fk3aGv8ydcrYI)v)PO#G&3Sgp$Dw9j40Lq`~a~Y!@6#J?~qJF<+7%iz2ZBl ztFhJ6_M?&{P7U-}<09_;S)qF=h(6xKc*2%Mn}9r=EF`G4EVZ-RW5mHpWO@DiF!Mn8 z_s7w%pO;cvQ2opUH~R-1Iv(*##*c3eVHy6V&$$_tt)c&W`8?bIVrlvuTcW&uj-{#o d^Ld}zoOfyJ+|K%tfA>Js=iIiO^F7d1|6jvR%mV-b diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sk-SK/wificonfig.ogg deleted file mode 100644 index 89906c60f6eeac51127482d68e74d6db0fdb6e60..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5506 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 GsOvu-Z-yuU diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/1.ogg deleted file mode 100644 index fcd0f70202c11dce6bdc0aa6d2b00657d4739550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1324 zcmZ{ec~BB)7{)~tZxc-sR|3z<+!FJ?N2SzUS&!Px4#5Kw!$eujC`?p5GG$%aycTuL zaxGU&!2^%hG(5_p%n}_z%Z{OS5Y!b77Mf=N+h^vT?|Z-J_r33f!eXP<)YZPJQ{e8W zy3$L+QUE5X3#5#YBy=JG-~kvq{S`r}@c*R30m|-XR+j_7SB1x*u^IZxmvHpY$!>@P z?gtP~PAUSbtRzB0T4EB>SLr1vJ%p#yM8H$eVbYWzzYgBf-KXS~QVmvxx?$2Z4?2Gi zi_1(8adkmj1!QR}g{SVe1!UzX2{$oDix+R%h<+DIxKH|u_duU*B$C^PEpFy?97={1 zkOghQ(?Ez0w`4BzgV9l0xHElfpe(98cF4_l*`!CY6qE31bOV%IP+%E=vd0d z`;}q3YcLH~_#9>?A$h`0jHg=La#rm@rd`H|`doHqnjnf;dR2}@yMZSMxBZ2}s)f}| zPb8;5EM-67g1X`lAG;GjkSnfIdsqHCc;B`2^gL6WXc@r^eK5lzA;lt|mn>YiWsCLq zSnxhlq=pffZEmS3<4SDKSE*Aw}vmp28k7`9+fy2sp>zi^elL$|!Yl65Y7O?$(? zkfvAD8;5EH;33Q&T)KU`{P{*jQc`NHGJSz@S9 zPe_S*LPw$}V`3drjo9<}wWF5-{>(4%Ml9#B$J0mSFWVP0#z)z#30dLoz$2u3GTnG# zJ;gr0j~8IQvPHTa>#YTrW@`z9uH&gTww>D;mm)aYl?g__hxB?}5{us^M=Vi5n=}Jc zoYmm~=`@l494wFWs>@y4%E07BkqzSgCh@qlR-@Jpa|^-n={1k)*Zfk^i(1K9^B6UE zV5lOjUM>&I&5;aTcZSno0U1rEHg+YDnf4TgFeIy+x-;Jl5?9`2! z$V4@m)lksAq{ZV5m%F(loq|P16+zkp-H9?>wR)&i@#~->y0%XDZS7}teGs3jzw6BL z8j>FE$X;OOXaH?lA(9}>gG5q1vC-gBF-0eSD2|4X+-^^j7P#yy%_|5@<5Nw{;>hT! z*|!jeCT&rg%WSALce9BmWG`<7GU$8_ zie#$f9{sbae$8r?0roSZfkWMddL3ZDKYMh9vXWt_hc_!-)iS0?V#jD)$NV{FP(pn_ z-frgM;a6k8lb|ov&fLFi8?9gp-M#&qWfYnJo%whQwQ3sOWNDNoaj2FAVuY3U>|v=S XqGfAdbH`ACusN2mp$e~z|3BxyNkM(( diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/2.ogg deleted file mode 100644 index d5c63609d21e1f085a3bdb476dfabd017b02aa3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1552 zcmY+A3pmqz7{_;^Nh9Ng#8KuJ5)q4BQyk5dORix>%!b^XTiTQ)`8| zNOGIpnhtUcP2xn!%4O*M=hTz)KF{xYe&65c`@Zk*eQkYx?LiRGk5FF}zH1eo?Q0BY|i;4TCKiCcvQYU%+WKY+sgPodM--4KLOTtrxSfR`T1 z4rQtV1fDFb0y$)@G`BgscEV|KXLz&9GErV2SuzHh@N$(g6ki@Eceu^m*>GgmwKwyT zd$8&5WYf_RvYfDFE(K(z1NUe{rivY@7lz*v5PO9Pu`Of7dee7vKmBFAySl2dF>?O> zUReVlE}ch1zDpi%PA_e!OKZfF6_CuP1fhXw7e|XA`&}!{uc`;6ooC%JWnq?FJ?Rb? zsDeQhGtZ;Eu>d54oi6I{d7E8QKjx0uVyGX)R^P>xy(FhNtb;+b?jyZ-0E~pygc~Y zK@*feCArpIeR5=Nh`MCdoy9qwUf8bV`cs95UT=EUrepsyLTw zfhJvDps2a0YN>Ae&!vADD9AxFlTOBHlHNkI@qM`}z($cZ8zSu6I*=A<@LjrnckKs_ zxGXfcttZM(u2KL+-~XSCR^} z1d1CC+G<1x)^3`WuDfPPCPB_bx)PU(5f00y^3Mx5Nb3=K;SX4EG<|*bzc(MPU zaPU|k4wJ9u--kjhu0AOZ8&?qAtmRE1*wII;bBNaciTMm~bwp`@3L-cKV~W$q!hUN2 z){CrYPD(PLK#gzAG>+aM(xe7^X}Ib78Fw1TKBFBhQH=3DhP7>bTg)zerO@|yGhK^^Ggf7qipVwh?x^-NYqXY zHv__x<(2e~WSKiu`?GHy5h2JfO}kI##dZ|I@?u=XtgC*Rr5(;*?UgPvQC7cQa5Ayh zp5eY?o*d*-;XBqosu!r(&B^Qr4Mz!Z4qf}mDoLZiHNG1p?J4-&#G&R%(<>o7SsWq3 zQ)=`|$$p=+(GN3JTAPZ0CajwKtb5zLR2Pq9U zA6mAUg7jL!y37(iFg{!IaP;)_$|7X~PnHqkLp8g?ahtB<>shx47P}xDB#7}h-G?X` zi`c<(YRVtp1sm)BA$sRRsVl$)qTe4LiX(4v4UTUqhnz~Ux@C9Ab=cFEs0#)m0-2Ng zfva4Ufbd#jNKXgexJy~)R=vkr5+3?9JA#4w(Fv%Pr)#iHJ#sKOzTFGxZL})vdtav} nAhRkAh1%|I$Uyz~t1SwsZJF&1)c@)NdK-QDYI~OvV7h++W6#sY diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/3.ogg deleted file mode 100644 index fa0774af9519b6d28afa6ad86fb5563583a292ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1385 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/5.ogg deleted file mode 100644 index d06e1def58788b959663729edbc50e6b7081aec8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1308 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/7.ogg deleted file mode 100644 index 36b701f3ac369d494940f8ab994648a75738640e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1623 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 IW#A3}0yWv_=>Px# diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/9.ogg deleted file mode 100644 index 944f9224508735adc54182540f959dde4fe1ee4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1522 zcmY+C3pA8@7{+}}G3#y+23sb#GR(L&X3ddXD~1u$Y+DI~Wi;a&Av;V<$d-)7M(Y|j zmyBy>T*_1iF*K5f;b?|(Yj8g07I z6pccO96I0=L&+q@4x&z!C+EJ}SGz#aWpW9UAac zOq?GULojhP0gFu6)tCD1dpt{qTe2=g9W0x!TaBF`B|3WyPkx$5QaElj9y;mR2k*m*+XGpN3#csPOD^Ika0vV#-!kxyg=B#&#f}L&&qvBi{lJ8Cb28`q2xUu-FCS5 zP@g4`y=;RZMAxLbNAc@EZDU3Rhv>Qkjp0xp`9Ji)va18u-T(ii9Il@4WTmc@otS6 zMrQI-K2u@&d0dLA_TgbS(JF1_c37y9BIgb~qy3lzlcqf@p)_}(SLivOJ2W|pGN!gH z8v7={`gs^q%e!^4@;@Majcl{&h+kZ~LM*zL+E{p!XpjpPB{thvm^ zr3AB1VPP^Mr(U*SgWcSlalN&>U23H*%)0~ru4VVB8;ME)h0|qk;yS*w@mIKPZ(-kL zx{crF!jv~MJw!8g?@+PB`}FA**EZre3kqS!(@bC2(feyUSFL4A7A&}G2c?#R0jnf#Uh3E`eKH-UEc4(fN|+KgPbx*P#s7X` z;RwKqBI%pU3?p9OQvh-Nb@T0=uZcf!c<%= zGFA#z&0A7!m7v*IYB?f;Aa2wiQy)0n*)S*-VsBHQi~?ZKb(q`nX4W%2W_EJ{I#umGajdvLBM^3W{HG zrtk~)DZb%%>$aN5`v~c7PC@`S3c^UMujUqSCcK!nqzH4$O1vUrHWeRP=pTE?QeOj3 zH)H%v66@?_U~I*`pcbR|nlWOzp!#3#2w$9nN~}`=F8B{N CcD337 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/activation.ogg deleted file mode 100644 index 73d10f3a709cc501d363c473cc2ebfed417ec40b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14764 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 V|E>kj{|~j<@&Df0?07x?{{Zif0K)(P diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/sl-SI/err_pin.ogg deleted file mode 100644 index dc692f04d537ba23ad51268ac70240ddf6f0c356..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5445 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

  • 7MADxTjr8WBy%}M%6-X*qYH(0h$Jmz)cLuS$YJtJDe8z#mbpz6O->KF zPpFnjt0Ng*rWLV@mCHCd+WD>LJm;*>^SsaVelFk7`@Vm?zLAlBGO{xNLSf|#O|tzE zurdqN@Qpi_xQ`GT4uhd#-67v2zLNNVki=mSt0jp?U>Hf z%r%9su2b)J-^!+bJS&%XTlArxgV$M~!{y%`P(0sA0$Zc9@3i%-BZ)e7?SzS`rh0{J z9alS(%Saj#K+9I85@at{UunB?)wHr=Lgirxy(MZq zBDz~Ia?0Bmb7U}OWrlY-+MvW9T})hbgHAJN+T6)@9Iv>nCOk<)ZjDE7P_g0MTL3-6 zdt?J0gO9hO9y6o23>EK`x34pN^>x`Q)tP;CUgN4;$yjt-9uVx>a?o(iqXYxLcBbJQ zjna$hWNfe278uKUc9S9}(zeNF)u5ewTg`N>J>2MCB>by61mk8UDD4tBJ*U9BOex7wCHj7p4ny+6(kyrgVg|_sd?S8ev8!yng*us7ewmUZ%dX*V{Nx#6j2JX3& zxo+s9@x8&;(Gqv_jo;iu8RzhAMKeu^tM8r2^ic<#JWf-v$b1**k=4|HVz1CU_={E8 zH+~>-^Hc4#*N1VAYd*1NNt%|wRsCJoM^wQFS>1AL$1wEk(p{Jo?6UXi@SGxU5+G+; z;33w&u8dCfq$|FzIh(6=$80oTsP5HpEypVq1UQ1frh6#rL0U{pry(`dU3Cjyl>OC~ zG(08IL4nL4uIn8IKy57*rAfw6(S4pc)BhCfKyA+Fr_IV}RV7zQ{ouKpu)EJ~l(n^` zn_cs=ac$NOmbp>w*n@84!V7BR!I)*<1Q`W@TH0%ORCIE;Pn~7C3*q;vy|b+xSUB=~M6;xXs$l(WCFSWz48tCo41h>gM8*635v9=4KQ}kQ zT{0XBNxhJAU}-=Wh}SRfc@BNoSv#*~9HnZmeBbjRT?YVEQ-d@|8vEw;X}5JUJ|T08 zJ{QWO{WQu7Xue?u#ToGSFDV#zA}gQIuI%b6umwP6Rd{di$Bfj@0FRc?Irxz7iv_d% zGa~AIQ`K8|S8vNe!_<=hFNe}K)3-GI-q_|i2*|YO<5$g#HHsg|%S- diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/8.ogg deleted file mode 100644 index 20e94daa54a27560b9255672eabf7cde105264f4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2181 zcmY*a2{aUJ7q$$8ke$g`r)kPQ4P&SwyFpDfB*Pfl8?t3Bq_O*mVzO`1l)Xj9nmyZS zKBO!eyHY4i^c8)h|3CjZ|2^kD=id7~@AKaGy!X5p>*;xkjf3sKrXtW;a_E+5E4Z_Z zV*P`I%-vnw*x6C+?M{Cv*hBjN?2yjRioTr_pJYcL(s3@HLHw+Yl}m^R60WAL2G`Iy zWXQ0V`*l}8H}^m^3v*>*a2*y1m-q3$>c`snAK`PaSUi>;3Lh4Q)bb+;6CJMx2l@vE z_yl=*yAqr&3`k^IIWEP*s01YR@lbY$;IeJi-9&fmBXSCe$JqrRhj%U@bcC_gMMW+r zyXRXW3{+JPnp&VFk#N(&NKXJ;wT{ralUT>rXjJxOx~o3BQjpH1k9zLe9JG`xcN$35 zlgJ8E2ptvAjRmvCH2pgh)q-ATGi4Q9&4of!jBxV0e_r zQ6$)X;1{mp3PMMb#y-N&wg4Sf%JHAJ1pXG;c(Hmg^TBj^BgW$ji42xO=tRd?EG*wb zNv@d;@|vW3>#1K<<(rN&FBIrUa2$uw=`tY4S;u$0Pfl(&$e3?0+Mg5WOd3~XAan^= zUSE{mOA8ASd(hLm!ZTAstn$GDN17zq$^X#_iz{we^xzqe=T=@z}m*!_@Z ziM$=!jz?$NzkSji1Ey82H~$jA?+O2nu*H@ zZXoNCU@h6jA|~}p++f#!8gErVQmoxvVkG*eP?nu;-G~u0Il7+Wu90er`xryWa!%1( zZ2Jk`bJ9{xRD9qYqx(;QUbOryl*Va;DBszw{X(kYXG-Ib<`+iMTpX|e{ch`uGr0kCYVZ?TSbDU_5L@3+B=7AQ#u#wR8x*oX zHX`A^ve7skf9E}Fz9hE}% z#s^w|w_yMFB`OQ-x>hcw3o0Z5;!?gx{=(kAvg?mS*~k9W?j86_u|0}yUc<{KEaO6uvv zkE-9_n+H9P^@m8wU~tU0^G~@(&KIsaStcP@Pv}^Z$S^3aaDrJ?DQS~CFSpni!AtMU z^ko`o>3L@^;2d+q;+}9BJ{Tu=Pc#G+Es}lQ#IrQoYKTo9p*Gh)l4fbf567nQ1G{Z@ zsgJU$)hl%_xqT0T)hgR&LsI88C2u^!R6`vqm>O^5{wfL<`GhB+xLGZu@ZuZiHbuc= zTp^Y>ueGbr>PZG4cZT&=X3Xj5p^aXy5wD+naKu7|NTPD7ON;7!#6p2gYN&^!xxVw>&UU*U5I@Md7xBzUF1J(4*A%7(MO4I4z7`gPTa4~tBRQu>3-D>XzK z_m3?jLV4=+xhhZ2eytND7?84*Aa@nQd&>q7^3mbeQ$KK%i9M0zYz%O=& zsJU;VQEmDIp5+=WNn9E}R*zG+r&xrDJV zO0QwmW^$=-A?5R*E;We_UyBSJmG-IYh~RhG8JtrQ*S%v5D59Hm1vcJ~`yDwg(9>J! z#Fu0=1l^A@sXd7xkwFqC+q-{D)XZryV|P5 zJQ?p^UWKlQh4^$Hkt=Q;*RaJ&fT=~1+trkEr3ZY?>a71wT#RpoikzeBZRUYgR`0Ak zsceK9c7Eo~FYAFA%s%8EsxesYsR-Y?RI0}tv{E^)p&wA@d4pC)eXS^I4b}NG-vG<= zf5zLN`Nqj|L!J`b0eTnXHM99n@a`EBSrWwK%PRb|EZ>lA`$Hyme`k&{=nJSs0~uvK zFrzW>SU$TeY_r2^@2EOp84>qgAJ|b^H)2?@U@_xwsxIM&x4zJ<(oP~v9b*AcIWrV; z&{OiQB|pFiof+`*GAWhrLnX*%ZYE-LA9Gi^G{5NQx;zI|no^7cz6Jf>{njv^_ob|k ud$T0n;)4=^L>3SP_6I_z((F>yPL&c-!2a;Q{>$y9B9Pl-sI&hUq5cK_o#`w9 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/9.ogg deleted file mode 100644 index 61f7b96fe482dd82d9c9d059861926bb58c3fe33..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2479 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/activation.ogg deleted file mode 100644 index 8fea3ae11a13b6a384c83cc8091677badec295e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12883 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/err_pin.ogg deleted file mode 100644 index 822176349d85217c7c8218aa83cad8125347d220..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4105 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/language.json deleted file mode 100644 index 5a6fc0b3..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "ms-MY" - }, - "strings": { - "WARNING": "Amaran", - "INFO": "Maklumat", - "ERROR": "Ralat", - "VERSION": "Versi ", - "LOADING_PROTOCOL": "Log masuk...", - "INITIALIZING": "Memulakan...", - "PIN_ERROR": "Sila masukkan kad SIM", - "REG_ERROR": "Tidak dapat mengakses rangkaian, sila semak status kad SIM", - "DETECTING_MODULE": "Mengesan modul...", - "REGISTERING_NETWORK": "Menunggu rangkaian...", - "CHECKING_NEW_VERSION": "Memeriksa versi baharu...", - "CHECK_NEW_VERSION_FAILED": "Pemeriksaan versi baharu gagal, akan cuba semula dalam %d saat: %s", - "SWITCH_TO_WIFI_NETWORK": "Bertukar ke Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Bertukar ke 4G...", - "STANDBY": "Bersedia", - "CONNECT_TO": "Sambung ke ", - "CONNECTING": "Menyambung...", - "CONNECTION_SUCCESSFUL": "Sambungan berjaya", - "CONNECTED_TO": "Disambungkan ke ", - "LISTENING": "Mendengar...", - "SPEAKING": "Bercakap...", - "SERVER_NOT_FOUND": "Mencari perkhidmatan yang tersedia", - "SERVER_NOT_CONNECTED": "Tidak dapat menyambung ke perkhidmatan, sila cuba lagi kemudian", - "SERVER_TIMEOUT": "Masa tamat menunggu respons", - "SERVER_ERROR": "Penghantaran gagal, sila semak rangkaian", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " URL konfigurasi: ", - "WIFI_CONFIG_MODE": "Mod Konfigurasi Wi-Fi", - "ENTERING_WIFI_CONFIG_MODE": "Memasuki mod konfigurasi Wi-Fi...", - "SCANNING_WIFI": "Mengimbas Wi-Fi...", - "NEW_VERSION": "Versi baharu ", - "OTA_UPGRADE": "Peningkatan OTA", - "UPGRADING": "Sistem sedang dinaik taraf...", - "UPGRADE_FAILED": "Peningkatan gagal", - "ACTIVATION": "Pengaktifan", - "BATTERY_LOW": "Bateri lemah", - "BATTERY_CHARGING": "Mengecas", - "BATTERY_FULL": "Bateri penuh", - "BATTERY_NEED_CHARGE": "Bateri lemah, sila cas", - "VOLUME": "Kelantangan ", - "MUTED": "Dibisukan", - "MAX_VOLUME": "Kelantangan maksimum", - "RTC_MODE_OFF": "AEC Dimatikan", - "RTC_MODE_ON": "AEC Dihidupkan", - "PLEASE_WAIT": "Sila tunggu...", - "FOUND_NEW_ASSETS": "Menemui aset baharu: %s", - "DOWNLOAD_ASSETS_FAILED": "Gagal memuat turun aset", - "LOADING_ASSETS": "Memuatkan aset...", - "HELLO_MY_FRIEND": "Hai, kawan saya!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/upgrade.ogg deleted file mode 100644 index 0bfcdcc6ecd85e4af6bc27eb33f6c09bca808a6c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4065 zcmYLL1yodBw5A)SK{}*E8ewPcq)VhbMG%k> z1m5ufZ@stIy6fJ%_jmR^=iL3BZv&m2jIeO9{@3bva)j<5p?~wXu&IHbzTR4ncCWFq zpJIQp`WFJchyS15!?7`M_6y6$*b4V>V>>5rGK@#Z&hH;-F%cONF;UTb1PkVJba(K0 z?Fd%D#2hd&Fn?$f~?c3G%YHadZNCx_Y@exr1K2 zf@Of$51moc7AMw+wif=FN{Cs=hWX{9QBnx_h{qQ(jK8E#+U+PRg zpR*hrO7IXahbRgw{6!wTU+_`}FQ&J~uX*qgullwH~(bRsTt!o<;c8ojAPo$rHBq%VolET4Mw2nQQH5&Z^t zx}D;K)Lh4~^prwM3Kjq9Z6VvylwApKL;~#;JcZ4RiGuG~L`|MDNPHsJ<5Y-33#EDj zbZ?=HPr!!fv+kKJxN_L8yCyq8XsqxpyTL;>CzABJkYD_z*`CYnjUWgo7s9mW^3?5P z)yb6gk3!V^1J+4lDP?HsFKn`aWW|b?dF=t6-I*nQY{k8FsR$G8KG!yiU8XbaxY@dm ztvyfmndHk9Hri~0)cm2$=I~_f!{)TQeUNd%+{|G${wuecu%>WlZ8T0j=D+h~Db-KW z%`c8bK#@ikAe?Dc>zzjO+=w&7_7>WMMY4JD++q(2;|$yG?6KJ7jpAsoo&r&JKD@XiEU^kp-`T%!AfG&}a>EaL&AccZ znW$+5o{6eEp3WA*u$B|`UhI>(HXHDz4*bbH-p%qv`ruRBaSD5#3c+BRqoo(b#H~>% zWonj9HlP%m%9$X`v4~Ud3T_esU~ebb<|Y^RF~N~eK#19Kv)`~zD7i{vy?%T{Kf&>0 zs!dqQr4=%N%q@FB*n`!8DR{2d7Vesea`9yz(tW+n6L?r-#e-}s{z9CNiC`-1_wsWQfmsZMfyMDnvi;-NAOcT;9L3i^#S?lzG)Jpk#{bxNtsmfu^( zcj>n}bhBHvMv9N$(jH;f#MN;9E89T3b-!XSfo^}WBWpLYI#z3m^C*op7;Jgd-ma~# zP~FDGuSL_|wUr+=s+!UC{U;zt)o0ta01zutkrUz0{ZtzFJ@S0wPv-@7G*lDdYgKR5 z)JVxI{fYG4&^m@gMLZEPP9rjbDaXff=uv&<>@_SI zQ)2v{B`kGwu5kx~@(K-oW$MU;5_Jrh*-^g3bzQS)g9u757}zndzcqGs0P=a79_I2^ znmjPq_YW%cwR4d~zu~?#fEUWz3}I!-nHws^7VRm?a`d+6_=OrQiVXS~PuoTutYS}+ zXep3do1}N}O)F}E@O}N4eGr733zd-*aAmqr$ubNK80oR}Q(VK6JunPhz7aNkXfp1{ z8NR37B;_%-v?E{?bN2Bf?%ali2E!~~-hT+`8zTgdi73@?u5WZyq% zqRMfb=`l^@UqKuJ>q+pW-|CsNXq=&059+{trs_y6xYe!H-vk5-8`OaPkVl!k;sLab zTW48zwEt-*F6OScEH*>w=I-R+ zc`+RYy#5(iK)|3nC zRFyH5o{!~nXvpNysM5zkqSal)Cb-IR7+M^D7VuCTwe!JA!YA%vo+%|vH=YDo!6d>W z0QA3OKPGXC^`fZMqsB3M(uVmMH!349U%+A)*EU*hFS&?})1+$yJMHZn6}x-J4Rw!U z{BjVACRD!#qO|&_TRCKLcHF2rwmwLsbOVWOKk+(==v|F5^b7i}2qTwG7_ZmUT-ia{ zk8Ln#An=}OQsEFrj$Zfbi{g|lvFczL!T_K?9rErQegb=)IA?ZlV|vgohjXc~3-kGhdY`&<(0PuR6Ht`qJ3 z=~ybFz6_^*YhTx<48`J$ZTJHUa`~ywNcwuJXNb!ccw#!#-LLoGVDx|;+G(=OHas#N6w>|drJdwog-1jM zJ4gG&4+0v($E!dvGmE$%D;;84==j_mukW*;YE1K0@pcp#POb=59mJorU)fgrt{(Jf zx&N8srcA=es{_=*1GLhCcK-x}TH-ww0>3^vImqlh0{Sp6U`{h0-pKE9NgP#ddo8Yo z62i_Jy4u*R`KF^Y9_sUsd^|-P$^7L>uK)*8l%ruguS%6hB-xresRdLOSNC^PVrH}Y zhl7ot6%@ypG5;uNTEBpARASjZr*cjC_K?N-bVNTqX!$B4w$<1+_q6?+k~+h%*Zqzn z(nl@JluFya2yrs@*oEssQC?m`R(ApOkI{_gInSOfi-A=5*2vQn`$)g`?=Ej{2JuM}xSu0+H?ar8;FVGlX zgD>&MURERBGfD8$UeGt6K`4A38)BH6nVKBe3XhxjtmLkAy}L)_Y_(>Itv(a#Xe8`3 z3F+r!w(v1ZdRqF0s7i$#DL=+niPQa;z&}0yYv@mL>E1v)XhU0?rLl`JYV(WJ4Z8cJ zcU%~e^+-4GPnVHs6-Ra+mH=Ht$*{2%L~-*L<$K;|krcBSV}hW%62?xke@P2>LJ4C5qP7H&>7a~1y$&aKz;RzywD*c6SPvhrrIkK(mpet-v zH@t>n4~QF+5BOH=-|nt)dVJu#?_(>S!N?IZSYjWch-nv|3>kkge1R|e7GG|DnXdLt z_y@eel6=-Kd`cFVFx478e`&ifc@6qy>Gd9Er+K0|+&7S51(Ueq_P)8VedkJ@ly34# zl>)KgKdflE@0lI4+U>rNY~lWN6oFlswK0^-vM>{;j_j}B1;~&R@V;x%B~*JE_Y8ig z?0pF-znE#mdzd%#Rz^}vg+-SVQGC_09WIQ1o`?E%>#h+5C!s`EeUAY&mGv_2NQCN~ z4v72dJuukuVe&$mbyZa>j+l$b7 z%~$}b(oXfakT!GhlQBcx&pDAR1SRY}(6xWn67ScC|5r;qj9TI|oaNvuYUqL>v{WQ- z5*3q0_nSB+(P2SmYeCP+iBgq_^GeaYj8O%*wIOQ+zibyWO_10}zgvqPdKHR}XjZmWp%-GoUxJ)0w-M3o~2)1Fd1NZU6uP diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/welcome.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/welcome.ogg deleted file mode 100644 index 7cd32e09e6009a301cdc4508c23e594104a6062a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5732 zcmYLt1yodB)HaQ@l!VkU3?m)VlF~UK-JL@Tf*{>pQX`-=2+}bFGnB*tN_T@G3Ib9p z4gc`H|N6eO)?GLDzWbcJ*FMkl>vd3^^8k-v8?dPlJXzPHD zErH!*`9Cg@d-wkx_wLx3yTbz-B5av^cLQ5zUsB8yEn9ylF(H0&ej!1@dk<#J;pl1a z<>2TegR$9TY(kP4qY#_BtDP6-#s31!cVql8<38~HqDGQ>Zz(-o-Mp+VT-~4^FJD33 zUb?$Nqk!y@al4JfqGUa*;kvbcCDn0#H(v!&Pju`jxk)wUv1lf(apf{!L`PR=z4odS zDh*-t;gV=Fc=$0Z+-RqJ#6uHRe7Q196+@sZz2Y5NJg;B7c}7*Y82P#d`!46aNnZ#6 z^@s-J(o%itheol1I)od!J`S_1?Ds19kOKXDBP%+)_EB`bu;xbCo0_q}4&O4uz-BPy zZDNjW)fM-pT8{o*19a#%-ae8-HCod8s%Pd!FH(20|DPOiY%lnlzwvt5e}E;QO80t4 zPJkB-F4}kc1&so+!ShrRkiy%xb;a+6O?yJ$-bHjls$5q*Z9F{L&ISwX1R}>tg;Af| zb6t=mlr&4NgXL<@0`?jr*~2j;PiQRpyWIHbvdF6NiAd; zE)NZ?3#o6OjN@~7h@gqszoDtu`M4&1qPfWG{L6Rh?*?am1u|*Eo8-ZR&L>|F!w2)W zeCe{b2Er%ET_PyiChROOO`%b&kCB0kvzFA_=xYzkrtf&V`fG3{drQHmzN7KupiNIo zr0*el{(vs^m3hrqa8Z>+7F~gKU5&(NTLpb&LdVG9HUMy``W8?6n4&!7l7>ybuwC-! zr94+FMcH-^G>VB8>95_BQx|vJ>FoFlaHOzp#lqgY zUAP`@UPcECn1gr!>)cO}t2sdtR%1`w7HZhhwUR&N)J8nqrnMjUA+@;bq|6KA#&7*a z9(-#r;%J1YWf;~fHUA?qrS|+xR=Ky?15ZDd)>_*(xQk=NjwI#i7IYO<9rWl18pRHT z|85h3czt+h`m_qTsFcJklqrWdBy1yvqV}~M8wspumVv*A`-ADjTLJ|tPje*C)_Q#^ zS5D_%jwxN9I_M0y;Sh${wVsewo6h9!Ei;2IUVWFR&W#R*UHeMuje<4gxPv`MvoQ4x zfa9dOrutnU=d7Lci%E_}HJfb~sO^nuA7e zxR&y@W#x2mAK4Um47XLbPoB)uaLb_Tl!!~8?9~*mio;aLy7vuuh1;1Vg{Eg>7n)=- zbp}L<89;$%?+@JD)tX)&S-uW1v1g_7+j(O6-D``}NsM#b z-lVQ!GRTRvsM$V$x8#Sf^QU3Ab71q_Ft2P2YL0O0P5uY|ykiUPL>$UrO?_Ht&wV-C zu7P@wR^jDHXCT?RWCf0_wB`lkwyIB@&dapjM5-Dk1b})jn7%2~7%#nh;jy^b>0sEB z_k<+(p}iYz-j zZE&=?@y_;QTf?u*DBM#9;j7laWA^<xGLA-aeHQ>jZ0j+zE+R5=YLm?sl~q{sz%x zxf+>v4$nVp51M0{Q=BRabJrXnw^y8g;;`wn$;=cK$62o#0HZ$=G4O9azJ%p$Lk-jh zk6|xJQYUi=?1PEgUNo$gU@d%-9;J56pyzWEQb zvt}Z~gbJvSFuzLsIRU2+FJT67l&P-I#v23YpvHt?fj17&x|!SIEd4#9#XY7d z;O!~6--;I3zOYKKf#+y$HZk?1^i%(v$O^eyHL>qJW2kZaW3>%$$-4vBol6}xbX~fy z5^}-|va;3QtS9YnQlAwz>jsfy>{cirk710{;1aRP#lj#hu#TzyvB+5ep0+7PXZ^WG zk;zJ1^Zexk6LA8w**#9(%A;lPNcr+OEu6b4TSKBFLNm}W9Kl#8 z)}sJ&Ac4H@-wrcWJ0RnUXzM)a=fpxJp_@Jk>)=Qi>WKdc42=S?637UAsxU<3>un~b z5s>xT@*xGn43s3NU9po-k0(gx{Ru=yPn;NGKlOg`m#a)&Ah5=c24o-0!2Ls#4wi?g z2)M_*LuASr2Z^Aag-t%sGkkDd73(tiXR9(vEV{}CuI<{UPh z5kl#1Yi46)ZENk|?&I#{?(XM)zgO`8fr;ZKr_0WH2=iNJ>`@x%$reoaAg`KFME5*ycllMBKaSYLEH04UH!WY_ez z9LeGz7m#dmC6E#sA48)UnZYIxej8q0W-U^GG3@Hw{XuKC6+(pCo9X$>PBn87@F(3$5clBvmceyFZX@8$S*cSvc?8?Shs3S- z81!dhr`DNCG#t`!;`{wg7XeV%8=MI9LH+U8ZN6oQ##%x=%DsJ;fw|@qJFe=`C}w7m#OiR# z=M7l5m~jw30#-Tti~3<_CR&`0ND=oNNYdisUBz16&uxmNMhR`@x5tiq?`5LX7QA-E zL)fVsGaGRBGR%)E;Zw5^Cz9#Jn}(>mVobuB*r`^tqr8FZESQh+P4FFNkUQA{PEzge%X?@@2 zHtrp>Vk`{ivqEer&0-*k1;|b{c6X}3(}-GLlbEXg&TWIc&^6_G6AIycveRM7POTp+ zGhQKhB{%>dOwiMh6=Zt8!gpGa5AdAf9}Y4PM+r+C$&dUXS%A zW(sNcSkVqM0VXTRXJGTj3d!(K8W)knry|*ghATWg;ED<=s&-kB_#`QT-`D5<`1z z01xrRRF$J8&UysuSBIA zIL;gKb(4u0VokFkaWek^WI)-+YH7jVpVEitKbbvZH@q_$^H2U;awLDi{+cpt|R#v8UnTa zjT>M(8eJUq{J3tNbA|BseU_XRyl6s5(l$|I%llQXvxp`XOBdB8zz?pm&xZc)T4mb# z@g}l6Nb!qi;sKS8s1Mc2KX0L)B?Khhc6+{l84o$7sup{1A@ndIG`d3=&{>vBncifkp{~KZyXp^}+e{6bwEQl-{G2i- zXDAeDpqHSK;Qbe&ZuEI6l7{?F5_6Z4sgs#p6v5$rr$#~7zYZ_wnE+viIpiM!1_d4R z6q?88IYq+Rl~J7ULZ8fcnK;o7%E<$)xsP%RB$|3#>!j02bRENK*DeAJrR35ER%qxA zMT}Gyzj1)&8O%OHqd39!4gC35R(-F~)!91q*x+=%6E3wrTD=`)@kN1(sS3f^1R)-n zsc!6r>vO92@)N%mt_YKn8U<_a6fzZk9Hv)RB`!`A!T80xv52p0h^L~$N!OWE>5r60 zGp>Hl_kTHAOsK5PVQHW?^h!KX&^)&6#;86(40EQ}`r3Q_;Zq;3N*@0JqtpS=Ceuyj z&|6>u6^(YXv6EC;jK^t02GQn+x2V}*X=$1hEq>%E-{0zF>K%?So2dfF+g!YGmYA)9 zbUP(|3+M0rX%~e@$@F4_blAty3u?mtT=`Gi{v*8}ng1Ht`>qiWLwb)Rs>mo^d|Vy% z3@qJW`g*#*4p1_{v>_Zo%9eDSQ*3RPe*Gbk&v z!;*lQ%drv{8zMRD$UE~y|HwUkgebP%@O$3FVfr6Rgl5lYVWY~b@z5c&f{rWidMsYRC00eEnp z&iHV1?F{L(3m-TJhwv?@PAKs-V01Pcdk0SZ;h)F9+*%l;kF3hgO!?}W1pB_XED0#d z3agR-zUVNtu)lNtGx0Na%NniPIV=?{4c_T8`jfY_Ml5=0W1X?o0roQMoTExGIh6c# zP5aB;?XP)zwwWe`A^b78x{2?>-23PEDePc3wOwgSAVrfcSYe0La3Sn7RD#y)B-)nV zT1okxzmDFW#qD5g^DjG*LPx2C;__2rp@ZatO_iL(=`0IZ9OGw=f;vGzP**@Y@aGOr zMJEkrA045cu6(nShePD^U9R;DM7FO~4YfkmK8^+mf8;B)aR?h!Jy z!6=A#xG+^gJyljF4N$&Se90>PT|sB^85*-lR%Dz&i7;Ej?tBNXW1l)-DttioR05%U z5SS;NQnIUxOo$D!LM^`t<5elOfG(%N4(M4de)KqQ`Tt8~345O$NTOZrbzOESl3y5DK3uaA?P*VJ2Y@_2)rD(yu+MOyEuC8sx%gp;{43 zecwGhJgj!FVHQC-JeV zg!AoMri4Z6Y*R4^%6JZM280UCr7vFpsPU!vJvvsjm!bLdLJh3=nzITXN02g$5z=+5 z1Qi+h@#LG9ymeX)M<`$Z(`l(_Q|)oDOo-S|JVSC_|4Ey{y$e~ z^kg^t^t8K_2a~ZoI(`1(R5=wb5GKzfkOOj`cxEVn}5S-XCjHkcIyB7(A|kiQ z71(R%z-M2{g6im7MTdeWsJy6U7FL8daQJHFm~XY(c4XU_{ z;#GM*OjWQ?I>|1=+J&^fvMd+a_adcjh_@~=^GyDtfji?Xyq^8Yb!ZVU0JQUndy415 z3q7?>AX}vgvW|=}uQF3k?%PE6H#IZi<*0{ru~V_!GDaMYXYifT}blFv~Jc&#N8uaufqofu5kioerLZ zKDlVg^^9D)6QwARhdRrZU1NpWcU)V@626s7C{?V%?$?*v576Zc(&qk6#>`QZ(;uG*yhv!dx2dBl&`s);(E>brgSXiN-#^n|J#zxD>Ht+RbLR9L zp#O*8@V>nGKYqi<@LR?cGG!bi{pF~~%*}f@qX`rO?;05$uc`h#HG|;ru)7&8y=Cu5 zH}BJmNNt<(664p!yk8d?NO|DN8NYC2G?R<;iS=Sj{YMA$>Iqm;NUF6-HI7VgvAF`9k*8l(j diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/ms-MY/wificonfig.ogg deleted file mode 100644 index a257b1dab29c32c96da3d806398787e4a0eaf78c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5042 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/0.ogg deleted file mode 100644 index cc146777c8d46816d6d784bf677048376d8f2c32..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1541 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/2.ogg deleted file mode 100644 index 00d3536b8d324568bac2ea9432283cec5bf257e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2024 zcmY+F3pmq#8^>)U#v)U4KF*mTa!5?%d@eaXv6wAPhD}YWFzeMMWMm?Tkjgn@awalQ zvdA$Kl9%d9tep1pOz(TWulK&L-*x@IzwhV1e~177x^B0N7titldHxg8v#mROQ%{BU z9e|iyWDMRO9T*G%m;gHbe>up1vv9)K>@(4Z?8~|6SO!oy&1!ukhZX>Joz3q9@D@l`+w1 zbVy8OG%h4G$Qw%%7ZF;XAMn-svE&p3w0 zWNx*D6^IPx6<-SD#8-i^Br&K!vAC&&0kO5A9Z{(En>|SwWBC9fw z4y74_lXoxJS$k-He3hTT(~IT6rLZJnQ83jj%IOP6{Fl%PHj)XB`qpWGiNEuG#QSBrA-DoY5E> zpZD+$FD-a(4NFo|XmL_~P}0;Fc^{M})C>s<+qVMkQCkNA95=<#6T`Q$eI7dH_=((zik-df{zxc z!jfbZo37Y8C|KLbE$kNIsjB1dP=EMj4^Z$9;Y#i$Mq3w0t6+-HsK#%k3jcc1X=upy zE?eUqvQ=I~vh?=5*gL-N=7_OXHIS7Az;jc0`)0u$zS~}-ANSJ5aZan7xy8@mPyEp+QiTdf|I+=sc z*4@OgO3kFA+tkGtEJ;C){*@~7B~#9R7I3&FqT;S#z&Vqnee3Q&3H);mb}O-xzE zZ4KyIqX40wfig%Xcw~|Sb>dN}u<>?CP9sMPr@L3faPvRF&xb4JhLcSe0PK#En3jK~ER0!4>k4l_0IB;nu)_ zEC?$!c*4T60j$1QI-Pk`(r$TT#y;9{8Lo|a7q?udf)Zn3+zQ{H&U_AMGve6B2iWW5 z#Jc=p-S(8Y{)ftC zqjb~R2NPPQukWL>i*xz5!NGEParnBfO*v00mL#v7N)}8Hl3H*;&3m!n?{r&b z(TYcXGTvL=$*K+!r}?IsDOIO7*0`_+z8>T`Uw35Y$c>m=)7{g?Q+ieb<=}|ZbR5Og zHO8m}X(F7zTB31Yk7`af$idM&jMS?jF8yyej&V@i-1k$wo%o`I-Z|pB` z{kpS478)OWe$Y)lXmH8F)`Vc^CH;oPIe{g~Dky9aJO<=(O!r@YOU;K$uP|rtZRp$d zJ|)P+be@sTn)abEd;T&o-(KwHbku&|N?sotk%-hteNlx0oi-4?C+~ku0#s6{>y!p) zn>vM?MVg_6es>gJclPgw^1GvexKj&4AB)dIn;Tft5mBMtShK=VJUjR&1vYe2`fSJ# zbQ4%mH>)MgStTo{Gd?#)4DlgNfCBYOsEuM8&m9_Pv@RuKYztkmAbw_SAJe;|7^)oq zcBSusit=Oi^?tR|x1Y@tUD@Yy)xOLE{gv1IS+3saKJnO}`8;a%|5&cx$F^qdKLc0w F{SASms)+yq diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/3.ogg deleted file mode 100644 index d8d4711909049a6347d4679ea70cf0f98761fe9f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1767 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 G!+!&XO?BJ= diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/5.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/5.ogg deleted file mode 100644 index 61d36bcac754d90a5469cef916ecf3fcf9883495..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1778 zcmY*Z3sBPe78b1lGZB^AO*Efl7NV%3(qNg%Dtc>MpKJLhP5=2`ozM~$3}mhFeN98x z_TF4bjqqyg#*&$?4-&Q2Fw+t;^N|8tX}&IW@7(L2ncvL$e&6?pGMO`2B(wL)4a|{l0YCA(4){VlGAGW|3WPXsgOxhMk5HXmitG>rs=4D zd?Pbruo$#68e?y-Rv4?^`NZfX()m=pii=ip7*`dEF})ZUm83HMr|@y1N~a2SVf9e8 zHp5alAu%Q;F)^H!m=qs`$6`?^fNHpJw-P~MJO`k+W`lNPCXsE?I(<~_!rS-a;|fH1 zlDrss%(Gcj~d#T zte`*SGjgRpb@${)|4cZvHpexB>3ED?%&yWfFLJH=u0gkYAX5TRt;{PBfwlT&I^$T= z->Zx5JClxB%>?~S$uV?stja~u60q@~v<9gah+y*D-{81;sl{?lw(Re^C6=}+g6F7p zrxXdbeRWX=DW69&IpE06cRRpqRT+|r>C`l)!@=4D?Ax44R&l|~m=@e!`VOF)T338M zR*FT<;}%yg94vIGtxj#~@99-SW&S6*gw$38T0Rf|rsLtj6S`7*PG*urxW09X;nuJx z5&3%7d`Q^!=)hF{JI0oSfH3I&jU$~o@B5uD?%3y_k-H$C(FtCu(pIm^anHw0VwW?Z zB?xqi(sL-gCHkJ3jD1|3QQqP6e%S5hiqMl6gX=OOLD1GC0`Jm~H&VO;MsJ8T*N7z& zy$dJKTERE?W@8Vg*ZH7Kc4t++-~eyu$1|l*i=oXMaeDgZfi!dN*IaE*SoQ7nY9-1~;{0gAs_#BZ<{5(Fl!srtwDyJQux%&dlsVGi8OH9AY54r0eZ z5?lF=27!Bd+wYSu>lTkMU7&YZ?TmloX1EE*Zkr zCCleJ2Zs#tZJ8X$5R;aK+1>r!maSZ4dGIb@a2@#+$0%fl5p^ZyYZhDGt>s|??h^`v zf;V+!6fcnJoi#axHKZS<`BTeY_Za^nz8z-P%IlwVp{}oRv`}UJ_(Xv_1vabfnYGT9 zlLk?_SKb|StzzHj_}B7G@+332Ucwe46b;T@*}X(k@NFfLtFibYYVST|^iKfQ(zG!! z%W;sTGij-~t$qL7POA8WpF{hK4e!cg{P*dM9d@+3vGqHxH=!Kug4zgU;!ZL7VPzkI zcj)f8jgi^R^f2iM=Nq_F1Hr=g!F(p>Uxo*BO-&&VW{oP z_cm8ON?C@%7DofLkGLe$lRUi&Sx3oGcu>uTr+ zcZ(V$CZUY6l!L=;QXtvb$1Msu0j0cc7>WxGg4I<%FK;3@9&T5=Al2-1TQe=A@(GWj zI%$n7c&NQCZLLdu8~|Yr$f;!Tpmf?hf9buu>6_l@d`*QQY9DOZS`ZDYZS5tN6w>4FXw^{iq X@@-93=r2tLMcdgwc-u!%q3(YJ@9IbB diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/6.ogg deleted file mode 100644 index cfa848ee79c504ef578a4308e12ef7bcbbdebd2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1997 zcmY*a2{aq%7EUZ9sFGO13kF5(ZBSGxVksTeQe#(28j;vlo2UjUVw8whW35`oGHq#5 z=A}~0*rnP&`_R1V3>B?5g4Pnv3-6sb=AQGP^MC*SzI*?B&i(&;9*y<}2m$_Qvl4q( z_qQD}?SBAe&&OR!bVh|m0D%_3?%)H;`F;BTZJ!PlAg+YsB+z=FejyB1 zm~kJLq$Rvi3|JHW;F)CDy+?O*QWLC}l*^oY zX=qCmjQX`XO7$wiRrQ}ECEeP}N?U+Dlh-NyAq(`@=21kRA<%|)pZBR`#nR2IJNSj& zK+=d)0$`4(Y2E5BEBe;auL?`jfYT~>G?|b~4v9^}6uH>QOXcr$@tUQX1Q zF!2e?fx_c;LW{EvQNk<7=D&Ol=xa4D7^oNIf_KU_-jE2^0K<+e;eIcBnx4-yUhkJG z+I0gB@7P$X_eS4G7d&GFB#wOAy90v|L*lF7hJ36jrs5>@cH>~N63=NOS#qImx{093 z=hxH3)gbiddiZMi;!NAwA6t%_j%?f6#20q--ciqmt6)hgs@jXfS(u9_3Fji4YC{tB zKCYz|X}-7%kGTCZ*1`iC(`R4gDJLtgIzdFQKS%K!%EDor`bKkJTT?i9>6~FtbpK)s zqNx!)SgbanSz1<>_Q&)o=Q@I*EwqcDb+F1uxglB@1=IL~tz!Oa8)JCGM`~Kc`r3A( z%w#C?>t4$HE19(?{P{Y*JJSw^VZaPuG83o}6n-Os7{%feh&|7K*p<2#&&r`aAbvd) zG<~tW0S9yb$eZa`I412@IO3c;3)#(1=ckaBpfsc3u);KUYom}{?wmc+21%MG!3O$5 z$9TGK~&5 z%KX@Anv0@O!^$qhY z-1TKz_nmmB9`3s^E3SIWVAc``_IaH4U8k*d6~kYb{%^Clo`!=~W;HR&7>9Rx0h6Ss zbw)@)|D5e~CPH}7p42IpV|*LV?L|Kk`SI&^04kbrl*31vs)-2df@LfN&XC2|#|!1t z%+KF47~LUS7)BUwji$Tmj7V8!Pbods>G5f3e(N=p9kHtQ)pjmsabmrs-7!-FFImN_DoGKo$Zls%R87GA|4wDW8+|M2n)8W z01b?&<#7W811t$F101Qwg-571n~(Jt48(@#1e}9;&;6elB*?(Ge7K^x(gDSn*loFeaWsBM)@G-PMp|MPSa*U#JqnVPb{ p=HJjEZfiXEZ(IRB(?CSe*jyxpWXlf diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/7.ogg deleted file mode 100644 index 939148502d12c5ec763da204a2418922cd2d5c58..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1647 zcmY+A2~g5`6vstP@V++7BTW$SN+rxIF)gid6*SVQO(zBNK*Ia1B>q}vgq102mK_?Y zrG;6hQaI^&v4)kll1Ceuc9@Dyifgve?CiR4<~Q^EzVGL~_j^BlObkIqRpp<6XwQO_ z*BRdKMUXK*F)d{`C5j9Jd4L2FKM}kV|2LGlk|*0^z#xng-y0Q^qNB(JMWr8hLpixS zpKftYCE(y1uxw{sWU}`i(5jTH4)d`xkp_3&VoEd;8xc-Z?WJ;c-r*tV?pj<1D=PJAS4Z~{kDGUUFY3Wn!Q!B zhwly>+J;a8I9xII$aB!ha)GLBSM}i4W?_|Mk(ZBk?J$am`Vp?{gmuRL9p>7>tt0%V39T@T#x7LAEvZh&{+iP;z_xav) zDi}kVA5XWV46LO`2>Akgs**8oGl||}IvLo+M!NDn(;rrhXE2vLgnDOXxh)5=?xRe3 ziC?<*EV!POYBFQT?Cb4QOoa2juC9d2J7};+3#YD46VwWwYdyHvQh#XTR|rP=s&4Pi zbfWhp@QI@o@lCui=G#Q-#4U|}gw@(i#!*YVWsgNIeRsyTKfO^DDSz)SCldg7zY{ps z$WUilTbOHR9&!iAt*5XJvkhMYK2Gatf=FW2wV9k--4pV zvc-8on!zvj2NNwcde?>fzTpMPt$G_K zOW@K@eTxb7Y0-?}_eVM8G84bIyTv|l$yP~{<_z09@;q}>s<<=9A%!#6XloV?7R#Cu4~(wuq5|uT4dkwj`dAIy4V>$&BI^nA2si10bN{gBNtrJP z4Z7Ltzb>x5F;J5Tcht;H>3G&>(N(#%04~pA&kLx4z7gb_L_}+tJXU}IR{bH{8tfln(rb$BFo=H#L6o9zfWZn#79C zKmsR$3RviY2Til>KAgpC^M5h?`ev}7wd9vEeKlFU>?!C5_hfbV>=WEDf-weWh5u9C iRJH$f;oNFhp;lFv7|se;vy~{>s!j^EimeHi3I7H|j_+as diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/8.ogg deleted file mode 100644 index 946b7ac3229866e90e08bac5ea5a9ec53e0b148a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1507 zcmeZIPY-5bVt|5!@BL*#OiM-g2aLl01*OFvsfj6!j24UsV!=xMLCWC(q?{4RV}20R zz-S9n9+H?|%mWnhNi0h)~fz|LWS|b_Jdz z^^33f=XFj!`e3Vs_?e8X3s%m*fQHKO-F&Vf-pR94%;8pjm29Zq(bm}alcryI%VNy$ zp0z`4u1vPa*E_%No@8h!efncYO1qq0QQQJ4p`6?Tg{{St)}DJL`AyTITy{Z0qB0nAG zcWPMNvuB!FfFh%IvyNlxiXL8JC95QxKiqXuoQZ7crq^Y=H77H+-c>7e3Szg( zZWa{eVXn`eA_OKg?7oNe#Rr6z9DpPSn%I_s18Ux_Zx$y1hu zTzxN`X6*Np;e*F3kBSi9>}FAQ&KFjPCmgBm`oH46X}n8JIlIaZi>nQ`H$N3tM!Ux{ zA5gq=dG_(0QFkNtx2zQvE}uFz@lL6$U15E2f0OK9R-WgU-_9yePrThe`M&mN?Onpk z(-Ob^KWCp@bMLJo$EW=>FV5+(&u&&y-|O;fQ~ZnTF%@&ZS)@d4KjZ7F`E;Jsn)|u+ z@?89dD|8Zg_xdQTj)BW$*~!1hb9s^UtnqkApF zWg43nHFq%|w9~R{ifmzXnkaouLUbxqmhgJcdm0U~y&{Ea+01(;pYT$(J|}v*$!r;$ zqfRPksNqZX18t$zAr~w*tW%MBcl{L8ojuOSpU0@WZT+@gZcS2t#;3lDGog&?kH5;X zvu1_{UTjcNZuC@~9yepn!ySijH7WaFV3??1{2=r5|7)TPdSvfJo_vwzb|Xh_^UCt< zW@Yu3H#tt{_>bKye{JwgKYr1QS0CleO5Xl1pEO(kImf(UMZu$P&6ny|L^14R(-aP$ zUZ-?RU6gOzlO>{sd-g9m_l@IL%5;CJ9{y!VrkI#IPk&%;_eN%~OOn(LK5f~*x;bxc z9>4g-Y$l!EEGZ^6Y4ZNn4}|_4s~5gHqjpc~dWnVJT@S2x*9pq)UL5z~%682SiXlS( z4oua)G5I@_3Ab#6@lpPTm$$F{o6c-nIW1Hs4VZ2O1-MMw=W_1(u$q;5`R1#4uFPHl zOh{JZnoVd;W i{~rj#XmDxC^5qn`umqQu%s^(izGe~=2M0_Mj0OPG`kiqA diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/9.ogg deleted file mode 100644 index 8311b5818e980330839226879a3511da069f712f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1782 zcmY+Ec~p{F7{((gKhzrB#yv??%%!AdP*XEgb0c&_#gfc@?6ZJO({gLRB8<`!JGpBn zRxXH|OF)x#T)?HY!KRF{a+=gMC9|5WrulT{O!S^}&$-Wie$QS0xGy;_E^yiMW&f3i zv$O8vbcdU?8=*yJBqe&qL_{MH_J|JJ5<*_Y|F1Rs`@ry`~ z{eiHaxSn8Vw@4VnBj#WfJv!!)Gwemd9>D=N3D|`ANID$+cVpLEFbCJ-#*3Hoi5^kY zAlkbnGm;Mc#9&0aIy!FIxCMl?G}I<1JV>?SuOH7LGwVKha&Jo6K$V^ehr4c6D9*r> z!t^>wKxO_(LOSvNQ8lYAJVT$w7;u@Bq&j~;M5z4*>e%S5cZ7Qh5Z!U!WVsbPDCc+o zo?Mv41o*zDK^~lmNb>Ne=RY?J;G8z_Ykf!Y-RG^wIEsa?A;ZXK4IQ1$BL%N%(w4es z+aO9(pAK=j`_Z>Ny*tZWbxUji!W%!@t-qsxkN4SK86bo=&$0{lHG921H1oM*qJrze zPrhLy7^!);rh=VTKfx6OiG-{2`S%sO~q#M^{a{QCP^8IsZnv znV44pvbd$NHu@rVCm6_taOtM@;khXdDb?+UdX2H5pa^3*)LBYWk?oo310gf>hRwkE zIZJZk!*Lz`l`Y*gEb$6`y_I#K{`O|W`AUR)%I)Q$d{&5gwKzQtCmnogzMd^)9k6>- z^#N!QXrV&e%;E~g5|JRW!Fg)?jNkDoZ#|z&KW|9Z>sFH^YP+xu?YArbEan|Ff& zLKfy?R$AT!WC)J6nVmGp3(6|MTj~jMb8(_rN&M`i|33JfN$K9>< z8t?T$$|QH)*}WiSiWmFOx->t$UbCYK96RJYGSMP+si0_I*nFF}!MGTkna2af{-gbr z+1qb7i1p3>9+|GX{c1s0=CPKmdX9-hy?BDId1Bu%v9m<%cGaeu{^Cp2=SDepVA`MR z6i{Eb&$`HzRoBW(6M2IW&OkJ?$|1;d)lUBuY87{SK`5A-LiU9(b7yyx%LdNot3TkA zg=ev4Nt@f;XZ;`eCCBV94Jq-JwVyx5Hq;Rv&gCUQ<(U)H(M1k>^N-ayvU$ZVjt922 z7XlGI2hYvK(c(9sP%J%aV|a9(_|d_R_b#iuwwrW`1U5)fy5Iyor&j^q-{yAssL=jY zm3eH;hZ)22o`qN?aM%^p#2vqv6JSkqxN)y7bKu0#<-vIYc!&05 zEJvIxBz)(Sg&B$P%OzEjZfJ8st&-4muA6iB}3-L!D^);|B4sjv5TE z80$;uJD#1R#;djIHTjiFdE^N~x?1W_OPyZ5%f^|Y{AWjl=~N67Ws69osiv0r5U$x4 zq)UV2MD9^CYpZ@V>rKgZ9qG<98YA$n}c-}eeMq$@;{bPr`TE4genL(^@giduu7It)8WldO6C+_2b2*Gf!(G^oJI}xbPlK zCNC@`fWL$!t&Gk!}zaCM-^$RL>h4S(t_1hT?q*3tOhi6M)$k!OY8KJJ$TFv zpq4!yF{Lk2Asv;PxU3WfxXT$(!dD{mLw?mE4}jIVCkTH1`b)YbE#b>p7)6z)JEDrVbqG diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/activation.ogg deleted file mode 100644 index 8d7be020ab1d119f812a999d65e97ba0a314e8ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12110 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_pin.ogg deleted file mode 100644 index 1b6c81c3de02ba1d3da728134a3db934e6d971f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4175 zcmY*c2UHW=+D$?Y9fGt3=}oxwDn&X9C%YEltywdB_MTI}bM_n~XJ=CY2=IS_SEIDJeB=O!X#yce-T{6$ z;r5O|pdzrt=D!l7OZorDr5t!EKNYwGRK1j&**p8u5Z@Tu2Rg}1i7SXpNlIQSIEfeB z^O2V$+*g&zJtA^aN<>nM+uhZ{i}>L`1*^9cb;P(V__9$Z-D;MMI`%=HJ^{X7eh&75 zo?b2{ZU_`BgnB#CT=Rj9Z)3RHo|O4l@-|YxFW2B1l%26HMZY)4FU$oQ(_^md&+yVy z6??YXJd)H3S<5?L$?NS;7#eS8>!}Cn5i(}4^HvtK=F3Riaww2?OD3ITx zHFqSM_l#;c77B3oSPGE)>yx7VDs{H0i>r0W#+gA_Y*7aNxxEs7eFa z3iT_vp<2(Q-4zI*YI>`vFtL59n5#80iH;^RHCYH0FAq*BgtspAQ{v|rIlSV~#8XF& z`rB(Q<67rPo;lt1E`7^>oWaQ`B7D_PwS4EBtvI!-G0o$CMbhen6wue%oe!}K$v8#3 zE-ouQh8yeDhwOdDK|Z5Jh7BzWfP}|kUV3Y{7kge&X@Y1D5GWo2>`GTs)vk*qok$$n zK*KDH0F$LxTx^#nRmGR;0~3I0aWk?!T4qyIq@m(TNq}X!FEcAlS!zLkOz&bbwnqkB z*OUJ8Gz>G4$qw>pI}lJ8o!Ncp;2r2MCTQd`lRV%(kKgkJmv8iSZ`vEmAy9(+7;0yj z$xroEs36a4tAqk~%l4c5W#@Zsq0y($B^H84cjEnfFMKgAJ9Y8*n&0DUC*6Rpf#F^c zwq)~5{ovRU0NPa~G$6*hYphx26p}k1+dWITwxWCFb{NL*jMldv2;qxp0P8lpPDfJu zG~BW$L7)T#S}R}RctYj=E`Ezv&-i^{&GAJ)b^P~uQJj{9q}jI{55nSlpK0Jo@=aa& zXUH~yn?j#fMFXcPhPoZuNPHT+o;FBE(#O?jln0mLUy3z`P;^)KNhIMSEe@k6H8P=PBbfk;n**>Y`^O2DZ9Dx-%{>JiB z%URi6}CE{0n=9x5-i)Ahopj!zdzKi0$j^zHD1w5&`TQJI`Qr{qX5W44+9b zJ`p=xxq5#tq4$LD*_qAzuV+i_bF#$h1hF&njL?;QQL-Tq`BCc7y)!V>g8tRf!h(#0VDC7tSDvggINbv*i2y zh?^X*d;*kTlK*};KD;#x=Dc$!sr4vkngCXAl&2UuAx@+~Ocwtx%5C5$wP=x6nW&$% z%v`aZGCYM#F`a#g&m!j{%RdvMvKJ$1TBRM9J?J$tqA%HT=&?iiImnu$_`~nTs$#GH zaIr~4!@MB*)kqSvASN2>sXVXly#KZgi zanN^dWnHjBbQ7hl%y$=j_ZviK;P#n^1)7q!>)5)B_tnwpIdkyBKR7-vP z^t^o{8;yg2AJX0PNyo|L5ym(3pQ~s34Hl2kr|3W0QuCuH_K_#%b3}K3NHxDPwX}HA zxkzq7R1)uni|c(($&JTlE+TZnY8+`3mh8B{1l59&Wu3IrnFejA7az&umdK@dG%)ER z4s8)$c{fdQ>UOC;@!z*AF|Cv#jIgy_`^JUr8FN@Peb}qP=`yYImT=-q6U50+V?3>G zI>X4*wOh&A0k?QI;$lHxgsJC+tG;i(5h6WsD`3UC`mIpP3G;f>wsN-u)>Rgk*Lhj% z?e>?y+tB(Opko6ONuHn9>uw>h#uz^JUaWc3mYYn<+u`IEACM9Np+%sWA*6@#wBWaN z#!&whwkZqFyQOA6?7*Mt(vrc0;Y+fBLX90&dQb#M6iF#$=I5*<{$A7lXz@Dv0J;M8 z=>5H1P|wQB`G;%QHS{>R`>M2v`OF@@HI_0s@gx7X->J=~k<)(H-YzzC0Uec_%&k3i4P z6Mk2PIDLFE)yU52s+Q?2-=^9vZ&Oi-ZdnWsCL%-=vy+#nh|f`l$0`jCfN|g?zT(|J#LA%brFhhaCaF2k>7UTGgl1dC6n<&<4 zHnqAEzN4BB3N3mq`mO%9(ZkanDN4TWZ3*?B6n7Iw6oBdp17_^AhH6UG;p=V!Ltvg6 zEEk#4F?Q?2)cf^cM*G!Kop*@_B-A*t-aE3+_0GZJ=zR*uZ=bobjZtvTUoRI<6FtVY zl|4G^$vNlI?vX%~{o{~t+6QkJF-H6BX_`f*#c8AVs!%(9L&jL;-||g5SxRP$?$=0O z;Xj66Yxw)+>9aI;FNUA;!h2+ovLg6F?k<4KHIJ2c-Ogod2X6fuY0eAx8c(7SJi96z z0pW2d)YfB9*`>7v#@UocWow<#4ot}MwzZE4k9&9*r6SvM6j1?f!s7iT&J_fivyTNS z;E0-RWt}UCFa6nPxZ8%j4a^=IV?~zN%%6&CCyYdL`Yfh>wlW7eAy9nWF;8_w&oE@9 zH6^8l5jJhd$4$#z{G?$~i&Hdy$2#QoYxBVDapjAF9!~BLo$#pS+FuM&#-O*S6_rTa zxEgTrpe!u={0HGo>^nwgsrD}H+Fsb(-X5+83GQ_#GVCYUUs}6DPJVDx{(ad;979Vw ziO^5ICLM71K;gp6$XrdiKxgzOiMh^f{T2*=oy1;jwJ8G|vJFYEq0UWqjX-mYXNAXS zAHC957C7I9FuP~)v8H9u>_Gjs^KnJ98}pKIUcsplnopN7@)wdq}UmD!|(WbsSqQfNHcJw^5Z&`0vC_ zn|I+|xmRMGrlMh8v+_`Y##pCW;H2e34KuM<{8;A+t1Xsn2+zRZ6V`1vL7#fv`b>L5 zg&Dl)KcGF5OhRJkatI|B@Ad=BCrh~`3C$kcEU3GT+!byHgztrPO`~7KkS33i9~L&d zS_}aRgnRU+$UChNOTkFvkHah)gYIh=vPug%@{Y+ChcbJ_KX-N|+m7d%L6HGjWol;1d2q-u zUWQCKB@W6kXyq4fGzdLI3;_*;N=4Z@O-UDr&Uj2l-UZycVGuzDm^0PE?w_oQN~e_H ztpna!_$&6|M4+(zHOS!DPUgOlYZTrEf#T-F;+AY3$} zny~~{rtJi*ZqIC`@{5a$BjL_@_vid|neFey{5DKVfs=YGLjig*3_qevBFW=|u6%54 zYf6dR&J#8?uP06WsVU~MTM$tYL_Ctg6y7g$uz(gf;nk>MfVkrJ1)i(|ZEMc?OjEF~ z?NL}}%J;^o?%+)?*0Ncu56VEn{q{^obdQs*+pGn2=?1G}t+?lP^al~2sWAo<9t4Vw zfo8QkbjLD8YuN2Lz=>*|7VxlEN`2*NZbV7CjoxXzSbJ5YG&uG^A<;D9$81^- znWPR7_+Nu0z54NAgCr#yWZM`MGsSgzB{5fsZKeD0be;;D|Ak+LiXD8>UuJM2+pR#0lJ z!CqQ8Q|4*kF+)HI4maY;dy%63b`*V&Kh5vui|>7*0X-z9EFHz91_P@jyDM!;XZ8Ls z_GSHK?rHkmEppJMvhRLJ2@_xBxT4~}sM1VP1wryZ_z$+hUs2^>j))Zh)Z#M!WP2O0 k|Dh$K|Iv<)|H%^3AGLhNU;m#r5b+=EI`f~k5Ru}40Nq)!H2?qr diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/err_reg.ogg deleted file mode 100644 index c505fff1ebec2574ccbebf4af4e92748509a5a1b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8992 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/language.json deleted file mode 100644 index 71b0a57c..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "nb-NO" - }, - "strings": { - "WARNING": "Advarsel", - "INFO": "Informasjon", - "ERROR": "Feil", - "VERSION": "Versjon ", - "LOADING_PROTOCOL": "Logger inn...", - "INITIALIZING": "Initialiserer...", - "PIN_ERROR": "Vennligst sett inn SIM-kort", - "REG_ERROR": "Kan ikke få tilgang til nettverket, vennligst sjekk SIM-kortets status", - "DETECTING_MODULE": "Oppdager modul...", - "REGISTERING_NETWORK": "Venter på nettverk...", - "CHECKING_NEW_VERSION": "Sjekker for ny versjon...", - "CHECK_NEW_VERSION_FAILED": "Sjekk for ny versjon mislyktes, prøver på nytt om %d sekunder: %s", - "SWITCH_TO_WIFI_NETWORK": "Bytter til Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Bytter til 4G...", - "STANDBY": "Standby", - "CONNECT_TO": "Koble til ", - "CONNECTING": "Kobler til...", - "CONNECTION_SUCCESSFUL": "Tilkobling vellykket", - "CONNECTED_TO": "Koblet til ", - "LISTENING": "Lytter...", - "SPEAKING": "Snakker...", - "SERVER_NOT_FOUND": "Søker etter tilgjengelig tjeneste", - "SERVER_NOT_CONNECTED": "Kan ikke koble til tjeneste, vennligst prøv igjen senere", - "SERVER_TIMEOUT": "Tidsavbrudd for å vente på svar", - "SERVER_ERROR": "Sending mislyktes, vennligst sjekk nettverket", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Konfigurasjon-URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi konfigurasjonsmodus", - "ENTERING_WIFI_CONFIG_MODE": "Går inn i Wi-Fi konfigurasjonsmodus...", - "SCANNING_WIFI": "Skanner Wi-Fi...", - "NEW_VERSION": "Ny versjon ", - "OTA_UPGRADE": "OTA-oppgradering", - "UPGRADING": "Systemet oppgraderes...", - "UPGRADE_FAILED": "Oppgradering mislyktes", - "ACTIVATION": "Aktivering", - "BATTERY_LOW": "Lavt batteri", - "BATTERY_CHARGING": "Lader", - "BATTERY_FULL": "Batteriet er fullt", - "BATTERY_NEED_CHARGE": "Lavt batteri, vennligst lad", - "VOLUME": "Volum ", - "MUTED": "Dempet", - "MAX_VOLUME": "Maksimalt volum", - "RTC_MODE_OFF": "AEC av", - "RTC_MODE_ON": "AEC på", - "PLEASE_WAIT": "Vennligst vent...", - "FOUND_NEW_ASSETS": "Fant nye ressurser: %s", - "DOWNLOAD_ASSETS_FAILED": "Nedlasting av ressurser mislyktes", - "LOADING_ASSETS": "Laster ressurser...", - "HELLO_MY_FRIEND": "Hei, min venn!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/upgrade.ogg deleted file mode 100644 index dc914d58a6b1c9102454c6fa0ed745253762ab88..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3155 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 MM%-UzaF9v=3zN00J^%m! diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nb-NO/wificonfig.ogg deleted file mode 100644 index 2d0b4a47b286f22d5d5a98a9fa1241e9acc8ccd1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6131 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/3.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/3.ogg deleted file mode 100644 index 95a59cda06868500f364045a1b037aef8c7feefa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1547 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 BlOX^A diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/6.ogg deleted file mode 100644 index f03555bd70177812be5c396a9eda2d2c47aef37b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1872 zcmY*a3pf*c8#kBSnM*E_T*h_|6&Z#tk0E|GJN zqN2@+gNTxkG$w{>6geSBDQEM2&v*LX=lMU+`+I-C_x=Ch=l}mdFA9%8CnhfTUmF+n z&_(Wc@}C+2HB@8_=>!fN0sz1OU4FX~lt}(R6UhNWgeAO_10Y0lPb{9KAdH;B#{O(= zameP7g}J#%v0u1wmx3cgaM1`M7cAr~Y=xwS{zXDigfQ_xg^zU#bwU#r79HwS9tNx8 z6BQXp42lT9NW!_>+rrWIM4G-fK$|Y(5qpUnuBkN482t2^k9Mhnp4AGFq?t`vj?I2l zcEzGOb1n^;{K9CHMf0ayzerOAoe$~=suz%X^l-Q87H-K@`(9n8=Wp}kyGPTZRuKCd zBJBWJL(G$mswvD*I{5tH+6{CzxxE-+%>Rk7{fC7t$lHq=F>|7ZOc8J{z9v-05&Nl- zrcv&8@=_P;*6hRenP*pv$_ng0w9p=-@6orM=M?;ERp$cM49wFmWc+TYR06-Fnu-H9 z@*yZft}FQ5?f)Ya~}a2zS(o(OXHK~XdPxpyU95^A9Ss; zZK5Q%dv>B%P_CJH$!L%X6|h5_rt1+p8%@xF5L4-)7tuDB0|65cC$qa6Eo}t@TO^U_yB!e+VUobk#AM zGANoNv8{CUH4e0ou#Wg!K;5EIVub4>%}}jy)xQke8=+TUvY0RJBg$i0TXwHU+U~7N z42|gPDwH_|AP;vnG3LikM-mREas@sP^*bSUFd_|Xz*aB|k|>`U@-wt>z`BjfFY{~C zTbBHqo6}|&BpxP+kMhd^OP(ZlP3Ve(4oeT(c-*(=m*`>bs`x;U{DuSHPQ!vVbGIEM z+2u*=nfN}G)9mmkcMgWscCTWvXA>H-f+>8K-I^u5LOr%41^91+V7d8=wcnqK7gCVq9udO4)MkhJIa)WJe(BonfD)gbjg;lvas#dm`23HM1V;4e}K$s#C+Q zFE`m(0z+&Vx0RVizCA=#mvNMTg_ZSLZ%Lrx(VlnS*>`PBC}}jU)DM>3bM1xGlZTrA zWl1T&5^vR8Z$oKw>;J8|f3*~-n2s68oO zzXO>hC6<{kn7xvtx@AAh739@r#W2rXj}+VVbgt-B9~JS z1Md|lGLK&`LCn-2UO1v+;?)Y8IJxB)nAS?tn|Xw*1ONm?njyH*D>G;?D#hzD$Moc& z+!7}k=h3g0WusXzyt7!fW6>1HE6A>XyWu_dMDbVu@*g!h51d=VHX_~LXd5yoM&m!K zkQkW3Yb^L5`H4u~U~XG)m7Wip>eo>T8ZC9os#`DD^TJGHCa&6{*t}vHtmuE!CZG+O zuOOB4ZGKChv1#^P`6>gW9s^m2Vz`dHGlt=@+0;v_=h5bZzymw}9nzb14`hw@A*T3F z#;$$G!%{|<2g@?1rMiY=G2qfc^u~Q@ zrP?VV3xAGka9JIR+{$2&g8@ULRQZ6yySh(u_R-?{1gRgK_RlEDd;FC=Z)>#CuKt3% zbUA~{6U^$$fxg`|jbJGHesghat}`Oil+|S_Un?KY>Z`rU2CNKoVKU*B9WTu3jdEfi zzhYK>K%tBP2kDWTUXL}SJLL8^b3>)4(Yf#W0|+8bOIJjA$^@_Pxm2Zn{$VlM8aW@bc*f5e&Vu><#GmnGK$H@V^0XeQ4GI diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/7.ogg deleted file mode 100644 index 759a596b25797364301e254d9435c2a459a34aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1981 zcmY*ac{tR27dK;UvtXD@!BSs;105L);#GU*%$gaxs^zf0V9o4)UW4jsIzE*DTZtW2f=XQYjax-AJeN zWZ)v;A9M)-C`6nM&J_@aEz1PY)pX1#$M<@V7Au)TX!y911s6N$MVPN85Bp_^E~86V z`N5~WYNY8wzj_w*#eO#yU%BM)K&n}k;N50iH7q0`{SqlYi*QHZ)k-Xf0{HHr-wWyzcG1R zw;n>hyC0g0iA&_(*MY4L-!(?j?FU-YXz@I!5VyTmwyZpc8q`mSb@~TUFqk%6q{n3)s8pTGAh(S#^ef zgUsDmpVW?f6Y>(GLZ4r4Qp*PuV&%pu1m=SqMQw2M${dH*<^?d-QT3Phi6P@S3^n}a zXWusVd`hx5^r6~mn+Kf7{0Ocm&cQD|Y3yXboIv~R!C9tG$Td~0Tc!O%NA!o~{Zxl% zPu}PgyULQ8@G|iA_%l}TUYpZjm4eBo6a%j-Efa$5c!0SVQ_U;cI6|BeA>QhK5Us~V zrY;J58)b1!Nx z+FOZ%PR&DgMJHoLbX~&~LQR9cd3EXh%QktP1dLkiY^M~Sm7SGl7MLtZdMG}10lT)F zWxmn~7j&xBrx?{#CVJuK0~T<4;8gFP_dG9NMv0WjhI^AL^<+UE0CI9neN`;4$2x|WQJQ9YTp^)D zATAPDMTgX&V{2s_{zjBkX%bS-yUG1 zHS=p`#%3{NL%V5fvC}S}TNfwY&5BC3wHU|lz%ErY+mCzX>YzCmVnb!4F)D>gJb2^C z8+*OBjN*MLeTOFKxuFTjS4D8PV{-YyGm$ccEpZNGmY%g}>abK0`I^LfSb*~FPJ8Rl zzV==?O)1N$CPKELpnapFqBIC$Z^ey9HoVdLC^hN#^2G_W4hhsVaq%S)tN5Cht}e;h z^=nBU-S{N5{wAhkx%Ja;kScL`FADT)Wn%Le!WjP+uxI-HBdhL?Jip5`(cyj5q>_|rO#NMEe5xMsYyxJet^{LnH5RRX~=9b!XgB?*~CQ0CL{E=M*R zU@9PCK55zapc~mFm3N>3@^ONv>t_he3hrC|)mpad{Y&+xGH`CIWOY90=W77C6|%5w@W))IaB9Id{}&4dN-jzUkJ zT@$w|plV>=>`q;`w;}Lt@VucoYOrmb;hg)?bQkvfoq_x`_WjI!zcZr3v{IaOR@B2t zU-di^7NhtxqU=Nuz2v~!lG>bN<(9F1DW0!$fciLNUgvvs!iF_c|4xyVKcJG+SN eTsaJV5R3gkN?66(0HXiG|6tP;u>Wuh5%zCB{E&_S diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/8.ogg deleted file mode 100644 index 3d4183ab9a131d5f90cf7a537daaadc85b87902e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1787 zcmY*ac{JPk78in8O05ZLk)+nf5?c~YT6*Xh)iRcH1xC+r-QV-;u5Lu;iNDS2nP~e{A%%%+W!lw9VE#VVoRDpM5*16M5d}r7*A5t z6-SH})(T@|BXt~>{P392*syR4QKE%PGz?xMVvM39LSiL_|7q;Zm-r-*HkJkS2o;ZiIt^h;ppvoVnP;)h+Z%`__FFB?JHGXYJsgx$L+p0U}L>3hI zSBNW=ZqCreyY!Zjw>QDm(5AX>MS!8Eu9Q{J5*ZnY28@b1I$4mG@>hcDEuA0@Q{Fl(nKhG8ekkT&DAwaoh|I?&g{j6uF3BVKfw+J{qb77 z2DeI7b_9#(@07Y@ACs8Kff7$)>wbDv#zGfu&r6v2%R<8FP5_s_KaOB6Wk8 zS34I>s2Kbeb+`J-jNIyCQ&}3#1BDZ2+JUxTml?8+`5s`P5Ila_gz#J%7?F;} z_&V$$hkSn3BLrq%RTW(V8+4Oz6`2h1O1+QCkL4zNZWi0EBei@Ra+Fr$XB&Qeoc|q6 zL@yrL_At_2*NNa8yD+s#i7s@|@yz$;NPDq~@ z+Yoi}N|SG{m%VeCH>_cKkJ^l6)jnqxd`dfS3Xh2o+p-z&Tj*M>$fTKU&Ohrbp3P17V$99Y zfi;f>D$U-0s17_CkimESP!h?CPb$i@>q+Yf3}{2PRe3=c_&3OZBC8!gqRI+1!!5zCvJ@9 zX6S6Qy<7A>eRNRuQ#$hZmsIIHc;<>VzijFEJY}K7fffbtF0R+{Fd|KVEH0YdntmZ7 z6kx!QZf66YV0k$)aIm^OHUwap z8psB_q~Tn<8sDAn+~6Gr@}6~+{u0%xH|9~^yn2Rd-{kNri{UilddOChpYCvC{c^1@ z=G3QrmFg22Y&y-Y|MTg(&gh0r7)%6wf7?why(tG*C$t<21YL8J6=@-S(XO^8R}#pq znC1T7e8~z8ncmD`*UVe~wyvG%2j!=?s_fS-`(w9nFTl^uiT1Pd;Q({_j+#YuS@BUC zl>IiRUHOpRwQa+v^*wj3afhQb)|g3D1ZiK`E}EjC>ZXM?DkI>PmE|JK_l0jQ6pEmA z0K?FzRIoiqx!Ei`s5W&EZMb(<2ma=M)!GY};P8VU)n>L?iwc$W{`!8+uKrJLzxa@z z$}I&0Q5`N(6Mepx_A4V6e0<9FQ+d`z{}!xyzy`Ccx@3Ov1F2_FvdsTK}>w*%bW<4IqG^eG1v-$3|{oo3~(A8HQZRj)CUG~2e{ro`tqjocAW6M2u zpOi(N-=*=bK(nhkOAK}44BJBPC&&f7RPlFj_*d%#y9$A^ko+{F$eCcFS0PIP7>A&L z)v-g%_(=v^YoB(Xw{A7HMns1qb>1j;*F8MWtAw6<2U|<`oAh#xq6d z3arfQf^lCj1o-~=*8}nOLdZ!%NJML^EE)pHDGsDO8we28X`<*aaD@NMaR1BlH*tg+ Jx&1xq`#1C+D$D=? diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/9.ogg deleted file mode 100644 index af53ac42a68e5656e3ab21e129eec3f5e666a38f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2154 zcmY*a2{hF08Xrrxv3z5l3E8vFM`RiL$Tk>cXUY%;sWbH%O_D8TFeGG&EKM}JaYa;w zzqKo&kr~RU5D`-uhEQa=f8BfT)pO2!&ii|RzvuTn?>X;zAGh#uF9zd@AqvDw`| z(qHo6k#ZwOksQNi*ByPL%|HZDH2SfUAcE~I7t*daS6V7%EUm= zRL|hhp4AZK6(k_O6W&)_4##Qzvub$~iBc8zzNx?BBs9L(}a zNE9(Fgm{5Oym+4IZDma$%Sb_&4)YT(O38H@0Lb&1AF``t+}sm{^BO!FDq9AOB|2t; zDzoMI{I-N6@EhDj?I&WFUh*Ar`pHReCXiv$!T_E>C^GqYxI<_Qz?Uz(B@)w6yELM| z@F=&h)P6>3HfH{rxkxN2IkpsAC$(R znAD!05hDfS=ZkBR$=EMy6WA#T-~bI39C$b z!FSis`3GA8?C5=(b2UMQNhCFyY@-mZMujDW^B4a_%XpbD}~fH*Sd(bXo`AfmWB^?}NSE??e> zT3@xfOFYi(I$&M)uotZ-s!4?_juP=tk7$4p=PRV6Jrde_lWf)E3FHGxz^3VF7tZ{3 z?S?j7aq5%5%q`CL2Ww;2z<`ZX0=-o;aM4ZV{<~o%4vqK*@WqM`6(De#()-?78v5Y| zfvpY|3M@0?CnIv@=GBP)XB$4mwINKi4ZB%woY@)`oJ}CBY66SrG%_g<$NzyaOcI@K zk4e-DUCNa%KiHUB;gLQ>4(cN`(vVF_0HB_sw>`viO(sx>qGoRk$j zje768Y9C{W)8X&R%uE03xrSFF&Q7%FCM)0>V>Lt6xyt+&PtX1N#2Y^pV;G#l_*Qx4 za^C9qRu2A@fuDXjT*Wz!jpaeeaPrDJ@e}`Z?OZhEtCf7kXyWkd@qDY>I`f~M&ITFS zgEci;ro|B54M$tp%?^lUh)?}d4^M0|vEj0CvCcD|S%q_U1rCh5Np7oh0&XVTej1oU zNKP4RP0UHaZer1;)_h(*LywQZ5Zyhvbj^ParF6HoF@l3!uEOX1`Se9g;NIxY zwaEkCm797tq4HJ8-5*;?k!+64Y*E|I-fo z&zN3O`+M@H60I~g-NbsowcWHgye+c$#i)RvxlmcRff1@a%^S-}eV)A4ywc87 z4<$2hZ2+hf-o57>285A5XEbx-u|bTHr}4Q7+b~CZuA7@KSn(iL-Q~EI>z`fKQ?Z>a zc9g8Sr^DhDP0qDw%>4ArywvPr6{Apk@eUg#++P=hW90 zloQND?@cLhr**`Ds=4q5>~%BC6VY&F@_Mn|Z8h1w)`O)w0KmhJzZOpj|l$Wve3Yry4IIli3<|190RO6of*);EMV?hEub2T z?0$}c5xlZLL$KA*zz#+FKRw2ZOs&^#@3Mjqw=;O*1hSM2G_YBB$NX_{^Z5$RSog5M z-1(QlBc}*bMX-QzdVbE&uuENYeNh7>(tJa*+C+>M>Ql~Kv~A8OnT=R;Jbnme zOm8&2?l^|w$MidYf%Sr;MN(Yw-N<>tMf??!&X1Lz6o2V|AzKx?-(rqrUmgHw#s8~W|arGcdzf`NbVkA5beoq U%lW+r5bt4M)bFjrWG>VH4PII8l>h($ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/activation.ogg deleted file mode 100644 index 273d65adb837fef416be75f1905a78869b62bf5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13132 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 b*T_a!9)bU!7gYbR)~@9LUS*_-PvHLpA=1I) diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_pin.ogg deleted file mode 100644 index a2f83c4d567b84a9d6db3becfcb6bc4dafd4a24f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3190 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_reg.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/err_reg.ogg deleted file mode 100644 index 1f61dfd1e8e735d753b1f66ac8c4f5476f1ea1d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10114 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/language.json b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/language.json deleted file mode 100644 index 2c1a360e..00000000 --- a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/language.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "language": { - "type": "nl-NL" - }, - "strings": { - "WARNING": "Waarschuwing", - "INFO": "Informatie", - "ERROR": "Fout", - "VERSION": "Versie ", - "LOADING_PROTOCOL": "Inloggen...", - "INITIALIZING": "Initialiseren...", - "PIN_ERROR": "Plaats een SIM-kaart", - "REG_ERROR": "Geen toegang tot netwerk, controleer de SIM-kaartstatus", - "DETECTING_MODULE": "Module detecteren...", - "REGISTERING_NETWORK": "Wachten op netwerk...", - "CHECKING_NEW_VERSION": "Controleren op nieuwe versie...", - "CHECK_NEW_VERSION_FAILED": "Controle op nieuwe versie mislukt, opnieuw proberen over %d seconden: %s", - "SWITCH_TO_WIFI_NETWORK": "Overschakelen naar Wi-Fi...", - "SWITCH_TO_4G_NETWORK": "Overschakelen naar 4G...", - "STANDBY": "Stand-by", - "CONNECT_TO": "Verbinden met ", - "CONNECTING": "Verbinden...", - "CONNECTION_SUCCESSFUL": "Verbinding geslaagd", - "CONNECTED_TO": "Verbonden met ", - "LISTENING": "Luisteren...", - "SPEAKING": "Spreken...", - "SERVER_NOT_FOUND": "Zoeken naar beschikbare service", - "SERVER_NOT_CONNECTED": "Kan niet verbinden met service, probeer later opnieuw", - "SERVER_TIMEOUT": "Timeout bij wachten op reactie", - "SERVER_ERROR": "Verzenden mislukt, controleer het netwerk", - "CONNECT_TO_HOTSPOT": "Hotspot: ", - "ACCESS_VIA_BROWSER": " Configuratie-URL: ", - "WIFI_CONFIG_MODE": "Wi-Fi-configuratiemodus", - "ENTERING_WIFI_CONFIG_MODE": "Wi-Fi-configuratiemodus openen...", - "SCANNING_WIFI": "Wi-Fi scannen...", - "NEW_VERSION": "Nieuwe versie ", - "OTA_UPGRADE": "OTA-upgrade", - "UPGRADING": "Systeem wordt geüpgraded...", - "UPGRADE_FAILED": "Upgrade mislukt", - "ACTIVATION": "Activering", - "BATTERY_LOW": "Batterij bijna leeg", - "BATTERY_CHARGING": "Opladen", - "BATTERY_FULL": "Batterij vol", - "BATTERY_NEED_CHARGE": "Batterij bijna leeg, laad op", - "VOLUME": "Volume ", - "MUTED": "Gedempt", - "MAX_VOLUME": "Maximaal volume", - "RTC_MODE_OFF": "AEC uit", - "RTC_MODE_ON": "AEC aan", - "PLEASE_WAIT": "Een ogenblik geduld...", - "FOUND_NEW_ASSETS": "Nieuwe bronnen gevonden: %s", - "DOWNLOAD_ASSETS_FAILED": "Downloaden van bronnen mislukt", - "LOADING_ASSETS": "Bronnen laden...", - "HELLO_MY_FRIEND": "Hallo, mijn vriend!" - } -} - diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/upgrade.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/nl-NL/upgrade.ogg deleted file mode 100644 index 88797923258c68bfc8b50a4adc3e75cd90a895fc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3529 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/0.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/0.ogg deleted file mode 100644 index 7351d964aa89467fe9094e6b12f59291c800be59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2138 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/2.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/2.ogg deleted file mode 100644 index 8fa7c87cf84b82b5a766098c4c883b5cc119f685..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1762 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 U@iLs8WwjudVS6fMTL2O6F9|^|d;kCd diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/4.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/4.ogg deleted file mode 100644 index ea49088b3938c4fcfe08be28db5c82a2c01cdf63..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1883 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 ZsAD^GlvjF=vkZOAeQmySEH6WK{taT|g;M|k diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/7.ogg deleted file mode 100644 index 71395919d472c2a88b609ca580df346c7287b4db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2142 zcmY*a3pf*O8#Z&OC_kDBW6LS0GAmPZYzfH>F_|QpF*7!e4jB8>fl@h4p?#H8D8%G2 zr#@qH$T37Ym%hSmId#xC{{Q;_zUR8$>w50@x!?OeJ=gP~0|VW}#Krz=KamHdHe5?+ zN-IDS9d@2-AK-Tm05AhI`fO6r8}$F#1|1+mu$`CU02Ui`cfUZYtZ2r`kA^pe??vu~ z8yjyhAfgcv>Q6owK(P?T{6#VNK~WG64GB6+7A^dbuyuooC$bIUjYB=)kF(@Yd7KF$ zkg1WBPzoi`8{>A2$WVpJK3cj2Mg$)YsXunJ^fu8_a_a44=#JztUHoqBc9{X~YE z66o!)nWwJz&*e!gs-ESjj#<>#rCUK@b76+k7jfwVgK-$!V!+5}9ot)J!vk)MOAu2& zZ}8!$ap)fayk5C~`kT9-#>C*Cul8K%S5CKXZr*_-G9b#k=(!&DX;Tt^x(_ZiQfdX! zE&k@lDoX8607Yl68l5%55wjz%HVrVYR(niQ1lvo z*y12WXVLsE7M~VLH5A?FbN6j0A0iPM+OX7|7w*B+5TA<$Swlj(sLTCBZ=FrF?HwwI zk~(}G2dq1;D57lA>zdzif3sG%%5&rNMM?8=b1dZu#>(qIYWU4N&sYmF^6imiq3~ zhv#-0#lmBKRml^$gH^6R1RRR~!BaxbfymI+yi!ti4srW=X1pskVkfc0PL)uPm$82K zA*H|^Xz{Ap#dk{a1idtm8IGpa7M)4`m=Q?C#65Dq^o>PafFueieAiAZGHsV#M8 zzj|lGEFoWg39jb9FcTVda_yMWk$|uIN=+`V4Y&-^wX``GjMZqm$y?I}lRDU2=Of2J zG*}JD;O@Jms-E}sYzh9r{`Z`4w$9MoCex2?Grreyk(rtwkN!Zwcjq^^I&DX)9{MF` zePZz{C$JvU_5G(}-WqE5hWxadSCGo*vwK|FQPMHCAy^jyV9WhrK_?MdQ6e^>7VU1X zp@ofh22VF($r`>>lry*QG=}e!3i88@bo+=)p~nhigb-}z7A&)TP4BgW-zRi{X5NY7 zkz>of8AF63xm+4=hIV>j{l)RP17{>>feSocW<19t_b;AG~TE5&D-cCy? zNqX#D)6K8QcYG7<69JI{)#TVp$~-HDy6G_Vht=kb4(0Emr<`&$)b6UM9GNf>H6$ zaO`Y57)9EyR`^itG1(&owNx+KO_vQ00AKpZx_mE0oz+&{(5cfP9Zc;UtS?Khd_@S0 zurJpmw;dmgco3fTA-f%y@K@EroYc(B(UUIAhLh-K--N!x*X*@$RJm6M%_(8xYD%W! z^je=(A!lhcY-F}55Z$B@9ba}f!QIKBd}|Cxl&V?<{B%dJ_)_EI|$b>A6p$* zH|<{d4h~q@a_n!c#^lE6Bh(Uk!6=zZBd)0um%y)w;th*h=Dwl_}6rV6OMM`fM?$yG3C1g?{k$$CArr|E*x7`=Q~ zXY`4x>_7v(n;bfRLO}8)5+?jc=FJKK{WejywDCO*Ls8vQ*O499N)7Q%v;j7auXfw< zI~5pLt5L!(k5aODBaGFxz!xSRsmr;;PqG-+|5y6TI=8AY5?Q1YAE>2XKfW?g2~WJ+ zcO~sdX$))d8AT4l-N}~!(55dcw7VdKhsgTJw57uNqzF<*tY6vcYHlhKTFS3jQdX_k z7>2t8)^qS^h^^h{#1b}M5$NXhg@FCg@- zIi1^9XM$*-CT90W^Wt%ngE6z)+?`j1LnM5%(sZUE^gN2%?#O8M9n`fK26HdWfP(Q4&0Ud zRIu;zJx_vk)1xwoR^|4}~(8wR^4Rd>ls?sxe$(&p_o z_@k0L&694sz-#kte59aB@8Ng+1M!H!|Kl5rzeh#rx0Pw~f`4#XaKUd%BJ>;g2}aQI EH?kS-v;Y7A diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/8.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/8.ogg deleted file mode 100644 index 8e2dd5696c77c7b6266c366c7e479f66000aef18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1963 zcmY*a2{;t$8n(z7^7w^2V*;8GL$7EAxn)d66PSw zpbi=%Tax9VQxTJ`3UdIZ#}62KPu1MckKhXI=s$|fKX&|#tkJ(cYh;hyVCjdTy-~3r}p}jyGS%;h+ zl8_vo`8j;hp!XC;VXVh9Dk=8Rw#tq2$guDkyQ?G`5=pI0mIZv0@B1iBvzoi4nRFKN zQDk~6p>J83PS(qOgY%C*A=vW%mv(4mqSfZHJH#)ZQYh%eSU+}nzioHut&n;X{+(Pu z#j-&hX@96A$kslGTs8CDS@Pxn8C^F`U$9dR@c8pL$^2P*l?$&2>q#^Oym2cf{oM%T zw$xIPbccOrVyCRpTpXjsGeZv71ogHXn6XY~R^jfi%CiGrj$A9kv&z|b5&}1);o|~5 zYY7X7Ij_8kE-mx!kHmc*I@oSZVmzi=U%qp&}YxI0U=3;1d}CAjR5uz*Z+0HWh?ItevpFPLo|LR${n{F24{6!*n<2zzUt%vTeh^b&*OnN@3 z#_`F5dZ!l${-3qZtU&#n6y7bPB&PX-^ zb&zOq!~@Bgh9;R1T+$ak#icQ^j5?0m?c5gQ?GX6K=)&lL;q~ssVyF|91%7Suthu-* zt;0P2A4|LqW;McXU30nEV=toal{jRrEdXR{IIv@i;wYqY+YXRkm(1aH!rdw|5!2<6^ z{O)wKuzD+D@=k0=IIKBv{qyiTA~Gq~9Dy?Gip-RY0>px9s!Opedu0p8VUsY1mwe6G z_x9%WiYoclZvk)ItWzcCHDT=Y`6Qa^ks8V0<_QoTHQ;Vkc4K51pG-=~X@DBwQxjbb zv=(^f($RTDSs39g!-|mMod)){%Yoe}?UdaTA2Z5x5VPB~nC(^w?t-*57q|}dtA3}31D;^F74z(5BeXpj)zT0SyX_HeARw=ve;+PhtdS~jIlH|Qg zQw^Qb%epu;38<*KLA|sgHz7q=gKqaXato=b$};LJI0i_yUlPxMvJB(^*((zo3Dl%! zUzWn9TcVDBK;-xY+g(kgWmG}49{2P+oFe6v(7E^inAxfFu>0z;#XkZH5c%=;ji1rf zw0%R9%gxrcsTp{D&R&hprgFpfCW)p3Rmv-LHFNg6&NruiG#hM#SNKr9aa8iu$lVwI zqX;a7B6_Z;R{!xigr~Em5M07@hBLQ}O$I#}l`DgUg{;5ba6GQEu-Gl1qCJ8Hst{2h zs`dC*47oqHJcJ@^!z|kzO5uBFqUo>g_N3FF5&rZ76haAu=ocV>AaJ|^M=Zlmbv(;^ zaWiT*QueGC*x}Ils~1{W&wE;+xX-rn=)WsSG)0K;P#OFB53h=PIs#Dr4eozUg0O1q zcYL9TN1#Uf45B`$%RZ!@p^}*u!>*2n13W*%ZJ*MfhOHD){uMK%rM&`xmq`B!>mkwP zB!tHlBU+-1eZ55Z!R8um3QHMoO+CWBQ9Zq`9VK7{_3iq=|Dm3r(+ZF@@^e`IoK}L| rEnS6^C!nE068xVyW$j=n7ad5OExkT)P@65idVr;)R}U2BqMm;N8OVX0 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/9.ogg deleted file mode 100644 index b88ab8737baea7651766ff2d91cfe956d47cdb17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2386 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/err_pin.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/err_pin.ogg deleted file mode 100644 index 4d35f3cf26f23e78b149c45b2d3fb913e3dafb84..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4294 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/wificonfig.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pl-PL/wificonfig.ogg deleted file mode 100644 index 0d2222ff74a8e4427ca3586745a25472d7d6670e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4551 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 w09LFBZmv=2=U-VdM+gr81_|bc!~g&Q diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/1.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/1.ogg deleted file mode 100644 index 4299bc8fbe7bc8b54329253d8821eceaee400275..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1496 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 V);Io7%fbI(sgRAHzbiS2@fTPV_=Nxf diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/6.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/6.ogg deleted file mode 100644 index 32ea27b74fc04b76d77d0aa5237a3304a0c32a8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1886 zcmY+F2{aqn8po5G*4}3~N{YlXkI?Wc_S8-=f-#H>XLY_|gVwX6fs;r;=^ zK>-+yiLO4<0*w>l}-al}1|pgSF=6VmmaBSDbw)M1H|&!+vMyt_F=me0f-G(-F6?8Qf1Wy;*CxV0g== zLV3tBDJsq*2RyUhcn_&Zdw)_nmXwrH)6E;$0P{7F`!NCQ)NCn=}ySKXO3fD(7Jsg zD~&+V&~+b|Ok)O>U=M#+@=Ji}kcZqy)qhaE3+~jW*M@Vde5JS*t&nooPtZ77d4eYZ z`}sK`@w8{Iql*J32n)WZadMI5f3XodokBRUf6eV|A=|tm#O*e3g2g% z$;O8->D#Y>BcQMadL~7}`k;75p)F{jCJf~;UvR@t>)Ys-I&~;x^NkZ9@^|U00AJs< zg$hbN)d-D)NVfh80#V&Xe+d=8=J&9!^wc=RGFzAdf2{vNsjpDcZD7v8pml$)!;#_A zQr|_~-P9|dJ__ybh`mor2+bb>c7_kPW=fozyDoYz4&&gKh3UavsT}O9$EDSf0wX0r zLPvY2D@cSnlXRQYEvm+^(Y7`v#5K^Oj-Po7LU?N5icb4?X!H7%!rBdK5pSywVa+K&1_lI0fA z6dft0QEI48GTwvA|JV@N3-x(-Ltkw8w?eB!5snd@T72cbtTOzyJC788UhD#~Oa<`~%a1t?J&D@-{6ye!~8n(Q1+Hc}pMJLf7V&{m> zigP`L<$83lM6|dB$t5 zACvY>xx<=^X^sD+ThulMEo<;YC~|%u94Zw^@{pddtk;bzleVwN;(7nzxinj0m^t7Z zHZb?0Fz($Rh)m3LelQNdtc{4^#}_pmA*qlSw8u90rySjXtyG5Bg>Bz`W^2l3k}V>C zD|NN;#`!`MAE=T&roH|k9lBGHztcyIc!()rh|xqOCz!WHP*iFb8qyM($J^ubg%qM7 zzC-y_h#$VJm-p%U5vWDpPn{FBOXodrwKMF_vqBdri4qK7IufKmRAiJ?s+qA}qTlpp z{)__LzNP*0(neP()>iYx%DxzrJ;A*T@!VRY2@OpM3XI}@sP>e@LRXl}ZcNp3Ji-5& z%}H>&!SrYb8Ye8o8RX_{8d4U$c$;tc5^*oKY~nZ4TaJd(e%Yy*>CLCnUz+T~a%K5PNRQ&jvpi zSI4ncC_K-S%TA~-UP;_a>1|akbL1Jmu$w0>ynF`Mue1ty=H7b~)$#%^qIxr|>Yx|e zbyin?NG6|^m9x6S#_V!1`ist~L75A_$WD2FA=2qH*EmKN6nLdnU}!)7Cmr^osKFtJ ft`Y%A+&iuR_cYLKf78eN|4W&k#@~z}q^0v0ss4cg diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/7.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/7.ogg deleted file mode 100644 index c8542ed05d7014bfb8124b4b647c0f5180d884c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2094 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 diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/9.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/9.ogg deleted file mode 100644 index e97c8fc4b9dea645ca7336f077db9091e2e2baa9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1809 zcmY+Fc{tly7spBLRgFDDNDzu3u?C?*Y;Em|G4`EbRIP(nguzxZH1yoSC8 z9*1KSNY)Cv8W0&66m87%0$3j2fMw!QlraBD*2RAdlX_SjE7*nEk1~^Y=MyIQ$3|a^ z0wRMV{mpGi=43|zlz^StS4P4q#e+|0c_2Aa`&@F+ zdG+K+RR6kknzY6WAxiY5yp+NmjJu;`tLG+9T>Kt3v{+lHA_1YrsSmx{n*3O8o!%ht zGXGgVqi)aBG{C!82WK%FxAKwQv(BU1uIuW%u+$8A{c={lZNOfZmgA#Lwf;tUiq98?;9aWFI_Q@`VL6@rBU5Lo8;#xEQJ<@H5P0hDXdzt1a&8!>PqPN}bjve_O{yJ&z(R%Ni(!mHuN3VCq)sr&q zOe?$Lmh-+O6lgtNE8n>z#gk$rx#~`*GAZo_*E<({ev+Xd9yi0@{M>f;R&;@RD#JUt zy|=H5D3y}UW2W(nl66sJnR1vcxN8+_xN(;}fYqP)0RR;+oyYMU*@#??f}T{`arIg3 zZklD?Vg()T6oQ^;6%fb)uWokgYYT+>$RZr2A~mH4rK8hvo**^dNN)A1WxK&{TF-Yj z!_bY^GC%l}_hl|CmGtKzR&ftYkLNX^Y%7 zOp)|5>VZJ-ig6Z+Nau&V*NKazKl`sS;VTuWA`YXFE=Y}Ld+=*ziI z;=y@kZom1hpT8K>*~9b?;Ih}bU_5Esbgy;E9zO9|Pp-JOc^o-cy<0Wt#m%)$SL)ZM z7c!oh+!{kpXto3Ao~b}Irs^%J#Tv4&of~yFC&t@y8V9l*%?6)>qqSn~>jXZixk&TI&)rwZ% zvAv2dBF{Y#!lT>WbR8`RiQX_C@K`KQj?=aYY@ueYA3~{(4cj6nNu~g(h_3mw!LFN}8()7h_ zP}*F=aLUM0#pf&BeR-a-ykc>pxQot&QG0m$vbJAHnu5q18x#yjyS^DqS#`7s2S5~t zTix*6!Jej8N7TdpR|nM4X;O!IggkDF6mLadROL@l`Mo7kb$`%Ew1?5Gi0{lUgmNY3 zjn+R;b=$u(d!)KT$aN#mDBBq35$D5?@b9!7qpFz#voMz$v)f)D4FFI~0#T@kFAtfrCgz3Q}JP(_D~2n6p_JQ86Wjk#s8$ z!V3EV5H5LEhGvqb(@u~(oe`Av;ev_Am0Dz>4(Nj1Wlvw;RM9n8Y7l>w*k^5aMr|qs zqzQzx@RZ~As)4ZgL;laELr1l(jK2p!VKM%Pl>-VEL;WdUbPnFT;;VaXK^dJOG!=bc z`mNE1>SU?^Cq72y0ERgROU9+$l$qRBI`_8_e7%#%`inT*QZQS%u=8z8-6!&V$#dOR z!!P(Ggsj?;@Dh%n=h%#Ijv?}u(o8Z7RVKcAFdb0C5t#~Yh=E=-0YFJHUS{Qh)6RG( zqqbJ*+H7^5gXB9Xw-Vute2i?J2Z-s~g Rb;gkRe;MI_*}X$U;y;NNCG7wJ diff --git a/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/activation.ogg b/examples/xiaozhi/XiaoZhiCode_V2.1.0/main/assets/locales/pt-PT/activation.ogg deleted file mode 100644 index 1c980ac0b5abe0e95714abd28bfafb64303b6e97..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14660 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