176 Commits

Author SHA1 Message Date
Kuba Szczodrzyński
159ffa76fd [release] v1.3.0
Some checks failed
Release / Run Clang lint (push) Has been cancelled
Release / Publish PlatformIO platform (push) Has been cancelled
Release / Publish GitHub release (push) Has been cancelled
2023-08-29 19:21:09 +02:00
Kuba Szczodrzyński
1ac3d30d84 [libs] Implement Update MD5 2023-08-29 19:19:28 +02:00
Kuba Szczodrzyński
631ef6ba59 [github] Reuse GitHub workflows 2023-08-29 14:39:39 +02:00
Kuba Szczodrzyński
27393e47c3 [beken-72xx] Initialize UART to fix deep sleep 2023-08-23 16:08:03 +02:00
Péter Sárközi
bd47772c04 [beken-72xx] Fix GPIO deep sleep wakeup edge (#159)
Manufacturer docs: https://docs-bekencorp-com.translate.goog/sdk_3.0.x/bk7238/html/developer-guide/power_save/sleep_test.html?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=hu&_x_tr_pto=wapp

Discussion: https://github.com/libretiny-eu/libretiny-esphome/pull/11
2023-08-23 16:06:55 +02:00
Kuba Szczodrzyński
f3871388ce [docs] Restore feature support table 2023-08-18 13:47:06 +02:00
Ivan Kravets
62874bebf4 [misc] Fix PlatformIO repository URL (#157) 2023-08-17 19:23:10 +02:00
Kuba Szczodrzyński
2ca368305c [release] v1.2.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-08-17 19:04:50 +02:00
Kuba Szczodrzyński
f697ae6f11 [docs] Add migration to OpenBeken guide 2023-08-17 18:38:04 +02:00
Kuba Szczodrzyński
ef6dd35977 [docs] Rewrite flashing guides 2023-08-17 17:17:10 +02:00
Hajo Noerenberg
ccf21b4eab [realtek-ambz] Enable Mbed-TLS for MD5 hashing, remove Polar SSL (#156)
* Enable Mbed-TLS, remove Polar SSL

* Reformat lt_defs.h

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-08-17 15:20:02 +02:00
Kuba Szczodrzyński
e99c6124e7 [docs] Add video guide link, use ready Docker images 2023-07-13 21:19:04 +02:00
Kuba Szczodrzyński
5721bd74d7 [docs] Update LibreTiny ESPHome component naming 2023-07-13 20:41:21 +02:00
Kuba Szczodrzyński
ff443ca488 [release] v1.2.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-07-13 18:02:58 +02:00
Péter Sárközi
93e0a5d066 [beken-72xx] Implement deep sleep (#140)
* Initial support code for Deep Sleep

* Global functions

* Remove unnecessary override

* clang-format

* Support for multiple pins

* Fix math

* Add a way to unset GPIOs

* Clang format

* Update brief

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-07-13 18:00:14 +02:00
Kuba Szczodrzyński
150c2ef26d Merge branch 'family/ambz2' 2023-07-13 17:31:52 +02:00
Kuba Szczodrzyński
4d81fcac26 [realtek-ambz2] Flash bootloader & partition table in UF2 2023-07-13 17:00:42 +02:00
Kuba Szczodrzyński
a3bbdf1c16 [core] Migrate to uf2ota v5.0.0, refactor OTA API 2023-07-13 12:15:48 +02:00
Kuba Szczodrzyński
39df2e7b54 [core] Move C types to API units 2023-07-13 12:06:37 +02:00
Sonic-Amiga
6169f68119 [realtek-ambz] Improve flashing guide, add test pads for WR2 board (#147)
* platform/realtek-ambz: Improve flashing guide

Known USB adapter compatibility issues. Emphasize, so that the paragraph is
easier to notice.

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>

* base/wr2: Add UART2 test pads to the WR2 diagram

The module has UART2, necessary for flashing, only on test pads. Document this.

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>

* Move test pads to separate files, update variants

* Update wiring guide

---------

Signed-off-by: Pavel Fedin <pavel_fedin@mail.ru>
Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-07-11 11:46:36 +02:00
Kuba Szczodrzyński
e38e53bac0 [core] Split lt_api.c into separate units 2023-06-22 18:30:14 +02:00
Kuba Szczodrzyński
b38a4d5d46 [core] Add hardware peripheral availability defines 2023-06-21 17:02:48 +02:00
Kuba Szczodrzyński
96412624d9 Merge branch 'master' into family/ambz2 2023-06-21 13:35:52 +02:00
Kuba Szczodrzyński
f8876bba87 [release] v1.1.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-06-20 19:37:25 +02:00
Kuba Szczodrzyński
68b5773827 [core] Remove boardgen submodule, again 2023-06-20 19:28:12 +02:00
Kuba Szczodrzyński
74659901c0 [boards] Fix BW15 PCB template name 2023-06-20 19:09:46 +02:00
Kuba Szczodrzyński
73ede2838c Merge branch 'master' into family/ambz2 2023-06-20 18:53:46 +02:00
Kuba Szczodrzyński
273a86532b [beken-72xx] Add initial BK7231Q support, add WA2 board 2023-06-20 17:22:12 +02:00
Kuba Szczodrzyński
05e13dafed [beken-72xx] Rename BK7231U to BK7231T, add BK7231Q family 2023-06-20 17:19:21 +02:00
Kuba Szczodrzyński
6af97d2691 [boards] Add Tuya series 1 boards 2023-06-18 20:19:05 +02:00
Kuba Szczodrzyński
f9fb78feed [boards] Add T102 and T103 boards 2023-06-18 16:48:49 +02:00
Kuba Szczodrzyński
96dbbe0919 [boards] Move custom templates from boardgen, add WB2L_M1 board 2023-06-18 16:11:55 +02:00
Kuba Szczodrzyński
0ef66af342 [boards] Embed shielding in PCB template 2023-06-18 11:34:24 +02:00
Kuba Szczodrzyński
7ed48bf9fc [boards] Add Tuya WBLC5 and CBLC5 boards 2023-06-18 00:13:05 +02:00
Adrián Panella
1335b84391 [boards] Add Tuya CBU board (#106)
* add CBU module

* boardgen templates

These should go in boardgen package.
Included here for reference

* boardgen output

* [boards] Update for latest version of boardgen

* [boards] Change CBU silkscreen, add variant file

---------

Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
2023-06-17 21:25:17 +02:00
Kuba Szczodrzyński
e2794d5f84 [builder] Fix running ltchiptool with no baudrate 2023-05-31 12:38:15 +02:00
Kuba Szczodrzyński
e7f35c584b [realtek-ambz2] Reuse Log UART for Serial 2023-05-31 12:37:34 +02:00
Kuba Szczodrzyński
1e49c3ff6f [realtek-ambz2] Fix missing flash API resource lock unit 2023-05-31 12:36:46 +02:00
Kuba Szczodrzyński
e256ac8e46 [builder] Fix ltchiptool empty quotes on Windows 2023-05-30 18:49:58 +02:00
Kuba Szczodrzyński
9c6e9d1525 [realtek-ambz2] Disable SoftwareSerial and Wire 2023-05-30 18:15:44 +02:00
Kuba Szczodrzyński
41985e5743 [core] Move common flags to base.py 2023-05-29 22:26:33 +02:00
Kuba Szczodrzyński
f1e41f7cc1 [realtek-ambz2] Add GDB init command 2023-05-29 22:25:23 +02:00
Kuba Szczodrzyński
6135e4f7b0 [boards] Update flash layouts, add W302 chip 2023-05-29 16:16:58 +02:00
Kuba Szczodrzyński
af8c7417b3 [realtek-ambz2] Keep LOG UART enabled, wipe OTA2 in UF2 2023-05-28 19:18:54 +02:00
Kuba Szczodrzyński
babdb1287f [realtek-ambz2] Replace lwIP with external port 2023-05-27 20:54:40 +02:00
Kuba Szczodrzyński
4532c88873 [core] Add lt_set_debug_mode() function, update core types 2023-05-27 16:03:46 +02:00
Kuba Szczodrzyński
bc1b83d931 Merge branch 'master' into family/ambz2 2023-05-27 15:43:35 +02:00
Kuba Szczodrzyński
87ad0798e4 [realtek-ambz2] Adapt WiFi library to ambz2_sdk 2023-05-27 15:41:07 +02:00
Kuba Szczodrzyński
a80032d46c [core] Move Wiring common core to wiring/, reset watchdog in yield() 2023-05-26 15:29:33 +02:00
Kuba Szczodrzyński
4dae304f51 [core] Add lt_get_device_mac() function 2023-05-25 20:43:00 +02:00
Kuba Szczodrzyński
9b7d34fa65 [realtek-ambz2] Fix C++ support, implement SerialClass 2023-05-25 14:35:41 +02:00
Kuba Szczodrzyński
c0cc602c9a [core] Add configure() for SerialClass 2023-05-25 14:29:35 +02:00
Kuba Szczodrzyński
e5f98ff41f [core] Refactor Wiring, use PinData for parameters 2023-05-24 22:01:05 +02:00
Kuba Szczodrzyński
bc74c21599 [realtek-ambz2] Enable compilation of Arduino core 2023-05-24 13:02:33 +02:00
Kuba Szczodrzyński
3836ad20b7 [core] Refactor SerialClass as API library 2023-05-24 11:55:07 +02:00
Kuba Szczodrzyński
b073290989 [realtek-ambz2] Implement base C API 2023-05-23 19:54:00 +02:00
Kuba Szczodrzyński
43c9d0db10 [docs] Add Porting new families guide 2023-05-23 15:58:11 +02:00
Kuba Szczodrzyński
c40bdd68af [realtek-ambz2] Use external FreeRTOS port 2023-05-23 15:14:59 +02:00
Kuba Szczodrzyński
620e457eb6 [realtek-ambz2] Fix C++ linker support 2023-05-23 12:56:42 +02:00
Kuba Szczodrzyński
5c4da6e82b [core] Fix ltchiptool installation in PlatformIO 2023-05-23 12:12:42 +02:00
Kuba Szczodrzyński
8c636e44f7 [realtek-ambz2] Add initial SDK fixups and API layer 2023-05-23 12:11:17 +02:00
Kuba Szczodrzyński
07e9aa1ded [realtek-ambz2] Make compiling base core possible 2023-05-19 10:42:59 +02:00
Kuba Szczodrzyński
27a7faaab7 [core] Remove boardgen submodule 2023-05-18 22:14:58 +02:00
Kuba Szczodrzyński
752768b1e2 [docs] Update supported chip list, remove AmebaZ2 boards for now 2023-05-18 21:03:08 +02:00
Kuba Szczodrzyński
f7c28eeea4 [release] v1.0.2
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-05-11 16:20:26 +02:00
Albert Koczy
113b2fc31d [docs] Fix dead link to Boards & CPU list (#124) 2023-05-07 12:31:27 +02:00
Stroe Andrei Catalin
86924d8785 [beken-72xx] Fix delay, yet again (#116) 2023-05-01 23:28:01 +02:00
Stroe Andrei Catalin
219415174e [libs] Fix mDNS after a wifi disconnect / reconnect event (#112)
* [libs] Fix mDNS not responding when device disconnects / reconnects to wifi

* Minor bugfix

* Reworked mDNS fix

* Update LwIPmDNS.cpp
2023-05-01 21:44:03 +02:00
Stroe Andrei Catalin
8999cb9091 [beken-72xx] Fix delay macro (#114)
* [beken-72xx] Fix delay macro

* Better fix for delay
2023-05-01 21:08:01 +02:00
Kuba Szczodrzyński
8337ac121e [core] Fix reentrant malloc wrappers 2023-05-01 20:58:37 +02:00
Kuba Szczodrzyński
d332315e7a [beken-72xx] Fix WiFi compilation issue 2023-04-28 21:24:41 +02:00
Péter Sárközi
882f58bae4 [beken-72xx] Implement WiFi powersave (#111)
* Rebase

* Clang-format
2023-04-28 17:21:49 +02:00
Kuba Szczodrzyński
2c86a36fe0 [release] v1.0.1
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-28 14:19:21 +02:00
Kuba Szczodrzyński
b984519546 [core] Update ltchiptool to fix PlatformIO publishing 2023-04-28 14:18:51 +02:00
Kuba Szczodrzyński
7b0f6b22c1 [release] v1.0.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-27 23:39:11 +02:00
Kuba Szczodrzyński
3b8a4f1b60 Merge branch 'structure-refactor' 2023-04-27 23:36:51 +02:00
Kuba Szczodrzyński
edd2c0542b [core] Update ltchiptool to v4.0.0 2023-04-27 23:32:28 +02:00
Kuba Szczodrzyński
dbc905dca3 [core] Rename project to LibreTiny 2023-04-27 23:30:46 +02:00
Kuba Szczodrzyński
461e4c6df0 [core] Prepare for project name change 2023-04-24 11:35:39 +02:00
Kuba Szczodrzyński
85a687fc56 [docs] Add migration page 2023-04-24 10:47:06 +02:00
Kuba Szczodrzyński
c5361a4738 [beken-72xx] Use realloc() based on malloc() 2023-04-22 18:29:52 +02:00
Kuba Szczodrzyński
42c18859f3 [core] Update ltchiptool to fix activating OTA 2023-04-22 18:10:47 +02:00
Kuba Szczodrzyński
1ba6834391 [docs] Update configuration docs 2023-04-11 20:11:42 +02:00
Kuba Szczodrzyński
376a4db4cb [release] v0.13.0
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-04-11 19:34:24 +02:00
Kuba Szczodrzyński
775e06b259 [core] Fix compilation on Linux 2023-04-11 19:15:56 +02:00
Kuba Szczodrzyński
3ba3c2a2be [realtek-ambz] Fix linker script XIP region length 2023-04-05 10:48:46 +02:00
Kuba Szczodrzyński
76ad89e2f1 [release] v1.0.0-alpha.1 2023-03-26 19:30:42 +02:00
Kuba Szczodrzyński
2a7f1b52a0 [core] Update ltchiptool to v4.0.0 2023-03-26 17:44:40 +02:00
Kuba Szczodrzyński
bd75b54dce [core] Allow customizing flash layout 2023-03-25 21:13:11 +01:00
Kuba Szczodrzyński
070f2afd66 [core] Generate linker scripts based on flash layout 2023-03-25 20:44:19 +01:00
Kuba Szczodrzyński
0e84e08a18 [core] Support adding custom board JSON, pass it to ltchiptool 2023-03-25 20:10:15 +01:00
Kuba Szczodrzyński
4c1ab20ba4 [core] Allow specifying custom library options 2023-03-23 22:49:48 +01:00
Kuba Szczodrzyński
63ac7b365d [core] Add ESP inline library 2023-03-20 21:29:57 +01:00
Kuba Szczodrzyński
c51bf0b7db [core] Migrate to GPIO-based pin numbering 2023-03-20 21:28:50 +01:00
Kuba Szczodrzyński
201db4668e [realtek-ambz] Fix WiFi AP mode and DNS 2023-03-18 13:27:16 +01:00
Kuba Szczodrzyński
250e67ab1f [realtek-ambz] Update stdlib compatibility 2023-03-17 18:17:35 +01:00
Kuba Szczodrzyński
2e30d34021 [core] Update Arduino compatibility, fix MD5 library 2023-03-17 17:33:43 +01:00
Kuba Szczodrzyński
2882eaa0c2 [core] Print platform versions, add GCC version to startup banner 2023-03-17 17:32:28 +01:00
Kuba Szczodrzyński
8faffedddc [core] Fix swapped flash reading/writing API 2023-03-16 17:48:34 +01:00
Kuba Szczodrzyński
5260930919 Merge branch 'master' into structure-refactor 2023-03-16 11:21:17 +01:00
Kuba Szczodrzyński
24832d3277 [beken-72xx] Fix bootloop by aggressive GCC optimization 2023-03-15 23:19:26 +01:00
Kuba Szczodrzyński
8f338a6b30 [beken-72xx] Fix bootloop by undefined instruction on GCC 10 2023-03-15 17:26:09 +01:00
Kuba Szczodrzyński
3d3f3700a8 [core] Update lwIP for SDK-independent headers 2023-03-14 13:07:44 +01:00
Kuba Szczodrzyński
eae64d34e2 [core] Update ltchiptool to v3.0.2 2023-03-14 11:34:09 +01:00
Kuba Szczodrzyński
a27e76bfa7 [realtek-ambz] Backport UART fix from structure-refactor 2023-03-13 22:30:02 +01:00
Kuba Szczodrzyński
b050662a5c [core] Use external FreeRTOS library 2023-03-13 22:18:02 +01:00
Kuba Szczodrzyński
f69b4bea4f Merge branch 'master' into structure-refactor 2023-03-13 17:46:13 +01:00
Kuba Szczodrzyński
4e3b081c60 [core] Include GCC version in the startup banner 2023-03-13 17:27:21 +01:00
Kuba Szczodrzyński
a2de77ce30 [core] Use GCC 10.3.1 with -Os for all families 2023-03-13 16:50:13 +01:00
Kuba Szczodrzyński
5de98ed56c [realtek-ambz] Selectively update GCC to v10.3.1 2023-03-12 22:27:26 +01:00
Kuba Szczodrzyński
ff8ac6036c [realtek-ambz] Update GCC to v5.4.1 2023-03-12 14:12:04 +01:00
Kuba Szczodrzyński
c3f12ab247 [core] Rename CPU and memory APIs 2023-03-12 14:11:16 +01:00
Kuba Szczodrzyński
dfcb36361e [docs] Refactor & update API documentation 2023-03-11 21:58:43 +01:00
Kuba Szczodrzyński
c4a3e9e2ee [beken-72xx] Re-enable OTA encryption 2023-03-11 16:59:57 +01:00
Kuba Szczodrzyński
fd1afea1bc [core] Refactor LT class into C methods 2023-03-10 19:08:55 +01:00
Kuba Szczodrzyński
65cf460691 [core] Migrate to UF2 OTA format version 2 2023-03-09 11:46:40 +01:00
Kuba Szczodrzyński
046f7df7d1 [realtek-ambz] Fix UART setup and receiving, implement ADR 2023-03-05 16:45:16 +01:00
Kuba Szczodrzyński
8323bafd4c [beken-72xx] Fix include path and delay() alias 2023-03-05 14:42:59 +01:00
Kuba Szczodrzyński
6b92aac1da [core] Organize GCC compilation flags 2023-03-04 17:19:24 +01:00
Kuba Szczodrzyński
3113b387c3 [boards] Move docs generation to GitHub Actions 2023-03-04 16:56:49 +01:00
Kuba Szczodrzyński
6d2b653f61 [core] Remove public FreeRTOS dependency 2023-03-04 12:47:45 +01:00
Kuba Szczodrzyński
47daefe675 [realtek-amb] Fix or suppress compilation warnings 2023-03-04 11:12:58 +01:00
Kuba Szczodrzyński
e8c18f4e66 [core] Add common malloc() implementation 2023-03-04 11:12:55 +01:00
Kuba Szczodrzyński
76a82768fe [realtek-ambz2] Update base core to new structure 2023-03-04 11:12:48 +01:00
Kuba Szczodrzyński
8be5aeab59 [core] Update Arduino compatibility 2023-03-04 11:12:36 +01:00
Kuba Szczodrzyński
fbfd96ecdb [realtek-ambz] Update Arduino core to new structure 2023-03-04 11:10:38 +01:00
Kuba Szczodrzyński
dee20c859c [core] Use void instead of MD5 context struct 2023-03-04 11:10:35 +01:00
Kuba Szczodrzyński
ce0a88147b [realtek-ambz] Update base core to new structure 2023-03-04 11:10:30 +01:00
Kuba Szczodrzyński
7f62f1e965 [beken-72xx] Make WiFiData private 2023-03-04 11:10:25 +01:00
Kuba Szczodrzyński
b51501fb21 [beken-72xx] Update Arduino core to new structure 2023-03-04 11:10:18 +01:00
Kuba Szczodrzyński
72ab64461c [builder] Add library queue to manage cloned environments 2023-03-04 11:10:05 +01:00
Kuba Szczodrzyński
26b393e059 [core] Replace usages of PIN_SERIAL_TX with HAS_SERIAL 2023-03-04 11:09:38 +01:00
Kuba Szczodrzyński
bc328657aa [beken-72xx] Update base core to new structure 2023-03-04 11:09:27 +01:00
Kuba Szczodrzyński
c579219427 [core] Make PIO detach existing packages instead of overwriting 2023-03-04 11:06:04 +01:00
Kuba Szczodrzyński
3413d70210 [core] Update PIO builders to new structure 2023-03-04 11:05:56 +01:00
Kuba Szczodrzyński
8bbc7e13fb [core] Move arduino/ files to cores/ 2023-03-04 11:05:28 +01:00
Kuba Szczodrzyński
f1ecb312c7 [core] Move platform/ files to cores/ 2023-03-04 11:05:24 +01:00
Kuba Szczodrzyński
3407891e9c [core] Refactor families.json 2023-03-04 11:05:19 +01:00
Kuba Szczodrzyński
8f447a4a72 [release] v0.12.6
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-02-02 22:28:52 +01:00
Kuba Szczodrzyński
8ace11e462 [core] Fix Python lint 2023-02-02 22:28:10 +01:00
Kuba Szczodrzyński
949dfe7266 [core] Use PIO repackages of vendor frameworks 2023-02-02 22:21:12 +01:00
Kuba Szczodrzyński
f0d490aef9 [docs] Fix ESPHome sample config indent 2023-02-02 21:59:14 +01:00
Kuba Szczodrzyński
bdedae981a [beken-72xx] Fix UF2 RBL relative offset 2023-01-28 16:38:28 +01:00
Kuba Szczodrzyński
9e0750c9d3 [release] v0.12.5
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-28 13:00:10 +01:00
Kuba Szczodrzyński
9a3e512b1b [boards] Add LSC LMA35 T variant 2023-01-28 13:00:10 +01:00
Kuba Szczodrzyński
861e741030 [beken-72xx] Disable OTA encryption 2023-01-28 12:53:57 +01:00
Kuba Szczodrzyński
a3e7e21d45 [core] Migrate to ltchiptool v3.0.0 2023-01-28 12:53:57 +01:00
Matt Shepcar
86db2fcf61 [beken-72xx] Fix for flicker when PWM lights turn on/off on bk7231n (#68) 2023-01-28 12:52:01 +01:00
Kuba Szczodrzyński
fcd72e013a [docs] Add ESPHome Dashboard usage docs 2023-01-26 20:41:57 +01:00
Kuba Szczodrzyński
2450f8c64b [release] v0.12.4
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-26 11:28:25 +01:00
Kuba Szczodrzyński
676a9b1686 [core] Fix reinstalling ltchiptool 2023-01-26 11:28:09 +01:00
Kuba Szczodrzyński
b10db63c74 [realtek-ambz] Fix WiFi station BSSID retrieval 2023-01-19 17:38:45 +01:00
Kuba Szczodrzyński
4b25ef7516 [realtek-ambz] Fix resetting OTA switch when it reaches 0 2023-01-19 16:53:27 +01:00
Kuba Szczodrzyński
de0d19cda6 [docs] Update ltchiptool installation info 2023-01-19 12:29:59 +01:00
Kuba Szczodrzyński
c55386af0e [docs] Add icons to external links 2023-01-18 19:06:18 +01:00
Kuba Szczodrzyński
33fe1c7a54 Merge branch 'docs-refactor' 2023-01-18 18:39:11 +01:00
Kuba Szczodrzyński
bf6d05e92a [docs] Remove AmbZ doxygen build 2023-01-18 18:38:52 +01:00
Kuba Szczodrzyński
b6113d8d2b [docs] Configure MkDocs Material 2023-01-18 18:32:34 +01:00
Kuba Szczodrzyński
bc31154035 [docs] Add Tuya Pinout Config to resources 2023-01-18 17:59:51 +01:00
Kuba Szczodrzyński
edfe0329bf [docs] Update links in board docs 2023-01-18 17:59:19 +01:00
Kuba Szczodrzyński
1e11dd776a [docs] Move resources to chip family docs 2023-01-18 17:56:09 +01:00
Kuba Szczodrzyński
028526d22d [docs] Add ltchiptool GUI download button 2023-01-18 15:00:01 +01:00
Kuba Szczodrzyński
7ac2d854f2 [docs] Move tools docs to a subdirectory 2023-01-18 14:59:36 +01:00
Kuba Szczodrzyński
279c81e431 [docs] Update code block styles 2023-01-18 14:02:12 +01:00
Kuba Szczodrzyński
4e319b40ed [docs] Fix ltchiptool docs badges 2023-01-18 13:30:13 +01:00
Kuba Szczodrzyński
d082b39980 [docs] Add ltchiptool screenshot 2023-01-17 22:45:00 +01:00
Kuba Szczodrzyński
277402f577 [docs] Update chip flashing guides, fix mkdocs building 2023-01-17 22:33:57 +01:00
Kuba Szczodrzyński
9e95c507b1 [docs] Refactor docs structure, add project upload guides 2023-01-17 18:56:15 +01:00
Kuba Szczodrzyński
7440fc6f46 [core] Add parent_description key to families 2023-01-16 10:42:30 +01:00
Kuba Szczodrzyński
a24028f674 [beken-72xx] Fix RBL app size typo 2023-01-16 10:41:17 +01:00
Stroe Andrei Catalin
00913b013f [beken-72xx] Fix compilation on ARM systems (#58)
* Fix toolchain for BK7231 on ARM cpus

* Fix format

* PR comments

* PR Comments, part 2
2023-01-03 21:15:03 +01:00
Mihai Ambrosie
447d08d613 [realtek-ambz] Fix 4M/980k linker script name (#56) 2023-01-03 10:56:48 +01:00
Kuba Szczodrzyński
d4f7736b2d [release] v0.12.3
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-02 20:32:46 +01:00
Kuba Szczodrzyński
60f72fffdf [core] Fix installing ltchiptool, again 2023-01-02 20:32:29 +01:00
Kuba Szczodrzyński
77af9c1cba [release] v0.12.2
Some checks failed
Lint check / Lint with clang-format (push) Has been cancelled
Lint check / Lint with black (push) Has been cancelled
PlatformIO Publish / publish (push) Has been cancelled
2023-01-02 19:41:39 +01:00
Kuba Szczodrzyński
1b2414337f [core] Fix installing ltchiptool 2023-01-02 19:40:55 +01:00
810 changed files with 20285 additions and 29301 deletions

View File

@@ -1,35 +0,0 @@
name: Lint check
on: [push, pull_request]
jobs:
lint-clang-format:
name: Lint with clang-format
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Check code with clang-format
uses: jidicula/clang-format-action@v4.5.0
with:
clang-format-version: "14"
lint-black:
name: Lint with black
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
- name: Install test dependencies
uses: BSFishy/pip-action@v1
with:
packages: |
black
isort
- name: Check code with black
run: black --check .
- name: Check code with isort
run: isort --profile black . --check-only

View File

@@ -1,46 +0,0 @@
name: PlatformIO Publish
on:
push:
tags:
- v*.*.*
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cache pip
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache PlatformIO
uses: actions/cache@v2
with:
path: ~/.platformio
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
- name: Set up Python
uses: actions/setup-python@v2
- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio
- name: Publish PlatformIO package
run: pio package publish --non-interactive
env:
CI: true
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
- name: Get latest version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
- name: Release on GitHub
uses: softprops/action-gh-release@v1
with:
name: ${{ steps.get_version.outputs.VERSION }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

12
.github/workflows/push-dev.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
name: Push (dev), Pull Request
on:
push:
branches: ["**"]
pull_request:
jobs:
lint-clang:
name: Run Clang lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-clang.yml@master
lint-python:
name: Run Python lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-python.yml@master

View File

@@ -1,10 +1,8 @@
name: Deploy docs on GitHub Pages
name: Push (master)
on:
push:
branches:
- master
branches: ["master"]
workflow_dispatch:
jobs:
docs:
name: Deploy docs
@@ -18,25 +16,29 @@ jobs:
with:
python-version: '3.10'
- name: Install ltchiptool
run: pip install ltchiptool
- name: Install docs dependencies
run: pip install -U ltchiptool boardgen
- name: Generate static JSON files
- name: Generate docs and static JSON files
run: |
mkdir -p site/
python docs/build_json.py
boardgen ltci
python docs/scripts/write_boards.py
python docs/scripts/write_apis.py
python docs/scripts/prepare_doxygen.py
python docs/scripts/build_json.py
cp *.json site/
- name: Set custom domain
run: |
mkdir -p site/
echo docs.libretuya.ml > site/CNAME
echo docs.libretiny.eu > site/CNAME
- name: Deploy docs
uses: libretuya/mkdocs-deploy-gh-pages@master
uses: libretiny-eu/mkdocs-deploy-gh-pages@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CONFIG_FILE: mkdocs.yml
EXTRA_PACKAGES: build-base doxygen
REQUIREMENTS: docs/requirements.txt
CUSTOM_DOMAIN: docs.libretuya.ml
CUSTOM_DOMAIN: docs.libretiny.eu

22
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Release
on:
push:
tags: ["v*.*.*"]
jobs:
lint-clang:
name: Run Clang lint
uses: kuba2k2/kuba2k2/.github/workflows/lint-clang.yml@master
publish-pio-platform:
name: Publish PlatformIO platform
needs:
- lint-clang
uses: kuba2k2/kuba2k2/.github/workflows/publish-pio-platform.yml@master
secrets:
PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_AUTH_TOKEN }}
gh-release:
name: Publish GitHub release
needs:
- publish-pio-platform
uses: kuba2k2/kuba2k2/.github/workflows/gh-release.yml@master
permissions:
contents: write

9
.gitignore vendored
View File

@@ -256,6 +256,13 @@ cython_debug/
# mkdocs
xml/
ltapi/
ltambz/
hashChanges.yaml
.piopm
# board files
docs/status/supported_*.md
docs/status/unsupported_boards_*.md
boards/**/*.svg
boards/**/*.md
# other generated files
docs/contrib/lt-api-functions.md

2
.gitmodules vendored
View File

@@ -1,2 +0,0 @@
[submodule "tools/boardgen"]
url = https://github.com/kuba2k2/boardgen

View File

@@ -1,15 +1,17 @@
# LibreTuya
# LibreTiny
<small>(formerly LibreTuya)</small>
<div align="center" markdown>
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/kuba2k2/libretuya/Deploy%20docs%20on%20GitHub%20Pages?label=docs&logo=markdown)](https://kuba2k2.github.io/libretuya/)
![GitHub last commit](https://img.shields.io/github/last-commit/kuba2k2/libretuya?logo=github)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/kuba2k2/libretiny/push-master.yml?label=docs&logo=markdown)](https://docs.libretiny.eu/)
![GitHub last commit](https://img.shields.io/github/last-commit/kuba2k2/libretiny?logo=github)
[![Code style: clang-format](https://img.shields.io/badge/code%20style-clang--format-purple.svg)](.clang-format)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Discord](https://img.shields.io/discord/967863521511608370?color=%235865F2&label=Discord&logo=discord&logoColor=white)](https://discord.gg/SyGCB9Xwtf)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/kuba2k2/platform/libretuya.svg)](https://registry.platformio.org/platforms/kuba2k2/libretuya)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/kuba2k2/platform/libretiny.svg)](https://registry.platformio.org/platforms/kuba2k2/libretiny)
![RTL8710BN](https://img.shields.io/badge/-rtl8710bn-blue)
![BK7231](https://img.shields.io/badge/-bk7231-blue)
@@ -20,70 +22,17 @@ PlatformIO development platform for IoT modules manufactured by Tuya Inc.
The main goal of this project is to provide a usable build environment for IoT developers. While also providing vendor SDKs as PlatformIO cores,
the project focuses on developing working Arduino-compatible cores for supported families. The cores are inspired by Espressif's official core for ESP32,
which should make it easier to port/run existing ESP apps on Tuya IoT (and 3-rd party) modules.
which should make it easier to port/run existing ESP apps on less-common, unsupported IoT modules.
LibreTuya also provides a common interface for all family implementations. The interface is based on ESP32 official libraries.
**There's an [ESPHome port](https://docs.libretiny.eu/docs/projects/esphome/) based on LibreTiny, which supports BK7231 and RTL8710B chips.**
**Note:** this project is work-in-progress.
## Usage
<div align="center" markdown>
1. [Install PlatformIO](https://platformio.org/platformio-ide)
2. `platformio platform install https://github.com/kuba2k2/libretuya`
3. Create a project, build it and upload!
4. See the [docs](https://kuba2k2.github.io/libretuya/) for any questions/problems.
## [⭐ Getting started ⭐](https://docs.libretiny.eu/docs/getting-started/)
## Board List
See [Boards & CPU list](https://kuba2k2.github.io/libretuya/docs/status/supported/).
## Arduino Core support status
Note: this list will probably change with each functionality update.
&nbsp; | `realtek-ambz` | `beken-72xx`
--------------------|----------------|-------------
Core functions | ✔️ | ✔️
GPIO/PWM/IRQ | ✔️/✔️/✔️ | ✔️/✔️/✔️
Analog input (ADC) | ✔️ | ✔️
Serial | ✔️ | ✔️
Serial (extra) | 0, 1, 2 | 1, 2
Flash I/O | ✔️ | ✔️
**CORE LIBRARIES** | |
SoftwareSerial | ✔️ | ❌
SPI | ❌ | ❌
Wire | ❗ | ❌
**OTHER LIBRARIES** | |
Wi-Fi STA/AP/Mixed | ✔️ | ✔️
Wi-Fi Events | ✔️ | ✔️
TCP Client (SSL) | ✔️ (✔️) | ✔️ (❗)
TCP Server | ✔️ | ✔️
IPv6 | ❌ | ❌
HTTP Client (SSL) | ✔️ (✔️) | ❓
HTTP Server | ✔️ | ✔️
NVS / Preferences | ❌ | ❌
SPIFFS | ❌ | ❌
BLE | - | ❌
NTP | ❌ | ❌
OTA | ✔️ | ✔️
MDNS | ✔️ | ✔️
MQTT | ✅ | ❌
SD | ❌ | ❌
Symbols:
- ✔️ working
- ✅ tested, external library
- ❓ untested
- ❗ broken
- ❌ not implemented (yet?)
- \- not applicable
Names:
- Core functions - stuff like delay(), millis(), yield(), etc.
- **CORE LIBRARIES** - included normally in all Arduino cores
- **OTHER LIBRARIES** - included in ESP32 core or downloadable
</div>
## License

View File

@@ -1,69 +1,63 @@
* [Home](README.md)
* 😊 Getting started
* [Start here](docs/getting-started/README.md)
* [Uploading](docs/getting-started/uploading.md)
* [Options & config](docs/reference/config.md)
* Examples
* [PinScan](examples/PinScan/README.md)
* [ESPHome port](docs/projects/esphome.md)
* [Using tuya-cloudcutter](docs/getting-started/cloudcutter.md)
* [Auto-download-reboot](docs/getting-started/adr.md)
* [💻 Boards & CPU list](docs/status/supported.md)
* [✔️ Implementation status](docs/status/arduino.md)
* Supported chip families
* Beken BK72xx
* [General info](docs/platform/beken-72xx/README.md)
* [Flashing](docs/platform/beken-72xx/flashing.md)
* [Dumping](docs/platform/beken-72xx/dumping.md)
* Realtek AmebaZ Series
* [General info](docs/platform/realtek/README.md)
* [Flashing (AmebaZ)](docs/platform/realtek-ambz/flashing.md)
* [Dumping (AmebaZ)](docs/platform/realtek-ambz/dumping.md)
* [Debugging](docs/platform/realtek/debugging.md)
* [Exception decoder](docs/platform/realtek/exception-decoder.md)
* C library
* [Built-in functions](docs/platform/realtek-ambz/stdlib.md)
* [Memory management](docs/platform/realtek-ambz/memory-management.md)
* [All supported boards](boards/)
* API & libraries
* [Options & config](docs/reference/config.md)
* [LibreTuya API](docs/reference/lt-api.md)
* [LT class reference](ltapi/class_libre_tuya.md)
* [Common methods](ltapi/_libre_tuya_a_p_i_8h.md)
* [Wiring custom methods](ltapi/_libre_tuya_custom_8h.md)
* [Logger](ltapi/lt__logger_8h.md)
* [Chip & family IDs](ltapi/_chip_type_8h_source.md)
* [POSIX utilities](ltapi/lt__posix__api_8h.md)
* Common API
* [FS](ltapi/classfs_1_1_f_s.md)
* [Preferences](ltapi/class_i_preferences.md)
* [😊 Getting started](docs/getting-started/README.md)
* [➡️ Info on accessing GPIOs](docs/getting-started/gpio.md)
* [](SUMMARY.md)
* [📺 Cloudcutter & ESPHome video guide](https://www.youtube.com/watch?v=sSj8f-HCHQ0)
* [💡 ESPHome setup guide](docs/projects/esphome.md)
* [🛖 ESPHome Hassio Add-On](https://github.com/libretiny-eu/esphome-hass-addon/pkgs/container/libretiny-esphome-hassio)
* [](SUMMARY.md)
* [📲 Flashing/dumping guide](docs/flashing/)
* [🔌 How to flash/enter download mode?](docs/platform/)
* [](SUMMARY.md)
* [💻 Chips, boards, features](docs/status/supported.md)
* [All boards](boards/)
* [](SUMMARY.md)
* 🍪 Chip family docs & info
* [Beken BK72xx](docs/platform/beken-72xx/README.md)
* [Realtek Ameba - info](docs/platform/realtek-amb/README.md)
* [Realtek AmebaZ](docs/platform/realtek-ambz/README.md)
* [Debugging](docs/platform/realtek-ambz/debugging.md)
* [Exception decoder](docs/platform/realtek-ambz/exception-decoder.md)
* [🔧 LT Configuration](docs/dev/config.md)
* 🧑 Programmer's manual
* [⚠️ Migration guide](docs/dev/migration_v1.0.0.md)
* [🔋 PlatformIO Examples](examples/)
* [📖 LibreTiny API](docs/dev/lt-api.md)
* [C API](ltapi/dir_c7e317b16142bccc961a83c0babf0065.md)
* [C++ API](ltapi/dir_930634efd5dc4a957bbb6e685a3ccda1.md)
* 📚 Arduino Libraries
* [SoftwareSerial](ltapi/class_software_serial.md)
* [WiFi API](ltapi/class_wi_fi_class.md)
* [TCP Client](ltapi/class_i_wi_fi_client.md)
* [SSL Client](ltapi/class_i_wi_fi_client_secure.md)
* [TCP Server](ltapi/class_i_wi_fi_server.md)
* [LibreTuya libraries](docs/libs-built-in.md)
* [base64](ltapi/classbase64.md)
* [WiFi](ltapi/class_wi_fi_class.md)
* [](SUMMARY.md)
* [Flash](ltapi/class_flash_class.md)
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
* [IPv6Address](ltapi/classarduino_1_1_i_pv6_address.md)
* [MD5](ltapi/libraries_2common_2_m_d5_2_m_d5_8h.md)
* [mDNS](ltapi/classm_d_n_s.md)
* NetUtils
* [ssl/MbedTLSClient](ltapi/class_mbed_t_l_s_client.md)
* [IPv6Address](ltapi/classarduino_1_1_i_pv6_address.md)
* [LwIPRxBuffer](ltapi/class_lw_i_p_rx_buffer.md)
* [Update](ltapi/class_update_class.md)
* [WiFiClient](ltapi/class_i_wi_fi_client.md)
* [WiFiClientSecure](ltapi/class_i_wi_fi_client_secure.md)
* [WiFiServer](ltapi/class_i_wi_fi_server.md)
* [WiFiUDP](ltapi/class_i_wi_fi_u_d_p.md)
* [](SUMMARY.md)
* [HTTPClient](ltapi/class_h_t_t_p_client.md)
* [StreamString](ltapi/class_stream_string.md)
* [WebServer](ltapi/class_web_server.md)
* [WiFiMulti](ltapi/class_wi_fi_multi.md)
* [Third party libraries](docs/libs-3rd-party.md)
* [](SUMMARY.md)
* [External compatible libraries](docs/dev/libs-3rd-party.md)
* Full documentation
* [Classes](ltapi/classes.md)
* [Functions](ltapi/functions.md)
* [Macros](ltapi/macros.md)
* [File list](ltapi/files.md)
* [📁 Project structure](docs/reference/project-structure.md)
* [✈️ OTA format](docs/ota/README.md)
* [uf2ota.py tool](docs/ota/uf2ota.md)
* [uf2ota.h library](docs/ota/library.md)
* [uf2ota.h reference](ltapi/uf2ota_8h.md)
* [📓 TODO](TODO.md)
* [🔗 Resources](docs/resources.md)
* 👷 Contributor's manual (WIP)
* [Porting new families](docs/contrib/porting.md)
* [API functions guide](docs/contrib/lt-api.md)
* [C standard library](docs/contrib/stdlib.md)
* [📁 Project structure](docs/contrib/project-structure.md)
* [✈️ OTA format](docs/contrib/ota/README.md)
* [uf2ota.py tool](docs/contrib/ota/uf2ota.md)
* [uf2ota.h library](docs/contrib/ota/library.md)
* [📓 TODO](docs/TODO.md)
* [](SUMMARY.md)
* [🔗 Resources](docs/resources/)

View File

@@ -1,32 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-14. */
#pragma once
#ifdef __cplusplus
#include "WCharacterFixup.h"
#endif
#define delay delayMilliseconds // change delay()'s signature - it's defined as static inline in WVariant.h
#include <api/ArduinoAPI.h>
#include <core/LibreTuyaAPI.h>
#undef delay
// Include family-specific code
#include "WVariant.h"
// Include board variant
#include "variant.h"
// Choose the main UART output port
#ifndef LT_UART_DEFAULT_PORT
#if defined(PIN_SERIAL2_TX)
#define LT_UART_DEFAULT_PORT 2
#else
#define LT_UART_DEFAULT_PORT 1
#endif
#endif
// Define available serial ports
#ifdef __cplusplus
#include "SerialClass.h"
#include <core/SerialExtern.h>
#endif

View File

@@ -1,208 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
#include <LibreTuyaAPI.h>
#include <libraries/Flash/Flash.h>
// can't include <flash.h> as it collides with <Flash.h> on Windows -_-
#define REG_FLASH_BASE 0x00803000
#define REG_FLASH_OPERATE_SW (REG_FLASH_BASE + 0 * 4)
#define REG_FLASH_RDID (REG_FLASH_BASE + 4 * 4)
#define FLASH_BUSY_SW (0x01UL << 31)
#define FLASH_WP_VALUE (0x01UL << 30)
#define FLASH_OP_SW (0x01UL << 29)
#define FLASH_OP_TYPE_POS 24
#define FLASH_OP_RDID 20
extern "C" {
#include <flash_pub.h>
#include <param_config.h>
#include <start_type_pub.h>
#include <sys_ctrl.h>
#include <sys_rtos.h>
#include <wdt_pub.h>
#include <wlan_ui_pub.h>
extern uint8_t system_mac[];
extern uint32_t wdt_ctrl(uint32_t cmd, void *param);
} // extern "C"
void LibreTuya::restart() {
bk_reboot();
}
void LibreTuya::restartDownloadMode() {
bk_reboot();
}
ResetReason LibreTuya::getResetReason() {
switch (bk_misc_get_start_type()) {
case RESET_SOURCE_POWERON:
return RESET_REASON_POWER;
case RESET_SOURCE_REBOOT:
return RESET_REASON_SOFTWARE;
case RESET_SOURCE_WATCHDOG:
return RESET_REASON_WATCHDOG;
case RESET_SOURCE_CRASH_XAT0:
case RESET_SOURCE_CRASH_UNDEFINED:
case RESET_SOURCE_CRASH_PREFETCH_ABORT:
case RESET_SOURCE_CRASH_DATA_ABORT:
case RESET_SOURCE_CRASH_UNUSED:
case RESET_SOURCE_CRASH_PER_XAT0:
return RESET_REASON_CRASH;
case RESET_SOURCE_DEEPPS_GPIO:
case RESET_SOURCE_DEEPPS_RTC:
return RESET_REASON_SLEEP;
}
return RESET_REASON_UNKNOWN;
}
/* CPU-related */
ChipType LibreTuya::getChipType() {
uint8_t chipId = *(uint8_t *)(SCTRL_CHIP_ID);
return CHIP_TYPE_ENUM(FAMILY, chipId);
}
const char *LibreTuya::getChipModel() {
return STRINGIFY_MACRO(MCU);
}
uint32_t LibreTuya::getChipId() {
uint8_t mac[6];
cfg_load_mac(mac); // force loading MAC from TLV (ignore user-set WiFi MAC)
return (mac[3]) | (mac[4] << 8) | (mac[5] << 16);
}
uint8_t LibreTuya::getChipCores() {
return 1;
}
const char *LibreTuya::getChipCoreType() {
return "ARM968E-S";
}
uint32_t LibreTuya::getCpuFreq() {
return configCPU_CLOCK_HZ;
}
uint32_t LibreTuya::getCycleCount() {
// TODO
return 0;
}
/* Flash memory utilities */
FlashId LibreTuya::getFlashChipId() {
uint32_t data = (FLASH_OP_RDID << FLASH_OP_TYPE_POS) | FLASH_OP_SW | FLASH_WP_VALUE;
REG_WRITE(REG_FLASH_OPERATE_SW, data);
while (REG_READ(REG_FLASH_OPERATE_SW) & FLASH_BUSY_SW) {}
FlashId id = {
.manufacturerId = REG_RD8(REG_FLASH_RDID, 2),
.chipId = REG_RD8(REG_FLASH_RDID, 1),
.chipSizeId = REG_RD8(REG_FLASH_RDID, 0),
};
return id;
}
/* Memory management */
uint32_t LibreTuya::getRamSize() {
return 256 * 1024;
}
uint32_t LibreTuya::getHeapSize() {
#if configDYNAMIC_HEAP_SIZE
extern unsigned char _empty_ram;
#if CFG_SOC_NAME == SOC_BK7231N
return (0x00400000 + 192 * 1024) - (uint32_t)(&_empty_ram);
#else
return (0x00400000 + 256 * 1024) - (uint32_t)(&_empty_ram);
#endif
#else
return configTOTAL_HEAP_SIZE;
#endif
}
uint32_t LibreTuya::getFreeHeap() {
return xPortGetFreeHeapSize();
}
uint32_t LibreTuya::getMinFreeHeap() {
return xPortGetMinimumEverFreeHeapSize();
}
uint32_t LibreTuya::getMaxAllocHeap() {
return 0;
}
/* OTA-related */
static int8_t otaImage2Valid = -1;
uint8_t LibreTuya::otaGetRunning() {
// Beken has bootloader-based OTA, running app is always index 1
return 1;
}
uint8_t LibreTuya::otaGetStoredIndex() {
return otaHasImage2() ? 2 : 1;
}
bool LibreTuya::otaSupportsDual() {
return true;
}
bool LibreTuya::otaHasImage1() {
return true;
}
bool LibreTuya::otaHasImage2() {
if (otaImage2Valid != -1)
return otaImage2Valid;
// check download RBL
// TODO: maybe check header CRC or even binary hashes
uint32_t magic;
Flash.readBlock(FLASH_DOWNLOAD_OFFSET, (uint8_t *)&magic, 4);
otaImage2Valid = magic == 0x004C4252; // "RBL\0", little-endian
return otaImage2Valid;
}
bool LibreTuya::otaSwitch(bool force) {
// no need to check otaGetStoredIndex() as it does the same as otaHasImage2()
// force checking validity again
otaImage2Valid = -1;
if (otaHasImage2() && force) {
// "rollback" - abort bootloader upgrade operation by wiping first sector
return Flash.eraseSector(FLASH_DOWNLOAD_OFFSET);
}
return otaHasImage2(); // false if second image is not valid
}
/* Watchdog */
bool LibreTuya::wdtEnable(uint32_t timeout) {
wdt_ctrl(WCMD_SET_PERIOD, &timeout);
wdt_ctrl(WCMD_POWER_UP, NULL);
}
void LibreTuya::wdtDisable() {
wdt_ctrl(WCMD_POWER_DOWN, NULL);
}
void LibreTuya::wdtFeed() {
wdt_ctrl(WCMD_RELOAD_PERIOD, NULL);
}
/* Global instance */
LibreTuya LT;
LibreTuya ESP = LT;

View File

@@ -1,109 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-23. */
#include "SerialClass.h"
extern "C" {
#include <uart_pub.h>
extern void bk_send_byte(uint8_t uport, uint8_t data);
extern void uart_hw_set_change(uint8_t uport, bk_uart_config_t *uart_config);
extern int uart_rx_callback_set(int uport, uart_callback callback, void *param);
} // extern "C"
#ifdef PIN_SERIAL1_TX
SerialClass Serial1(UART1_PORT);
#endif
#ifdef PIN_SERIAL2_TX
SerialClass Serial2(UART2_PORT);
#endif
SerialClass::SerialClass(uint8_t port) {
this->port = port;
this->buf = NULL;
}
#if LT_AUTO_DOWNLOAD_REBOOT
static uint8_t adrState = 0;
static const uint8_t adrCmd[] = {0x01, 0xE0, 0xFC, 0x01, 0x00};
static void adrParse(uint8_t c) {
// parse and respond to link check command (CMD_LinkCheck=0)
adrState = (adrState + 1) * (c == adrCmd[adrState]);
if (adrState == 5) {
LT_I("Auto download mode: rebooting");
LT.restart();
}
}
#endif
static void callback(int port, void *param) {
RingBuffer *buf = (RingBuffer *)param;
int ch;
while ((ch = uart_read_byte(port)) != -1) {
#if LT_AUTO_DOWNLOAD_REBOOT && defined(PIN_SERIAL1_RX)
// parse UART protocol commands on UART1
if (port == UART1_PORT)
adrParse(ch);
#endif
buf->store_char(ch);
}
}
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
uint8_t dataWidth = ((config & SERIAL_DATA_MASK) >> 8) - 1; // 0x100..0x400 -> 0..3
uint8_t parity = 3 - (config & SERIAL_PARITY_MASK); // 0x3..0x1 -> 0..2
uint8_t stopBits = (config & SERIAL_STOP_BIT_MASK) == SERIAL_STOP_BIT_2; // 0x10..0x30 -> 0..1
bk_uart_config_t cfg = {
.baud_rate = baudrate,
.data_width = (uart_data_width_t)dataWidth,
.parity = (uart_parity_t)parity,
.stop_bits = (uart_stop_bits_t)stopBits,
.flow_control = FLOW_CTRL_DISABLED,
};
if (this->buf) {
this->buf->clear();
} else {
this->buf = new RingBuffer();
}
uart_hw_set_change(port, &cfg);
uart_rx_callback_set(port, callback, this->buf);
}
void SerialClass::end() {
uart_rx_callback_set(port, NULL, NULL);
switch (port) {
case 1:
uart1_exit();
break;
case 2:
uart2_exit();
break;
}
delete this->buf;
}
int SerialClass::available() {
return buf->available();
}
int SerialClass::peek() {
return buf->peek();
}
int SerialClass::read() {
return buf->read_char();
}
void SerialClass::flush() {
uart_wait_tx_over();
}
size_t SerialClass::write(uint8_t c) {
bk_send_byte(port, c);
return 1;
}

View File

@@ -1,22 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "sdk_extern.h"
#include "sdk_mem.h"
// define an inline delay() which overrides BDK's delay()
static inline __attribute__((always_inline)) void delay(unsigned long ms) {
delayMilliseconds(ms);
}
// from fixups/arch_main.c
extern unsigned char __bk_rf_is_init;
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,30 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
#pragma once
// for printf() etc (they are wrapped anyway)
#include <stdio.h>
// most stuff is here
#include <include.h>
// for os_printf
#include <uart_pub.h>
// for GPIO names
#include <gpio_pub.h>
// conflict with stl_algobase.h
#undef min
#undef max
// include printf() wrapper disable methods
#include <printf_port.h>
// make non-SDK code call the proper printf()
#undef bk_printf
#undef os_printf
#undef warning_prf
#undef fatal_prf
#define bk_printf printf
#define os_printf printf
#define warning_prf printf
#define fatal_prf printf

View File

@@ -1,20 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-18. */
#pragma once
#include <stddef.h>
// Beken SDK is actually pretty good, in terms of declaring
// stdlib functions properly! So no need for any #define hell.
#include <mem_pub.h>
// All the MemMang functions are in stdlib, just wrapped
// during linking.
#include <stdlib.h>
// for memcpy etc.
#include <string.h>
// ...except zalloc, which is apparently not in the stdlib
#define zalloc os_zalloc
#define LT_HEAP_FUNC xPortGetFreeHeapSize

View File

@@ -1,62 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-20. */
#include <Arduino.h>
void pinMode(pin_size_t pinNumber, PinMode pinMode) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_GPIO))
return;
if (pinEnabled(pin, PIN_PWM))
// disable PWM before using the pin
analogWrite(pinNumber, 0);
if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode)
return;
switch (pinMode) {
case INPUT:
gpio_config(pin->gpio, GMODE_INPUT);
break;
case OUTPUT:
gpio_config(pin->gpio, GMODE_OUTPUT);
break;
case INPUT_PULLUP:
gpio_config(pin->gpio, GMODE_INPUT_PULLUP);
break;
case INPUT_PULLDOWN:
gpio_config(pin->gpio, GMODE_INPUT_PULLDOWN);
break;
case OUTPUT_OPENDRAIN:
gpio_config(pin->gpio, GMODE_SET_HIGH_IMPENDANCE);
break;
}
pin->enabled |= PIN_GPIO;
pin->mode = pinMode;
}
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
// verify level is 0 or 1
if (status > HIGH)
return;
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
// pin is not GPIO yet or not OUTPUT; enable or disable input pullup
if (!pinEnabled(pin, PIN_GPIO) || !pinIsOutput(pin)) {
pinMode(pinNumber, status * INPUT_PULLUP);
return;
}
// write the new state
gpio_output(pin->gpio, status);
}
PinStatus digitalRead(pin_size_t pinNumber) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return 0;
// pin is not GPIO yet or not INPUT; change the mode
if (!pinEnabled(pin, PIN_GPIO) || !pinIsInput(pin))
pinMode(pinNumber, INPUT);
// read the value
return gpio_input(pin->gpio);
}

View File

@@ -1,99 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-31. */
#include <Arduino.h>
static void *irqHandlerList[PINS_COUNT] = {NULL};
static void *irqHandlerArgs[PINS_COUNT] = {NULL};
static bool irqChangeList[PINS_COUNT];
static void irqHandler(unsigned char gpio) {
int pin = -1;
for (pin_size_t i = 0; i < PINS_COUNT; i++) {
if (pinTable[i].gpio == gpio) {
pin = i;
break;
}
}
if (pin == -1)
return;
if (!irqHandlerList[pin])
return;
if (irqChangeList[pin]) {
if (pinTable[pin].mode == INPUT_PULLDOWN) {
pinTable[pin].mode = INPUT_PULLUP;
gpio_int_enable(pinTable[pin].gpio, GPIO_INT_LEVEL_FALLING, irqHandler);
} else if (pinTable[pin].mode == INPUT_PULLUP) {
pinTable[pin].mode = INPUT_PULLDOWN;
gpio_int_enable(pinTable[pin].gpio, GPIO_INT_LEVEL_RISING, irqHandler);
}
}
if (irqHandlerArgs[pin] == NULL) {
((voidFuncPtr)irqHandlerList[pin])();
} else {
((voidFuncPtrParam)irqHandlerList[pin])(irqHandlerArgs[pin]);
}
}
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
attachInterruptParam(interruptNumber, (voidFuncPtrParam)callback, mode, NULL);
}
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) {
PinInfo *pin = pinInfo(interruptNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_IRQ))
return;
uint32_t event = 0;
PinMode modeNew = 0;
bool change = 0;
switch (mode) {
case LOW:
event = GPIO_INT_LEVEL_LOW;
modeNew = INPUT_PULLUP;
change = false;
break;
case HIGH:
event = GPIO_INT_LEVEL_HIGH;
modeNew = INPUT_PULLDOWN;
change = false;
break;
case FALLING:
event = GPIO_INT_LEVEL_FALLING;
modeNew = INPUT_PULLUP;
change = false;
break;
case RISING:
event = GPIO_INT_LEVEL_RISING;
modeNew = INPUT_PULLDOWN;
change = false;
break;
case CHANGE:
event = GPIO_INT_LEVEL_FALLING;
modeNew = INPUT_PULLUP;
change = true;
break;
default:
return;
}
irqHandlerList[interruptNumber] = callback;
irqHandlerArgs[interruptNumber] = param;
irqChangeList[interruptNumber] = change;
gpio_int_enable(pin->gpio, event, irqHandler);
pin->enabled |= PIN_IRQ | PIN_GPIO;
pin->mode = modeNew;
}
void detachInterrupt(pin_size_t interruptNumber) {
PinInfo *pin = pinInfo(interruptNumber);
if (!pin)
return;
if (!pinSupported(pin, PIN_IRQ))
return;
irqHandlerList[interruptNumber] = NULL;
irqHandlerArgs[interruptNumber] = NULL;
irqChangeList[interruptNumber] = false;
gpio_int_disable(pin->gpio);
pin->enabled &= ~PIN_IRQ;
}

View File

@@ -1,5 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-11. */
#pragma once
#define LT_MD5_USE_HOSTAPD 1

View File

@@ -1,10 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
#pragma once
#include <Arduino.h>
#include <api/WiFi/WiFi.h>
#include "WiFiClient.h"
#include "WiFiClientSecure.h"
#include "WiFiServer.h"

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPClient.h>
typedef LwIPClient WiFiClient;

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-04. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <ssl/MbedTLSClient.h>
typedef MbedTLSClient WiFiClientSecure;

View File

@@ -1,25 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-26. */
#pragma once
#include <Arduino.h>
extern "C" {
#include <FreeRTOS.h>
#include <rw_msg_pub.h>
#include <semphr.h>
} // extern "C"
typedef struct {
void *configSta;
void *configAp;
unsigned long scannedAt;
SemaphoreHandle_t scanSem;
void *statusIp;
void *statusLink;
rw_evt_type lastStaEvent;
rw_evt_type lastApEvent;
bool apEnabled;
} WiFiData;

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPServer.h>
typedef LwIPServer WiFiServer;

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-09-10. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPUdp.h>
typedef LwIPUDP WiFiUDP;

View File

@@ -1,61 +0,0 @@
/*
Copyright (c) 2015 Arduino LLC. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
static void __empty() {
// Empty
}
void yield(void) __attribute__((weak, alias("__empty")));
/**
* SysTick hook
*
* This function is called from SysTick handler, before the default
* handler provided by Arduino.
*/
static int __false() {
// Return false
return 0;
}
int sysTickHook(void) __attribute__((weak, alias("__false")));
/**
* SVC hook
* PendSV hook
*
* These functions are called from SVC handler, and PensSV handler.
* Default action is halting.
*/
static void __halt() {
// Halts
while (1)
;
}
void svcHook(void) __attribute__((weak, alias("__halt")));
void pendSVHook(void) __attribute__((weak, alias("__halt")));

View File

@@ -1,37 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
#pragma once
#define CHIP_TYPE(family, chip_id) (((family >> 24) << 8) | chip_id)
#define CHIP_TYPE_ENUM(family, chip_id) (ChipType) CHIP_TYPE(family, chip_id)
enum ChipFamily {
// used in UF2 Family ID
F_RTL8710A = 0x9FFFD543, // Realtek Ameba1
F_RTL8710B = 0x22E0D6FC, // Realtek AmebaZ (realtek-ambz)
F_RTL8720C = 0xE08F7564, // Realtek AmebaZ2
F_RTL8720D = 0x3379CFE2, // Realtek AmebaD
F_BK7231U = 0x675A40B0, // Beken 7231U/7231T
F_BK7231N = 0x7B3EF230, // Beken 7231N
F_BK7251 = 0x6A82CC42, // Beken 7251/7252
F_BL602 = 0xDE1270B7, // Boufallo 602
F_XR809 = 0x51E903A8, // Xradiotech 809
F_NATIVE = 0xDEADBEEF, // Host-native
};
enum ChipType {
// Realtek AmebaZ
// IDs copied from rtl8710b_efuse.h
RTL8710BL = CHIP_TYPE(F_RTL8710B, 0xE0), // ???
RTL8710BN = CHIP_TYPE(F_RTL8710B, 0xFF), // CHIPID_8710BN / QFN32
RTL8710BU = CHIP_TYPE(F_RTL8710B, 0xFE), // CHIPID_8710BU / QFN48
RTL8710BX = CHIP_TYPE(F_RTL8710B, 0xF6), // found on an actual RTL8710BX
RTL8710L0 = CHIP_TYPE(F_RTL8710B, 0xFB), // CHIPID_8710BN_L0 / QFN32
RTL8711BN = CHIP_TYPE(F_RTL8710B, 0xFD), // CHIPID_8711BN / QFN48
RTL8711BU = CHIP_TYPE(F_RTL8710B, 0xFC), // CHIPID_8711BG / QFN68
// Beken 72XX
BK7231T = CHIP_TYPE(F_BK7231U, 0x1A), // *SCTRL_CHIP_ID = 0x7231a
BK7231N = CHIP_TYPE(F_BK7231N, 0x1C), // *SCTRL_CHIP_ID = 0x7231c
BL2028N = CHIP_TYPE(F_BK7231N, 0x1C), // *SCTRL_CHIP_ID = 0x7231c
BK7252 = CHIP_TYPE(F_BK7251, 0x00), // TODO
};

View File

@@ -1,65 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
#include "LibreTuyaAPI.h"
String ipToString(const IPAddress &ip) {
char szRet[16];
sprintf(szRet, "%hhu.%hhu.%hhu.%hhu", ip[0], ip[1], ip[2], ip[3]);
return String(szRet);
}
/**
* @brief Generate random bytes using rand().
*
* @param buf destination pointer
* @param len how many bytes to generate
*/
extern "C" {
void lt_rand_bytes(uint8_t *buf, size_t len) {
int *data = (int *)buf;
size_t i;
for (i = 0; len >= sizeof(int); len -= sizeof(int)) {
data[i++] = rand();
}
if (len) {
int rem = rand();
unsigned char *pRem = (unsigned char *)&rem;
memcpy(buf + i * sizeof(int), pRem, len);
}
}
#undef putchar
/**
* @brief Print data pointed to by buf in hexdump-like format (hex+ASCII).
*
* @param buf source pointer
* @param len how many bytes to print
* @param offset increment printed offset by this value
* @param width how many bytes on a line
*/
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width) {
uint16_t pos = 0;
while (pos < len) {
// print hex offset
printf("%06x ", offset + pos);
// calculate current line width
uint8_t lineWidth = min(width, len - pos);
// print hexadecimal representation
for (uint8_t i = 0; i < lineWidth; i++) {
if (i % 8 == 0) {
printf(" ");
}
printf("%02x ", buf[pos + i]);
}
// print ascii representation
printf(" |");
for (uint8_t i = 0; i < lineWidth; i++) {
char c = buf[pos + i];
putchar((c >= 0x20 && c <= 0x7f) ? c : '.');
}
puts("|\r");
pos += lineWidth;
}
}
}

View File

@@ -1,80 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-28. */
#pragma once
// C standard libraries
#include <inttypes.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// C++ standard libraries
#ifdef __cplusplus
#include <algorithm>
#include <cmath>
using ::round;
using std::abs;
using std::isinf;
using std::isnan;
using std::max;
using std::min;
#endif
// LibreTuya version macros
#ifndef LT_VERSION
#define LT_VERSION 1.0.0
#endif
#ifndef LT_BOARD
#define LT_BOARD unknown
#endif
#define STRINGIFY(x) #x
#define STRINGIFY_MACRO(x) STRINGIFY(x)
#define LT_VERSION_STR STRINGIFY_MACRO(LT_VERSION)
#define LT_BOARD_STR STRINGIFY_MACRO(LT_BOARD)
// Includes
#include "LibreTuyaClass.h" // global LT class
#include "LibreTuyaCompat.h" // compatibility methods
#include "LibreTuyaConfig.h" // configuration macros
#include "LibreTuyaCustom.h" // family-defined methods (Wiring custom)
#include <Arduino.h>
// C includes
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include "lt_logger.h"
#include "lt_posix_api.h"
#ifdef __cplusplus
} // extern "C"
#endif
// Functional macros
#define LT_BANNER() \
LT_LOG( \
LT_LEVEL_INFO, \
__FUNCTION__, \
__LINE__, \
"LibreTuya v" LT_VERSION_STR " on " LT_BOARD_STR ", compiled at " __DATE__ " " __TIME__ \
)
#ifdef __cplusplus
String ipToString(const IPAddress &ip);
extern "C" {
void lt_rand_bytes(uint8_t *buf, size_t len);
void hexdump(const uint8_t *buf, size_t len, uint32_t offset = 0, uint8_t width = 16);
}
#else
void lt_rand_bytes(uint8_t *buf, size_t len);
void hexdump(const uint8_t *buf, size_t len, uint32_t offset, uint8_t width);
#endif

View File

@@ -1,148 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-06. */
#include "LibreTuyaClass.h"
/**
* @brief Get LibreTuya version string.
*/
const char *LibreTuya::getVersion() {
return LT_VERSION_STR;
}
/**
* @brief Get board name.
*/
const char *LibreTuya::getBoard() {
return LT_BOARD_STR;
}
/**
* @brief Get CPU family ID.
*/
ChipFamily LibreTuya::getChipFamily() {
return FAMILY;
}
/**
* @brief Get CPU family name as string.
*/
const char *LibreTuya::getChipFamilyName() {
return STRINGIFY_MACRO(FAMILY) + 2;
}
static char *deviceName = NULL;
/**
* @brief Get device friendly name in format "LT-<board>-<chip id>".
* Can be used as hostname.
*/
const char *LibreTuya::getDeviceName() {
if (deviceName)
return deviceName;
uint32_t chipId = getChipId();
uint8_t *id = (uint8_t *)&chipId;
const char *board = getBoard();
uint8_t boardLen = strlen(board);
deviceName = (char *)malloc(3 + boardLen + 1 + 6 + 1);
sprintf(deviceName, "LT-%s-%02x%02x%02x", board, id[0], id[1], id[2]);
return deviceName;
}
/**
* @brief Get a textual representation of a reset reason.
*
* @param reason value to convert to text, uses getResetReason() by default
*/
const char *LibreTuya::getResetReasonName(ResetReason reason) {
if (reason >= RESET_REASON_MAX)
reason = getResetReason();
switch (reason) {
case RESET_REASON_POWER:
return "Power-On";
case RESET_REASON_BROWNOUT:
return "Brownout";
case RESET_REASON_HARDWARE:
return "HW Reboot";
case RESET_REASON_SOFTWARE:
return "SW Reboot";
case RESET_REASON_WATCHDOG:
return "WDT Reset";
case RESET_REASON_CRASH:
return "Crash";
case RESET_REASON_SLEEP:
return "Sleep Wakeup";
}
return "Unknown";
}
/**
* @brief Get CPU frequency in MHz.
*/
uint32_t LibreTuya::getCpuFreqMHz() {
return getCpuFreq() / 1000000;
}
/**
* @brief Get flash chip total size.
* The default implementation uses the least significant
* byte of the chip ID to determine the size.
*/
__attribute__((weak)) uint32_t LibreTuya::getFlashChipSize() {
FlashId id = getFlashChipId();
if (id.chipSizeId >= 0x14 && id.chipSizeId <= 0x19) {
return (1 << id.chipSizeId);
}
#ifdef FLASH_LENGTH
return FLASH_LENGTH;
#else
return 0;
#endif
}
/**
* @brief Get the OTA index for updated firmware.
*
* Note: returns 1 for chips without dual-OTA.
*/
uint8_t LibreTuya::otaGetTarget() {
if (!otaSupportsDual())
return 1;
return otaGetRunning() ^ 0b11;
}
/**
* @brief Perform OTA rollback: switch to the previous image, or abort current
* switched OTA update, if not rebooted yet.
*
* @return false if no second image to run, writing failed or dual-OTA not supported
*/
bool LibreTuya::otaRollback() {
if (!otaCanRollback())
return false;
if (otaGetRunning() != otaGetStoredIndex())
// force switching back to current image
return otaSwitch(true);
return true;
}
/**
* @brief Check if OTA rollback is supported and available (there is another image to run).
* @return false if no second image to run or dual-OTA not supported
*/
bool LibreTuya::otaCanRollback() {
if (!otaSupportsDual())
return false;
if (otaGetRunning() == otaGetStoredIndex())
return true;
if (otaGetRunning() == 1 && otaHasImage1())
return true;
if (otaGetRunning() == 2 && otaHasImage2())
return true;
return false;
}
__attribute__((weak)) void LibreTuya::gpioRecover() {
// nop by default
}

View File

@@ -1,193 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-06. */
#pragma once
#ifdef __cplusplus
#include "LibreTuyaAPI.h"
#include <core/ChipType.h>
typedef enum {
RESET_REASON_UNKNOWN = 0,
RESET_REASON_POWER = 1,
RESET_REASON_BROWNOUT = 2,
RESET_REASON_HARDWARE = 3,
RESET_REASON_SOFTWARE = 4,
RESET_REASON_WATCHDOG = 5,
RESET_REASON_CRASH = 6,
RESET_REASON_SLEEP = 7,
RESET_REASON_MAX = 8,
} ResetReason;
/**
* @brief Flash chip ID structure.
*/
typedef struct {
uint8_t manufacturerId;
uint8_t chipId;
uint8_t chipSizeId;
} FlashId;
/**
* @brief Main LibreTuya API class.
*
* This class contains all functions common amongst all families.
* Implementations of these methods may vary between families.
*
* The class is accessible using the `LT` global object (defined by the family).
*/
class LibreTuya {
public: /* Common methods - note: these are documented in LibreTuyaAPI.cpp */
const char *getVersion();
const char *getBoard();
ChipFamily getChipFamily();
const char *getChipFamilyName();
const char *getDeviceName();
const char *getResetReasonName(ResetReason reason = RESET_REASON_MAX);
uint32_t getCpuFreqMHz();
uint32_t getFlashChipSize();
uint8_t otaGetTarget();
bool otaRollback();
bool otaCanRollback();
public: /* Compatibility methods */
/**
* @brief Alias of getMaxAllocHeap().
*/
inline uint32_t getMaxFreeBlockSize() {
return getMaxAllocHeap();
}
public: /* Family-defined methods */
/**
* @brief Reboot the CPU.
*/
void restart();
/**
* @brief Reboot the CPU and stay in download mode (if possible).
*/
void restartDownloadMode();
/**
* @brief Get the reason of last chip reset.
*/
ResetReason getResetReason();
/**
* @brief Reconfigure GPIO pins used for debugging
* (SWD/JTAG), so that they can be used as normal I/O.
*/
void gpioRecover();
public: /* CPU-related */
/**
* @brief Get CPU model ID.
*/
ChipType getChipType();
/**
* @brief Get CPU model name as string.
*/
const char *getChipModel();
/**
* @brief Get CPU unique ID. This may be based on MAC, eFuse, etc.
* Note: the number should be 24-bit (with most significant byte being zero).
*/
uint32_t getChipId();
/**
* @brief Get CPU core count.
*/
uint8_t getChipCores();
/**
* @brief Get CPU core type name as string.
*/
const char *getChipCoreType();
/**
* @brief Get CPU frequency in Hz.
*/
uint32_t getCpuFreq();
/**
* @brief Get CPU cycle count.
*/
uint32_t getCycleCount();
public: /* Flash memory utilities */
/**
* @brief Read flash chip ID and return a FlashId struct.
*/
FlashId getFlashChipId();
public: /* Memory management */
/**
* @brief Get total RAM size.
*/
uint32_t getRamSize();
/**
* @brief Get total heap size.
*/
uint32_t getHeapSize();
/**
* @brief Get free heap size.
*/
uint32_t getFreeHeap();
/**
* @brief Get lowest level of free heap memory.
*/
uint32_t getMinFreeHeap();
/**
* @brief Get largest block of heap that can be allocated at once.
*/
uint32_t getMaxAllocHeap();
public: /* OTA-related */
/**
* @brief Get the currently running firmware OTA index.
*/
uint8_t otaGetRunning();
/**
* @brief Read the currently active OTA index, i.e. the one that will boot upon restart.
*/
uint8_t otaGetStoredIndex();
/**
* @brief Check if the chip supports dual-OTA (i.e. OTA is flashed to a different partition).
*
* TODO: make this work for actual dual-OTA chips; remove checking this in otaGetTarget() etc.
*/
bool otaSupportsDual();
/**
* @brief Check if OTA1 image is valid.
*/
bool otaHasImage1();
/**
* @brief Check if OTA2 image is valid.
*/
bool otaHasImage2();
/**
* @brief Try to switch OTA index to the other image.
*
* Note: should return true for chips without dual-OTA. Should return false if one of two images is not valid.
*
* @param force switch even if other image already marked as active
* @return false if writing failed; true otherwise
*/
bool otaSwitch(bool force = false);
public: /* Watchdog */
/**
* @brief Enable the hardware watchdog.
*
* @param timeout watchdog timeout, milliseconds (defaults to 10s)
* @return whether the chip has a hardware watchdog
*/
bool wdtEnable(uint32_t timeout = 10000);
/**
* @brief Disable the hardware watchdog.
*/
void wdtDisable();
/**
* @brief Feed/reset the hardware watchdog timer.
*/
void wdtFeed();
};
extern LibreTuya LT;
extern LibreTuya ESP;
#endif

View File

@@ -1,33 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-04. */
#include "LibreTuyaCompat.h"
#if LT_HAS_FREERTOS
BaseType_t xTaskCreateUniversal(
TaskFunction_t pxTaskCode,
const char *const pcName,
const uint32_t usStackDepth,
void *const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *const pxCreatedTask,
const BaseType_t xCoreID
) {
// #ifndef CONFIG_FREERTOS_UNICORE
// if (xCoreID >= 0 && xCoreID < 2) {
// return xTaskCreatePinnedToCore(
// pxTaskCode,
// pcName,
// usStackDepth,
// pvParameters,
// uxPriority,
// pxCreatedTask,
// xCoreID
// );
// } else {
// #endif
return xTaskCreate(pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask);
// #ifndef CONFIG_FREERTOS_UNICORE
// }
// #endif
}
#endif

View File

@@ -1,25 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-04. */
#pragma once
#include <Arduino.h>
#ifdef HAS_SERIAL_CLASS // failsafe for circular inclusion
#ifdef PIN_SERIAL0_TX
extern SerialClass Serial0;
#endif
#ifdef PIN_SERIAL1_TX
extern SerialClass Serial1;
#endif
#ifdef PIN_SERIAL2_TX
extern SerialClass Serial2;
#endif
#define SerialN(x) Serial##x
#define SerialM(x) SerialN(x)
#define Serial SerialM(LT_UART_DEFAULT_SERIAL)
#endif

View File

@@ -1,74 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-19. */
#include <Arduino.h>
#include <api/HardwareSerial.h>
using namespace arduino;
extern "C" {
#include <fal.h>
fal_partition_t fal_root_part = NULL;
}
// Arduino framework initialization.
// May be redefined by family files.
void initArduino() __attribute__((weak));
// Weak empty variant initialization function.
// May be redefined by variant files.
void initVariant() __attribute__((weak));
// Initialize C library
extern "C" void __libc_init_array(void);
void mainTask(const void *arg) {
setup();
for (;;) {
loop();
if (serialEventRun)
serialEventRun();
yield();
}
}
static unsigned long periodicTasks[] = {0, 0};
void runPeriodicTasks() {
#if LT_LOG_HEAP
if (millis() - periodicTasks[0] > 1000) {
LT_HEAP_I();
periodicTasks[0] = millis();
}
#endif
#if LT_USE_TIME
if (millis() - periodicTasks[1] > 10000) {
gettimeofday(NULL, NULL);
periodicTasks[1] = millis();
}
#endif
}
int main(void) {
// print a startup banner
LT_BANNER();
// initialize C library
__libc_init_array();
// inform about the reset reason
LT_I("Reset reason: %u", LT.getResetReason());
// initialize Arduino framework
initArduino();
// optionally initialize per-variant code
initVariant();
// initialize FAL
fal_init();
// provide root partition
fal_root_part = (fal_partition_t)fal_partition_find("root");
// start the main task and OS kernel
if (!startMainTask()) {
LT_F("Couldn't start the main task");
}
while (1) {}
return 0;
}

View File

@@ -1,30 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-24. */
#include "Flash.h"
extern "C" {
#include <fal.h>
}
// Global Flash object.
FlashClass Flash;
FlashId FlashClass::getChipId() {
return LT.getFlashChipId();
}
uint32_t FlashClass::getSize() {
return LT.getFlashChipSize();
}
bool FlashClass::eraseSector(uint32_t offset) {
return fal_partition_erase(fal_root_part, offset, 1) >= 0;
}
bool FlashClass::readBlock(uint32_t offset, uint8_t *data, size_t size) {
return fal_partition_read(fal_root_part, offset, data, size) >= 0;
}
bool FlashClass::writeBlock(uint32_t offset, uint8_t *data, size_t size) {
return fal_partition_write(fal_root_part, offset, data, size) >= 0;
}

View File

@@ -1,17 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-24. */
#pragma once
#include <Arduino.h>
class FlashClass {
public:
FlashId getChipId();
uint32_t getSize();
bool eraseSector(uint32_t offset);
bool readBlock(uint32_t offset, uint8_t *data, size_t size);
bool writeBlock(uint32_t offset, uint8_t *data, size_t size);
};
extern FlashClass Flash;

View File

@@ -1,7 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-29. */
#pragma once
#include <time.h>
extern char *strptime(const char *buf, const char *fmt, struct tm *tm);

View File

@@ -1,28 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-11. */
#if LT_ARD_HAS_MD5
#include "MD5.h"
#if LT_MD5_USE_MBEDTLS
extern "C" {
void MD5Init(LT_MD5_CTX_T *context) {
mbedtls_md5_init(context);
mbedtls_md5_starts(context);
}
void MD5Update(LT_MD5_CTX_T *context, const unsigned char *buf, unsigned len) {
mbedtls_md5_update(context, buf, len);
}
void MD5Final(unsigned char digest[16], LT_MD5_CTX_T *context) {
mbedtls_md5_finish(context, digest);
}
} // extern "C"
#endif // LT_MD5_USE_MBEDTLS
#endif // LT_ARD_HAS_MD5

View File

@@ -1,14 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-11. */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <mbedtls/md5.h>
#define LT_MD5_CTX_T mbedtls_md5_context
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,28 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
#if LT_ARD_HAS_MD5
#include "MD5.h"
#if LT_MD5_USE_POLARSSL
extern "C" {
void MD5Init(LT_MD5_CTX_T *context) {
md5_init(context);
md5_starts(context);
}
void MD5Update(LT_MD5_CTX_T *context, const unsigned char *buf, unsigned len) {
md5_update(context, buf, len);
}
void MD5Final(unsigned char digest[16], LT_MD5_CTX_T *context) {
md5_finish(context, digest);
}
} // extern "C"
#endif // LT_MD5_USE_POLARSSL
#endif // LT_ARD_HAS_MD5

View File

@@ -1,14 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <polarssl/md5.h>
#define LT_MD5_CTX_T md5_context
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,224 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-29. */
#include "Update.h"
UpdateClass::UpdateClass() : ctx(NULL), info(NULL), buf(NULL) {
cleanup();
}
/**
* @brief Initialize the update process.
*
* @param size total UF2 file size
* @param command must be U_FLASH
* @return false if parameters are invalid or update is running, true otherwise
*/
bool UpdateClass::begin(size_t size, int command, int unused2, uint8_t unused3, const char *unused4) {
if (ctx)
return false;
cleanup();
LT_DM(OTA, "begin(%u, ...) / OTA curr: %u, trgt: %u", size, LT.otaGetRunning(), LT.otaGetTarget());
ctx = uf2_ctx_init(LT.otaGetTarget(), FAMILY);
info = uf2_info_init();
if (!size) {
cleanup(UPDATE_ERROR_SIZE);
return false;
}
if (command != U_FLASH) {
cleanup(UPDATE_ERROR_BAD_ARGUMENT);
return false;
}
bytesTotal = size;
return true;
}
/**
* @brief Finalize the update process. Check for errors and update completion, then activate the new firmware image.
*
* @param evenIfRemaining no idea
* @return false in case of errors or no update running, true otherwise
*/
bool UpdateClass::end(bool evenIfRemaining) {
if (hasError() || !ctx)
// false if not running
return false;
if (!isFinished() && !evenIfRemaining) {
// abort if not finished
cleanup(UPDATE_ERROR_ABORT);
return false;
}
// TODO what is evenIfRemaining for?
if (!LT.otaSwitch()) {
// try to activate the second OTA
cleanup(UPDATE_ERROR_ACTIVATE);
return false;
}
cleanup();
return true;
}
/**
* @brief Write a chunk of data to the buffer or flash memory.
*
* It's advised to write in 512-byte chunks (or its multiples).
*
* @param data
* @param len
* @return size_t
*/
size_t UpdateClass::write(uint8_t *data, size_t len) {
size_t written = 0;
if (hasError() || !ctx)
// 0 if not running
return 0;
LT_VM(OTA, "write(%u) / buf %u/512", len, bufSize());
/* while (buf == bufPos && len >= UF2_BLOCK_SIZE) {
// buffer empty and entire block is in data
if (!tryWriteData(data, UF2_BLOCK_SIZE)) {
// returns 0 if data contains an invalid block
return written;
}
data += UF2_BLOCK_SIZE;
len -= UF2_BLOCK_SIZE;
written += UF2_BLOCK_SIZE;
} */
// write until buffer space is available
uint16_t toWrite; // 1..512
while (len && (toWrite = min(len, bufLeft()))) {
tryWriteData(data, toWrite);
if (hasError()) {
// return on errors
printErrorContext2(data, toWrite);
return written;
}
data += toWrite;
len -= toWrite;
written += toWrite;
}
return written;
}
size_t UpdateClass::writeStream(Stream &data) {
size_t written = 0;
if (hasError() || !ctx)
// 0 if not running
return 0;
uint32_t lastData = millis();
// loop until the update is complete
while (remaining()) {
// check stream availability
int available = data.available();
if (available <= 0) {
if (millis() - lastData > UPDATE_TIMEOUT_MS) {
// waited for data too long; abort with error
cleanup(UPDATE_ERROR_STREAM);
return written;
}
continue;
}
// available > 0
lastData = millis();
// read data to fit in the remaining buffer space
bufAlloc();
uint16_t read = data.readBytes(bufPos, bufLeft());
bufPos += read;
written += read;
tryWriteData();
if (hasError()) {
// return on errors
printErrorContext2(NULL, read); // buf is not valid anymore
return written;
}
}
return written;
}
/**
* @brief Try to use the buffer as a block to write. In case of UF2 errors,
* error codes are set, the update is aborted and 0 is returned
*
* @param data received data to copy to buffer or NULL if already in buffer
* @param len received data length - must be at most bufLeft()
* @return size_t "used" data size - 0 or 512
*/
size_t UpdateClass::tryWriteData(uint8_t *data, size_t len) {
uf2_block_t *block = NULL;
LT_VM(OTA, "Writing %u to buffer (%u/512)", len, bufSize());
if (len == UF2_BLOCK_SIZE) {
// data has a complete block
block = (uf2_block_t *)data;
} else if (data && len) {
// data has a part of a block, copy it to buffer
bufAlloc();
memcpy(bufPos, data, len);
bufPos += len;
}
if (!block && bufSize() == UF2_BLOCK_SIZE) {
// use buffer as block (only if not found above)
block = (uf2_block_t *)buf;
}
// a complete block has been found
if (block) {
if (checkUf2Error(uf2_check_block(ctx, block)))
// block is invalid
return 0;
if (errUf2 == UF2_ERR_IGNORE)
// treat ignored blocks as valid
return UF2_BLOCK_SIZE;
if (!bytesWritten) {
// parse header block to allow retrieving firmware info
if (checkUf2Error(uf2_parse_header(ctx, block, info)))
// header is invalid
return 0;
LT_IM(OTA, "%s v%s - LT v%s @ %s", info->fw_name, info->fw_version, info->lt_version, info->board);
if (bytesTotal == UPDATE_SIZE_UNKNOWN) {
// set total update size from block count info
bytesTotal = block->block_count * UF2_BLOCK_SIZE;
} else if (bytesTotal != block->block_count * UF2_BLOCK_SIZE) {
// given update size does not match the block count
LT_EM(OTA, "Image size wrong; got %u, calculated %u", bytesTotal, block->block_count * UF2_BLOCK_SIZE);
cleanup(UPDATE_ERROR_SIZE);
return 0;
}
} else {
// write data blocks normally
if (checkUf2Error(uf2_write(ctx, block)))
// block writing failed
return 0;
}
// increment total writing progress
bytesWritten += UF2_BLOCK_SIZE;
// call progress callback
if (callback)
callback(bytesWritten, bytesTotal);
// reset the buffer as it's used already
if (bufSize() == UF2_BLOCK_SIZE)
bufPos = buf;
return UF2_BLOCK_SIZE;
}
return 0;
}
UpdateClass Update;

View File

@@ -1,154 +0,0 @@
#pragma once
#include <Arduino.h>
#include <functional>
#include <uf2ota/uf2ota.h>
// No Error
#define UPDATE_ERROR_OK (0)
// Flash Write Failed
#define UPDATE_ERROR_WRITE (1)
// Flash Erase Failed
#define UPDATE_ERROR_ERASE (2)
// Flash Read Failed
#define UPDATE_ERROR_READ (3)
// Not Enough Space
#define UPDATE_ERROR_SPACE (4)
// Bad Size Given
#define UPDATE_ERROR_SIZE (5)
// Stream Read Timeout
#define UPDATE_ERROR_STREAM (6)
// MD5 Check Failed
#define UPDATE_ERROR_MD5 (7)
// Wrong Magic Byte
#define UPDATE_ERROR_MAGIC_BYTE (8)
// Could Not Activate The Firmware
#define UPDATE_ERROR_ACTIVATE (9)
// Partition Could Not be Found
#define UPDATE_ERROR_NO_PARTITION (10)
// Bad Argument
#define UPDATE_ERROR_BAD_ARGUMENT (11)
// Aborted
#define UPDATE_ERROR_ABORT (12)
#define UPDATE_SIZE_UNKNOWN 0xFFFFFFFF
#define U_FLASH 0
#define U_SPIFFS 100
#define U_AUTH 200
#define ENCRYPTED_BLOCK_SIZE 16
#define UPDATE_TIMEOUT_MS 30 * 1000
class UpdateClass {
public:
typedef std::function<void(size_t, size_t)> THandlerFunction_Progress;
public: /* Update.cpp */
UpdateClass();
bool begin(
size_t size = UPDATE_SIZE_UNKNOWN,
int command = U_FLASH,
int unused2 = -1,
uint8_t unused3 = LOW,
const char *unused4 = NULL // this is for SPIFFS
);
bool end(bool evenIfRemaining = false);
size_t write(uint8_t *data, size_t len);
size_t writeStream(Stream &data);
bool canRollBack();
bool rollBack();
// bool setMD5(const char *expected_md5);
private: /* Update.cpp */
size_t tryWriteData(uint8_t *data = NULL, size_t len = 0);
public: /* UpdateUtil.cpp */
UpdateClass &onProgress(THandlerFunction_Progress callback);
void abort();
void printError(Print &out);
const char *errorString();
const char *getFirmwareName();
const char *getFirmwareVersion();
const char *getLibreTuyaVersion();
const char *getBoardName();
private: /* UpdateUtil.cpp */
void cleanup(uint8_t ardErr = UPDATE_ERROR_OK, uf2_err_t uf2Err = UF2_ERR_OK);
bool checkUf2Error(uf2_err_t err);
void bufAlloc();
void printErrorContext1();
void printErrorContext2(const uint8_t *data, size_t len);
uint16_t bufLeft();
uint16_t bufSize();
private:
// uf2ota context
uf2_ota_t *ctx;
uf2_info_t *info;
// block buffer
uint8_t *buf;
uint8_t *bufPos;
// update progress - multiplies of 512 bytes
uint32_t bytesWritten;
uint32_t bytesTotal;
// errors
uf2_err_t errUf2;
uint8_t errArd;
// progress callback
THandlerFunction_Progress callback;
// String _target_md5;
// MD5Builder _md5;
public:
String md5String(void) {
// return _md5.toString();
}
void md5(uint8_t *result) {
// return _md5.getBytes(result);
}
uint8_t getError() {
return errArd;
}
uf2_err_t getUF2Error() {
return errUf2;
}
uint16_t getErrorCode() {
return (errArd << 8) | errUf2;
}
void clearError() {
cleanup(UPDATE_ERROR_OK);
}
bool hasError() {
return errArd != UPDATE_ERROR_OK;
}
bool isRunning() {
return ctx != NULL;
}
bool isFinished() {
return bytesWritten == bytesTotal;
}
size_t size() {
return bytesTotal;
}
size_t progress() {
return bytesWritten;
}
size_t remaining() {
return bytesTotal - bytesWritten;
}
};
extern UpdateClass Update;

View File

@@ -1,190 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-30. */
#include "Update.h"
static const uint8_t errorMap[] = {
UPDATE_ERROR_OK, /* UF2_ERR_OK - no error */
UPDATE_ERROR_OK, /* UF2_ERR_IGNORE - block should be ignored */
UPDATE_ERROR_MAGIC_BYTE, /* UF2_ERR_MAGIC - wrong magic numbers */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_FAMILY - family ID mismatched */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_NOT_HEADER - block is not a header */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_OTA_VER - unknown/invalid OTA format version */
UPDATE_ERROR_MAGIC_BYTE, /* UF2_ERR_OTA_WRONG - no data for current OTA index */
UPDATE_ERROR_NO_PARTITION, /* UF2_ERR_PART_404 - no partition with that name */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_PART_ONE - only one partition tag in a block */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_PART_UNSET - attempted to write without target partition */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_DATA_TOO_LONG - data too long - tags won't fit */
UPDATE_ERROR_BAD_ARGUMENT, /* UF2_ERR_SEQ_MISMATCH - sequence number mismatched */
UPDATE_ERROR_ERASE, /* UF2_ERR_ERASE_FAILED - erasing flash failed */
UPDATE_ERROR_WRITE, /* UF2_ERR_WRITE_FAILED - writing to flash failed */
UPDATE_ERROR_WRITE /* UF2_ERR_WRITE_LENGTH - wrote fewer data than requested */
};
static char errorStr[14];
/**
* @brief Set the callback invoked after writing data to flash.
*/
UpdateClass &UpdateClass::onProgress(THandlerFunction_Progress callback) {
this->callback = callback;
return *this;
}
void UpdateClass::cleanup(uint8_t ardErr, uf2_err_t uf2Err) {
errUf2 = uf2Err;
errArd = ardErr;
#if LT_DEBUG_OTA
if (hasError())
printErrorContext1();
#endif
free(ctx); // NULL in constructor
ctx = NULL;
uf2_info_free(info); // NULL in constructor
info = NULL;
free(buf); // NULL in constructor
buf = bufPos = NULL;
bytesWritten = 0;
bytesTotal = 0;
}
/**
* @brief Check for UF2 errors. Set errArd and errUf2 in case of errors.
* Ignored blocks are not reported as errors.
* Abort the update.
* Use like: "if (errorUf2(...)) return false;"
* @return true if err is not OK, false otherwise
*/
bool UpdateClass::checkUf2Error(uf2_err_t err) {
if (err <= UF2_ERR_IGNORE)
return false;
cleanup(errorMap[err], err);
return true;
}
/**
* @brief Abort the update with UPDATE_ERROR_ABORT reason.
*/
void UpdateClass::abort() {
LT_DM(OTA, "Aborting update");
cleanup(UPDATE_ERROR_ABORT);
}
void UpdateClass::bufAlloc() {
if (!buf)
buf = bufPos = (uint8_t *)malloc(UF2_BLOCK_SIZE);
}
uint16_t UpdateClass::bufLeft() {
return buf + UF2_BLOCK_SIZE - bufPos;
}
uint16_t UpdateClass::bufSize() {
return bufPos - buf;
}
/**
* @brief Print string error info to the stream.
*/
void UpdateClass::printError(Print &out) {
out.println(errorString());
}
/**
* @brief Print details about the error and current OTA state.
*/
void UpdateClass::printErrorContext1() {
#if LT_DEBUG_OTA
LT_EM(OTA, "Error: %s", errorString());
if (errArd == UPDATE_ERROR_ABORT)
return;
LT_EM(OTA, "- written: %u of %u", bytesWritten, bytesTotal);
LT_EM(OTA, "- buf: size=%u, left=%u", bufSize(), bufLeft());
hexdump(buf, bufSize());
if (ctx)
LT_EM(
OTA,
"- ctx: seq=%u, part1=%s, part2=%s",
ctx->seq - 1, // print last parsed block seq
ctx->part1 ? ctx->part1->name : NULL,
ctx->part2 ? ctx->part2->name : NULL
);
uf2_block_t *block = (uf2_block_t *)buf;
if (buf)
LT_EM(OTA, "- buf: seq=%u/%u, addr=%u, len=%u", block->block_seq, block->block_count, block->addr, block->len);
#endif
}
void UpdateClass::printErrorContext2(const uint8_t *data, size_t len) {
#if LT_DEBUG_OTA
LT_EM(OTA, "- while writing %u bytes", len);
if (data)
hexdump(data, len);
#endif
}
/**
* @brief Get string representation of the error in format
* "ard=..,uf2=..". Returns "" if no error.
*/
const char *UpdateClass::errorString() {
if (!errArd && !errUf2)
return "";
sprintf(errorStr, "ard=%u,uf2=%u", errArd, errUf2);
return errorStr;
}
/**
* @brief Get firmware name from UF2 info.
*/
const char *UpdateClass::getFirmwareName() {
if (info)
return info->fw_name;
return NULL;
}
/**
* @brief Get firmware version from UF2 info.
*/
const char *UpdateClass::getFirmwareVersion() {
if (info)
return info->fw_version;
return NULL;
}
/**
* @brief Get LibreTuya version from UF2 info.
*/
const char *UpdateClass::getLibreTuyaVersion() {
if (info)
return info->lt_version;
return NULL;
}
/**
* @brief Get target board name from UF2 info.
*/
const char *UpdateClass::getBoardName() {
if (info)
return info->board;
return NULL;
}
/**
* @brief See LT.otaCanRollback() for more info.
*/
bool UpdateClass::canRollBack() {
return LT.otaCanRollback();
}
/**
* @brief See LT.otaRollback() for more info.
*/
bool UpdateClass::rollBack() {
return LT.otaRollback();
}

View File

@@ -1,34 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-23. */
#pragma once
#ifdef __cplusplus
#include "WCharacterFixup.h"
#endif
#define PinMode PinModeArduino // this conflicts with SDK enum
#include <api/ArduinoAPI.h>
#include <core/LibreTuyaAPI.h>
#undef PinMode
// Include family-specific code
#include "WVariant.h"
// Include board variant
#include "variant.h"
// Choose the main UART output port
#ifndef LT_UART_DEFAULT_PORT
#if defined(PIN_SERIAL2_TX)
#define LT_UART_DEFAULT_PORT 2
#elif defined(PIN_SERIAL0_TX)
#define LT_UART_DEFAULT_PORT 0
#else
#define LT_UART_DEFAULT_PORT 1
#endif
#endif
// Define available serial ports
#ifdef __cplusplus
#include "SerialClass.h"
#include <core/SerialExtern.h>
#endif

View File

@@ -1,208 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-28. */
#include <LibreTuyaAPI.h>
extern "C" {
#include <flash_api.h>
#include <rtl8710b.h>
#include <sys_api.h>
#include <wdt_api.h>
}
void LibreTuya::restart() {
// The Watchdog Way
wdtEnable(1L);
while (1) {}
}
void LibreTuya::restartDownloadMode() {
// mww 0x40000138 0x8
HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_NORESET_FF, 0x08);
// reboot it the ugly way
sys_reset();
while (1) {}
}
ResetReason LibreTuya::getResetReason() {
return RESET_REASON_UNKNOWN;
}
void LibreTuya::gpioRecover() {
// PA14 and PA15 are apparently unusable with SWD enabled
sys_jtag_off();
Pinmux_Config(PA_14, PINMUX_FUNCTION_GPIO);
Pinmux_Config(PA_15, PINMUX_FUNCTION_GPIO);
}
/* CPU-related */
ChipType LibreTuya::getChipType() {
uint8_t chipId;
EFUSE_OneByteReadROM(9902, 0xF8, &chipId, L25EOUTVOLTAGE);
return CHIP_TYPE_ENUM(FAMILY, chipId);
}
const char *LibreTuya::getChipModel() {
return STRINGIFY_MACRO(MCU);
}
uint32_t LibreTuya::getChipId() {
uint32_t chipId = 0;
uint8_t *id = (uint8_t *)&chipId;
// 9902 was extracted from ROM disassembly, probably not needed
/* EFUSE_OneByteReadROM(9902, 0x3B, id + 0, L25EOUTVOLTAGE);
EFUSE_OneByteReadROM(9902, 0x3C, id + 1, L25EOUTVOLTAGE);
EFUSE_OneByteReadROM(9902, 0x3D, id + 2, L25EOUTVOLTAGE); */
// new method, based on EFUSE logical map
uint8_t *efuse = (uint8_t *)malloc(512);
// TODO do what EFUSE_LogicalMapRead() does, and read only the used data
EFUSE_LogicalMap_Read(efuse);
memcpy(id, efuse + 0x11A + 3, 3);
free(efuse);
return chipId;
}
uint8_t LibreTuya::getChipCores() {
return 1;
}
const char *LibreTuya::getChipCoreType() {
return "ARM Cortex-M4F";
}
uint32_t LibreTuya::getCpuFreq() {
return CPU_ClkGet(false);
}
uint32_t LibreTuya::getCycleCount() {
return microsecondsToClockCycles(micros());
}
/* Flash memory utilities */
FlashId LibreTuya::getFlashChipId() {
FlashId id;
uint8_t idBytes[3];
flash_read_id(NULL, idBytes, 3);
id.manufacturerId = idBytes[0];
id.chipId = idBytes[1];
id.chipSizeId = idBytes[2];
return id;
}
/* Memory management */
uint32_t LibreTuya::getRamSize() {
return 256 * 1024;
}
uint32_t LibreTuya::getHeapSize() {
return configTOTAL_HEAP_SIZE;
}
uint32_t LibreTuya::getFreeHeap() {
return xPortGetFreeHeapSize();
}
uint32_t LibreTuya::getMinFreeHeap() {
return xPortGetMinimumEverFreeHeapSize();
}
uint32_t LibreTuya::getMaxAllocHeap() {
return 0;
}
/* OTA-related */
uint8_t LibreTuya::otaGetRunning() {
// RTL8710B is XIP, so check the code offset in flash
uint32_t addr = (uint32_t)lt_log;
uint32_t offs = addr - SPI_FLASH_BASE;
return offs > FLASH_OTA2_OFFSET ? 2 : 1;
}
uint8_t LibreTuya::otaGetStoredIndex() {
uint32_t *otaAddress = (uint32_t *)0x8009000;
if (*otaAddress == 0xFFFFFFFF)
return 1;
uint32_t otaCounter = *((uint32_t *)0x8009004);
// even count of zero-bits means OTA1, odd count means OTA2
// this allows to switch OTA images by simply clearing next bits,
// without needing to erase the flash
uint8_t count = 0;
for (uint8_t i = 0; i < 32; i++) {
if ((otaCounter & (1 << i)) == 0)
count++;
}
return 1 + (count % 2);
}
bool LibreTuya::otaSupportsDual() {
return true;
}
bool LibreTuya::otaHasImage1() {
uint8_t *ota1Addr = (uint8_t *)(SPI_FLASH_BASE + FLASH_OTA1_OFFSET);
return memcmp(ota1Addr, "81958711", 8) == 0;
}
bool LibreTuya::otaHasImage2() {
uint8_t *ota2Addr = (uint8_t *)(SPI_FLASH_BASE + FLASH_OTA2_OFFSET);
return memcmp(ota2Addr, "81958711", 8) == 0;
}
bool LibreTuya::otaSwitch(bool force) {
if (!force && otaGetRunning() != otaGetStoredIndex())
// OTA has already been switched
return true;
// this function does:
// - read OTA1 firmware magic from 0xB000
// - read OTA2 address from 0x9000
// - read OTA2 firmware magic from that address
// - read current OTA switch value from 0x9004
// - reset OTA switch to 0xFFFFFFFF if it's 0x0
// - check first non-zero bit of OTA switch
// - write OTA switch with first non-zero bit cleared
// sys_clear_ota_signature();
// ok, this function is broken (crashes with HardFault)
if (!otaHasImage1() || !otaHasImage2())
return false;
uint32_t value = HAL_READ32(SPI_FLASH_BASE, FLASH_SYSTEM_OFFSET + 4);
if (value == 0) {
// TODO does this work at all?
FLASH_EreaseDwordsXIP(FLASH_SYSTEM_OFFSET + 4, 1);
}
uint8_t i;
// find first non-zero bit
for (i = 0; i < 32; i++) {
if (value & (1 << i))
break;
}
// clear the bit
value &= ~(1 << i);
// write OTA switch to flash
flash_write_word(NULL, FLASH_SYSTEM_OFFSET + 4, value);
return true;
}
/* Watchdog */
bool LibreTuya::wdtEnable(uint32_t timeout) {
watchdog_init(timeout);
watchdog_start();
}
void LibreTuya::wdtDisable() {
watchdog_stop();
}
void LibreTuya::wdtFeed() {
watchdog_refresh();
}
/* Global instance */
LibreTuya LT;
LibreTuya ESP = LT;

View File

@@ -1,98 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-03. */
#include "SerialClass.h"
#ifdef PIN_SERIAL0_TX
SerialClass Serial0(UART0_DEV, UART0_IRQ, PIN_SERIAL0_RX, PIN_SERIAL0_TX);
#endif
#ifdef PIN_SERIAL1_TX
SerialClass Serial1(UART1_DEV, UART1_IRQ, PIN_SERIAL1_RX, PIN_SERIAL1_TX);
#endif
#ifdef PIN_SERIAL2_TX
SerialClass Serial2(UART2_DEV, UART_LOG_IRQ, PIN_SERIAL2_RX, PIN_SERIAL2_TX);
#endif
SerialClass::SerialClass(UART_TypeDef *uart, IRQn irq, pin_size_t rx, pin_size_t tx) {
data.uart = uart;
data.buf = NULL;
this->irq = irq;
this->rx = rx;
this->tx = tx;
}
static uint32_t callback(void *param) {
SerialData *data = (SerialData *)param;
uint32_t intcr = data->uart->DLH_INTCR;
data->uart->DLH_INTCR = 0;
uint8_t c;
UART_CharGet(data->uart, &c);
if (c)
data->buf->store_char(c);
data->uart->DLH_INTCR = intcr;
return 0;
}
void SerialClass::begin(unsigned long baudrate, uint16_t config) {
// RUART_WLS_7BITS / RUART_WLS_8BITS
uint8_t dataWidth = (config & SERIAL_DATA_MASK) == SERIAL_DATA_8;
// RUART_PARITY_DISABLE / RUART_PARITY_ENABLE
uint8_t parity = (config & SERIAL_PARITY_MASK) != SERIAL_PARITY_NONE;
// RUART_ODD_PARITY / RUART_EVEN_PARITY
uint8_t parityType = (config & SERIAL_PARITY_MASK) == SERIAL_PARITY_EVEN;
// RUART_STOP_BIT_1 / RUART_STOP_BIT_2
uint8_t stopBits = (config & SERIAL_STOP_BIT_MASK) == SERIAL_STOP_BIT_2;
UART_InitTypeDef cfg;
UART_StructInit(&cfg);
cfg.WordLen = dataWidth;
cfg.Parity = parity;
cfg.ParityType = parityType;
cfg.StopBit = stopBits;
UART_Init(data.uart, &cfg);
UART_SetBaud(data.uart, baudrate);
if (data.buf) {
data.buf->clear();
} else {
data.buf = new RingBuffer();
}
Pinmux_Config(pinInfo(this->rx)->gpio, PINMUX_FUNCTION_UART);
Pinmux_Config(pinInfo(this->tx)->gpio, PINMUX_FUNCTION_UART);
VECTOR_IrqUnRegister(this->irq);
VECTOR_IrqRegister(callback, this->irq, (uint32_t)&data, 10);
}
void SerialClass::end() {
if (data.uart == UART2_DEV) {
// restore command line mode
DIAG_UartReInit((IRQ_FUN)UartLogIrqHandle);
}
delete data.buf;
}
int SerialClass::available() {
return data.buf->available();
}
int SerialClass::peek() {
return data.buf->peek();
}
int SerialClass::read() {
return data.buf->read_char();
}
void SerialClass::flush() {
UART_WaitBusy(data.uart, 10);
}
size_t SerialClass::write(uint8_t c) {
while (UART_Writable(data.uart) == 0) {}
UART_CharPut(data.uart, c);
return 1;
}

View File

@@ -1,46 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-03. */
#pragma once
#include <Arduino.h>
#include <api/HardwareSerial.h>
#include <api/RingBuffer.h>
using namespace arduino;
typedef struct {
UART_TypeDef *uart;
RingBuffer *buf;
} SerialData;
class SerialClass : public HardwareSerial {
private:
// data accessible to IRQ handler
SerialData data;
IRQn irq;
pin_size_t rx;
pin_size_t tx;
public:
SerialClass(UART_TypeDef *uart, IRQn irq, pin_size_t rx, pin_size_t tx);
inline void begin(unsigned long baudrate) {
begin(baudrate, SERIAL_8N1);
}
void begin(unsigned long baudrate, uint16_t config);
void end();
int available();
int peek();
int read();
void flush();
size_t write(uint8_t c);
operator bool() {
return !!data.buf;
}
using Print::write;
};
#define HAS_SERIAL_CLASS 1

View File

@@ -1,12 +0,0 @@
#include <Arduino.h>
extern void pinRemoveMode(pin_size_t pinNumber);
extern void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration);
void tone(uint32_t ulPin, unsigned int frequency, unsigned long duration) {
_tone(ulPin, frequency, duration);
}
void noTone(uint32_t ulPin) {
pinRemoveMode(ulPin);
}

View File

@@ -1,86 +0,0 @@
#include <Arduino.h>
#include <gpio_api.h>
#include <gpio_irq_api.h>
#include <gpio_irq_ex_api.h>
extern void *gpio_pin_struct[PINS_COUNT];
static void *gpio_irq_handler_list[PINS_COUNT] = {NULL};
static void *gpio_irq_handler_args[PINS_COUNT] = {NULL};
extern bool pinInvalid(pin_size_t pinNumber);
extern void pinRemoveMode(pin_size_t pinNumber);
static void gpioIrqHandler(uint32_t id, gpio_irq_event event) {
if (gpio_irq_handler_list[id] != NULL) {
if (gpio_irq_handler_args[id] == NULL)
((voidFuncPtr)gpio_irq_handler_list[id])();
else
((voidFuncPtrParam)gpio_irq_handler_list[id])(gpio_irq_handler_args[id]);
}
}
void attachInterrupt(pin_size_t interruptNumber, voidFuncPtr callback, PinStatus mode) {
attachInterruptParam(interruptNumber, callback, mode, NULL);
}
void attachInterruptParam(pin_size_t interruptNumber, voidFuncPtrParam callback, PinStatus mode, void *param) {
if (pinInvalid(interruptNumber))
return;
gpio_irq_handler_list[interruptNumber] = callback;
gpio_irq_handler_args[interruptNumber] = param;
if (pinTable[interruptNumber].enabled == PIN_IRQ && pinTable[interruptNumber].mode == mode)
// Nothing changes in pin mode
return;
if (pinTable[interruptNumber].enabled != PIN_IRQ)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(interruptNumber);
gpio_irq_t *gpio;
if (pinTable[interruptNumber].enabled == PIN_NONE) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_irq_t));
gpio_pin_struct[interruptNumber] = gpio;
gpio_irq_init(gpio, pinTable[interruptNumber].gpio, gpioIrqHandler, interruptNumber);
pinTable[interruptNumber].enabled = PIN_IRQ;
} else {
// pin already used as irq
gpio = (gpio_irq_t *)gpio_pin_struct[interruptNumber];
}
pinTable[interruptNumber].mode = mode;
gpio_irq_event event;
switch (mode) {
case LOW:
event = IRQ_LOW;
break;
case HIGH:
event = IRQ_HIGH;
break;
case FALLING:
event = IRQ_FALL;
break;
case RISING:
event = IRQ_RISE;
break;
default:
return;
}
gpio_irq_set(gpio, event, 1);
gpio_irq_enable(gpio);
}
void detachInterrupt(pin_size_t interruptNumber) {
if (pinInvalid(interruptNumber))
return;
if (pinTable[interruptNumber].enabled == PIN_IRQ) {
pinRemoveMode(interruptNumber);
}
gpio_irq_handler_list[interruptNumber] = NULL;
}

View File

@@ -1,36 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "sdk_extern.h"
#include "sdk_mem.h"
#include "sdk_os.h"
#define DEFAULT 1
#define EXTERNAL 0
#define round(x) ((x) >= 0 ? (long)((x) + 0.5) : (long)((x)-0.5))
// Additional Wiring functions
extern uint32_t digitalPinToPort(uint32_t pinNumber);
extern uint32_t digitalPinToBitMask(uint32_t pinNumber);
extern void analogOutputInit(void);
extern void wait_for_debug();
#ifdef __cplusplus
extern "C" uint32_t SystemCoreClock;
#else
extern uint32_t SystemCoreClock;
#endif
#define clockCyclesPerMicrosecond() (SystemCoreClock / 1000000L)
#define clockCyclesToMicroseconds(a) (a * 1000L / (SystemCoreClock / 1000L))
#define microsecondsToClockCycles(a) (a * (SystemCoreClock / 1000000L))
#define interrupts() vPortClearInterruptMask(0)
#define noInterrupts() ulPortSetInterruptMask()
#ifdef __cplusplus
} // extern "C"
#endif

View File

@@ -1,60 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-06. */
#pragma once
// va_list is declared by SDK and conflicting
#include <stdarg.h>
// disable typedef in basic_types.h
#define boolean boolean_rtl
#include <strproc.h> // define string macros first
#undef isdigit // then remove them, as they conflict
#undef islower // with ctype.h macros
#undef isprint
#undef isspace
#undef isxdigit
#undef strtol
#undef strtoul
#include <ameba_soc.h>
#include <gpio_api.h>
#include <main.h>
#include <rand.h>
#include <rt_lib_rom.h>
#include <rtl_lib.h>
#include <wait_api.h>
// remove previously defined workaround
#undef boolean
// undefine ROM stdio in favor of printf() library (wrappers)
#undef printf
#undef sprintf
#undef vsprintf
#undef snprintf
#undef vsnprintf
#undef vprintf
#include <stdio.h>
// moved from syscalls.h
#define _close __rtl_close
#define _fstat __rtl_fstat
#define _isatty __rtl_isatty
#define _lseek __rtl_lseek
#define _open __rtl_open
#define _read __rtl_read
#define _write __rtl_write
#define _sbrk __rtl_sbrk
#define delay_us wait_us
extern void wait_us(int us);
extern int LOGUART_SetBaud(uint32_t BaudRate); // from fixups/log_uart.c
extern void DumpForOneBytes(void *addr, int cnt); // cnt max 0x70!
extern void SystemCoreClockUpdate(void);
extern int _sscanf_patch(const char *buf, const char *fmt, ...);
// include printf() wrapper disable methods
#include <printf_port.h>

View File

@@ -1,16 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-06. */
#include "sdk_mem.h"
#include <Arduino.h> // for memset
void *pvPortZalloc(size_t size) {
void *pvReturn = pvPortMalloc(size);
if (pvReturn)
memset(pvReturn, 0, size);
return pvReturn;
}
void *pvPortCalloc(size_t nmemb, size_t size) {
return pvPortZalloc(nmemb * size);
}

View File

@@ -1,21 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-06. */
#pragma once
#include <stddef.h>
// provide extern functions directly, as callers
// generally don't expect needing to include malloc()
extern void *pvPortMalloc(size_t xWantedSize);
extern void *pvPortZalloc(size_t size);
extern void *pvPortCalloc(size_t nmemb, size_t size);
extern void *pvPortReAlloc(void *pv, size_t xWantedSize);
extern void vPortFree(void *pv);
#define malloc pvPortMalloc
#define zalloc pvPortZalloc
#define calloc pvPortCalloc
#define realloc pvPortReAlloc
#define free vPortFree
#define LT_HEAP_FUNC xPortGetFreeHeapSize

View File

@@ -1,110 +0,0 @@
#include "sdk_os.h"
#include <Arduino.h>
#include <cmsis_os.h>
uint32_t os_thread_create(void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size) {
osThreadDef_t thread_def;
thread_def.pthread = task;
thread_def.tpriority = (osPriority)priority;
// the underlying freertos implementation on cmsis os divide stack size by 4
thread_def.stacksize = stack_size * 4;
thread_def.name = "ARDUINO";
return (uint32_t)osThreadCreate(&thread_def, argument);
}
uint32_t os_thread_get_id(void) {
return osThreadGetId();
}
uint32_t os_thread_terminate(uint32_t thread_id) {
return (uint32_t)osThreadTerminate(thread_id);
}
uint32_t os_thread_yield(void) {
return (uint32_t)osThreadYield();
}
uint32_t os_thread_set_priority(uint32_t thread_id, int priority) {
return (uint32_t)osThreadSetPriority(thread_id, (osPriority)priority);
}
int os_thread_get_priority(uint32_t thread_id) {
return (int)osThreadGetPriority(thread_id);
}
int32_t os_signal_set(uint32_t thread_id, int32_t signals) {
return osSignalSet(thread_id, signals);
}
int32_t os_signal_clear(uint32_t thread_id, int32_t signals) {
return osSignalClear(thread_id, signals);
}
os_event_t os_signal_wait(int32_t signals, uint32_t millisec) {
osEvent evt;
os_event_t ret;
evt = osSignalWait(signals, millisec);
ret.status = (uint32_t)evt.status;
ret.value.signals = evt.value.signals;
ret.def.message_id = evt.def.message_id;
return ret;
}
typedef void (*os_ptimer)(const void *argument);
uint32_t os_timer_create(void (*callback)(const void *argument), uint8_t isPeriodic, void *argument) {
osTimerDef_t *pTimerDef;
pTimerDef = (osTimerDef_t *)malloc(sizeof(osTimerDef_t));
pTimerDef->ptimer = callback;
pTimerDef->custom = (struct os_timer_custom *)malloc(sizeof(struct os_timer_custom));
return osTimerCreate(pTimerDef, (isPeriodic ? osTimerPeriodic : osTimerOnce), argument);
}
uint32_t os_timer_start(uint32_t timer_id, uint32_t millisec) {
return osTimerStart(timer_id, millisec);
}
uint32_t os_timer_stop(uint32_t timer_id) {
return osTimerStop(timer_id);
}
uint32_t os_timer_delete(uint32_t timer_id) {
osTimerDef_t *pTimerDef;
pTimerDef = (osTimerDef_t *)pvTimerGetTimerID(timer_id);
free(pTimerDef->custom);
free(pTimerDef);
return osTimerDelete(timer_id);
}
uint32_t os_semaphore_create(int32_t count) {
return (uint32_t)osSemaphoreCreate(NULL, count);
}
int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec) {
if (osSemaphoreWait((osSemaphoreId)semaphore_id, millisec) == 0) {
return 1;
} else {
return 0;
}
}
uint32_t os_semaphore_release(uint32_t semaphore_id) {
return (uint32_t)osSemaphoreRelease((osSemaphoreId)semaphore_id);
}
uint32_t os_semaphore_delete(uint32_t semaphore_id) {
return (uint32_t)osSemaphoreDelete((osSemaphoreId)semaphore_id);
}

View File

@@ -1,302 +0,0 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
/**
* @defgroup os_status os_status
* Redefinition from enum osStatus
* @{
*/
/** function completed; no error or event occurred. */
#define OS_OK 0x00
/** function completed; signal event occurred. */
#define OS_EVENT_SIGNAL 0x08
/** function completed; message event occurred. */
#define OS_EVENT_MESSAGE 0x10
/** function completed; mail event occurred. */
#define OS_EVENT_MAIL 0x20
/** function completed; timeout occurred. */
#define OS_EVENT_TIMEOUT 0x40
/** parameter error: a mandatory parameter was missing or specified an incorrect object. */
#define OS_ERROR_PARAMETER 0x80
/** resource not available: a specified resource was not available. */
#define OS_ERROR_RESOURCE 0x81
/** resource not available within given time: a specified resource was not available within the timeout period. */
#define OS_ERROR_TIMEOUT_RESOURCE 0xC1
/** not allowed in ISR context: the function cannot be called from interrupt service routines. */
#define OS_ERROR_ISR 0x82
/** function called multiple times from ISR with same object. */
#define OS_ERROR_ISR_RECURSIVE 0x83
/** system cannot determine priority or thread has illegal priority. */
#define OS_ERROR_PRIORITY 0x84
/** system is out of memory: it was impossible to allocate or reserve memory for the operation. */
#define OS_ERROR_NO_MEMORY 0x85
/** value of a parameter is out of range. */
#define OS_ERROR_VALUE 0x86
/** unspecified RTOS error: run-time error but no other error message fits. */
#define OS_ERROR_OS 0xFF
/** @} */ // end of group os_status
/**
* @defgroup os_priority os_priority
* Redefinition from enum osPriority
* @{
*/
/** priority: idle (lowest) */
#define OS_PRIORITY_IDLE (-3)
/** priority: low */
#define OS_PRIORITY_LOW (-2)
/** priority: below normal */
#define OS_PRIORITY_BELOW_NORMAL (-1)
/** priority: normal (default) */
#define OS_PRIORITY_NORMAL (0)
/** priority: above normal */
#define OS_PRIORITY_ABOVENORMAL (+1)
/** priority: high */
#define OS_PRIORITY_HIGH (+2)
/** priority: realtime (highest) */
#define OS_PRIORITY_REALTIME (+3)
/** @} */ // end of group os_priority
#ifndef DEFAULT_STACK_SIZE
/**
* @ingroup wiring_os
* @brief default stack size
*
* It is suggest that thread is assigned stack size more than DEFAULT_STACK_SIZE
*/
#define DEFAULT_STACK_SIZE 512
#endif
/**
* @ingroup wiring_os
* @struct os_event_t
* Redefine osEvent in cmsis_os.h
*/
typedef struct {
uint32_t status; ///< status code: event or error information
union {
uint32_t v; ///< message as 32-bit value
void *p; ///< message or mail as void pointer
int32_t signals; ///< signal flags
} value; ///< event value
union {
void *mail_id; ///< mail id obtained by osMailCreate
void *message_id; ///< message id obtained by osMessageCreate
} def; ///< event definition
} os_event_t;
/**
* @defgroup thread_management thread_management
* Thread management include create, get thread id, terminate, yield, and set/get priority
**/
/**
* @ingroup thread_management
* @brief Create a thread and add it to Active Threads and set it to state READY.
*
* @param[in] task Function pointer which is the thread body. It should not run into the end of function unless
* os_thread_terminate is invoked
* @param[in] argument the data pointer which brings to task
* @param[in] priority The underlying os is FreeRTOS. It executes tasks with highest priority which are not in idle
* state.\n If there are more than 2 tasks to be executed, then they share the time slice.
* @param[in] stack_size The stack_size is used as memory heap only for this task. \n
* The local variables and call stacks would occupy this heap. Please make sure the the stack_size is big enough to
* avoid curroption
* @return The thread id which is used in thread operation and signaling.
*/
extern uint32_t os_thread_create(void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size);
/**
* @ingroup thread_management
* @brief Return the thread ID of the current running thread.
*
* @return Current thread id which calls os_thread_get_id
*/
extern uint32_t os_thread_get_id(void);
/**
* @ingroup thread_management
* @brief Terminate execution of a thread and remove it from Active Threads.
*
* Thread should not ended without terminate first
*
* @param[in] thread_id Terminate the thread with specific thread_id
* @return os_status code
*/
extern uint32_t os_thread_terminate(uint32_t thread_id);
/**
* @ingroup thread_management
* @brief Pass control to next thread that is in state \b READY.
*
* By default the minimal execution unit is 1 millisecond. In a scenario that if a thread with smaller want to handout
* execution right to a thread with higher priority immediately without waiting for the ending of current 1 millisecond,
* then invoke os_thread_yield can transfer exection right to OS's idle task and check which is the next execution
* thread.
*
* @return os_status code
*/
extern uint32_t os_thread_yield(void);
/**
* @ingroup thread_management
* @brief Change priority of an active thread.
*
* @param[in] thread_id The target thread with the thread id to be changed
* @param[in] priority The updated priority
* @return os_status code
*/
extern uint32_t os_thread_set_priority(uint32_t thread_id, int priority);
/**
* @ingroup thread_management
* @brief Get current priority of an active thread.
*
* @param[in] thread_id The target thread with the thread id to be searched
* @return os_priority
*/
extern int os_thread_get_priority(uint32_t thread_id);
/**
* @defgroup signal_management signal_management
* Signaling between threads include set, clear, and wait
*/
/**
* @ingroup signal_management
* @brief Set the specified Signal Flags of an active thread.
*
* @param[in] thread_id Send signal to a thread with the thread id
* @param[in] signals the signals to be send
* @return os_status code
*/
extern int32_t os_signal_set(uint32_t thread_id, int32_t signals);
/**
* @ingroup signal_management
* @brief Clear the specified Signal Flags of an active thread.
*
* @param[in] thread_id Clear signal to a thread with the thread id
* @param[in] signals The signals to be clear
* @return os_status code
*/
extern int32_t os_signal_clear(uint32_t thread_id, int32_t signals);
/**
* @ingroup signal_management
* @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
*
* @param[in] signals the signals to be wait
* @param[in] millisec the timeout value if no signal comes in. Fill in 0xFFFFFFFF for infinite wait.
* @return os_status code
*/
extern os_event_t os_signal_wait(int32_t signals, uint32_t millisec);
/**
* @defgroup timer_management timer_management
* Software timer management include create, start, stop, delete.
*/
/**
* @ingroup timer_management
* @brief specify timer type that invoke only once
*/
#define OS_TIMER_ONCE (0)
/**
* @ingroup timer_management
* @brief specify timer type that invoke periodically
*/
#define OS_TIMER_PERIODIC (1)
/**
* @ingroup timer_management
* @brief Create a timer.
*
* @param[in] callback The function to be invoke when timer timeout
* @param[in] isPeriodic \b OS_TIMER_ONCE or \b OS_TIMER_PERIODIC
* @param[in] argument The argument that is bring into callback function
* @return timer id
*/
extern uint32_t os_timer_create(void (*callback)(const void *argument), uint8_t isPeriodic, void *argument);
/**
* @ingroup timer_management
* @brief Start or restart a timer.
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @param[in] millisec The delays after timer starts
* @return os_status code
*/
extern uint32_t os_timer_start(uint32_t timer_id, uint32_t millisec);
/**
* @ingroup timer_management
* @brief Stop the timer.
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @return os_status code
*/
extern uint32_t os_timer_stop(uint32_t timer_id);
/**
* @ingroup timer_management
* @brief Delete a timer that was created by os_timer_create
*
* @param[in] timer_id The timer id obtained from by os_timer_create
* @return os_status code
*/
extern uint32_t os_timer_delete(uint32_t timer_id);
/**
* @defgroup semaphore_management semaphore_management
* Semaphore API between threads include create, wait, release, delete.
*/
/**
* @ingroup semaphore_management
* @brief Create and Initialize a Semaphore object used for managing resources
*
* @param[in] count The number of available resources
* @return semaphore ID
*/
extern uint32_t os_semaphore_create(int32_t count);
/**
* @ingroup semaphore_management
* @brief Wait until a Semaphore token becomes available
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @param[in] millisec timeout value
* @return os_status code
*/
extern int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec);
/**
* @ingroup semaphore_management
* @brief Release a Semaphore token
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @return os_status code
*/
extern uint32_t os_semaphore_release(uint32_t semaphore_id);
/**
* @ingroup semaphore_management
* @brief Delete a Semaphore that was created by os_semaphore_create.
*
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
* @return os_status code
*/
extern uint32_t os_semaphore_delete(uint32_t semaphore_id);
#ifdef __cplusplus
}
#endif

View File

@@ -1,93 +0,0 @@
/*
Copyright (c) 2011 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <cmsis_os.h>
#ifndef portNVIC_SYSTICK_CURRENT_VALUE_REG
#define portNVIC_SYSTICK_CURRENT_VALUE_REG (*((volatile uint32_t *)0xe000e018))
#endif
extern uint32_t xTaskGetTickCount();
extern uint32_t xTaskGetTickCountFromISR();
static __inline uint32_t __get_ipsr__(void) {
volatile uint32_t __regIPSR __asm("ipsr");
return (__regIPSR);
}
void *gpio_pin_struct[PINS_COUNT] = {NULL};
void delay(uint32_t ms) {
/* osStatus ret; */
/* ret = */ osDelay(ms);
/* if ((ret != osEventTimeout) && (ret != osOK)) {
printf("delay : ERROR : 0x%x \n", ret);
} */
}
void delayMicroseconds(unsigned int us) {
int i;
uint32_t t0, tn;
int dfactor = 20 * us - 10 + (81 * us / 100);
if (us > 100) {
t0 = micros();
do {
tn = micros();
} while (tn >= t0 && tn < (t0 + us - 1));
} else {
for (i = 0; i < dfactor; i++) {
asm("nop");
}
}
}
unsigned long millis(void) {
return (__get_ipsr__() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR();
}
unsigned long micros(void) {
uint32_t tick1, tick2;
uint32_t us;
uint32_t tick_per_us = F_CPU / 1000;
if (__get_ipsr__() == 0) {
tick1 = xTaskGetTickCount();
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
tick2 = xTaskGetTickCount();
} else {
tick1 = xTaskGetTickCountFromISR();
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
tick2 = xTaskGetTickCountFromISR();
}
if (tick1 == tick2) {
return tick1 * 1000 - us * 1000 / tick_per_us;
} else if ((us * 1000 / tick_per_us) < 500) {
return tick1 * 1000 - us * 1000 / tick_per_us;
} else {
return tick1 * 1000;
}
}
void yield(void) {
vTaskDelay(1);
taskYIELD();
}

View File

@@ -1,161 +0,0 @@
/*
Copyright (c) 2011 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <Arduino.h>
#include <analogin_api.h>
#include <analogout_api.h>
#include <gpio_ex_api.h>
#include <pwmout_api.h>
/* ADC */
analogin_t adc1;
analogin_t adc2;
analogin_t adc3;
bool g_adc_enabled[] = {false, false, false};
// from realtek_amebaz_va0_example/example_sources/adc_vbat/src/main.c
#define AD2MV(ad, offset, gain) (((ad >> 4) - offset) * 1000 / gain)
extern void *gpio_pin_struct[];
extern void pinRemoveMode(pin_size_t pinNumber);
// TODO implement custom ADC calibration
uint16_t analogReadVoltage(pin_size_t pinNumber) {
uint16_t ret = 0;
switch (pinNumber) {
#ifdef PIN_A1
case PIN_A1:
if (g_adc_enabled[1] == false) {
analogin_init(&adc2, AD_2);
g_adc_enabled[1] = true;
}
ret = analogin_read_u16(&adc2);
// AD_1 - 0.0V-5.0V
return AD2MV(ret, 0x496, 0xBA);
#endif
#ifdef PIN_A0
case PIN_A0:
if (g_adc_enabled[0] == false) {
analogin_init(&adc1, AD_1);
g_adc_enabled[0] = true;
}
ret = analogin_read_u16(&adc1);
break;
#endif
#ifdef PIN_A2
case PIN_A2:
if (g_adc_enabled[2] == false) {
analogin_init(&adc3, AD_3);
g_adc_enabled[2] = true;
}
ret = analogin_read_u16(&adc3);
break;
#endif
default:
return 0;
}
// AD_0, AD_2 - 0.0V-3.3V
return AD2MV(ret, 0x418, 0x342);
}
uint16_t analogReadMaxVoltage(pin_size_t pinNumber) {
#ifdef PIN_A1
if (pinNumber == PIN_A1)
return 5000;
#endif
return 3300;
}
void analogWrite(pin_size_t pinNumber, int value) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
pwmout_t *obj;
if (pinSupported(pin, PIN_PWM)) {
float percent = value * 1.0 / (1 << _analogWriteResolution);
if (pin->enabled != PIN_PWM) {
if ((pin->enabled == PIN_GPIO) || (pin->enabled == PIN_IRQ)) {
pinRemoveMode(pinNumber);
}
gpio_pin_struct[pinNumber] = malloc(sizeof(pwmout_t));
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_init(obj, pin->gpio);
pwmout_period_us(obj, _analogWritePeriod);
pwmout_write(obj, percent);
pin->enabled = PIN_PWM;
} else {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
// pwmout_period_us(obj, _writePeriod);
pwmout_write(obj, percent);
}
}
}
typedef struct _tone_argument {
uint32_t ulPin;
uint32_t timer_id;
};
void _tone_timer_handler(const void *argument) {
struct _tone_argument *arg = (struct _tone_argument *)argument;
uint32_t ulPin = (uint32_t)argument;
noTone(arg->ulPin);
os_timer_delete(arg->timer_id);
free((struct _tone_argument *)arg);
}
void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration) {
pwmout_t *obj;
if ((pinTable[ulPin].supported & PIN_PWM) != PIN_PWM) {
return;
}
if (pinTable[ulPin].enabled != PIN_PWM) {
if ((pinTable[ulPin].enabled == PIN_GPIO) || (pinTable[ulPin].enabled == PIN_IRQ)) {
pinRemoveMode(ulPin);
}
gpio_pin_struct[ulPin] = malloc(sizeof(pwmout_t));
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
pwmout_init(obj, pinTable[ulPin].gpio);
pwmout_period(obj, 1.0 / frequency);
pwmout_pulsewidth(obj, 1.0 / (frequency * 2));
pinTable[ulPin].enabled = PIN_PWM;
} else {
// There is already a PWM configured
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
pwmout_period(obj, 1.0 / frequency);
pwmout_pulsewidth(obj, 1.0 / (frequency * 2));
}
if (duration > 0) {
struct _tone_argument *arg = (struct _tone_argument *)malloc(sizeof(struct _tone_argument));
arg->ulPin = ulPin;
arg->timer_id = os_timer_create(_tone_timer_handler, 0, arg);
os_timer_start(arg->timer_id, duration);
}
}

View File

@@ -1,137 +0,0 @@
#include <Arduino.h>
#include <gpio_api.h>
#include <gpio_irq_api.h>
#include <gpio_irq_ex_api.h>
#include <pwmout_api.h>
extern void *gpio_pin_struct[PINS_COUNT];
void pinRemoveMode(pin_size_t pinNumber) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinEnabled(pin, PIN_PWM)) {
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[pinNumber];
pwmout_free(obj);
}
if (pinEnabled(pin, PIN_GPIO)) {
gpio_t *obj = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_deinit(obj, pin->gpio);
free(obj);
}
if (pinEnabled(pin, PIN_IRQ)) {
gpio_irq_t *obj = (gpio_irq_t *)gpio_pin_struct[pinNumber];
gpio_irq_deinit(obj);
free(obj);
}
gpio_pin_struct[pinNumber] = NULL;
pin->enabled = PIN_NONE;
}
void pinMode(pin_size_t pinNumber, PinModeArduino pinMode) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pinEnabled(pin, PIN_GPIO) && pin->mode == pinMode)
// Nothing changes in pin mode
return;
if (!pinSupported(pin, PIN_GPIO))
// cannot set ADC as I/O
return;
/* if (pin->enabled == PIN_PWM) {
// If this pin has been configured as PWM, then it cannot change to another mode
return;
} */
if (pin->enabled != PIN_GPIO)
// pin mode changes; deinit gpio and free memory
pinRemoveMode(pinNumber);
gpio_t *gpio;
if (pin->enabled == PIN_NONE) {
// allocate memory if pin not used before
gpio = malloc(sizeof(gpio_t));
gpio_pin_struct[pinNumber] = gpio;
gpio_init(gpio, pin->gpio);
pin->enabled = PIN_GPIO;
} else {
// pin already used as gpio
gpio = (gpio_t *)gpio_pin_struct[pinNumber];
}
pin->mode = pinMode;
PinDirection dir;
PinMode mode;
switch (pinMode) {
case INPUT:
dir = PIN_INPUT;
mode = PullNone;
break;
case INPUT_PULLDOWN:
dir = PIN_INPUT;
mode = PullDown;
break;
case INPUT_PULLUP:
dir = PIN_INPUT;
mode = PullUp;
break;
case OUTPUT:
dir = PIN_OUTPUT;
mode = PullNone;
break;
case OUTPUT_OPENDRAIN:
dir = PIN_OUTPUT;
mode = OpenDrain;
break;
default:
return;
}
gpio_dir(gpio, dir);
gpio_mode(gpio, mode);
}
void digitalWrite(pin_size_t pinNumber, PinStatus status) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pin->enabled != PIN_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
gpio_write(gpio, status);
}
PinStatus digitalRead(pin_size_t pinNumber) {
PinInfo *pin = pinInfo(pinNumber);
if (!pin)
return;
if (pin->enabled != PIN_GPIO)
return;
gpio_t *gpio = (gpio_t *)gpio_pin_struct[pinNumber];
return gpio_read(gpio);
}
/**************************** Extend API by RTK ***********************************/
uint32_t digitalPinToPort(uint32_t pinNumber) {
if (pinInvalid(pinNumber))
return 0xFFFFFFFF;
uint32_t pin_name = HAL_GPIO_GetPinName(pinTable[pinNumber].gpio);
return HAL_GPIO_GET_PORT_BY_NAME(pin_name);
}
uint32_t digitalPinToBitMask(uint32_t pinNumber) {
if (pinInvalid(pinNumber))
return 0xFFFFFFFF;
uint32_t pin_name = HAL_GPIO_GetPinName(pinTable[pinNumber].gpio);
return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name));
}

View File

@@ -1,5 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-03. */
#pragma once
#define LT_MD5_USE_POLARSSL 1

View File

@@ -1,58 +0,0 @@
#include "PowerManagement.h"
#include <Arduino.h>
#ifdef __cplusplus
extern "C" {
#include <freertos_pmu.h>
#include <sleep_ex_api.h>
#include <sys_api.h>
}
#endif
#if defined(BOARD_RTL8195A)
#define SAVE_LOCK_PIN 18
#elif defined(BOARD_RTL8710)
#define SAVE_LOCK_PIN 7 // PB_1
#else
#define SAVE_LOCK_PIN 18
#endif
bool PowerManagementClass::reservePLL = true;
void PowerManagementClass::sleep(uint32_t bitflg) {
if (!safeLock()) {
pmu_release_wakelock(bitflg);
}
}
void PowerManagementClass::sleep(void) {
if (!safeLock()) {
pmu_release_wakelock(BIT(PMU_OS));
}
}
void PowerManagementClass::active(uint32_t bitflg) {
pmu_acquire_wakelock(bitflg);
}
void PowerManagementClass::active(void) {
pmu_acquire_wakelock(BIT(PMU_OS));
}
void PowerManagementClass::deepsleep(uint32_t duration_ms) {
if (!safeLock()) {
deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, duration_ms);
}
}
bool PowerManagementClass::safeLock() {
pinMode(SAVE_LOCK_PIN, INPUT_PULLUP);
return (digitalRead(SAVE_LOCK_PIN) == 1) ? false : true;
}
void PowerManagementClass::softReset() {
sys_reset();
}
PowerManagementClass PowerManagement;

View File

@@ -1,73 +0,0 @@
#pragma once
#include <inttypes.h>
/**
* @class PowerManagementClass PowerManagement.h
* @brief Power management in Ameba
*/
class PowerManagementClass {
public:
/**
* @brief Allow OS automatically save power while idle
*
* As OS consider it would idle for more than 2s, it will invoke system suspend.
* If wlan is associated with AP, than it will under asslociated idle state.
*/
static void sleep(void);
static void sleep(uint32_t bitflg);
/**
* @brief Disallow OS automatically save power while idle
*/
static void active(void);
static void active(uint32_t bitflg);
/**
* @brief Reserved PLL while sleep
*
* Reserve PLL would keep FIFO of peripherals (Ex. UART) but cost more power (around 5mA).
* If we don't reserve PLL, it saves more power but we might missing data because FIFO is turned of this way.
*
* @param[in] reserve true for reserved, false for non-reserved
*/
static void setPllReserved(bool reserve);
/**
* @brief Enter deepsleep immediately
*
* Invoke deepsleep would make system enter deepsleep state immediately.
* It's the state that saves most power.
* As it wakeup from deepsleep, the system would behave just like reboot.
*
* @param[in] duration_ms wakeup after specific time in unit of millisecond
*/
static void deepsleep(uint32_t duration_ms);
/**
* @brief Check if system is allowed enter any power save state
*
* The pin 18 (GPIOE_5) is designed as safe lock.
* If pin 18 is HIGH, then we prevent Ameba enter any power save state.\n\n
* Under any power save state, we are not able to flash image to Ameba.
* Thus if user misuse deepsleep and make Ameba enter deepsleep immediately after boot up,
* then he would find it's hard to flash image.
* In this case, he can pull up pin 18.
*
* @return true if system not allowed enter any power save state, and false vise versa
*/
static bool safeLock();
/**
* @brief Reboot system
*
* Reboot system in soft way. Some registers is not powered off in this case, but mostly we could regard this as
* reboot.
*/
static void softReset();
private:
static bool reservePLL;
};
extern PowerManagementClass PowerManagement;

View File

@@ -1,5 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-07-03. */
#pragma once
#include <api/SoftwareSerial.h>

View File

@@ -1,10 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
#pragma once
#include <Arduino.h>
#include <api/WiFi/WiFi.h>
#include "WiFiClient.h"
#include "WiFiClientSecure.h"
#include "WiFiServer.h"

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPClient.h>
typedef LwIPClient WiFiClient;

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-04. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <ssl/MbedTLSClient.h>
typedef MbedTLSClient WiFiClientSecure;

View File

@@ -1,18 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-23. */
#pragma once
#include <Arduino.h>
extern "C" {
#include <FreeRTOS.h>
#include <semphr.h>
} // extern "C"
typedef struct {
bool initialized;
bool sleep;
SemaphoreHandle_t scanSem;
} WiFiData;

View File

@@ -1,109 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
#include "WiFiPriv.h"
int32_t WiFiClass::channel() {
int channel = 0;
wifi_get_channel(&channel);
return channel;
}
bool WiFiClass::modePriv(WiFiMode mode, WiFiModeAction sta, WiFiModeAction ap) {
__wrap_rtl_printf_disable();
__wrap_DiagPrintf_disable();
startWifiTask();
if (!data.initialized) {
// initialize wifi first
LT_IM(WIFI, "Initializing LwIP");
LwIP_Init();
reset_wifi_struct();
data.initialized = true;
}
LT_HEAP_I();
if (getMode()) {
// stop wifi to change mode
LT_DM(WIFI, "Stopping WiFi to change mode");
if (wifi_off() != RTW_SUCCESS)
goto error;
vTaskDelay(20);
if (mode == WIFI_MODE_NULL)
goto error;
}
if (wifi_on((rtw_mode_t)mode) != RTW_SUCCESS) {
LT_EM(WIFI, "Error while changing mode(%u)", mode);
goto error;
}
// send STA start/stop events and AP stop event (start is handled in softAP())
if (sta == WLMODE_ENABLE) {
wifi_indication(WIFI_EVENT_CONNECT, NULL, ARDUINO_EVENT_WIFI_STA_START, -2);
} else if (sta == WLMODE_DISABLE) {
wifi_indication(WIFI_EVENT_CONNECT, NULL, ARDUINO_EVENT_WIFI_STA_STOP, -2);
}
if (ap == WLMODE_DISABLE) {
wifi_indication(WIFI_EVENT_CONNECT, NULL, ARDUINO_EVENT_WIFI_AP_STOP, -2);
}
LT_HEAP_I();
__wrap_rtl_printf_enable();
__wrap_DiagPrintf_enable();
return true;
error:
__wrap_rtl_printf_enable();
__wrap_DiagPrintf_enable();
return false;
}
WiFiMode WiFiClass::getMode() {
if (!data.initialized)
return WIFI_MODE_NULL;
return (WiFiMode)wifi_mode;
}
WiFiStatus WiFiClass::status() {
if (wifi_is_connected_to_ap() == 0) {
return WL_CONNECTED;
} else {
return WL_DISCONNECTED;
}
}
bool WiFiClass::setSleep(bool enable) {
LT_DM(WIFI, "WiFi sleep mode %u", enable);
if (enable) {
if (wifi_enable_powersave() != RTW_SUCCESS)
return false;
} else {
if (wifi_disable_powersave() != RTW_SUCCESS)
return false;
}
data.sleep = enable;
return true;
}
bool WiFiClass::getSleep() {
return data.sleep;
}
bool WiFiClass::setTxPower(int power) {
return false; // wifi_set_txpower(power) == RTW_SUCCESS;
}
int WiFiClass::getTxPower() {
return 0;
int power = 0;
wifi_get_txpower(&power);
return power;
}
IPAddress WiFiClass::hostByName(const char *hostname) {
ip_addr_t ip;
int ret = netconn_gethostbyname(hostname, &ip);
if (ret == ERR_OK) {
return ip.addr;
}
return IPAddress();
}

View File

@@ -1,47 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-04-25. */
#pragma once
#include <api/WiFi/WiFi.h>
extern "C" {
// copy defines from PIO builder (for IDE to understand)
#define LWIP_TIMEVAL_PRIVATE 0
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_SO_RCVBUF 1
#include <FreeRTOS.h>
#include <autoconf.h>
#include <dhcp/dhcps.h>
#include <lwip/api.h>
#include <lwip/dns.h>
#include <lwip/err.h>
#include <lwip_netconf.h>
#include <semphr.h>
#include <wifi_conf.h>
#include <wifi_constants.h>
#include <wifi_structures.h>
extern struct netif xnetif[NET_IF_NUM];
} // extern "C"
// WiFi.cpp
extern rtw_network_info_t wifi;
extern rtw_ap_info_t ap;
extern rtw_wifi_setting_t wifi_setting;
extern unsigned char sta_password[65];
extern unsigned char ap_password[65];
extern void reset_wifi_struct(void);
extern rtw_mode_t wifi_mode;
extern WiFiAuthMode securityTypeToAuthMode(uint8_t type);
// WiFiEvents.cpp
extern void startWifiTask();
extern void handleRtwEvent(uint16_t event, char *data, int len, int flags);
#define NETIF_RTW_STA &xnetif[RTW_STA_INTERFACE]
#define NETIF_RTW_AP (wifi_mode == WIFI_MODE_APSTA ? &xnetif[RTW_AP_INTERFACE] : NETIF_RTW_STA)
#define NETNAME_STA WLAN0_NAME
#define NETNAME_AP (wifi_mode == WIFI_MODE_APSTA ? WLAN1_NAME : WLAN0_NAME)

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-06-27. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPServer.h>
typedef LwIPServer WiFiServer;

View File

@@ -1,8 +0,0 @@
/* Copyright (c) Kuba Szczodrzyński 2022-09-10. */
#pragma once
#include <api/WiFi/WiFi.h>
#include <lwip/LwIPUdp.h>
typedef LwIPUDP WiFiUDP;

View File

@@ -1,31 +0,0 @@
<!-- This file is auto-generated -->
- [Generic - BK7231N (Tuya QFN32)](../boards/generic-bk7231n-qfn32-tuya/README.md)
- [Generic - BK7231T (Tuya QFN32)](../boards/generic-bk7231t-qfn32-tuya/README.md)
- [Generic - BK7252](../boards/generic-bk7252/README.md)
- [Generic - RTL8710BN (2M/468k)](../boards/generic-rtl8710bn-2mb-468k/README.md)
- [Generic - RTL8710BN (2M/788k)](../boards/generic-rtl8710bn-2mb-788k/README.md)
- [Generic - RTL8710BX (4M/980k)](../boards/generic-rtl8710bx-4mb-980k/README.md)
- [Generic - RTL8720CF (2M/992k)](../boards/generic-rtl8720cf-2mb-992k/README.md)
- [BW12](../boards/bw12/README.md)
- [BW15](../boards/bw15/README.md)
- [CB2L](../boards/cb2l/README.md)
- [CB2S](../boards/cb2s/README.md)
- [CB3L](../boards/cb3l/README.md)
- [CB3S](../boards/cb3s/README.md)
- [CB3SE](../boards/cb3se/README.md)
- [WB2L](../boards/wb2l/README.md)
- [WB2S](../boards/wb2s/README.md)
- [WB3L](../boards/wb3l/README.md)
- [WB3S](../boards/wb3s/README.md)
- [WR2](../boards/wr2/README.md)
- [WR2E](../boards/wr2e/README.md)
- [WR3](../boards/wr3/README.md)
- [WR3E](../boards/wr3e/README.md)
- [WR3N](../boards/wr3n/README.md)
- [WR2L](../boards/wr2l/README.md)
- [WR2LE](../boards/wr2le/README.md)
- [WR3L](../boards/wr3l/README.md)
- [WR3LE](../boards/wr3le/README.md)
- [LSC LMA35](../boards/lsc-lma35/README.md)
- [Generic - Host-native](../boards/generic-native/README.md)

View File

@@ -0,0 +1,8 @@
{
"build": {
"bkcrypt_coeffs": "510fb093a3cbeadc5993a17ec7adeb03"
},
"flash": {
"tuya": "0x1ED000+0x13000"
}
}

View File

@@ -0,0 +1,10 @@
{
"build": {
"ldscript": "bk7231_bsp.ld",
"bkoffset_app": "0x10000",
"bkrbl_size_app": "0x108700"
},
"upload": {
"maximum_size": 1083136
}
}

View File

@@ -1,6 +0,0 @@
{
"build": {
"bkcrypt_coeffs": "510fb093a3cbeadc5993a17ec7adeb03",
"bkboot_version": "1.0.1-bk7231n"
}
}

View File

@@ -1,10 +1,10 @@
{
"build": {
"family": "BK7231N",
"ldscript_sdk": "bk7231n_bsp.ld",
"ldscript_arduino": "bk7231n_bsp.ld",
"ldscript": "bk7231n_bsp.ld",
"bkboot_version": "1.0.1-bk7231n",
"bkrbl_size_app": "0x107800"
"bkoffset_app": "0x10000",
"bkrbl_size_app": "0x108700"
},
"flash": {
"bootloader": "0x000000+0x11000",

View File

@@ -0,0 +1,19 @@
{
"build": {
"family": "BK7231Q",
"bkboot_version": "bk7231q"
},
"flash": {
"bootloader": "0x000000+0x11000",
"app": "0x011000+0x121000",
"download": "0x132000+0xA6000",
"kvs": "0x1D8000+0x8000",
"calibration": "0x1E0000+0x1000",
"tlv": "0x1E1000+0x1000",
"net": "0x1E2000+0x1000",
"userdata": "0x1E3000+0x1D000"
},
"upload": {
"speed": 460800
}
}

View File

@@ -1,6 +0,0 @@
{
"build": {
"bkcrypt_coeffs": "510fb093a3cbeadc5993a17ec7adeb03",
"bkboot_version": "1.0.5-bk7231s"
}
}

View File

@@ -1,10 +1,7 @@
{
"build": {
"family": "BK7231U",
"ldscript_sdk": "bk7231_bsp.ld",
"ldscript_arduino": "bk7231_bsp.ld",
"bkboot_version": "1.0.8-bk7231u",
"bkrbl_size_app": "0x108700"
"family": "BK7231T",
"bkboot_version": "1.0.5-bk7231s"
},
"flash": {
"bootloader": "0x000000+0x11000",
@@ -17,7 +14,6 @@
"userdata": "0x1E3000+0x1D000"
},
"upload": {
"maximum_size": 1083136,
"speed": 921600
},
"connectivity": [

View File

@@ -2,9 +2,9 @@
"build": {
"family": "BK7251",
"f_cpu": "180000000L",
"ldscript_sdk": "bk7231_bsp.ld",
"ldscript_arduino": "bk7231_bsp.ld",
"ldscript": "bk7231_bsp.ld",
"bkboot_version": "0.1.3-bk7252",
"bkoffset_app": "0x10000",
"bkrbl_size_app": "0x1A0000"
},
"flash": {

View File

@@ -22,10 +22,6 @@
"mem 0x000000 0x200000 ro"
]
},
"frameworks": [
"beken-72xx-sdk",
"beken-72xx-arduino"
],
"upload": {
"maximum_ram_size": 262144,
"flash_size": 2097152,
@@ -45,9 +41,7 @@
}
},
"links": {
"General info": "../../docs/platform/beken-72xx/README.md",
"Flashing guide": "../../docs/platform/beken-72xx/flashing.md",
"BkWriter v1.6.0": "https://images.tuyacn.com/smart/bk_writer1.60/bk_writer1.60.exe"
"Info & flashing guide": "../../docs/platform/beken-72xx/README.md"
},
"extra": [
"Bootloader and app partitions contain CRC16 sums every 32 bytes. That results in the actual flash offsets/sizes not aligned to sector boundaries. To simplify calculations, the values shown in the table (extracted from bootloader's partition table) were aligned to 4096 bytes."

View File

@@ -0,0 +1,170 @@
{
"pcb": {
"ic": {
"11": {
"C_NAME": "GPIO30",
"GPIO": "P30",
"IRQ": null,
"USB": "DN"
},
"12": {
"C_NAME": "GPIO29",
"GPIO": "P29",
"IRQ": null,
"USB": "DP"
},
"14": {
"C_NAME": "GPIO6",
"GPIO": "P6",
"IRQ": null,
"PWM": 0
},
"15": {
"C_NAME": "GPIO7",
"GPIO": "P7",
"IRQ": null,
"PWM": 1
},
"16": {
"C_NAME": "GPIO8",
"GPIO": "P8",
"IRQ": null,
"PWM": 2
},
"17": {
"C_NAME": "GPIO17",
"GPIO": "P17",
"IRQ": null,
"SD": "D1",
"SPI": "MISO"
},
"18": {
"C_NAME": "GPIO16",
"GPIO": "P16",
"IRQ": null,
"SD": "D0",
"SPI": "MOSI"
},
"19": {
"C_NAME": "GPIO14",
"GPIO": "P14",
"IRQ": null,
"SD": "CLK",
"SPI": "SCK"
},
"20": {
"C_NAME": "GPIO15",
"GPIO": "P15",
"IRQ": null,
"SD": "CMD",
"SPI": "CS"
},
"21": {
"C_NAME": "GPIO19",
"GPIO": "P19",
"IRQ": null,
"SD": "D3",
"PWM": 5
},
"22": {
"C_NAME": "GPIO18",
"GPIO": "P18",
"IRQ": null,
"SD": "D2",
"PWM": 4
},
"23": {
"IO": "I",
"CTRL": "TEST"
},
"24": {
"C_NAME": "GPIO9",
"GPIO": "P9",
"IRQ": null,
"PWM": 3
},
"25": {
"C_NAME": "GPIO10",
"GPIO": "P10",
"IRQ": null,
"UART": "1_RX"
},
"26": {
"C_NAME": "GPIO11",
"GPIO": "P11",
"IRQ": null,
"UART": "1_TX"
},
"27": {
"C_NAME": "GPIO1",
"GPIO": "P1",
"IRQ": null,
"UART": "2_RX",
"I2C": "2_SDA"
},
"28": {
"C_NAME": "GPIO0",
"GPIO": "P0",
"IRQ": null,
"UART": "2_TX",
"I2C": "2_SCL"
},
"29": {
"C_NAME": "GPIO20",
"GPIO": "P20",
"IRQ": null,
"I2C": "1_SCL",
"JTAG": "TCK",
"FLASH": "FSCK"
},
"30": {
"C_NAME": "GPIO21",
"GPIO": "P21",
"IRQ": null,
"I2C": "1_SDA",
"JTAG": "TMS",
"FLASH": "^FCS"
},
"31": {
"C_NAME": "GPIO22",
"GPIO": "P22",
"IRQ": null,
"JTAG": "TDI",
"FLASH": "FSI"
},
"32": {
"C_NAME": "GPIO23",
"GPIO": "P23",
"IRQ": null,
"ADC": 3,
"JTAG": "TDO",
"FLASH": "FSO"
},
"33": {
"C_NAME": "GPIO25",
"GPIO": "P25",
"IRQ": null
},
"34": {
"C_NAME": "GPIO28",
"GPIO": "P28",
"IRQ": null
},
"35": {
"C_NAME": "GPIO4",
"GPIO": "P4",
"IRQ": null,
"ADC": 1,
"I2S": "DIN"
},
"36": {
"IO": "I",
"CTRL": "CODE"
},
"37": {
"IO": "I",
"CTRL": "CEN"
}
}
}
}

View File

@@ -103,7 +103,7 @@
"C_NAME": "GPIO19",
"GPIO": "P19",
"IRQ": null,
"SD": "D1"
"SD": "D3"
},
"31": {
"C_NAME": "GPIO17",

View File

@@ -92,6 +92,7 @@
},
"27": {
"C_NAME": "AD_2",
"GPIONUM": 41,
"IO": "I",
"ADC": 2
},

View File

@@ -2,14 +2,11 @@
"pcb": {
"templates": [
"esp12s",
"esp12s-shield",
"rf-16mm-type1"
"pcb-black",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_black",
"TRACE_COLOR": "#FAFD9D",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole"
"TRACE_COLOR": "#FAFD9D"
},
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
"pinout": {

View File

@@ -2,15 +2,9 @@
"pcb": {
"templates": [
"esp12s",
"esp12s-shield",
"rf-16mm-type1"
"pcb-black",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_black",
"TRACE_COLOR": "#FAFD9D",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole"
},
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
"pinout": {
"1": {

View File

@@ -0,0 +1,69 @@
{
"pcb": {
"scale": 10,
"test_pads": {
"TSCK": "cb1s.back.sck.anchor",
"TCSN": "cb1s.back.csn.anchor",
"TSI": "cb1s.back.si.anchor",
"TSO": "cb1s.back.so.anchor"
},
"back": [
{
"name": "test_pad_1mm",
"pos": "2.66,14.4"
},
{
"name": "test_pad_1mm",
"pos": "2.66,15.9"
},
{
"name": "test_pad_1mm",
"pos": "2.66,17.4"
},
{
"name": "test_pad_1mm",
"pos": "2.66,18.9"
},
{
"id": "sck",
"name": "label_line_down",
"pos": "3.5,14.3",
"vars": {
"DIR": "right",
"W": 1.0,
"H": 0
}
},
{
"id": "csn",
"name": "label_line_down",
"pos": "3.5,15.8",
"vars": {
"DIR": "right",
"W": 1.0,
"H": 0
}
},
{
"id": "si",
"name": "label_line_down",
"pos": "3.5,17.3",
"vars": {
"DIR": "right",
"W": 1.0,
"H": 0
}
},
{
"id": "so",
"name": "label_line_down",
"pos": "3.5,18.8",
"vars": {
"DIR": "right",
"W": 1.0,
"H": 0
}
}
]
}
}

101
boards/_base/pcb/cb1s.json Normal file
View File

@@ -0,0 +1,101 @@
{
"pcb": {
"templates": [
"tuya1",
"pcb-blue-light",
"tuya-16x24",
"rf-type1"
],
"scale": 15,
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD",
"pinout": {
"1": {
"PWR": "VCC5"
},
"2": {
"IC": 27,
"ARD": "D0"
},
"3": {
"IC": 26,
"ARD": "D1"
},
"4": {
"PWR": 3.3
},
"5": {
"GND": null
},
"6": {
"IC": 22,
"ARD": "D2"
},
"7": {
"IC": 23,
"ARD": "D3"
},
"8": {
"IC": 29,
"ARD": "D4"
},
"9": {
"IC": 25,
"ARD": "D5"
},
"10": {
"IC": 24,
"ARD": "D6"
},
"11": {
"IC": 28,
"ARD": "D7"
},
"12": {
"IC": 16,
"ARD": "D8"
},
"13": {
"IC": 15,
"ARD": "D9"
},
"14": {
"GND": null
},
"15": {
"GND": null
},
"16": {
"IC": 21
},
"17": {
"IC": 17,
"ARD": [
"D10",
"A0"
]
},
"18": {
"GND": null
},
"TSCK": {
"IC": 20,
"ARD": "D11"
},
"TCSN": {
"IC": 19,
"ARD": "D12"
},
"TSO": {
"IC": 17,
"ARD": [
"D10",
"A0"
]
},
"TSI": {
"IC": 18,
"ARD": "D13"
}
}
}
}

View File

@@ -10,26 +10,12 @@
"TCSN": "cb2l.back.f_csn.anchor"
},
"back": [
{
"type": "rect",
"pos": "0,0",
"size": "15,17.3",
"preset": "${MASK_PRESET}"
},
{
"name": "pins_horz7_2mm_0.7mm",
"pos": "1.15,17.3",
"vars": {
"PINTYPE": "${PINTYPE_HORZ}",
"PINDIR": "down"
}
},
{
"name": "test_pad_1mm",
"pos": "1.5,7.5"
},
{
"name": "label_line_2mm_down",
"name": "label_line_down",
"pos": "0.4,4.7",
"vars": {
"DIR": "right",
@@ -51,7 +37,7 @@
},
{
"id": "u2_txd",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "2.2,5.1",
"vars": {
"DIR": "left",
@@ -65,7 +51,7 @@
},
{
"id": "u1_txd",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "4.0,5.1",
"vars": {
"DIR": "left",
@@ -79,7 +65,7 @@
},
{
"id": "gnd",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "9.2,5.1",
"vars": {
"DIR": "left",
@@ -93,7 +79,7 @@
},
{
"id": "rst",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "2.2,9.9",
"vars": {
"DIR": "left",
@@ -107,7 +93,7 @@
},
{
"id": "f_csn",
"name": "label_line_2mm_down",
"name": "label_line_down",
"pos": "2.2,12.8",
"vars": {
"DIR": "left",

View File

@@ -2,15 +2,9 @@
"pcb": {
"templates": [
"tuya2l",
"rf-15mm-type1",
"tuya2l-shield"
"pcb-white",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_white",
"TRACE_COLOR": "#E0E0E0",
"SILK_COLOR": "black",
"PINTYPE_HORZ": "pin_horz_2mm_cast_hole"
},
"pinout_hidden": "I2S,I2C,JTAG,FLASH",
"pinout": {
"1": {

View File

@@ -15,7 +15,7 @@
},
{
"id": "u2_txd",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "6.7,6.1",
"vars": {
"DIR": "left",
@@ -29,7 +29,7 @@
},
{
"id": "u2_rxd",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "6.2,8.1",
"vars": {
"DIR": "left",
@@ -43,7 +43,7 @@
},
{
"id": "csn",
"name": "label_line_2mm_up",
"name": "label_line_up",
"pos": "4.2,11.1",
"vars": {
"DIR": "left",

View File

@@ -2,14 +2,9 @@
"pcb": {
"templates": [
"tuya2",
"rf-15mm-type1",
"tuya2-shield"
"pcb-blue-light",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_blue_light",
"TRACE_COLOR": "#58839B",
"SILK_COLOR": "white"
},
"pinout_hidden": "I2S,JTAG,FLASH",
"pinout": {
"1": {

View File

@@ -2,16 +2,12 @@
"pcb": {
"templates": [
"esp12s",
"esp12e-shield",
"pcb-white",
"tuya-16x24",
"rf-16mm-type1"
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_blue_light",
"TRACE_COLOR": "#58839B",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_hole",
"PINTYPE_HORZ": "pin_horz_2mm_cast_hole"
"PINHOLE": 1
},
"pinout_hidden": "I2S,SD,SPI,I2C,JTAG,FLASH",
"pinout": {

View File

@@ -2,16 +2,12 @@
"pcb": {
"templates": [
"esp12e-22",
"esp12e-shield-nohole",
"pcb-blue-light",
"tuya-16x24",
"rf-16mm-type1"
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_blue_light",
"TRACE_COLOR": "#58839B",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole",
"PINTYPE_HORZ": "pin_horz_2mm_cast_nohole"
"PINHOLE": 0
},
"pinout_hidden": "I2S,SD,SPI,SCL2",
"pinout": {

View File

@@ -2,16 +2,12 @@
"pcb": {
"templates": [
"esp12e-22",
"esp12e-shield-nohole",
"pcb-blue-light",
"tuya-16x24",
"rf-16mm-type1"
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_blue_light",
"TRACE_COLOR": "#58839B",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole",
"PINTYPE_HORZ": "pin_horz_2mm_cast_nohole"
"PINHOLE": 0
},
"pinout_hidden": "I2S,SD,JTAG,FLASH,SCL1",
"pinout": {

View File

@@ -0,0 +1,104 @@
{
"pcb": {
"test_pads": {
"TRST": "cblc5.back.rst.anchor",
"TRX1": "cblc5.back.r1.anchor",
"TTX1": "cblc5.back.t1.anchor",
"TRX2": "cblc5.back.r2.anchor",
"TTX2": "cblc5.back.t2.anchor",
"TCSN": "cblc5.back.csn.anchor"
},
"back": [
{
"name": "test_pad_1mm",
"pos": "1.1,1.1"
},
{
"id": "t1",
"name": "label_line_up",
"pos": "1.1,0.6",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 3.8,
"H": 1.4
}
},
{
"name": "test_pad_1mm",
"pos": "0.8,3.3"
},
{
"id": "r1",
"name": "label_line_up",
"pos": "0.8,2.8",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 4.1,
"H": 1.6
}
},
{
"name": "test_pad_1mm",
"pos": "2.4,4.1"
},
{
"id": "r2",
"name": "label_line_up",
"pos": "2.4,3.6",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 2.5,
"H": 0.4
}
},
{
"name": "test_pad_1mm",
"pos": "3.9,4.1"
},
{
"id": "t2",
"name": "label_line_down",
"pos": "3.9,4.6",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 1,
"H": 0.4
}
},
{
"name": "test_pad_1mm",
"pos": "1.2,4.9"
},
{
"name": "test_pad_1mm",
"pos": "1.7,7.0"
},
{
"id": "rst",
"name": "label_line_down",
"pos": "1.2,5.4",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 3.7,
"H": 1.6
}
},
{
"id": "csn",
"name": "label_line_down",
"pos": "1.7,7.5",
"vars": {
"DIR": "right",
"RASTER": 2,
"W": 3.2,
"H": 1.5
}
}
]
}
}

View File

@@ -0,0 +1,78 @@
{
"pcb": {
"templates": [
"tuyalc5",
"pcb-white"
],
"pinout_hidden": "I2S,JTAG,FLASH,SDA1",
"pinout": {
"1": {
"CTRL": "ANT"
},
"2": {
"GND": null
},
"3": {
"IC": 16,
"ARD": "D0"
},
"4": {
"IC": 15,
"ARD": "D2"
},
"5": {
"IC": 22,
"ARD": "D1"
},
"6": {
"PWR": 3.3
},
"TRST": {
"IC": 21
},
"TRX1": {
"IC": 26,
"ARD": "D4"
},
"TTX1": {
"IC": 27,
"ARD": "D3"
},
"TRX2": {
"IC": 28,
"ARD": "D5"
},
"TTX2": {
"IC": 29,
"ARD": "D6"
},
"TCSN": {
"IC": 19,
"ARD": "D7"
}
},
"front": [
{
"name": "chip",
"pos": "2.7,3.8",
"vars": {
"W": 5,
"POS": 1
}
},
{
"name": "osc",
"pos": "2.5,0.5"
},
{
"type": "text",
"pos": "0.7,4.2",
"text": "${SYMBOL}",
"font_size": 1.2,
"fill": {
"color": "${SILK_COLOR}"
}
}
]
}
}

View File

@@ -0,0 +1,30 @@
{
"pcb": {
"test_pads": {
"TCSN": "cbu.back.csn.anchor"
},
"back": [
{
"type": "rect",
"pos": "6.3,11.6",
"size": "2.9,2.9",
"preset": "copper1"
},
{
"id": "csn",
"name": "label_line_up",
"pos": "3.7,13.5",
"vars": {
"DIR": "left",
"RASTER": 2,
"W": 0,
"H": 0
}
},
{
"name": "test_pad_1mm",
"pos": "4.4,13.4"
}
]
}
}

100
boards/_base/pcb/cbu.json Normal file
View File

@@ -0,0 +1,100 @@
{
"pcb": {
"templates": [
"tuyau",
"pcb-white",
"rf-type1"
],
"pinout_hidden": "I2S,USB,SD,FLASH",
"pinout": {
"1": {
"IC": 11,
"ARD": "D0"
},
"2": {
"IC": 12,
"ARD": "D1"
},
"3": {
"IC": 20,
"ARD": "D2"
},
"4": {
"IC": 18,
"ARD": "D3"
},
"5": {
"IC": 17,
"ARD": [
"D4",
"A0"
]
},
"6": {
"IC": 28,
"ARD": "D5"
},
"7": {
"IC": 29,
"ARD": "D6"
},
"8": {
"IC": 24,
"ARD": "D7"
},
"9": {
"IC": 23,
"ARD": "D8"
},
"10": {
"IC": 22,
"ARD": "D9"
},
"11": {
"IC": 15,
"ARD": "D10"
},
"12": {
"IC": 16,
"ARD": "D11"
},
"13": {
"GND": null
},
"14": {
"PWR": 3.3
},
"15": {
"IC": 27,
"ARD": "D12"
},
"16": {
"IC": 26,
"ARD": "D13"
},
"17": {
"IC": 10,
"ARD": "D14"
},
"18": {
"IC": 21
},
"19": {
"IC": 25,
"ARD": "D15"
},
"20": {
"IC": 14,
"ARD": "D16"
},
"21": {
"IC": 13,
"ARD": "D17"
},
"TCSN": {
"IC": 19,
"ARD": "D18"
}
}
}
}

View File

@@ -2,15 +2,9 @@
"pcb": {
"templates": [
"custom-20x24-22",
"rf-20mm-type1"
"pcb-blue-light",
"rf-type1"
],
"vars": {
"MASK_PRESET": "mask_blue_light",
"TRACE_COLOR": "#58839B",
"SILK_COLOR": "white",
"PINTYPE_VERT": "pin_vert_2mm_cast_nohole",
"PINTYPE_HORZ": "pin_horz_2mm_cast_nohole"
},
"pinout_hidden": "I2S,JTAG,FLASH,SD,SPI,SDA1",
"pinout": {
"1": {

View File

@@ -0,0 +1,55 @@
{
"pcb": {
"templates": [
"tuya2",
"pcb-black",
"rf-type1"
],
"scale": 10.5,
"pinout_hidden": "I2S,TRIG,WAKE,CTS,RTS,SD,SPI",
"pinout": {
"1": {
"PWR": 3.3
},
"2": {
"IC": 17,
"ARD": "D0"
},
"3": {
"GND": null
},
"4": {
"IC": 16,
"ARD": "D1"
},
"5": {
"IC": 29,
"ARD": "D5"
},
"6": {
"IC": 28,
"ARD": "D2"
},
"7": {
"IC": 32,
"ARD": "D6"
},
"8": {
"IC": 1,
"ARD": "D3"
},
"9": {
"IC": 13,
"ARD": "D7"
},
"10": {
"IC": 2,
"ARD": "D4"
},
"11": {
"IC": 14,
"ARD": "D8"
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More