mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-15 07:12:34 +00:00
Compare commits
710 Commits
v2.3.8.d49
...
end-2-end-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
700397d3ed | ||
|
|
cd65497ac4 | ||
|
|
3c90a65a66 | ||
|
|
9e8f0814ab | ||
|
|
36cadd03ee | ||
|
|
15ee827efd | ||
|
|
d6dac1737a | ||
|
|
23844389ac | ||
|
|
8847945734 | ||
|
|
5514aab007 | ||
|
|
aa54335e21 | ||
|
|
2a279c7f3d | ||
|
|
7abc194ef5 | ||
|
|
f99b81acf7 | ||
|
|
0850ad6c8d | ||
|
|
00ea9182a4 | ||
|
|
601ae29fe9 | ||
|
|
ff500bc5a9 | ||
|
|
734f36589d | ||
|
|
1e655052fc | ||
|
|
6ddee795d6 | ||
|
|
d556ae762c | ||
|
|
48e0fd7ed0 | ||
|
|
ab7de7f6a0 | ||
|
|
6ee30043c3 | ||
|
|
314009a10f | ||
|
|
2d9126f873 | ||
|
|
d404a49336 | ||
|
|
ee9e46ec92 | ||
|
|
929b3e4f88 | ||
|
|
2043ad3bd0 | ||
|
|
2472c7cdc7 | ||
|
|
058e9769d6 | ||
|
|
3b2c37c47f | ||
|
|
ef5279e85e | ||
|
|
bd21a0455b | ||
|
|
9b4ad68f43 | ||
|
|
e20d57f3ad | ||
|
|
48dc222b75 | ||
|
|
ab9268cba9 | ||
|
|
6de3ca4301 | ||
|
|
e65e79c6c9 | ||
|
|
14146d6ff5 | ||
|
|
273beef148 | ||
|
|
94d5ee9fe6 | ||
|
|
7b64c4a5bf | ||
|
|
ecb4fb72db | ||
|
|
f439081674 | ||
|
|
bfbc4bf93a | ||
|
|
22e129e716 | ||
|
|
a85df199a5 | ||
|
|
7a65c8838d | ||
|
|
e3e36e23f9 | ||
|
|
7129cee944 | ||
|
|
23e3e6db92 | ||
|
|
a8999d7759 | ||
|
|
c7c620ac69 | ||
|
|
1bbc273ba6 | ||
|
|
33ced7e87a | ||
|
|
578ac6711b | ||
|
|
e37acae405 | ||
|
|
daddaf7146 | ||
|
|
5ff1078c8c | ||
|
|
0b010b4fd8 | ||
|
|
f86dde3c40 | ||
|
|
fdaaf71366 | ||
|
|
a577dd4142 | ||
|
|
9dad62e3c4 | ||
|
|
e0b4a8e31e | ||
|
|
7cbae56e6c | ||
|
|
6eabbaf432 | ||
|
|
cec8233cd1 | ||
|
|
0ebdc7ab0c | ||
|
|
e61bd84116 | ||
|
|
b0c1b7b7b5 | ||
|
|
eefe9efa9f | ||
|
|
390de724ba | ||
|
|
85176756ec | ||
|
|
6f1dae1b1b | ||
|
|
ef56fae976 | ||
|
|
d398419aef | ||
|
|
96cf78aadd | ||
|
|
ced87596cb | ||
|
|
1be635a797 | ||
|
|
36f1a62b0b | ||
|
|
8ef72a5c08 | ||
|
|
efc27f2051 | ||
|
|
837c4e9e7b | ||
|
|
181325103a | ||
|
|
207b9b49a5 | ||
|
|
8ce1c07c4e | ||
|
|
2661fc694f | ||
|
|
b528290fde | ||
|
|
ff89dca5b3 | ||
|
|
80fd121d87 | ||
|
|
f3fa8daedf | ||
|
|
bcd77c4523 | ||
|
|
308c0a6bb8 | ||
|
|
754db3f2bc | ||
|
|
c16f20de21 | ||
|
|
b4cbea1b3d | ||
|
|
0e7253d309 | ||
|
|
b91d66b436 | ||
|
|
7537b55586 | ||
|
|
2d18130235 | ||
|
|
67ddae2851 | ||
|
|
884bc529f0 | ||
|
|
8f3614d66c | ||
|
|
e7dfabc20f | ||
|
|
185eb318ad | ||
|
|
c86a3200f0 | ||
|
|
c3aa56ef30 | ||
|
|
192af05a25 | ||
|
|
26d0b2b477 | ||
|
|
b726792efd | ||
|
|
c451db3a3f | ||
|
|
95682c9095 | ||
|
|
da53b8152d | ||
|
|
8d1a34a4bf | ||
|
|
464f270b12 | ||
|
|
7740b4bccd | ||
|
|
e85a2e827b | ||
|
|
62a0321c7d | ||
|
|
6e8300287b | ||
|
|
f97ae52263 | ||
|
|
9bd293a941 | ||
|
|
bc69621c3e | ||
|
|
2ee53d1500 | ||
|
|
bee959150b | ||
|
|
c74bce9360 | ||
|
|
48eee747da | ||
|
|
a28f10e0c2 | ||
|
|
6cd1882aaa | ||
|
|
0bd17e6da6 | ||
|
|
9bc2224164 | ||
|
|
e1b4b226c9 | ||
|
|
cf392a4c20 | ||
|
|
54a2e14e35 | ||
|
|
1cfd5d12d2 | ||
|
|
b573e0eacc | ||
|
|
8ca884bafd | ||
|
|
864b793ce0 | ||
|
|
74afd13171 | ||
|
|
8daebf80dd | ||
|
|
a767997cea | ||
|
|
861f0b6769 | ||
|
|
2012a0ae1c | ||
|
|
3513d88794 | ||
|
|
debf4b934f | ||
|
|
3878e025e4 | ||
|
|
3ab4bebdcb | ||
|
|
e38aca3cba | ||
|
|
d8bdb92efe | ||
|
|
c6a9edf8c7 | ||
|
|
a7da3537e2 | ||
|
|
5b4530325f | ||
|
|
b498c0bfbf | ||
|
|
02ae24b6fa | ||
|
|
5111bd703a | ||
|
|
789e8f02bf | ||
|
|
92526fca23 | ||
|
|
9ec7dbd695 | ||
|
|
66c41e683d | ||
|
|
c1870f91fc | ||
|
|
06eaf2ba5d | ||
|
|
4a79a690db | ||
|
|
1f458d6397 | ||
|
|
02231fd487 | ||
|
|
66a4632f34 | ||
|
|
e509a91019 | ||
|
|
d8f3c3324c | ||
|
|
9ddfc6de4c | ||
|
|
1a38c4e51d | ||
|
|
40d6b99911 | ||
|
|
7d00e1cef9 | ||
|
|
5bbafdfd31 | ||
|
|
5453c495e2 | ||
|
|
d1ff160256 | ||
|
|
dd552a99e1 | ||
|
|
09ea198205 | ||
|
|
703da1d8c7 | ||
|
|
48c0635188 | ||
|
|
8db6039264 | ||
|
|
4b4c1669a9 | ||
|
|
d2ea430a3e | ||
|
|
4c1c5b070e | ||
|
|
bcdda4de8a | ||
|
|
24ecfa1a45 | ||
|
|
106a50bce2 | ||
|
|
103ab0c242 | ||
|
|
848b9773b9 | ||
|
|
ce1eb149ac | ||
|
|
29fe6e7448 | ||
|
|
a111f54b61 | ||
|
|
9f5f630dca | ||
|
|
1f9dacf486 | ||
|
|
5dde738a31 | ||
|
|
1951569b1a | ||
|
|
93ba19d1e1 | ||
|
|
a1c998e7e0 | ||
|
|
302caa854a | ||
|
|
59cc57fc29 | ||
|
|
6813b8e4e9 | ||
|
|
4aa6f60e95 | ||
|
|
2ffc93324d | ||
|
|
c501cc501d | ||
|
|
8c0ff89972 | ||
|
|
cf22b7ff04 | ||
|
|
811a9ae261 | ||
|
|
8b0208d1c6 | ||
|
|
1a1d545c38 | ||
|
|
32bc2f1137 | ||
|
|
1b249c32bf | ||
|
|
bca9fbe7e4 | ||
|
|
e70435ebd7 | ||
|
|
f583837b4e | ||
|
|
6f235232f0 | ||
|
|
8641777bac | ||
|
|
4ee15d8128 | ||
|
|
394e0e1b3e | ||
|
|
755952c261 | ||
|
|
f645ae943d | ||
|
|
4b0bbb8af1 | ||
|
|
7ac64bd762 | ||
|
|
1481ce987e | ||
|
|
c5f2d2736d | ||
|
|
a000a8d347 | ||
|
|
01e089fd07 | ||
|
|
300c3d32aa | ||
|
|
e27375d331 | ||
|
|
1d3ac57943 | ||
|
|
316928deb0 | ||
|
|
0d2a9b6282 | ||
|
|
6e648b9b77 | ||
|
|
d8fd3f615d | ||
|
|
7568a35372 | ||
|
|
50238fbaf5 | ||
|
|
646f5ad262 | ||
|
|
2248ac51be | ||
|
|
5781149f88 | ||
|
|
8bd74588ce | ||
|
|
94a10e011c | ||
|
|
bdd1c53072 | ||
|
|
1123223058 | ||
|
|
fa6624548b | ||
|
|
dadf9234e5 | ||
|
|
f9d79964ef | ||
|
|
54df153e9e | ||
|
|
f25644e8cf | ||
|
|
46d7b82ac1 | ||
|
|
9db3552e5a | ||
|
|
0f5fdfbab7 | ||
|
|
a04de8c6b3 | ||
|
|
5cc8ca59a3 | ||
|
|
3fa8b357e5 | ||
|
|
9e4ce86c2a | ||
|
|
141ae296b7 | ||
|
|
ca2b45a6e2 | ||
|
|
4286f2c2dd | ||
|
|
c5d747cd3e | ||
|
|
0fa9974518 | ||
|
|
699d37b04c | ||
|
|
eabec5ae34 | ||
|
|
df194ca0f0 | ||
|
|
974fc31856 | ||
|
|
e79a7dce07 | ||
|
|
33831cd41c | ||
|
|
11bca437fd | ||
|
|
e59e50af0e | ||
|
|
51d54a7d99 | ||
|
|
17c2d60b78 | ||
|
|
c887675bb4 | ||
|
|
5c71187db1 | ||
|
|
8048fab084 | ||
|
|
e74d77dc44 | ||
|
|
ba8d17b9c1 | ||
|
|
9ad0addbbf | ||
|
|
1626667400 | ||
|
|
a3777e8f29 | ||
|
|
8b388d1e27 | ||
|
|
9f089746da | ||
|
|
33c46d6eb1 | ||
|
|
308060b1fe | ||
|
|
a664d4597f | ||
|
|
2b9848bf1b | ||
|
|
d97e6b86b8 | ||
|
|
deb7c274c4 | ||
|
|
e1bf4c32f3 | ||
|
|
86ca81b555 | ||
|
|
f59d98482f | ||
|
|
27dfe10689 | ||
|
|
7b838d388d | ||
|
|
c3d3dfa8c8 | ||
|
|
8be378c227 | ||
|
|
2df8093fef | ||
|
|
ae420dcd21 | ||
|
|
c1df621711 | ||
|
|
2ba88d305f | ||
|
|
fc63d956e7 | ||
|
|
4b82634d1a | ||
|
|
8bca3e168d | ||
|
|
8785adf6e4 | ||
|
|
9c46bdad1a | ||
|
|
10b157a38d | ||
|
|
e65c309af6 | ||
|
|
9701f35a83 | ||
|
|
3219d65387 | ||
|
|
8177329eac | ||
|
|
469ae0ff84 | ||
|
|
b5d7718319 | ||
|
|
47a94d7a07 | ||
|
|
20c1d71214 | ||
|
|
6f3d7ca4d2 | ||
|
|
ca969e26a5 | ||
|
|
5263c738f3 | ||
|
|
9c232da00f | ||
|
|
0016e747e9 | ||
|
|
ce58a23f9b | ||
|
|
c95b2c2d3c | ||
|
|
f86a0e5228 | ||
|
|
51f3ce5e60 | ||
|
|
41d633bfd8 | ||
|
|
2cb6e7bd37 | ||
|
|
a966d84e3d | ||
|
|
0425551341 | ||
|
|
626aa762df | ||
|
|
aa12e28568 | ||
|
|
58c00d0447 | ||
|
|
64531fa1ae | ||
|
|
23ac6b6514 | ||
|
|
f5098dc6d8 | ||
|
|
2e0d96cece | ||
|
|
8078e03f5f | ||
|
|
eb6bd3a06f | ||
|
|
d32cdecc06 | ||
|
|
f8db38cf99 | ||
|
|
02d8715ca0 | ||
|
|
0dd363fa98 | ||
|
|
0bcc60d535 | ||
|
|
2d39911f91 | ||
|
|
bd3e4e572b | ||
|
|
ddc406209b | ||
|
|
f145b5f16f | ||
|
|
e050888b26 | ||
|
|
9266a53f4e | ||
|
|
9a80951d6f | ||
|
|
ecf5519b56 | ||
|
|
f0a38a5cf0 | ||
|
|
1515c8e763 | ||
|
|
3e9e0fdd49 | ||
|
|
ca560d64ea | ||
|
|
c59cb3c292 | ||
|
|
f79039fe57 | ||
|
|
e780b9a798 | ||
|
|
3c4fa2101f | ||
|
|
8fa0911ec8 | ||
|
|
5fceab7f0f | ||
|
|
5cebe4a0a7 | ||
|
|
275e393115 | ||
|
|
e7181988b6 | ||
|
|
e822525ce5 | ||
|
|
5e92136ed0 | ||
|
|
cd60ee80bd | ||
|
|
9d8a5221a9 | ||
|
|
30b14c57e7 | ||
|
|
7a25e0b69a | ||
|
|
b6066a78c1 | ||
|
|
5d2f7d1962 | ||
|
|
83f5ba0161 | ||
|
|
12b8dc1918 | ||
|
|
00162b4ccf | ||
|
|
ce3be5b4e8 | ||
|
|
cf2a824cc1 | ||
|
|
1f214211ba | ||
|
|
96853aeeea | ||
|
|
af36ee3a05 | ||
|
|
c593e7ce56 | ||
|
|
15250a566a | ||
|
|
7afa8107ae | ||
|
|
c2097d38fd | ||
|
|
163a732ddc | ||
|
|
ea69b999f9 | ||
|
|
7aea056ac0 | ||
|
|
369d379720 | ||
|
|
02050a4775 | ||
|
|
aca0807acf | ||
|
|
4fe281cf7f | ||
|
|
11c3ca541f | ||
|
|
ceb884cf18 | ||
|
|
e546220a80 | ||
|
|
f50073ed9f | ||
|
|
0c45c99b15 | ||
|
|
abdb7f52bc | ||
|
|
471ee78a5e | ||
|
|
85d621d9c6 | ||
|
|
a453d7f52c | ||
|
|
ba14ffb8d3 | ||
|
|
2eb3cfd5e0 | ||
|
|
ce9e63a2cb | ||
|
|
dbb254ba7a | ||
|
|
27bb3506d3 | ||
|
|
97e8b1fd18 | ||
|
|
5e01b4251f | ||
|
|
d7c52c33b9 | ||
|
|
a38a18da0d | ||
|
|
96be051bff | ||
|
|
b1cf5778b4 | ||
|
|
32702e2750 | ||
|
|
21d47adb8d | ||
|
|
3e4e1b2202 | ||
|
|
e55604b8e5 | ||
|
|
8b8e056b7b | ||
|
|
1a5227c826 | ||
|
|
39c9f92c6e | ||
|
|
16b41b51af | ||
|
|
85bca8a32a | ||
|
|
96943fe4b5 | ||
|
|
75d5cd2c35 | ||
|
|
26d4d06e2a | ||
|
|
ce5f73bb00 | ||
|
|
f7433eb4ee | ||
|
|
b42185c722 | ||
|
|
d80bcd7d67 | ||
|
|
871f6854b5 | ||
|
|
78fd17c12e | ||
|
|
c7769274dd | ||
|
|
5b1d3ed173 | ||
|
|
b09cee118c | ||
|
|
992d1c42e6 | ||
|
|
d60d1d7447 | ||
|
|
0c23e3109a | ||
|
|
e63278cf43 | ||
|
|
0852a170a3 | ||
|
|
7f2647abb1 | ||
|
|
8b1b6faf89 | ||
|
|
53fc22178b | ||
|
|
62b310ac5c | ||
|
|
4f906ae3ae | ||
|
|
24458a73d6 | ||
|
|
a2fb3d23a1 | ||
|
|
237944aaf0 | ||
|
|
1d98e48bab | ||
|
|
01a214aa59 | ||
|
|
4da3f202e5 | ||
|
|
2f99a8dbb8 | ||
|
|
f59cbc8ffb | ||
|
|
095887de40 | ||
|
|
46b8e2a850 | ||
|
|
27ad3da0ac | ||
|
|
2335352fbe | ||
|
|
2fa55b7b6f | ||
|
|
da5bca31ed | ||
|
|
8a4e91e848 | ||
|
|
d91fdc5ea7 | ||
|
|
355c610824 | ||
|
|
a52db85ebe | ||
|
|
338244de32 | ||
|
|
90d45f24fd | ||
|
|
d09da96780 | ||
|
|
a5c96a29d5 | ||
|
|
1f9f885aca | ||
|
|
646b252786 | ||
|
|
08e1c2f681 | ||
|
|
537814df58 | ||
|
|
d1d49efc6e | ||
|
|
3cda598673 | ||
|
|
5554cc46a7 | ||
|
|
d82d9f5ef1 | ||
|
|
96b286cd48 | ||
|
|
7874ebc568 | ||
|
|
fb3c141231 | ||
|
|
f1906c38f1 | ||
|
|
14b7c5b6ef | ||
|
|
d8775d94e3 | ||
|
|
2cc5598f89 | ||
|
|
fbc8f6c03b | ||
|
|
d0ca616c19 | ||
|
|
c37316e723 | ||
|
|
67b67a481f | ||
|
|
181f03cb95 | ||
|
|
9632e4c405 | ||
|
|
a218c6fb4d | ||
|
|
b43c7c0f23 | ||
|
|
7cbfe7aa54 | ||
|
|
86f2000382 | ||
|
|
79333c85a3 | ||
|
|
4a93e4d85e | ||
|
|
b551c8b592 | ||
|
|
06c635eca0 | ||
|
|
97a5abbc82 | ||
|
|
2723ae6e9b | ||
|
|
6ce2fdc1c8 | ||
|
|
9a855c0b6f | ||
|
|
2740a56944 | ||
|
|
ffff2a03fc | ||
|
|
4fa2427b8c | ||
|
|
eddda3ca43 | ||
|
|
17142f8778 | ||
|
|
953aa4d091 | ||
|
|
b9edc7563b | ||
|
|
c88278724c | ||
|
|
54bccb898e | ||
|
|
8d90c496d0 | ||
|
|
10e3040494 | ||
|
|
f138eaa970 | ||
|
|
cd8a7e44a8 | ||
|
|
0b48663cbc | ||
|
|
af9d825266 | ||
|
|
038413f46f | ||
|
|
77cf5c6200 | ||
|
|
aa33ad1d58 | ||
|
|
34553c9714 | ||
|
|
c46c3427f0 | ||
|
|
dca8615eaa | ||
|
|
79511aa61e | ||
|
|
80762518d5 | ||
|
|
2233507667 | ||
|
|
9a38a4b024 | ||
|
|
1d288414a5 | ||
|
|
2f9dc813d3 | ||
|
|
1a253dccc3 | ||
|
|
7d873eb06b | ||
|
|
1631462db1 | ||
|
|
7bcb8f1fee | ||
|
|
0c9da9aec7 | ||
|
|
a12b9922ed | ||
|
|
cdf86f4166 | ||
|
|
040b851615 | ||
|
|
d19607ba98 | ||
|
|
b829ee795d | ||
|
|
2fdc2e2c3c | ||
|
|
b9a6d21dff | ||
|
|
8c5dee5881 | ||
|
|
55d46bae92 | ||
|
|
ed8abea11b | ||
|
|
5f107569f3 | ||
|
|
b68ef3d98a | ||
|
|
34aec70998 | ||
|
|
e8cdac8fa0 | ||
|
|
afae3a488e | ||
|
|
85e238ca76 | ||
|
|
45b05c9896 | ||
|
|
7d1a925892 | ||
|
|
72fb8a30a1 | ||
|
|
1c67f491d4 | ||
|
|
f7a4cd33b4 | ||
|
|
d2390cb98a | ||
|
|
a37f309c03 | ||
|
|
3a628047ef | ||
|
|
a5fdb663e2 | ||
|
|
3719ddac03 | ||
|
|
4a05874dba | ||
|
|
1ec0e750a3 | ||
|
|
84d3117a7a | ||
|
|
300b26c6b5 | ||
|
|
cf0424922a | ||
|
|
7ef9fec446 | ||
|
|
2244b0efec | ||
|
|
108dfdc2ec | ||
|
|
b161649989 | ||
|
|
a2284e3d52 | ||
|
|
ce40f91613 | ||
|
|
314d2e2da1 | ||
|
|
b4a7e78d18 | ||
|
|
f3cf9a5e71 | ||
|
|
8e35e19fda | ||
|
|
14839bd9ba | ||
|
|
f109bc25c9 | ||
|
|
0976705f25 | ||
|
|
14392c22fd | ||
|
|
10010baacc | ||
|
|
8c327cc573 | ||
|
|
4087bd93a9 | ||
|
|
57575f8e49 | ||
|
|
d02e12a424 | ||
|
|
fce281f54c | ||
|
|
d95e3acab3 | ||
|
|
cc864291c2 | ||
|
|
c04c589ae7 | ||
|
|
51d2795b26 | ||
|
|
04837b3302 | ||
|
|
1d42a6c48f | ||
|
|
4cd70f3cbd | ||
|
|
c18b4920ae | ||
|
|
eeb9a368f0 | ||
|
|
306b8d3205 | ||
|
|
0c9eadc507 | ||
|
|
fe2356ae87 | ||
|
|
c57d45ba52 | ||
|
|
fc03eee4d9 | ||
|
|
53dea44983 | ||
|
|
3342395a0b | ||
|
|
6dbc858102 | ||
|
|
79628c73cd | ||
|
|
eaa7fcf3dc | ||
|
|
861bec05f4 | ||
|
|
ce25381f67 | ||
|
|
e08c808c3f | ||
|
|
9e8ca69a11 | ||
|
|
bd9156de24 | ||
|
|
938aba481a | ||
|
|
419820f483 | ||
|
|
73087f667a | ||
|
|
7810e59b0c | ||
|
|
64dc6cc215 | ||
|
|
33812a2082 | ||
|
|
78a1b6a9a8 | ||
|
|
49a9aa3e36 | ||
|
|
8d89e78bbf | ||
|
|
0aa449bca9 | ||
|
|
a3e47b8d9b | ||
|
|
022e1f472d | ||
|
|
77e76bc92b | ||
|
|
5da798c625 | ||
|
|
15178da566 | ||
|
|
c12b9b928b | ||
|
|
1f9ff68f1d | ||
|
|
3b5d4e92c5 | ||
|
|
2388eb91ae | ||
|
|
a9a208de73 | ||
|
|
078f33ff78 | ||
|
|
4d8c98c23d | ||
|
|
859fd7c251 | ||
|
|
5de0c71a3e | ||
|
|
96b5bd2fd0 | ||
|
|
d8d831b27a | ||
|
|
6ee995e262 | ||
|
|
c6f028a5f3 | ||
|
|
42cb9b854c | ||
|
|
e28f869d35 | ||
|
|
ef1f2e47c3 | ||
|
|
3b6ce29cca | ||
|
|
38347fa6db | ||
|
|
86b14793de | ||
|
|
58484d7fe5 | ||
|
|
69d765622f | ||
|
|
f06c56a51b | ||
|
|
ac22a503de | ||
|
|
676319a9ca | ||
|
|
5d9800b7c2 | ||
|
|
0c89aff0f6 | ||
|
|
5e160b21c7 | ||
|
|
39336847ad | ||
|
|
75dc8cccec | ||
|
|
147de75a02 | ||
|
|
5371f134ba | ||
|
|
8105c0440a | ||
|
|
6c75f2e627 | ||
|
|
5aef921962 | ||
|
|
8c3b9a6139 | ||
|
|
73ab43c67a | ||
|
|
23466b5a5f | ||
|
|
f19aa49eb2 | ||
|
|
1d583341e4 | ||
|
|
8e7ede16ef | ||
|
|
8886d2df55 | ||
|
|
cbf20e4cee | ||
|
|
81ecd6d926 | ||
|
|
b63997b36f | ||
|
|
76adcbb46b | ||
|
|
c009c0db1e | ||
|
|
2c99f11073 | ||
|
|
0d57d29cbd | ||
|
|
353c7e07d1 | ||
|
|
77a66e1dce | ||
|
|
e98c3bf5d0 | ||
|
|
5e9d48d0d7 | ||
|
|
8e91f895a6 | ||
|
|
b155a5b6dc | ||
|
|
2c30923e3e | ||
|
|
0afe2d459f | ||
|
|
0b239e618d | ||
|
|
e9ebdfeff2 | ||
|
|
6fb7d7f2d7 | ||
|
|
70712d859c | ||
|
|
4d9081b3b1 | ||
|
|
7643a1acb1 | ||
|
|
61216e579e | ||
|
|
e31bb2d513 | ||
|
|
a8c38c4580 | ||
|
|
85e0372d26 | ||
|
|
53bd9de9b8 | ||
|
|
13ad524538 | ||
|
|
5f90f45ac4 | ||
|
|
dc0593c5a7 | ||
|
|
df3cceb108 | ||
|
|
827dcfca4a | ||
|
|
9fb6148aff | ||
|
|
6c1377aa39 | ||
|
|
077ca5919a | ||
|
|
668b716119 | ||
|
|
eaa7e21bc7 | ||
|
|
be0e882be1 | ||
|
|
09080d76ad | ||
|
|
472db5b237 | ||
|
|
1c0227f90c | ||
|
|
c6e940af81 | ||
|
|
048f0a1601 | ||
|
|
675d8fe089 | ||
|
|
952393ca0f | ||
|
|
a231cd2ad0 | ||
|
|
a957065fe8 | ||
|
|
402b0d7e0b | ||
|
|
13ebda6b2f | ||
|
|
1dd19cec6e | ||
|
|
1f9c295c9e | ||
|
|
5218aaafcf | ||
|
|
c480f0870c | ||
|
|
94e1f016e5 | ||
|
|
9170fe0580 |
24
.devcontainer/Dockerfile
Normal file
24
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
FROM mcr.microsoft.com/devcontainers/cpp:1-debian-12
|
||||||
|
|
||||||
|
# [Optional] Uncomment this section to install additional packages.
|
||||||
|
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||||
|
&& apt-get -y install --no-install-recommends \
|
||||||
|
ca-certificates \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
libbluetooth-dev \
|
||||||
|
libgpiod-dev \
|
||||||
|
liborcania-dev \
|
||||||
|
libssl-dev \
|
||||||
|
libulfius-dev \
|
||||||
|
libyaml-cpp-dev \
|
||||||
|
pkg-config \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
|
python3-venv \
|
||||||
|
python3-wheel \
|
||||||
|
wget \
|
||||||
|
zip \
|
||||||
|
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN pip3 install --no-cache-dir -U platformio==6.1.15
|
||||||
28
.devcontainer/devcontainer.json
Normal file
28
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||||
|
// README at: https://github.com/devcontainers/templates/tree/main/src/cpp
|
||||||
|
{
|
||||||
|
"name": "Meshtastic Firmware Dev",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/python:1": {
|
||||||
|
"installTools": true,
|
||||||
|
"version": "latest"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"platformio.platformio-ide",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||||
|
"forwardPorts": [ 4403 ],
|
||||||
|
|
||||||
|
// Run commands to prepare the container for use
|
||||||
|
"postCreateCommand": ".devcontainer/setup.sh",
|
||||||
|
}
|
||||||
3
.devcontainer/setup.sh
Executable file
3
.devcontainer/setup.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
git submodule update --init
|
||||||
1
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
1
.github/ISSUE_TEMPLATE/Bug Report.yml
vendored
@@ -52,6 +52,7 @@ body:
|
|||||||
- Raspberry Pi Pico (W)
|
- Raspberry Pi Pico (W)
|
||||||
- Relay v1
|
- Relay v1
|
||||||
- Relay v2
|
- Relay v2
|
||||||
|
- Seeed Wio Tracker 1110
|
||||||
- DIY
|
- DIY
|
||||||
- Other
|
- Other
|
||||||
validations:
|
validations:
|
||||||
|
|||||||
3
.github/ISSUE_TEMPLATE/feature.yml
vendored
3
.github/ISSUE_TEMPLATE/feature.yml
vendored
@@ -16,6 +16,9 @@ body:
|
|||||||
options:
|
options:
|
||||||
- NRF52
|
- NRF52
|
||||||
- ESP32
|
- ESP32
|
||||||
|
- RP2040
|
||||||
|
- Linux Native
|
||||||
|
- other
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
|
|||||||
40
.github/actions/setup-base/action.yml
vendored
40
.github/actions/setup-base/action.yml
vendored
@@ -5,48 +5,38 @@ runs:
|
|||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: "recursive"
|
submodules: "recursive"
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
- name: Install cppcheck
|
- name: Install dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install -y cppcheck
|
sudo apt-get -y update --fix-missing
|
||||||
|
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev libyaml-cpp-dev
|
||||||
- name: Install libbluetooth
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sudo apt-get install -y libbluetooth-dev
|
|
||||||
- name: Install libgpiod
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sudo apt-get install -y libgpiod-dev
|
|
||||||
- name: Install libyaml-cpp
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
sudo apt-get install -y libyaml-cpp-dev
|
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
- name: Cache python libs
|
# - name: Cache python libs
|
||||||
uses: actions/cache@v3
|
# uses: actions/cache@v4
|
||||||
id: cache-pip # needed in if test
|
# id: cache-pip # needed in if test
|
||||||
with:
|
# with:
|
||||||
path: ~/.cache/pip
|
# path: ~/.cache/pip
|
||||||
key: ${{ runner.os }}-pip
|
# key: ${{ runner.os }}-pip
|
||||||
|
|
||||||
- name: Upgrade python tools
|
- name: Upgrade python tools
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio adafruit-nrfutil
|
pip install -U --no-build-isolation --no-cache-dir "setuptools<72"
|
||||||
pip install -U meshtastic --pre
|
pip install -U platformio adafruit-nrfutil --no-build-isolation
|
||||||
|
pip install -U poetry --no-build-isolation
|
||||||
|
pip install -U meshtastic --pre --no-build-isolation
|
||||||
|
|
||||||
- name: Upgrade platformio
|
- name: Upgrade platformio
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
9
.github/workflows/build_esp32.yml
vendored
9
.github/workflows/build_esp32.yml
vendored
@@ -11,13 +11,13 @@ jobs:
|
|||||||
build-esp32:
|
build-esp32:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/web
|
repo: meshtastic/web
|
||||||
file: build.tar
|
file: build.tar
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
- name: Pull OTA Firmware
|
- name: Pull OTA Firmware
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/firmware-ota
|
repo: meshtastic/firmware-ota
|
||||||
file: firmware.bin
|
file: firmware.bin
|
||||||
@@ -54,9 +54,10 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
release/*.bin
|
release/*.bin
|
||||||
release/*.elf
|
release/*.elf
|
||||||
|
|||||||
9
.github/workflows/build_esp32_c3.yml
vendored
9
.github/workflows/build_esp32_c3.yml
vendored
@@ -13,13 +13,13 @@ jobs:
|
|||||||
build-esp32-c3:
|
build-esp32-c3:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/web
|
repo: meshtastic/web
|
||||||
file: build.tar
|
file: build.tar
|
||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
- name: Pull OTA Firmware
|
- name: Pull OTA Firmware
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/firmware-ota
|
repo: meshtastic/firmware-ota
|
||||||
file: firmware-c3.bin
|
file: firmware-c3.bin
|
||||||
@@ -54,9 +54,10 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
release/*.bin
|
release/*.bin
|
||||||
release/*.elf
|
release/*.elf
|
||||||
|
|||||||
9
.github/workflows/build_esp32_s3.yml
vendored
9
.github/workflows/build_esp32_s3.yml
vendored
@@ -11,13 +11,13 @@ jobs:
|
|||||||
build-esp32-s3:
|
build-esp32-s3:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/web
|
repo: meshtastic/web
|
||||||
file: build.tar
|
file: build.tar
|
||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
- name: Pull OTA Firmware
|
- name: Pull OTA Firmware
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/firmware-ota
|
repo: meshtastic/firmware-ota
|
||||||
file: firmware-s3.bin
|
file: firmware-s3.bin
|
||||||
@@ -52,9 +52,10 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
release/*.bin
|
release/*.bin
|
||||||
release/*.elf
|
release/*.elf
|
||||||
|
|||||||
85
.github/workflows/build_native.yml
vendored
Normal file
85
.github/workflows/build_native.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
name: Build Native
|
||||||
|
|
||||||
|
on: workflow_call
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-native:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install libbluetooth
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update --fix-missing
|
||||||
|
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Upgrade python tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -U platformio adafruit-nrfutil
|
||||||
|
pip install -U meshtastic --pre
|
||||||
|
|
||||||
|
- name: Upgrade platformio
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pio upgrade
|
||||||
|
|
||||||
|
- name: Build Native
|
||||||
|
run: bin/build-native.sh
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Store binaries as an artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
release/meshtasticd_linux_x86_64
|
||||||
|
bin/config-dist.yaml
|
||||||
|
|
||||||
|
- name: Docker login
|
||||||
|
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
continue-on-error: true # FIXME: Failing docker login auth
|
||||||
|
with:
|
||||||
|
username: meshtastic
|
||||||
|
password: ${{ secrets.DOCKER_FIRMWARE_TOKEN }}
|
||||||
|
|
||||||
|
- name: Docker setup
|
||||||
|
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||||
|
continue-on-error: true # FIXME: Failing docker login auth
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Docker build and push tagged versions
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
continue-on-error: true # FIXME: Failing docker login auth
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: meshtastic/device-simulator:${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
|
- name: Docker build and push
|
||||||
|
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
||||||
|
continue-on-error: true # FIXME: Failing docker login auth
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: meshtastic/device-simulator:latest
|
||||||
6
.github/workflows/build_nrf52.yml
vendored
6
.github/workflows/build_nrf52.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
build-nrf52:
|
build-nrf52:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
@@ -24,10 +24,12 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
|
release/*.hex
|
||||||
release/*.uf2
|
release/*.uf2
|
||||||
release/*.elf
|
release/*.elf
|
||||||
release/*.zip
|
release/*.zip
|
||||||
|
|||||||
11
.github/workflows/build_raspbian.yml
vendored
11
.github/workflows/build_raspbian.yml
vendored
@@ -10,8 +10,14 @@ jobs:
|
|||||||
build-raspbian:
|
build-raspbian:
|
||||||
runs-on: [self-hosted, linux, ARM64]
|
runs-on: [self-hosted, linux, ARM64]
|
||||||
steps:
|
steps:
|
||||||
|
- name: Install libbluetooth
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
apt-get update -y --fix-missing
|
||||||
|
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
@@ -37,9 +43,10 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
release/meshtasticd_linux_aarch64
|
release/meshtasticd_linux_aarch64
|
||||||
bin/config-dist.yaml
|
bin/config-dist.yaml
|
||||||
|
|||||||
52
.github/workflows/build_raspbian_armv7l.yml
vendored
Normal file
52
.github/workflows/build_raspbian_armv7l.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
name: Build Raspbian Arm
|
||||||
|
|
||||||
|
on: workflow_call
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-raspbian-armv7l:
|
||||||
|
runs-on: [self-hosted, linux, ARM]
|
||||||
|
steps:
|
||||||
|
- name: Install libbluetooth
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
apt-get update -y --fix-missing
|
||||||
|
apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Upgrade python tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -U platformio adafruit-nrfutil
|
||||||
|
pip install -U meshtastic --pre
|
||||||
|
|
||||||
|
- name: Upgrade platformio
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pio upgrade
|
||||||
|
|
||||||
|
- name: Build Raspbian
|
||||||
|
run: bin/build-native.sh
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Store binaries as an artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
release/meshtasticd_linux_armv7l
|
||||||
|
bin/config-dist.yaml
|
||||||
5
.github/workflows/build_rpi2040.yml
vendored
5
.github/workflows/build_rpi2040.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
build-rpi2040:
|
build-rpi2040:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
@@ -24,9 +24,10 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
- name: Store binaries as an artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
release/*.uf2
|
release/*.uf2
|
||||||
release/*.elf
|
release/*.elf
|
||||||
|
|||||||
33
.github/workflows/build_stm32.yml
vendored
Normal file
33
.github/workflows/build_stm32.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Build STM32
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
board:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-stm32:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Build base
|
||||||
|
id: base
|
||||||
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
|
- name: Build STM32
|
||||||
|
run: bin/build-stm32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Store binaries as an artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
release/*.hex
|
||||||
|
release/*.bin
|
||||||
268
.github/workflows/main_matrix.yml
vendored
268
.github/workflows/main_matrix.yml
vendored
@@ -8,7 +8,7 @@ on:
|
|||||||
branches: [master, develop]
|
branches: [master, develop]
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- "**.md"
|
- "**.md"
|
||||||
- "version.properties"
|
- version.properties
|
||||||
|
|
||||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
@@ -20,209 +20,114 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
setup:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
arch: [esp32, esp32s3, esp32c3, nrf52840, rp2040, stm32, check]
|
||||||
- board: rak11200
|
runs-on: ubuntu-latest
|
||||||
- board: tlora-v2-1-1_6
|
steps:
|
||||||
- board: tbeam
|
- id: checkout
|
||||||
- board: heltec-v2_1
|
uses: actions/checkout@v4
|
||||||
- board: meshtastic-diy-v1
|
name: Checkout base
|
||||||
- board: rak4631
|
- id: jsonStep
|
||||||
- board: t-echo
|
run: |
|
||||||
- board: station-g2
|
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
|
||||||
- board: m5stack-coreink
|
echo "$TARGETS"
|
||||||
- board: tbeam-s3-core
|
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
|
||||||
- board: tlora-t3s3-v1
|
outputs:
|
||||||
- board: t-watch-s3
|
esp32: ${{ steps.jsonStep.outputs.esp32 }}
|
||||||
- board: t-deck
|
esp32s3: ${{ steps.jsonStep.outputs.esp32s3 }}
|
||||||
#- board: rak11310
|
esp32c3: ${{ steps.jsonStep.outputs.esp32c3 }}
|
||||||
|
nrf52840: ${{ steps.jsonStep.outputs.nrf52840 }}
|
||||||
|
rp2040: ${{ steps.jsonStep.outputs.rp2040 }}
|
||||||
|
stm32: ${{ steps.jsonStep.outputs.stm32 }}
|
||||||
|
check: ${{ steps.jsonStep.outputs.check }}
|
||||||
|
|
||||||
|
check:
|
||||||
|
needs: setup
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.setup.outputs.check) }}
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Build base
|
- name: Build base
|
||||||
id: base
|
id: base
|
||||||
uses: ./.github/actions/setup-base
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
- name: Trunk Check
|
|
||||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
|
||||||
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
|
||||||
|
|
||||||
- name: Check ${{ matrix.board }}
|
- name: Check ${{ matrix.board }}
|
||||||
run: bin/check-all.sh ${{ matrix.board }}
|
run: bin/check-all.sh ${{ matrix.board }}
|
||||||
|
|
||||||
build-esp32:
|
build-esp32:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix: ${{ fromJson(needs.setup.outputs.esp32) }}
|
||||||
include:
|
|
||||||
- board: rak11200
|
|
||||||
- board: tlora-v2
|
|
||||||
- board: tlora-v1
|
|
||||||
- board: tlora_v1_3
|
|
||||||
- board: tlora-v2-1-1_6
|
|
||||||
- board: tlora-v2-1-1_6-tcxo
|
|
||||||
- board: tlora-v2-1-1_8
|
|
||||||
- board: tbeam
|
|
||||||
- board: heltec-v2_0
|
|
||||||
- board: heltec-v2_1
|
|
||||||
- board: tbeam0_7
|
|
||||||
- board: meshtastic-diy-v1
|
|
||||||
- board: hydra
|
|
||||||
- board: meshtastic-dr-dev
|
|
||||||
- board: nano-g1
|
|
||||||
- board: station-g1
|
|
||||||
- board: m5stack-core
|
|
||||||
- board: m5stack-coreink
|
|
||||||
- board: nano-g1-explorer
|
|
||||||
- board: chatter2
|
|
||||||
uses: ./.github/workflows/build_esp32.yml
|
uses: ./.github/workflows/build_esp32.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-esp32-s3:
|
build-esp32-s3:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix: ${{ fromJson(needs.setup.outputs.esp32s3) }}
|
||||||
include:
|
|
||||||
- board: heltec-v3
|
|
||||||
- board: heltec-wsl-v3
|
|
||||||
- board: heltec-wireless-tracker
|
|
||||||
- board: heltec-wireless-tracker-V1-0
|
|
||||||
- board: heltec-wireless-paper-v1_0
|
|
||||||
- board: heltec-wireless-paper #v1.1
|
|
||||||
- board: tbeam-s3-core
|
|
||||||
- board: tlora-t3s3-v1
|
|
||||||
- board: t-watch-s3
|
|
||||||
- board: t-deck
|
|
||||||
- board: picomputer-s3
|
|
||||||
- board: station-g2
|
|
||||||
- board: unphone
|
|
||||||
uses: ./.github/workflows/build_esp32_s3.yml
|
uses: ./.github/workflows/build_esp32_s3.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-esp32-c3:
|
build-esp32-c3:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||||
include:
|
|
||||||
- board: heltec-ht62-esp32c3-sx1262
|
|
||||||
uses: ./.github/workflows/build_esp32_c3.yml
|
uses: ./.github/workflows/build_esp32_c3.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-nrf52:
|
build-nrf52:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||||
include:
|
|
||||||
- board: rak4631
|
|
||||||
- board: rak4631_eink
|
|
||||||
- board: monteops_hw1
|
|
||||||
- board: t-echo
|
|
||||||
- board: canaryone
|
|
||||||
- board: pca10059_diy_eink
|
|
||||||
- board: feather_diy
|
|
||||||
- board: nano-g2-ultra
|
|
||||||
uses: ./.github/workflows/build_nrf52.yml
|
uses: ./.github/workflows/build_nrf52.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-rpi2040:
|
build-rpi2040:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||||
include:
|
|
||||||
- board: pico
|
|
||||||
- board: picow
|
|
||||||
- board: rak11310
|
|
||||||
- board: senselora_rp2040
|
|
||||||
- board: rp2040-lora
|
|
||||||
uses: ./.github/workflows/build_rpi2040.yml
|
uses: ./.github/workflows/build_rpi2040.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-raspbian:
|
build-stm32:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
max-parallel: 1
|
matrix: ${{ fromJson(needs.setup.outputs.stm32) }}
|
||||||
uses: ./.github/workflows/build_raspbian.yml
|
uses: ./.github/workflows/build_stm32.yml
|
||||||
|
with:
|
||||||
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
package-raspbian:
|
package-raspbian:
|
||||||
uses: ./.github/workflows/package_raspbian.yml
|
uses: ./.github/workflows/package_raspbian.yml
|
||||||
|
|
||||||
build-native:
|
package-raspbian-armv7l:
|
||||||
runs-on: ubuntu-latest
|
uses: ./.github/workflows/package_raspbian_armv7l.yml
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Build base
|
|
||||||
id: base
|
|
||||||
uses: ./.github/actions/setup-base
|
|
||||||
|
|
||||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
package-native:
|
||||||
#- name: Build for native
|
uses: ./.github/workflows/package_amd64.yml
|
||||||
# run: platformio run -e native
|
|
||||||
#- name: Integration test
|
|
||||||
# run: |
|
|
||||||
#.pio/build/native/program
|
|
||||||
#& sleep 20 # 5 seconds was not enough
|
|
||||||
#echo "Simulator started, launching python test..."
|
|
||||||
#python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
|
||||||
|
|
||||||
- name: Build Native
|
|
||||||
run: bin/build-native.sh
|
|
||||||
|
|
||||||
- name: Get release version string
|
|
||||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
|
||||||
id: version
|
|
||||||
|
|
||||||
- name: Store binaries as an artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
|
||||||
path: |
|
|
||||||
release/device-*.sh
|
|
||||||
release/device-*.bat
|
|
||||||
|
|
||||||
- name: Docker login
|
|
||||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
username: meshtastic
|
|
||||||
password: ${{ secrets.DOCKER_TOKEN }}
|
|
||||||
|
|
||||||
- name: Docker setup
|
|
||||||
if: ${{ github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
|
||||||
uses: docker/setup-buildx-action@v2
|
|
||||||
|
|
||||||
- name: Docker build and push tagged versions
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: meshtastic/device-simulator:${{ steps.version.outputs.version }}
|
|
||||||
|
|
||||||
- name: Docker build and push
|
|
||||||
if: ${{ github.ref == 'refs/heads/master' && github.event_name != 'pull_request_target' && github.event_name != 'pull_request' }}
|
|
||||||
uses: docker/build-push-action@v3
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
push: true
|
|
||||||
tags: meshtastic/device-simulator:latest
|
|
||||||
|
|
||||||
after-checks:
|
after-checks:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [check]
|
needs: [check]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
@@ -238,21 +143,23 @@ jobs:
|
|||||||
build-esp32-s3,
|
build-esp32-s3,
|
||||||
build-esp32-c3,
|
build-esp32-c3,
|
||||||
build-nrf52,
|
build-nrf52,
|
||||||
build-raspbian,
|
|
||||||
build-native,
|
|
||||||
build-rpi2040,
|
build-rpi2040,
|
||||||
|
build-stm32,
|
||||||
package-raspbian,
|
package-raspbian,
|
||||||
|
package-raspbian-armv7l,
|
||||||
|
package-native,
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
path: ./
|
path: ./
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
@@ -262,25 +169,31 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Move files up
|
- name: Move files up
|
||||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./*tbeam-s3*/bleota-s3.bin ./*esp32c3*/bleota-c3.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase_v2.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat ./firmware-raspbian-*/release/meshtasticd_linux_aarch64 ./firmware-raspbian-*/bin/config-dist.yaml
|
run: mv -b -t ./ ./release/meshtasticd_linux_* ./bin/config-dist.yaml ./bin/device-*.sh ./bin/device-*.bat
|
||||||
|
|
||||||
- name: Repackage in single firmware zip
|
- name: Repackage in single firmware zip
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ steps.version.outputs.version }}
|
name: firmware-${{ steps.version.outputs.version }}
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
./*.bin
|
./firmware-*.bin
|
||||||
./*.uf2
|
./firmware-*.uf2
|
||||||
|
./firmware-*.hex
|
||||||
./firmware-*-ota.zip
|
./firmware-*-ota.zip
|
||||||
./device-*.sh
|
./device-*.sh
|
||||||
./device-*.bat
|
./device-*.bat
|
||||||
./meshtasticd_linux_arm64
|
./meshtasticd_linux_*
|
||||||
./config-dist.yaml
|
./config-dist.yaml
|
||||||
|
./littlefs-*.bin
|
||||||
|
./bleota*bin
|
||||||
|
./Meshtastic_nRF52_factory_erase*.uf2
|
||||||
retention-days: 90
|
retention-days: 90
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ steps.version.outputs.version }}
|
name: firmware-${{ steps.version.outputs.version }}
|
||||||
|
merge-multiple: true
|
||||||
path: ./output
|
path: ./output
|
||||||
|
|
||||||
# For diagnostics
|
# For diagnostics
|
||||||
@@ -296,9 +209,10 @@ jobs:
|
|||||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||||
|
|
||||||
- name: Repackage in single elfs zip
|
- name: Repackage in single elfs zip
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
path: ./*.elf
|
path: ./*.elf
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|
||||||
@@ -320,10 +234,10 @@ jobs:
|
|||||||
needs: [gather-artifacts, after-checks]
|
needs: [gather-artifacts, after-checks]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup Python
|
- name: Setup Python
|
||||||
uses: actions/setup-python@v4
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.x
|
||||||
|
|
||||||
@@ -331,14 +245,17 @@ jobs:
|
|||||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
id: version
|
id: version
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-${{ steps.version.outputs.version }}
|
name: firmware-${{ steps.version.outputs.version }}
|
||||||
|
merge-multiple: true
|
||||||
path: ./output
|
path: ./output
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifact-deb
|
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
@@ -349,11 +266,12 @@ jobs:
|
|||||||
chmod +x ./output/device-update.sh
|
chmod +x ./output/device-update.sh
|
||||||
|
|
||||||
- name: Zip firmware
|
- name: Zip firmware
|
||||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output -x *.deb
|
||||||
|
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
|
merge-multiple: true
|
||||||
path: ./elfs
|
path: ./elfs
|
||||||
|
|
||||||
- name: Zip Elfs
|
- name: Zip Elfs
|
||||||
@@ -396,22 +314,42 @@ jobs:
|
|||||||
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
asset_name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
- name: Add raspbian .deb
|
- name: Add raspbian aarch64 .deb
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ github.token }}
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: ./meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||||
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||||
asset_content_type: application/vnd.debian.binary-package
|
asset_content_type: application/vnd.debian.binary-package
|
||||||
|
|
||||||
|
- name: Add raspbian armv7l .deb
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||||
|
asset_name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||||
|
asset_content_type: application/vnd.debian.binary-package
|
||||||
|
|
||||||
|
- name: Add raspbian amd64 .deb
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: ./output/meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
|
asset_name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
|
asset_content_type: application/vnd.debian.binary-package
|
||||||
|
|
||||||
- name: Bump version.properties
|
- name: Bump version.properties
|
||||||
run: >-
|
run: >-
|
||||||
bin/bump_version.py
|
bin/bump_version.py
|
||||||
|
|
||||||
- name: Create version.properties pull request
|
- name: Create version.properties pull request
|
||||||
uses: peter-evans/create-pull-request@v3
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
add-paths: |
|
add-paths: |
|
||||||
version.properties
|
version.properties
|
||||||
|
|||||||
2
.github/workflows/nightly.yml
vendored
2
.github/workflows/nightly.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
uses: trunk-io/trunk-action@782e83f803ca6e369f035d64c6ba2768174ba61b
|
||||||
|
|||||||
78
.github/workflows/package_amd64.yml
vendored
Normal file
78
.github/workflows/package_amd64.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
name: Package Native
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-native:
|
||||||
|
uses: ./.github/workflows/build_native.yml
|
||||||
|
|
||||||
|
package-native:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-native
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Pull web ui
|
||||||
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
|
with:
|
||||||
|
repo: meshtastic/web
|
||||||
|
file: build.tar
|
||||||
|
target: build.tar
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: build .debpkg
|
||||||
|
run: |
|
||||||
|
mkdir -p .debpkg/DEBIAN
|
||||||
|
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||||
|
mkdir -p .debpkg/usr/sbin
|
||||||
|
mkdir -p .debpkg/etc/meshtasticd
|
||||||
|
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||||
|
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
|
||||||
|
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||||
|
cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd
|
||||||
|
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||||
|
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||||
|
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||||
|
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||||
|
chmod +x .debpkg/DEBIAN/conffiles
|
||||||
|
|
||||||
|
- uses: jiro4989/build-deb-action@v3
|
||||||
|
with:
|
||||||
|
package: meshtasticd
|
||||||
|
package_root: .debpkg
|
||||||
|
maintainer: Jonathan Bennett
|
||||||
|
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||||
|
arch: amd64
|
||||||
|
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||||
|
desc: Native Linux Meshtastic binary.
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./*.deb
|
||||||
17
.github/workflows/package_raspbian.yml
vendored
17
.github/workflows/package_raspbian.yml
vendored
@@ -17,14 +17,14 @@ jobs:
|
|||||||
needs: build-raspbian
|
needs: build-raspbian
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
ref: ${{github.event.pull_request.head.ref}}
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
- name: Pull web ui
|
- name: Pull web ui
|
||||||
uses: dsaltares/fetch-gh-release-asset@a40c8b4a0471f9ab81bdf73a010f74cc51476ad4
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
with:
|
with:
|
||||||
repo: meshtastic/web
|
repo: meshtastic/web
|
||||||
file: build.tar
|
file: build.tar
|
||||||
@@ -36,16 +36,17 @@ jobs:
|
|||||||
id: version
|
id: version
|
||||||
|
|
||||||
- name: Download artifacts
|
- name: Download artifacts
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
name: firmware-raspbian-${{ steps.version.outputs.version }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
- name: Display structure of downloaded files
|
- name: Display structure of downloaded files
|
||||||
run: ls -R
|
run: ls -R
|
||||||
|
|
||||||
- name: build .debpkg
|
- name: build .debpkg
|
||||||
run: |
|
run: |
|
||||||
mkdir -p .debpkg/debian
|
mkdir -p .debpkg/DEBIAN
|
||||||
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||||
mkdir -p .debpkg/usr/sbin
|
mkdir -p .debpkg/usr/sbin
|
||||||
mkdir -p .debpkg/etc/meshtasticd
|
mkdir -p .debpkg/etc/meshtasticd
|
||||||
@@ -56,7 +57,8 @@ jobs:
|
|||||||
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||||
chmod +x .debpkg/usr/sbin/meshtasticd
|
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||||
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||||
echo "etc/meshtasticd/config.yaml" > .debpkg/debian/conffiles
|
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||||
|
chmod +x .debpkg/DEBIAN/conffiles
|
||||||
|
|
||||||
- uses: jiro4989/build-deb-action@v3
|
- uses: jiro4989/build-deb-action@v3
|
||||||
with:
|
with:
|
||||||
@@ -68,8 +70,9 @@ jobs:
|
|||||||
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||||
desc: Native Linux Meshtastic binary.
|
desc: Native Linux Meshtastic binary.
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: artifact-deb
|
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||||
|
overwrite: true
|
||||||
path: |
|
path: |
|
||||||
./*.deb
|
./*.deb
|
||||||
|
|||||||
78
.github/workflows/package_raspbian_armv7l.yml
vendored
Normal file
78
.github/workflows/package_raspbian_armv7l.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
name: Package Raspbian
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-raspbian_armv7l:
|
||||||
|
uses: ./.github/workflows/build_raspbian_armv7l.yml
|
||||||
|
|
||||||
|
package-raspbian_armv7l:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-raspbian_armv7l
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
ref: ${{github.event.pull_request.head.ref}}
|
||||||
|
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||||
|
|
||||||
|
- name: Pull web ui
|
||||||
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
|
with:
|
||||||
|
repo: meshtastic/web
|
||||||
|
file: build.tar
|
||||||
|
target: build.tar
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
|
id: version
|
||||||
|
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: firmware-raspbian-armv7l-${{ steps.version.outputs.version }}.zip
|
||||||
|
merge-multiple: true
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
|
- name: build .debpkg
|
||||||
|
run: |
|
||||||
|
mkdir -p .debpkg/DEBIAN
|
||||||
|
mkdir -p .debpkg/usr/share/doc/meshtasticd/web
|
||||||
|
mkdir -p .debpkg/usr/sbin
|
||||||
|
mkdir -p .debpkg/etc/meshtasticd
|
||||||
|
mkdir -p .debpkg/usr/lib/systemd/system/
|
||||||
|
tar -xf build.tar -C .debpkg/usr/share/doc/meshtasticd/web
|
||||||
|
gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz
|
||||||
|
cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd
|
||||||
|
cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml
|
||||||
|
chmod +x .debpkg/usr/sbin/meshtasticd
|
||||||
|
cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service
|
||||||
|
echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles
|
||||||
|
chmod +x .debpkg/DEBIAN/conffiles
|
||||||
|
|
||||||
|
- uses: jiro4989/build-deb-action@v3
|
||||||
|
with:
|
||||||
|
package: meshtasticd
|
||||||
|
package_root: .debpkg
|
||||||
|
maintainer: Jonathan Bennett
|
||||||
|
version: ${{ steps.version.outputs.version }} # refs/tags/v*.*.*
|
||||||
|
arch: armhf
|
||||||
|
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||||
|
desc: Native Linux Meshtastic binary.
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./*.deb
|
||||||
7
.github/workflows/sec_sast_flawfinder.yml
vendored
7
.github/workflows/sec_sast_flawfinder.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# step 1
|
# step 1
|
||||||
- name: clone application source code
|
- name: clone application source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# step 2
|
# step 2
|
||||||
- name: flawfinder_scan
|
- name: flawfinder_scan
|
||||||
@@ -27,14 +27,15 @@ jobs:
|
|||||||
|
|
||||||
# step 3
|
# step 3
|
||||||
- name: save report as pipeline artifact
|
- name: save report as pipeline artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: flawfinder_report.sarif
|
name: flawfinder_report.sarif
|
||||||
|
overwrite: true
|
||||||
path: flawfinder_report.sarif
|
path: flawfinder_report.sarif
|
||||||
|
|
||||||
# step 4
|
# step 4
|
||||||
- name: publish code scanning alerts
|
- name: publish code scanning alerts
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
with:
|
with:
|
||||||
sarif_file: flawfinder_report.sarif
|
sarif_file: flawfinder_report.sarif
|
||||||
category: flawfinder
|
category: flawfinder
|
||||||
|
|||||||
7
.github/workflows/sec_sast_semgrep_cron.yml
vendored
7
.github/workflows/sec_sast_semgrep_cron.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# step 1
|
# step 1
|
||||||
- name: clone application source code
|
- name: clone application source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# step 2
|
# step 2
|
||||||
- name: full scan
|
- name: full scan
|
||||||
@@ -29,14 +29,15 @@ jobs:
|
|||||||
|
|
||||||
# step 3
|
# step 3
|
||||||
- name: save report as pipeline artifact
|
- name: save report as pipeline artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: report.sarif
|
name: report.sarif
|
||||||
|
overwrite: true
|
||||||
path: report.sarif
|
path: report.sarif
|
||||||
|
|
||||||
# step 4
|
# step 4
|
||||||
- name: publish code scanning alerts
|
- name: publish code scanning alerts
|
||||||
uses: github/codeql-action/upload-sarif@v2
|
uses: github/codeql-action/upload-sarif@v3
|
||||||
with:
|
with:
|
||||||
sarif_file: report.sarif
|
sarif_file: report.sarif
|
||||||
category: semgrep
|
category: semgrep
|
||||||
|
|||||||
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
2
.github/workflows/sec_sast_semgrep_pull.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
# step 1
|
# step 1
|
||||||
- name: clone application source code
|
- name: clone application source code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
|||||||
57
.github/workflows/test_simulator.yml
vendored
Normal file
57
.github/workflows/test_simulator.yml
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
name: Test Simulator
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *" # Run every day at midnight
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-simulator:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Install libbluetooth
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
sudo apt-get update --fix-missing
|
||||||
|
sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Upgrade python tools
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install -U platformio adafruit-nrfutil
|
||||||
|
pip install -U meshtastic --pre
|
||||||
|
|
||||||
|
- name: Upgrade platformio
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
pio upgrade
|
||||||
|
|
||||||
|
- name: Build Native
|
||||||
|
run: bin/build-native.sh
|
||||||
|
|
||||||
|
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||||
|
- name: Build for native
|
||||||
|
run: platformio run -e native
|
||||||
|
|
||||||
|
- name: Integration test
|
||||||
|
run: |
|
||||||
|
.pio/build/native/program & sleep 10 # 5 seconds was not enough
|
||||||
|
echo "Simulator started, launching python test..."
|
||||||
|
python3 -c 'from meshtastic.test import testSimulator; testSimulator()'
|
||||||
|
|
||||||
|
- name: PlatformIO Tests
|
||||||
|
run: platformio test -e native --junit-output-path testreport.xml
|
||||||
|
|
||||||
|
- name: Test Report
|
||||||
|
uses: dorny/test-reporter@v1.9.1
|
||||||
|
if: success() || failure() # run this step even if previous step failed
|
||||||
|
with:
|
||||||
|
name: PlatformIO Tests
|
||||||
|
path: testreport.xml
|
||||||
|
reporter: java-junit
|
||||||
2
.github/workflows/trunk-check.yml
vendored
2
.github/workflows/trunk-check.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Trunk Check
|
- name: Trunk Check
|
||||||
uses: trunk-io/trunk-action@v1
|
uses: trunk-io/trunk-action@v1
|
||||||
|
|||||||
4
.github/workflows/update_protobufs.yml
vendored
4
.github/workflows/update_protobufs.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
|
|
||||||
@@ -26,7 +26,7 @@ jobs:
|
|||||||
./bin/regen-protos.sh
|
./bin/regen-protos.sh
|
||||||
|
|
||||||
- name: Create pull request
|
- name: Create pull request
|
||||||
uses: peter-evans/create-pull-request@v3
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
add-paths: |
|
add-paths: |
|
||||||
protobufs
|
protobufs
|
||||||
|
|||||||
2
.gitpod.yml
Normal file
2
.gitpod.yml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
tasks:
|
||||||
|
- init: pip install platformio && pip install --upgrade pip
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
.github/workflows/main_matrix.yml
|
.github/workflows/main_matrix.yml
|
||||||
src/mesh/compression/unishox2.c
|
src/mesh/compression/unishox2.cpp
|
||||||
|
|||||||
2
.trunk/configs/.bandit
Normal file
2
.trunk/configs/.bandit
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[bandit]
|
||||||
|
skips = B101
|
||||||
@@ -1,36 +1,40 @@
|
|||||||
version: 0.1
|
version: 0.1
|
||||||
cli:
|
cli:
|
||||||
version: 1.20.1
|
version: 1.22.2
|
||||||
plugins:
|
plugins:
|
||||||
sources:
|
sources:
|
||||||
- id: trunk
|
- id: trunk
|
||||||
ref: v1.4.4
|
ref: v1.5.0
|
||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- trufflehog@3.68.5
|
- trufflehog@3.76.3
|
||||||
- yamllint@1.35.1
|
- yamllint@1.35.1
|
||||||
- bandit@1.7.7
|
- bandit@1.7.8
|
||||||
- checkov@3.2.32
|
- checkov@3.2.95
|
||||||
- terrascan@1.19.1
|
- terrascan@1.19.1
|
||||||
- trivy@0.49.1
|
- trivy@0.51.1
|
||||||
#- trufflehog@3.63.2-rc0
|
#- trufflehog@3.63.2-rc0
|
||||||
- taplo@0.8.1
|
- taplo@0.8.1
|
||||||
- ruff@0.3.1
|
- ruff@0.4.4
|
||||||
- isort@5.13.2
|
- isort@5.13.2
|
||||||
- markdownlint@0.39.0
|
- markdownlint@0.40.0
|
||||||
- oxipng@9.0.0
|
- oxipng@9.1.1
|
||||||
- svgo@3.2.0
|
- svgo@3.3.2
|
||||||
- actionlint@1.6.27
|
- actionlint@1.7.0
|
||||||
- flake8@7.0.0
|
- flake8@7.0.0
|
||||||
- hadolint@2.12.0
|
- hadolint@2.12.0
|
||||||
- shfmt@3.6.0
|
- shfmt@3.6.0
|
||||||
- shellcheck@0.9.0
|
- shellcheck@0.10.0
|
||||||
- black@24.2.0
|
- black@24.4.2
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.18.2
|
- gitleaks@8.18.2
|
||||||
- clang-format@16.0.3
|
- clang-format@16.0.3
|
||||||
- prettier@3.2.5
|
- prettier@3.2.5
|
||||||
|
ignore:
|
||||||
|
- linters: [ALL]
|
||||||
|
paths:
|
||||||
|
- bin/**
|
||||||
runtimes:
|
runtimes:
|
||||||
enabled:
|
enabled:
|
||||||
- python@3.10.8
|
- python@3.10.8
|
||||||
|
|||||||
4
.vscode/extensions.json
vendored
4
.vscode/extensions.json
vendored
@@ -2,8 +2,8 @@
|
|||||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||||
// for the documentation about the extensions.json format
|
// for the documentation about the extensions.json format
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"ms-vscode.cpptools",
|
"ms-vscode.cpptools",
|
||||||
"platformio.platformio-ide",
|
"platformio.platformio-ide",
|
||||||
"trunk.io"
|
"trunk.io"
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -3,5 +3,9 @@
|
|||||||
"editor.defaultFormatter": "trunk.io",
|
"editor.defaultFormatter": "trunk.io",
|
||||||
"trunk.enableWindows": true,
|
"trunk.enableWindows": true,
|
||||||
"files.insertFinalNewline": false,
|
"files.insertFinalNewline": false,
|
||||||
"files.trimFinalNewlines": false
|
"files.trimFinalNewlines": false,
|
||||||
|
"cmake.configureOnOpen": false,
|
||||||
|
"[cpp]": {
|
||||||
|
"editor.defaultFormatter": "trunk.io"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,6 @@ ENV TZ=Etc/UTC
|
|||||||
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
|
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
|
||||||
ENV LANG C.UTF-8
|
ENV LANG C.UTF-8
|
||||||
|
|
||||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|
||||||
|
|
||||||
# Install build deps
|
# Install build deps
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
@@ -24,10 +22,10 @@ USER mesh
|
|||||||
|
|
||||||
WORKDIR /tmp/firmware
|
WORKDIR /tmp/firmware
|
||||||
RUN python3 -m venv /tmp/firmware
|
RUN python3 -m venv /tmp/firmware
|
||||||
RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14
|
RUN bash -o pipefail -c "source bin/activate; pip3 install --no-cache-dir -U platformio==6.1.15"
|
||||||
# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
|
# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
|
||||||
COPY --chown=mesh:mesh . /tmp/firmware
|
COPY --chown=mesh:mesh . /tmp/firmware
|
||||||
RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh
|
RUN bash -o pipefail -c "source ./bin/activate && bash ./bin/build-native.sh"
|
||||||
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||||
|
|
||||||
|
|
||||||
@@ -48,6 +46,7 @@ USER mesh
|
|||||||
WORKDIR /home/mesh
|
WORKDIR /home/mesh
|
||||||
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
|
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
|
||||||
|
|
||||||
|
RUN mkdir data
|
||||||
VOLUME /home/mesh/data
|
VOLUME /home/mesh/data
|
||||||
|
|
||||||
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
|
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||||
[esp32_base]
|
[esp32_base]
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform = platformio/espressif32@6.3.2 # This is a temporary fix to the S3-based devices bluetooth issues until we can determine what within ESP-IDF changed and can develop a suitable patch.
|
custom_esp32_kind = esp32
|
||||||
|
platform = platformio/espressif32@6.7.0
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
||||||
@@ -15,8 +16,10 @@ board_build.filesystem = littlefs
|
|||||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||||
|
build_unflags = -fno-lto
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
|
-flto
|
||||||
-Wall
|
-Wall
|
||||||
-Wextra
|
-Wextra
|
||||||
-Isrc/platform/esp32
|
-Isrc/platform/esp32
|
||||||
@@ -41,10 +44,11 @@ lib_deps =
|
|||||||
${networking_base.lib_deps}
|
${networking_base.lib_deps}
|
||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||||
h2zero/NimBLE-Arduino@^1.4.1
|
h2zero/NimBLE-Arduino@^1.4.2
|
||||||
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
https://github.com/dbSuS/libpax.git#7bcd3fcab75037505be9b122ab2b24cc5176b587
|
||||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||||
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
https://github.com/meshtastic/ESP32_Codec2.git#633326c78ac251c059ab3a8c430fcdf25b41672f
|
||||||
|
rweather/Crypto@^0.4.0
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
segger_rtt
|
segger_rtt
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[esp32c3_base]
|
[esp32c3_base]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
custom_esp32_kind = esp32c3
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
monitor_filters = esp32_c3_exception_decoder
|
monitor_filters = esp32_c3_exception_decoder
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[esp32s2_base]
|
[esp32s2_base]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
custom_esp32_kind = esp32s2
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${esp32_base.build_src_filter} - <libpax/> -<nimble/> -<mesh/raspihttp>
|
${esp32_base.build_src_filter} - <libpax/> -<nimble/> -<mesh/raspihttp>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
[esp32s3_base]
|
[esp32s3_base]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
custom_esp32_kind = esp32s3
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
|||||||
208
arch/nrf52/cpp_overrides/lfs_util.h
Normal file
208
arch/nrf52/cpp_overrides/lfs_util.h
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
/*
|
||||||
|
* lfs utility functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// MESHTASTIC/@geeksville note: This file is copied from the Adafruit nrf52 arduino lib. And we use a special -include in
|
||||||
|
// nrf52.ini to load it before EVERY file we do this hack because the default definitions for LFS_ASSERT are quite poor and we
|
||||||
|
// don't want to fork the adafruit lib (again) and send in a PR that they probably won't merge anyways. This file might break if
|
||||||
|
// they ever update lfs.util on their side, in which case we'll need to update this file to match their new version. The version
|
||||||
|
// this is a copy from is almost exactly
|
||||||
|
// https://github.com/adafruit/Adafruit_nRF52_Arduino/blob/c25d93268a3b9c23e9a1ccfcaf9b208beca624ca/libraries/Adafruit_LittleFS/src/littlefs/lfs_util.h
|
||||||
|
|
||||||
|
#ifndef LFS_UTIL_H
|
||||||
|
#define LFS_UTIL_H
|
||||||
|
|
||||||
|
// Users can override lfs_util.h with their own configuration by defining
|
||||||
|
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
||||||
|
//
|
||||||
|
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
||||||
|
// provided by the config file. To start I would suggest copying lfs_util.h and
|
||||||
|
// modifying as needed.
|
||||||
|
#ifdef LFS_CONFIG
|
||||||
|
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
||||||
|
#define LFS_STRINGIZE2(x) #x
|
||||||
|
#include LFS_STRINGIZE(LFS_CONFIG)
|
||||||
|
#else
|
||||||
|
|
||||||
|
// System includes
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#endif
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#include <assert.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LFS_NO_DEBUG) || !defined(LFS_NO_WARN) || !defined(LFS_NO_ERROR)
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||||
|
// macros must not have side-effects as the macros can be removed for a smaller
|
||||||
|
// code footprint
|
||||||
|
|
||||||
|
// Logging functions
|
||||||
|
#ifndef LFS_NO_DEBUG
|
||||||
|
|
||||||
|
void logLegacy(const char *level, const char *fmt, ...);
|
||||||
|
#define LFS_DEBUG(fmt, ...) logLegacy("DEBUG", "lfs debug:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_DEBUG(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_WARN
|
||||||
|
#define LFS_WARN(fmt, ...) logLegacy("WARN", "lfs warn:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_WARN(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LFS_NO_ERROR
|
||||||
|
#define LFS_ERROR(fmt, ...) logLegacy("ERROR", "lfs error:%d: " fmt "\n", __LINE__, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LFS_ERROR(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Runtime assertions
|
||||||
|
#ifndef LFS_NO_ASSERT
|
||||||
|
#define LFS_ASSERT(test) assert(test)
|
||||||
|
#else
|
||||||
|
extern void lfs_assert(const char *reason);
|
||||||
|
#define LFS_ASSERT(test) \
|
||||||
|
if (!(test)) \
|
||||||
|
lfs_assert(#test)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Builtin functions, these may be replaced by more efficient
|
||||||
|
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||||
|
// expensive basic C implementation for debugging purposes
|
||||||
|
|
||||||
|
// Min/max functions for unsigned 32-bit numbers
|
||||||
|
static inline uint32_t lfs_max(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t lfs_min(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (a < b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the next smallest power of 2 less than or equal to a
|
||||||
|
static inline uint32_t lfs_npw2(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
|
return 32 - __builtin_clz(a - 1);
|
||||||
|
#else
|
||||||
|
uint32_t r = 0;
|
||||||
|
uint32_t s;
|
||||||
|
a -= 1;
|
||||||
|
s = (a > 0xffff) << 4;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0xff) << 3;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0xf) << 2;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
s = (a > 0x3) << 1;
|
||||||
|
a >>= s;
|
||||||
|
r |= s;
|
||||||
|
return (r | (a >> 1)) + 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of trailing binary zeros in a
|
||||||
|
// lfs_ctz(0) may be undefined
|
||||||
|
static inline uint32_t lfs_ctz(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||||
|
return __builtin_ctz(a);
|
||||||
|
#else
|
||||||
|
return lfs_npw2((a & -a) + 1) - 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of binary ones in a
|
||||||
|
static inline uint32_t lfs_popc(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||||
|
return __builtin_popcount(a);
|
||||||
|
#else
|
||||||
|
a = a - ((a >> 1) & 0x55555555);
|
||||||
|
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||||
|
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the sequence comparison of a and b, this is the distance
|
||||||
|
// between a and b ignoring overflow
|
||||||
|
static inline int lfs_scmp(uint32_t a, uint32_t b)
|
||||||
|
{
|
||||||
|
return (int)(unsigned)(a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from 32-bit little-endian to native order
|
||||||
|
static inline uint32_t lfs_fromle32(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(LFS_NO_INTRINSICS) && ((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_LITTLE_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||||
|
return a;
|
||||||
|
#elif !defined(LFS_NO_INTRINSICS) && \
|
||||||
|
((defined(BYTE_ORDER) && BYTE_ORDER == ORDER_BIG_ENDIAN) || (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
|
return __builtin_bswap32(a);
|
||||||
|
#else
|
||||||
|
return (((uint8_t *)&a)[0] << 0) | (((uint8_t *)&a)[1] << 8) | (((uint8_t *)&a)[2] << 16) | (((uint8_t *)&a)[3] << 24);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to 32-bit little-endian from native order
|
||||||
|
static inline uint32_t lfs_tole32(uint32_t a)
|
||||||
|
{
|
||||||
|
return lfs_fromle32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||||
|
void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
|
||||||
|
|
||||||
|
// Allocate memory, only used if buffers are not provided to littlefs
|
||||||
|
static inline void *lfs_malloc(size_t size)
|
||||||
|
{
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
extern void *pvPortMalloc(size_t xWantedSize);
|
||||||
|
return pvPortMalloc(size);
|
||||||
|
#else
|
||||||
|
(void)size;
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||||
|
static inline void lfs_free(void *p)
|
||||||
|
{
|
||||||
|
#ifndef LFS_NO_MALLOC
|
||||||
|
extern void vPortFree(void *pv);
|
||||||
|
vPortFree(p);
|
||||||
|
#else
|
||||||
|
(void)p;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
@@ -1,20 +1,26 @@
|
|||||||
[nrf52_base]
|
[nrf52_base]
|
||||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||||
platform = platformio/nordicnrf52@^10.4.0
|
platform = platformio/nordicnrf52@^10.5.0
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
|
platform_packages =
|
||||||
|
; our custom Git version until they merge our PR
|
||||||
|
framework-arduinoadafruitnrf52 @ https://github.com/geeksville/Adafruit_nRF52_Arduino.git
|
||||||
|
|
||||||
build_type = debug ; I'm debugging with ICE a lot now
|
build_type = debug
|
||||||
build_flags =
|
build_flags =
|
||||||
|
-include arch/nrf52/cpp_overrides/lfs_util.h
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
-DSERIAL_BUFFER_SIZE=1024
|
-DSERIAL_BUFFER_SIZE=1024
|
||||||
-Wno-unused-variable
|
-Wno-unused-variable
|
||||||
-Isrc/platform/nrf52
|
-Isrc/platform/nrf52
|
||||||
|
-DLFS_NO_ASSERT ; Disable LFS assertions , see https://github.com/meshtastic/firmware/pull/3818
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
||||||
|
|
||||||
lib_deps=
|
lib_deps=
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
|
rweather/Crypto@^0.4.0
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
||||||
@@ -7,3 +7,72 @@ lib_deps =
|
|||||||
${nrf52_base.lib_deps}
|
${nrf52_base.lib_deps}
|
||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
|
https://github.com/Kongduino/Adafruit_nRFCrypto.git#e31a8825ea3300b163a0a3c1ddd5de34e10e1371
|
||||||
|
|
||||||
|
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
|
||||||
|
|
||||||
|
; We want the initial breakpoint at setup() instead of main(). Also we want to enable semihosting at that point so instead of
|
||||||
|
debug_init_break = tbreak setup
|
||||||
|
; we just turn off the platformio tbreak and do it in .gdbinit (where we have more flexibility for scripting)
|
||||||
|
; also we use a permanent breakpoint so it gets reused each time we restart the debugging session?
|
||||||
|
; debug_init_break = tbreak main
|
||||||
|
|
||||||
|
; Note: add "monitor arm semihosting_redirect tcp 4444 all" if you want the stdout from the device to go to that port number instead
|
||||||
|
; (for use by meshtastic command line)
|
||||||
|
; monitor arm semihosting disable
|
||||||
|
; monitor debug_level 3
|
||||||
|
;
|
||||||
|
; IMPORTANT: fileio must be disabled before using port 5555 - openocd ver 0.12 has a bug where if enabled it never properly parses the special :tt name
|
||||||
|
; for stdio access.
|
||||||
|
; monitor arm semihosting_redirect tcp 5555 stdio
|
||||||
|
|
||||||
|
; Also note: it is _impossible_ to do non blocking reads on the semihost console port (an oversight when ARM specified the semihost API).
|
||||||
|
; So we'll neve be able to general purpose bi-directional communication with the device over semihosting.
|
||||||
|
debug_extra_cmds =
|
||||||
|
echo Running .gdbinit script
|
||||||
|
;monitor arm semihosting enable
|
||||||
|
;monitor arm semihosting_fileio enable
|
||||||
|
;monitor arm semihosting_redirect disable
|
||||||
|
commands 1
|
||||||
|
; echo Breakpoint at setup() has semihosting console, connect to it with "telnet localhost 5555"
|
||||||
|
; set wantSemihost = 1
|
||||||
|
set useSoftDevice = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
; Only reprogram the board if the code has changed
|
||||||
|
debug_load_mode = modified
|
||||||
|
;debug_load_mode = manual
|
||||||
|
; We default to the stlink adapter because it is very cheap and works well, though others (such as jlink) are also supported.
|
||||||
|
;debug_tool = jlink
|
||||||
|
debug_tool = stlink
|
||||||
|
debug_speed = 4000
|
||||||
|
;debug_tool = custom
|
||||||
|
; debug_server =
|
||||||
|
; openocd
|
||||||
|
; -f
|
||||||
|
; /usr/local/share/openocd/scripts/interface/stlink.cfg
|
||||||
|
; -f
|
||||||
|
; /usr/local/share/openocd/scripts/target/nrf52.cfg
|
||||||
|
; $PLATFORMIO_CORE_DIR/packages/tool-openocd/openocd/scripts/interface/cmsis-dap.cfg
|
||||||
|
|
||||||
|
; Allows programming and debug via the RAK NanoDAP as the default debugger tool for the RAK4631 (it is only $10!)
|
||||||
|
; programming time is about the same as the bootloader version.
|
||||||
|
; For information on this see the meshtastic developers documentation for "Development on the NRF52"
|
||||||
|
; We manually pass in the elf file so that pyocd can reverse engineer FreeRTOS data (running threads, etc...)
|
||||||
|
;debug_server =
|
||||||
|
; pyocd
|
||||||
|
; gdbserver
|
||||||
|
; -j
|
||||||
|
; ${platformio.workspace_dir}/..
|
||||||
|
; -t
|
||||||
|
; nrf52840
|
||||||
|
; --semihosting
|
||||||
|
; --elf
|
||||||
|
; ${platformio.build_dir}/${this.__env__}/firmware.elf
|
||||||
|
|
||||||
|
; If you want to debug the semihosting support you can turn on extra logging in pyocd with
|
||||||
|
; -L
|
||||||
|
; pyocd.debug.semihost.trace=debug
|
||||||
|
|
||||||
|
; The following is not needed because it automatically tries do this
|
||||||
|
;debug_server_ready_pattern = -.*GDB server started on port \d+.*
|
||||||
|
;debug_port = localhost:3333
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||||
[portduino_base]
|
[portduino_base]
|
||||||
platform = https://github.com/meshtastic/platform-native.git#9881bf3721d610cccacf5ae8e3a07839cce75d63
|
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
|
|||||||
37
arch/stm32/stm32.ini
Normal file
37
arch/stm32/stm32.ini
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[stm32_base]
|
||||||
|
extends = arduino_base
|
||||||
|
platform = ststm32
|
||||||
|
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32.git#361a7fdb67e2a7104e99b4f42a802469eef8b129
|
||||||
|
|
||||||
|
build_type = release
|
||||||
|
|
||||||
|
;board_build.flash_offset = 0x08000000
|
||||||
|
|
||||||
|
build_flags =
|
||||||
|
${arduino_base.build_flags}
|
||||||
|
-flto
|
||||||
|
-Isrc/platform/stm32wl -g
|
||||||
|
-DMESHTASTIC_MINIMIZE_BUILD
|
||||||
|
-DMESHTASTIC_EXCLUDE_GPS
|
||||||
|
-DDEBUG_MUTE
|
||||||
|
; -DVECT_TAB_OFFSET=0x08000000
|
||||||
|
-DconfigUSE_CMSIS_RTOS_V2=1
|
||||||
|
; -DSPI_MODE_0=SPI_MODE0
|
||||||
|
-fmerge-all-constants
|
||||||
|
-ffunction-sections
|
||||||
|
-fdata-sections
|
||||||
|
|
||||||
|
build_src_filter =
|
||||||
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
|
||||||
|
|
||||||
|
board_upload.offset_address = 0x08000000
|
||||||
|
upload_protocol = stlink
|
||||||
|
|
||||||
|
lib_deps =
|
||||||
|
${env.lib_deps}
|
||||||
|
charlesbaynham/OSFS@^1.2.3
|
||||||
|
https://github.com/caveman99/Crypto.git#f61ae26a53f7a2d0ba5511625b8bf8eff3a35d5e
|
||||||
|
|
||||||
|
lib_ignore =
|
||||||
|
https://github.com/mathertel/OneButton@~2.6.1
|
||||||
|
Wire
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
[stm32wl5e_base]
|
|
||||||
platform_packages = platformio/framework-arduinoststm32 @ https://github.com/stm32duino/Arduino_Core_STM32.git#6e3f9910d0122e82a6c3438507dfac3d2fd80a39
|
|
||||||
platform = ststm32
|
|
||||||
board = generic_wl5e
|
|
||||||
framework = arduino
|
|
||||||
|
|
||||||
build_type = debug
|
|
||||||
|
|
||||||
build_flags =
|
|
||||||
${arduino_base.build_flags}
|
|
||||||
-Isrc/platform/stm32wl -g
|
|
||||||
-DconfigUSE_CMSIS_RTOS_V2=1
|
|
||||||
-DVECT_TAB_OFFSET=0x08000000
|
|
||||||
|
|
||||||
build_src_filter =
|
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040> -<mesh/raspihttp>
|
|
||||||
|
|
||||||
board_upload.offset_address = 0x08000000
|
|
||||||
upload_protocol = stlink
|
|
||||||
|
|
||||||
lib_deps =
|
|
||||||
${env.lib_deps}
|
|
||||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
|
||||||
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
|
||||||
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
|
||||||
|
|
||||||
lib_ignore =
|
|
||||||
mathertel/OneButton
|
|
||||||
@@ -11,7 +11,7 @@ rm -f $OUTDIR/firmware*
|
|||||||
rm -r $OUTDIR/* || true
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
platformio pkg update
|
platformio pkg update -e $1
|
||||||
|
|
||||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||||
rm -f .pio/build/$1/firmware.*
|
rm -f .pio/build/$1/firmware.*
|
||||||
|
|||||||
@@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
platformioFailed() {
|
||||||
|
[[ $VIRTUAL_ENV != "" ]] && exit 1 # don't hint at virtualenv if it's already in use
|
||||||
|
echo -e "\nThere were issues running platformio and you are not using a virtual environment." \
|
||||||
|
"\nYou may try setting up virtualenv and downloading the latest platformio from pip:" \
|
||||||
|
"\n\tvirtualenv venv" \
|
||||||
|
"\n\tsource venv/bin/activate" \
|
||||||
|
"\n\tpip install platformio" \
|
||||||
|
"\n\t./bin/build-native.sh # retry building"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
VERSION=$(bin/buildinfo.py long)
|
VERSION=$(bin/buildinfo.py long)
|
||||||
SHORT_VERSION=$(bin/buildinfo.py short)
|
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||||
|
|
||||||
@@ -13,8 +24,8 @@ mkdir -p $OUTDIR/
|
|||||||
rm -r $OUTDIR/* || true
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
platformio pkg update --environment native
|
platformio pkg update --environment native || platformioFailed
|
||||||
pio run --environment native
|
pio run --environment native || platformioFailed
|
||||||
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||||
cp bin/device-install.* $OUTDIR
|
cp bin/device-install.* $OUTDIR
|
||||||
cp bin/device-update.* $OUTDIR
|
cp bin/device-update.* $OUTDIR
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
VERSION=`bin/buildinfo.py long`
|
VERSION=$(bin/buildinfo.py long)
|
||||||
SHORT_VERSION=`bin/buildinfo.py short`
|
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||||
|
|
||||||
OUTDIR=release/
|
OUTDIR=release/
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ rm -f $OUTDIR/firmware*
|
|||||||
rm -r $OUTDIR/* || true
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
platformio pkg update
|
platformio pkg update -e $1
|
||||||
|
|
||||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||||
rm -f .pio/build/$1/firmware.*
|
rm -f .pio/build/$1/firmware.*
|
||||||
@@ -23,14 +23,26 @@ basename=firmware-$1-$VERSION
|
|||||||
|
|
||||||
pio run --environment $1 # -v
|
pio run --environment $1 # -v
|
||||||
SRCELF=.pio/build/$1/firmware.elf
|
SRCELF=.pio/build/$1/firmware.elf
|
||||||
DFUPKG=.pio/build/$1/firmware.zip
|
|
||||||
cp $SRCELF $OUTDIR/$basename.elf
|
cp $SRCELF $OUTDIR/$basename.elf
|
||||||
|
|
||||||
|
echo "Generating NRF52 dfu file"
|
||||||
|
DFUPKG=.pio/build/$1/firmware.zip
|
||||||
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
cp $DFUPKG $OUTDIR/$basename-ota.zip
|
||||||
|
|
||||||
echo "Generating NRF52 uf2 file"
|
echo "Generating NRF52 uf2 file"
|
||||||
SRCHEX=.pio/build/$1/firmware.hex
|
SRCHEX=.pio/build/$1/firmware.hex
|
||||||
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
|
|
||||||
|
|
||||||
cp bin/device-install.* $OUTDIR
|
# if WM1110 target, merge hex with softdevice 7.3.0
|
||||||
cp bin/device-update.* $OUTDIR
|
if (echo $1 | grep -q "wio-sdk-wm1110"); then
|
||||||
cp bin/*.uf2 $OUTDIR
|
echo "Merging with softdevice"
|
||||||
|
bin/mergehex -m bin/s140_nrf52_7.3.0_softdevice.hex $SRCHEX -o .pio/build/$1/$basename.hex
|
||||||
|
SRCHEX=.pio/build/$1/$basename.hex
|
||||||
|
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
|
||||||
|
cp $SRCHEX $OUTDIR
|
||||||
|
cp bin/*.uf2 $OUTDIR
|
||||||
|
else
|
||||||
|
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/$basename.uf2 -f 0xADA52840
|
||||||
|
cp bin/device-install.* $OUTDIR
|
||||||
|
cp bin/device-update.* $OUTDIR
|
||||||
|
cp bin/*.uf2 $OUTDIR
|
||||||
|
fi
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ rm -f $OUTDIR/firmware*
|
|||||||
rm -r $OUTDIR/* || true
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
platformio pkg update
|
platformio pkg update -e $1
|
||||||
|
|
||||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||||
rm -f .pio/build/$1/firmware.*
|
rm -f .pio/build/$1/firmware.*
|
||||||
|
|||||||
29
bin/build-stm32.sh
Executable file
29
bin/build-stm32.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
VERSION=$(bin/buildinfo.py long)
|
||||||
|
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||||
|
|
||||||
|
OUTDIR=release/
|
||||||
|
|
||||||
|
rm -f $OUTDIR/firmware*
|
||||||
|
rm -r $OUTDIR/* || true
|
||||||
|
|
||||||
|
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||||
|
platformio pkg update -e $1
|
||||||
|
|
||||||
|
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||||
|
rm -f .pio/build/$1/firmware.*
|
||||||
|
|
||||||
|
# The shell vars the build tool expects to find
|
||||||
|
export APP_VERSION=$VERSION
|
||||||
|
|
||||||
|
basename=firmware-$1-$VERSION
|
||||||
|
|
||||||
|
pio run --environment $1 # -v
|
||||||
|
SRCELF=.pio/build/$1/firmware.elf
|
||||||
|
cp $SRCELF $OUTDIR/$basename.elf
|
||||||
|
|
||||||
|
SRCBIN=.pio/build/$1/firmware.bin
|
||||||
|
cp $SRCBIN $OUTDIR/$basename.bin
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import configparser
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from readprops import readProps
|
from readprops import readProps
|
||||||
|
|
||||||
|
verObj = readProps("version.properties")
|
||||||
verObj = readProps('version.properties')
|
|
||||||
propName = sys.argv[1]
|
propName = sys.argv[1]
|
||||||
print(f"{verObj[propName]}")
|
print(f"{verObj[propName]}")
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ Lora:
|
|||||||
# TXen: x # TX and RX enable pins
|
# TXen: x # TX and RX enable pins
|
||||||
# RXen: x
|
# RXen: x
|
||||||
|
|
||||||
|
# ch341_quirk: true # Uncomment this to use the chunked SPI transfer that seems to fix the ch341
|
||||||
|
|
||||||
|
# spiSpeed: 2000000
|
||||||
|
|
||||||
### Set gpio chip to use in /dev/. Defaults to 0.
|
### Set gpio chip to use in /dev/. Defaults to 0.
|
||||||
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
|
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
|
||||||
# gpiochip: 4
|
# gpiochip: 4
|
||||||
@@ -109,6 +113,9 @@ Display:
|
|||||||
# Height: 320
|
# Height: 320
|
||||||
# Rotate: true
|
# Rotate: true
|
||||||
|
|
||||||
|
### You can also specify the spi device for the display to use
|
||||||
|
# spidev: spidev0.0
|
||||||
|
|
||||||
Touchscreen:
|
Touchscreen:
|
||||||
### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
|
### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
|
||||||
|
|
||||||
@@ -124,15 +131,21 @@ Touchscreen:
|
|||||||
# CS: 7
|
# CS: 7
|
||||||
# IRQ: 17
|
# IRQ: 17
|
||||||
|
|
||||||
### Configure device for direct keyboard input
|
### You can also specify the spi device for the touchscreen to use
|
||||||
|
# spidev: spidev0.0
|
||||||
|
|
||||||
|
|
||||||
Input:
|
Input:
|
||||||
|
### Configure device for direct keyboard input
|
||||||
|
|
||||||
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
|
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
Logging:
|
Logging:
|
||||||
LogLevel: info # debug, info, warn, error
|
LogLevel: info # debug, info, warn, error
|
||||||
|
# TraceFile: /var/log/meshtasticd.json
|
||||||
|
# AsciiLogs: true # default if not specified is !isatty() on stdout
|
||||||
|
|
||||||
Webserver:
|
Webserver:
|
||||||
# Port: 443 # Port for Webserver & Webservices
|
# Port: 443 # Port for Webserver & Webservices
|
||||||
@@ -140,3 +153,4 @@ Webserver:
|
|||||||
|
|
||||||
General:
|
General:
|
||||||
MaxNodes: 200
|
MaxNodes: 200
|
||||||
|
MaxMessageQueue: 100
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""Generate the CI matrix"""
|
"""Generate the CI matrix."""
|
||||||
|
|
||||||
import configparser
|
import configparser
|
||||||
import json
|
import json
|
||||||
@@ -34,5 +34,10 @@ for subdir, dirs, files in os.walk(rootdir):
|
|||||||
outlist.append(section)
|
outlist.append(section)
|
||||||
else:
|
else:
|
||||||
outlist.append(section)
|
outlist.append(section)
|
||||||
|
if "board_check" in config[config[c].name]:
|
||||||
|
if (config[config[c].name]["board_check"] == "true") & (
|
||||||
|
"check" in options
|
||||||
|
):
|
||||||
|
outlist.append(section)
|
||||||
|
|
||||||
print(json.dumps(outlist))
|
print(json.dumps(outlist))
|
||||||
|
|||||||
BIN
bin/mergehex
Executable file
BIN
bin/mergehex
Executable file
Binary file not shown.
@@ -1,13 +1,15 @@
|
|||||||
import subprocess
|
#!/usr/bin/env python3
|
||||||
import configparser
|
# trunk-ignore-all(ruff/F821)
|
||||||
import traceback
|
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||||
import sys
|
import sys
|
||||||
from os.path import join
|
from os.path import join
|
||||||
|
|
||||||
from readprops import readProps
|
from readprops import readProps
|
||||||
|
|
||||||
Import("env")
|
Import("env")
|
||||||
platform = env.PioPlatform()
|
platform = env.PioPlatform()
|
||||||
|
|
||||||
|
|
||||||
def esp32_create_combined_bin(source, target, env):
|
def esp32_create_combined_bin(source, target, env):
|
||||||
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
|
# this sub is borrowed from ESPEasy build toolchain. It's licensed under GPL V3
|
||||||
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
|
# https://github.com/letscontrolit/ESPEasy/blob/mega/tools/pio/post_esp32.py
|
||||||
@@ -20,8 +22,8 @@ def esp32_create_combined_bin(source, target, env):
|
|||||||
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
|
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
|
||||||
chip = env.get("BOARD_MCU")
|
chip = env.get("BOARD_MCU")
|
||||||
flash_size = env.BoardConfig().get("upload.flash_size")
|
flash_size = env.BoardConfig().get("upload.flash_size")
|
||||||
flash_freq = env.BoardConfig().get("build.f_flash", '40m')
|
flash_freq = env.BoardConfig().get("build.f_flash", "40m")
|
||||||
flash_freq = flash_freq.replace('000000L', 'm')
|
flash_freq = flash_freq.replace("000000L", "m")
|
||||||
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
|
flash_mode = env.BoardConfig().get("build.flash_mode", "dio")
|
||||||
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
|
memory_type = env.BoardConfig().get("build.arduino.memory_type", "qio_qspi")
|
||||||
if flash_mode == "qio" or flash_mode == "qout":
|
if flash_mode == "qio" or flash_mode == "qout":
|
||||||
@@ -51,23 +53,47 @@ def esp32_create_combined_bin(source, target, env):
|
|||||||
print(f" - {hex(app_offset)} | {firmware_name}")
|
print(f" - {hex(app_offset)} | {firmware_name}")
|
||||||
cmd += [hex(app_offset), firmware_name]
|
cmd += [hex(app_offset), firmware_name]
|
||||||
|
|
||||||
print('Using esptool.py arguments: %s' % ' '.join(cmd))
|
print("Using esptool.py arguments: %s" % " ".join(cmd))
|
||||||
|
|
||||||
esptool.main(cmd)
|
esptool.main(cmd)
|
||||||
|
|
||||||
if (platform.name == "espressif32"):
|
|
||||||
|
if platform.name == "espressif32":
|
||||||
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
|
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
|
||||||
import esptool
|
import esptool
|
||||||
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
|
|
||||||
|
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", esp32_create_combined_bin)
|
||||||
|
|
||||||
|
esp32_kind = env.GetProjectOption("custom_esp32_kind")
|
||||||
|
if esp32_kind == "esp32":
|
||||||
|
# Free up some IRAM by removing auxiliary SPI flash chip drivers.
|
||||||
|
# Wrapped stub symbols are defined in src/platform/esp32/iram-quirk.c.
|
||||||
|
env.Append(
|
||||||
|
LINKFLAGS=[
|
||||||
|
"-Wl,--wrap=esp_flash_chip_gd",
|
||||||
|
"-Wl,--wrap=esp_flash_chip_issi",
|
||||||
|
"-Wl,--wrap=esp_flash_chip_winbond",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# For newer ESP32 targets, using newlib nano works better.
|
||||||
|
env.Append(LINKFLAGS=["--specs=nano.specs", "-u", "_printf_float"])
|
||||||
|
|
||||||
|
if platform.name == "nordicnrf52":
|
||||||
|
env.AddPostAction("$BUILD_DIR/${PROGNAME}.hex",
|
||||||
|
env.VerboseAction(f"{sys.executable} ./bin/uf2conv.py $BUILD_DIR/firmware.hex -c -f 0xADA52840 -o $BUILD_DIR/firmware.uf2",
|
||||||
|
"Generating UF2 file"))
|
||||||
|
|
||||||
Import("projenv")
|
Import("projenv")
|
||||||
|
|
||||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||||
verObj = readProps(prefsLoc)
|
verObj = readProps(prefsLoc)
|
||||||
print("Using meshtastic platformio-custom.py, firmware version " + verObj['long'])
|
print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"])
|
||||||
|
|
||||||
# General options that are passed to the C and C++ compilers
|
# General options that are passed to the C and C++ compilers
|
||||||
projenv.Append(CCFLAGS=[
|
projenv.Append(
|
||||||
"-DAPP_VERSION=" + verObj['long'],
|
CCFLAGS=[
|
||||||
"-DAPP_VERSION_SHORT=" + verObj['short']
|
"-DAPP_VERSION=" + verObj["long"],
|
||||||
])
|
"-DAPP_VERSION_SHORT=" + verObj["short"],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import configparser
|
import configparser
|
||||||
import traceback
|
import subprocess
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def readProps(prefsLoc):
|
def readProps(prefsLoc):
|
||||||
@@ -11,27 +7,36 @@ def readProps(prefsLoc):
|
|||||||
|
|
||||||
config = configparser.RawConfigParser()
|
config = configparser.RawConfigParser()
|
||||||
config.read(prefsLoc)
|
config.read(prefsLoc)
|
||||||
version = dict(config.items('VERSION'))
|
version = dict(config.items("VERSION"))
|
||||||
verObj = dict(short = "{}.{}.{}".format(version["major"], version["minor"], version["build"]),
|
verObj = dict(
|
||||||
long = "unset")
|
short="{}.{}.{}".format(version["major"], version["minor"], version["build"]),
|
||||||
|
long="unset",
|
||||||
|
)
|
||||||
|
|
||||||
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
|
# Try to find current build SHA if if the workspace is clean. This could fail if git is not installed
|
||||||
try:
|
try:
|
||||||
sha = subprocess.check_output(
|
sha = (
|
||||||
['git', 'rev-parse', '--short', 'HEAD']).decode("utf-8").strip()
|
subprocess.check_output(["git", "rev-parse", "--short", "HEAD"])
|
||||||
isDirty = subprocess.check_output(
|
.decode("utf-8")
|
||||||
['git', 'diff', 'HEAD']).decode("utf-8").strip()
|
.strip()
|
||||||
|
)
|
||||||
|
isDirty = (
|
||||||
|
subprocess.check_output(["git", "diff", "HEAD"]).decode("utf-8").strip()
|
||||||
|
)
|
||||||
suffix = sha
|
suffix = sha
|
||||||
# if isDirty:
|
# if isDirty:
|
||||||
# # short for 'dirty', we want to keep our verstrings source for protobuf reasons
|
# # short for 'dirty', we want to keep our verstrings source for protobuf reasons
|
||||||
# suffix = sha + "-d"
|
# suffix = sha + "-d"
|
||||||
verObj['long'] = "{}.{}.{}.{}".format(
|
verObj["long"] = "{}.{}.{}.{}".format(
|
||||||
version["major"], version["minor"], version["build"], suffix)
|
version["major"], version["minor"], version["build"], suffix
|
||||||
|
)
|
||||||
except:
|
except:
|
||||||
# print("Unexpected error:", sys.exc_info()[0])
|
# print("Unexpected error:", sys.exc_info()[0])
|
||||||
# traceback.print_exc()
|
# traceback.print_exc()
|
||||||
verObj['long'] = verObj['short']
|
verObj["long"] = verObj["short"]
|
||||||
|
|
||||||
# print("firmware version " + verStr)
|
# print("firmware version " + verStr)
|
||||||
return verObj
|
return verObj
|
||||||
# print("path is" + ','.join(sys.path))
|
|
||||||
|
|
||||||
|
# print("path is" + ','.join(sys.path))
|
||||||
9726
bin/s140_nrf52_7.3.0_softdevice.hex
Normal file
9726
bin/s140_nrf52_7.3.0_softdevice.hex
Normal file
File diff suppressed because it is too large
Load Diff
12
bin/setup-python-for-esp-debug.sh
Normal file
12
bin/setup-python-for-esp-debug.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# shellcheck shell=bash
|
||||||
|
# (this minor script is actually shell agnostic, and is intended to be sourced rather than run in a subshell)
|
||||||
|
|
||||||
|
# This is a little script you can source if you want to make ESP debugging work on a modern (24.04) ubuntu machine
|
||||||
|
# It assumes you have built and installed python 2.7 from source with:
|
||||||
|
# ./configure --enable-optimizations --enable-shared --enable-unicode=ucs4
|
||||||
|
# sudo make clean
|
||||||
|
# make
|
||||||
|
# sudo make altinstall
|
||||||
|
|
||||||
|
export LD_LIBRARY_PATH=$HOME/packages/python-2.7.18/
|
||||||
|
export PYTHON_HOME=/usr/local/lib/python2.7/
|
||||||
223
bin/uf2conv.py
223
bin/uf2conv.py
@@ -1,39 +1,38 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys
|
import argparse
|
||||||
import struct
|
|
||||||
import subprocess
|
|
||||||
import re
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import argparse
|
import re
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
|
||||||
UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
|
UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
|
||||||
UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
|
UF2_MAGIC_END = 0x0AB16F30 # Ditto
|
||||||
UF2_MAGIC_END = 0x0AB16F30 # Ditto
|
|
||||||
|
|
||||||
families = {
|
families = {
|
||||||
'SAMD21': 0x68ed2b88,
|
"SAMD21": 0x68ED2B88,
|
||||||
'SAML21': 0x1851780a,
|
"SAML21": 0x1851780A,
|
||||||
'SAMD51': 0x55114460,
|
"SAMD51": 0x55114460,
|
||||||
'NRF52': 0x1b57745f,
|
"NRF52": 0x1B57745F,
|
||||||
'STM32F0': 0x647824b6,
|
"STM32F0": 0x647824B6,
|
||||||
'STM32F1': 0x5ee21072,
|
"STM32F1": 0x5EE21072,
|
||||||
'STM32F2': 0x5d1a0a2e,
|
"STM32F2": 0x5D1A0A2E,
|
||||||
'STM32F3': 0x6b846188,
|
"STM32F3": 0x6B846188,
|
||||||
'STM32F4': 0x57755a57,
|
"STM32F4": 0x57755A57,
|
||||||
'STM32F7': 0x53b80f00,
|
"STM32F7": 0x53B80F00,
|
||||||
'STM32G0': 0x300f5633,
|
"STM32G0": 0x300F5633,
|
||||||
'STM32G4': 0x4c71240a,
|
"STM32G4": 0x4C71240A,
|
||||||
'STM32H7': 0x6db66082,
|
"STM32H7": 0x6DB66082,
|
||||||
'STM32L0': 0x202e3a91,
|
"STM32L0": 0x202E3A91,
|
||||||
'STM32L1': 0x1e1f432d,
|
"STM32L1": 0x1E1F432D,
|
||||||
'STM32L4': 0x00ff6919,
|
"STM32L4": 0x00FF6919,
|
||||||
'STM32L5': 0x04240bdf,
|
"STM32L5": 0x04240BDF,
|
||||||
'STM32WB': 0x70d16653,
|
"STM32WB": 0x70D16653,
|
||||||
'STM32WL': 0x21460ff0,
|
"STM32WL": 0x21460FF0,
|
||||||
'ATMEGA32': 0x16573617,
|
"ATMEGA32": 0x16573617,
|
||||||
'MIMXRT10XX': 0x4FB2D5BD
|
"MIMXRT10XX": 0x4FB2D5BD,
|
||||||
}
|
}
|
||||||
|
|
||||||
INFO_FILE = "/INFO_UF2.TXT"
|
INFO_FILE = "/INFO_UF2.TXT"
|
||||||
@@ -46,15 +45,17 @@ def is_uf2(buf):
|
|||||||
w = struct.unpack("<II", buf[0:8])
|
w = struct.unpack("<II", buf[0:8])
|
||||||
return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1
|
return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1
|
||||||
|
|
||||||
|
|
||||||
def is_hex(buf):
|
def is_hex(buf):
|
||||||
try:
|
try:
|
||||||
w = buf[0:30].decode("utf-8")
|
w = buf[0:30].decode("utf-8")
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
return False
|
return False
|
||||||
if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf):
|
if w[0] == ":" and re.match(b"^[:0-9a-fA-F\r\n]+$", buf):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def convert_from_uf2(buf):
|
def convert_from_uf2(buf):
|
||||||
global appstartaddr
|
global appstartaddr
|
||||||
numblocks = len(buf) // 512
|
numblocks = len(buf) // 512
|
||||||
@@ -62,7 +63,7 @@ def convert_from_uf2(buf):
|
|||||||
outp = b""
|
outp = b""
|
||||||
for blockno in range(numblocks):
|
for blockno in range(numblocks):
|
||||||
ptr = blockno * 512
|
ptr = blockno * 512
|
||||||
block = buf[ptr:ptr + 512]
|
block = buf[ptr : ptr + 512]
|
||||||
hd = struct.unpack(b"<IIIIIIII", block[0:32])
|
hd = struct.unpack(b"<IIIIIIII", block[0:32])
|
||||||
if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
|
if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
|
||||||
print("Skipping block at " + ptr + "; bad magic")
|
print("Skipping block at " + ptr + "; bad magic")
|
||||||
@@ -80,7 +81,7 @@ def convert_from_uf2(buf):
|
|||||||
padding = newaddr - curraddr
|
padding = newaddr - curraddr
|
||||||
if padding < 0:
|
if padding < 0:
|
||||||
assert False, "Block out of order at " + ptr
|
assert False, "Block out of order at " + ptr
|
||||||
if padding > 10*1024*1024:
|
if padding > 10 * 1024 * 1024:
|
||||||
assert False, "More than 10M of padding needed at " + ptr
|
assert False, "More than 10M of padding needed at " + ptr
|
||||||
if padding % 4 != 0:
|
if padding % 4 != 0:
|
||||||
assert False, "Non-word padding size at " + ptr
|
assert False, "Non-word padding size at " + ptr
|
||||||
@@ -91,6 +92,7 @@ def convert_from_uf2(buf):
|
|||||||
curraddr = newaddr + datalen
|
curraddr = newaddr + datalen
|
||||||
return outp
|
return outp
|
||||||
|
|
||||||
|
|
||||||
def convert_to_carray(file_content):
|
def convert_to_carray(file_content):
|
||||||
outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {"
|
outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {"
|
||||||
for i in range(len(file_content)):
|
for i in range(len(file_content)):
|
||||||
@@ -100,6 +102,7 @@ def convert_to_carray(file_content):
|
|||||||
outp += "\n};\n"
|
outp += "\n};\n"
|
||||||
return outp
|
return outp
|
||||||
|
|
||||||
|
|
||||||
def convert_to_uf2(file_content):
|
def convert_to_uf2(file_content):
|
||||||
global familyid
|
global familyid
|
||||||
datapadding = b""
|
datapadding = b""
|
||||||
@@ -109,13 +112,21 @@ def convert_to_uf2(file_content):
|
|||||||
outp = b""
|
outp = b""
|
||||||
for blockno in range(numblocks):
|
for blockno in range(numblocks):
|
||||||
ptr = 256 * blockno
|
ptr = 256 * blockno
|
||||||
chunk = file_content[ptr:ptr + 256]
|
chunk = file_content[ptr : ptr + 256]
|
||||||
flags = 0x0
|
flags = 0x0
|
||||||
if familyid:
|
if familyid:
|
||||||
flags |= 0x2000
|
flags |= 0x2000
|
||||||
hd = struct.pack(b"<IIIIIIII",
|
hd = struct.pack(
|
||||||
UF2_MAGIC_START0, UF2_MAGIC_START1,
|
b"<IIIIIIII",
|
||||||
flags, ptr + appstartaddr, 256, blockno, numblocks, familyid)
|
UF2_MAGIC_START0,
|
||||||
|
UF2_MAGIC_START1,
|
||||||
|
flags,
|
||||||
|
ptr + appstartaddr,
|
||||||
|
256,
|
||||||
|
blockno,
|
||||||
|
numblocks,
|
||||||
|
familyid,
|
||||||
|
)
|
||||||
while len(chunk) < 256:
|
while len(chunk) < 256:
|
||||||
chunk += b"\x00"
|
chunk += b"\x00"
|
||||||
block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END)
|
block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END)
|
||||||
@@ -123,6 +134,7 @@ def convert_to_uf2(file_content):
|
|||||||
outp += block
|
outp += block
|
||||||
return outp
|
return outp
|
||||||
|
|
||||||
|
|
||||||
class Block:
|
class Block:
|
||||||
def __init__(self, addr):
|
def __init__(self, addr):
|
||||||
self.addr = addr
|
self.addr = addr
|
||||||
@@ -133,35 +145,44 @@ class Block:
|
|||||||
flags = 0x0
|
flags = 0x0
|
||||||
if familyid:
|
if familyid:
|
||||||
flags |= 0x2000
|
flags |= 0x2000
|
||||||
hd = struct.pack("<IIIIIIII",
|
hd = struct.pack(
|
||||||
UF2_MAGIC_START0, UF2_MAGIC_START1,
|
"<IIIIIIII",
|
||||||
flags, self.addr, 256, blockno, numblocks, familyid)
|
UF2_MAGIC_START0,
|
||||||
|
UF2_MAGIC_START1,
|
||||||
|
flags,
|
||||||
|
self.addr,
|
||||||
|
256,
|
||||||
|
blockno,
|
||||||
|
numblocks,
|
||||||
|
familyid,
|
||||||
|
)
|
||||||
hd += self.bytes[0:256]
|
hd += self.bytes[0:256]
|
||||||
while len(hd) < 512 - 4:
|
while len(hd) < 512 - 4:
|
||||||
hd += b"\x00"
|
hd += b"\x00"
|
||||||
hd += struct.pack("<I", UF2_MAGIC_END)
|
hd += struct.pack("<I", UF2_MAGIC_END)
|
||||||
return hd
|
return hd
|
||||||
|
|
||||||
|
|
||||||
def convert_from_hex_to_uf2(buf):
|
def convert_from_hex_to_uf2(buf):
|
||||||
global appstartaddr
|
global appstartaddr
|
||||||
appstartaddr = None
|
appstartaddr = None
|
||||||
upper = 0
|
upper = 0
|
||||||
currblock = None
|
currblock = None
|
||||||
blocks = []
|
blocks = []
|
||||||
for line in buf.split('\n'):
|
for line in buf.split("\n"):
|
||||||
if line[0] != ":":
|
if line[0] != ":":
|
||||||
continue
|
continue
|
||||||
i = 1
|
i = 1
|
||||||
rec = []
|
rec = []
|
||||||
while i < len(line) - 1:
|
while i < len(line) - 1:
|
||||||
rec.append(int(line[i:i+2], 16))
|
rec.append(int(line[i : i + 2], 16))
|
||||||
i += 2
|
i += 2
|
||||||
tp = rec[3]
|
tp = rec[3]
|
||||||
if tp == 4:
|
if tp == 4:
|
||||||
upper = ((rec[4] << 8) | rec[5]) << 16
|
upper = ((rec[4] << 8) | rec[5]) << 16
|
||||||
elif tp == 2:
|
elif tp == 2:
|
||||||
upper = ((rec[4] << 8) | rec[5]) << 4
|
upper = ((rec[4] << 8) | rec[5]) << 4
|
||||||
assert (upper & 0xffff) == 0
|
assert (upper & 0xFFFF) == 0
|
||||||
elif tp == 1:
|
elif tp == 1:
|
||||||
break
|
break
|
||||||
elif tp == 0:
|
elif tp == 0:
|
||||||
@@ -170,10 +191,10 @@ def convert_from_hex_to_uf2(buf):
|
|||||||
appstartaddr = addr
|
appstartaddr = addr
|
||||||
i = 4
|
i = 4
|
||||||
while i < len(rec) - 1:
|
while i < len(rec) - 1:
|
||||||
if not currblock or currblock.addr & ~0xff != addr & ~0xff:
|
if not currblock or currblock.addr & ~0xFF != addr & ~0xFF:
|
||||||
currblock = Block(addr & ~0xff)
|
currblock = Block(addr & ~0xFF)
|
||||||
blocks.append(currblock)
|
blocks.append(currblock)
|
||||||
currblock.bytes[addr & 0xff] = rec[i]
|
currblock.bytes[addr & 0xFF] = rec[i]
|
||||||
addr += 1
|
addr += 1
|
||||||
i += 1
|
i += 1
|
||||||
numblocks = len(blocks)
|
numblocks = len(blocks)
|
||||||
@@ -182,17 +203,28 @@ def convert_from_hex_to_uf2(buf):
|
|||||||
resfile += blocks[i].encode(i, numblocks)
|
resfile += blocks[i].encode(i, numblocks)
|
||||||
return resfile
|
return resfile
|
||||||
|
|
||||||
|
|
||||||
def to_str(b):
|
def to_str(b):
|
||||||
return b.decode("utf-8")
|
return b.decode("utf-8")
|
||||||
|
|
||||||
|
|
||||||
def get_drives():
|
def get_drives():
|
||||||
drives = []
|
drives = []
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
r = subprocess.check_output(["wmic", "PATH", "Win32_LogicalDisk",
|
r = subprocess.check_output(
|
||||||
"get", "DeviceID,", "VolumeName,",
|
[
|
||||||
"FileSystem,", "DriveType"])
|
"wmic",
|
||||||
for line in to_str(r).split('\n'):
|
"PATH",
|
||||||
words = re.split('\s+', line)
|
"Win32_LogicalDisk",
|
||||||
|
"get",
|
||||||
|
"DeviceID,",
|
||||||
|
"VolumeName,",
|
||||||
|
"FileSystem,",
|
||||||
|
"DriveType",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
for line in to_str(r).split("\n"):
|
||||||
|
words = re.split("\\s+", line)
|
||||||
if len(words) >= 3 and words[1] == "2" and words[2] == "FAT":
|
if len(words) >= 3 and words[1] == "2" and words[2] == "FAT":
|
||||||
drives.append(words[0])
|
drives.append(words[0])
|
||||||
else:
|
else:
|
||||||
@@ -206,7 +238,6 @@ def get_drives():
|
|||||||
for d in os.listdir(rootpath):
|
for d in os.listdir(rootpath):
|
||||||
drives.append(os.path.join(rootpath, d))
|
drives.append(os.path.join(rootpath, d))
|
||||||
|
|
||||||
|
|
||||||
def has_info(d):
|
def has_info(d):
|
||||||
try:
|
try:
|
||||||
return os.path.isfile(d + INFO_FILE)
|
return os.path.isfile(d + INFO_FILE)
|
||||||
@@ -217,7 +248,7 @@ def get_drives():
|
|||||||
|
|
||||||
|
|
||||||
def board_id(path):
|
def board_id(path):
|
||||||
with open(path + INFO_FILE, mode='r') as file:
|
with open(path + INFO_FILE, mode="r") as file:
|
||||||
file_content = file.read()
|
file_content = file.read()
|
||||||
return re.search("Board-ID: ([^\r\n]*)", file_content).group(1)
|
return re.search("Board-ID: ([^\r\n]*)", file_content).group(1)
|
||||||
|
|
||||||
@@ -235,30 +266,61 @@ def write_file(name, buf):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
global appstartaddr, familyid
|
global appstartaddr, familyid
|
||||||
|
|
||||||
def error(msg):
|
def error(msg):
|
||||||
print(msg)
|
print(msg)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.')
|
|
||||||
parser.add_argument('input', metavar='INPUT', type=str, nargs='?',
|
parser = argparse.ArgumentParser(description="Convert to UF2 or flash directly.")
|
||||||
help='input file (HEX, BIN or UF2)')
|
parser.add_argument(
|
||||||
parser.add_argument('-b' , '--base', dest='base', type=str,
|
"input",
|
||||||
default="0x2000",
|
metavar="INPUT",
|
||||||
help='set base address of application for BIN format (default: 0x2000)')
|
type=str,
|
||||||
parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str,
|
nargs="?",
|
||||||
help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible')
|
help="input file (HEX, BIN or UF2)",
|
||||||
parser.add_argument('-d' , '--device', dest="device_path",
|
)
|
||||||
help='select a device path to flash')
|
parser.add_argument(
|
||||||
parser.add_argument('-l' , '--list', action='store_true',
|
"-b",
|
||||||
help='list connected devices')
|
"--base",
|
||||||
parser.add_argument('-c' , '--convert', action='store_true',
|
dest="base",
|
||||||
help='do not flash, just convert')
|
type=str,
|
||||||
parser.add_argument('-D' , '--deploy', action='store_true',
|
default="0x2000",
|
||||||
help='just flash, do not convert')
|
help="set base address of application for BIN format (default: 0x2000)",
|
||||||
parser.add_argument('-f' , '--family', dest='family', type=str,
|
)
|
||||||
default="0x0",
|
parser.add_argument(
|
||||||
help='specify familyID - number or name (default: 0x0)')
|
"-o",
|
||||||
parser.add_argument('-C' , '--carray', action='store_true',
|
"--output",
|
||||||
help='convert binary file to a C array, not UF2')
|
metavar="FILE",
|
||||||
|
dest="output",
|
||||||
|
type=str,
|
||||||
|
help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d", "--device", dest="device_path", help="select a device path to flash"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-l", "--list", action="store_true", help="list connected devices"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-c", "--convert", action="store_true", help="do not flash, just convert"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-D", "--deploy", action="store_true", help="just flash, do not convert"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--family",
|
||||||
|
dest="family",
|
||||||
|
type=str,
|
||||||
|
default="0x0",
|
||||||
|
help="specify familyID - number or name (default: 0x0)",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-C",
|
||||||
|
"--carray",
|
||||||
|
action="store_true",
|
||||||
|
help="convert binary file to a C array, not UF2",
|
||||||
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
appstartaddr = int(args.base, 0)
|
appstartaddr = int(args.base, 0)
|
||||||
|
|
||||||
@@ -268,14 +330,17 @@ def main():
|
|||||||
try:
|
try:
|
||||||
familyid = int(args.family, 0)
|
familyid = int(args.family, 0)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
error("Family ID needs to be a number or one of: " + ", ".join(families.keys()))
|
error(
|
||||||
|
"Family ID needs to be a number or one of: "
|
||||||
|
+ ", ".join(families.keys())
|
||||||
|
)
|
||||||
|
|
||||||
if args.list:
|
if args.list:
|
||||||
list_drives()
|
list_drives()
|
||||||
else:
|
else:
|
||||||
if not args.input:
|
if not args.input:
|
||||||
error("Need input file")
|
error("Need input file")
|
||||||
with open(args.input, mode='rb') as f:
|
with open(args.input, mode="rb") as f:
|
||||||
inpbuf = f.read()
|
inpbuf = f.read()
|
||||||
from_uf2 = is_uf2(inpbuf)
|
from_uf2 = is_uf2(inpbuf)
|
||||||
ext = "uf2"
|
ext = "uf2"
|
||||||
@@ -291,8 +356,10 @@ def main():
|
|||||||
ext = "h"
|
ext = "h"
|
||||||
else:
|
else:
|
||||||
outbuf = convert_to_uf2(inpbuf)
|
outbuf = convert_to_uf2(inpbuf)
|
||||||
print("Converting to %s, output size: %d, start address: 0x%x" %
|
print(
|
||||||
(ext, len(outbuf), appstartaddr))
|
"Converting to %s, output size: %d, start address: 0x%x"
|
||||||
|
% (ext, len(outbuf), appstartaddr)
|
||||||
|
)
|
||||||
if args.convert or ext != "uf2":
|
if args.convert or ext != "uf2":
|
||||||
drives = []
|
drives = []
|
||||||
if args.output == None:
|
if args.output == None:
|
||||||
|
|||||||
30
bin/wio_tracker_bootloader_update.bin
Normal file
30
bin/wio_tracker_bootloader_update.bin
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# tips from mark on how to replace the (broken) bootloader on the red wio_tracker_1110 boards.
|
||||||
|
|
||||||
|
~/.platformio/penv/bin/adafruit-nrfutil --verbose dfu serial --package wio_tracker_1110_bootloader-0.9.1_s140_7.3.0.zip -p /dev/ttyACM1 -b 115200 --singlebank --touch 1200
|
||||||
|
|
||||||
|
exit
|
||||||
|
|
||||||
|
# Output should look like
|
||||||
|
|
||||||
|
Upgrading target on /dev/ttyACM1 with DFU package /home/kevinh/development/meshtastic/WioWM1110/wio_tracker_1110_bootloader-0.9.1_s140_7.3.0.zip. Flow control is disabled, Single bank, Touch 1200
|
||||||
|
Touched serial port /dev/ttyACM1
|
||||||
|
Opened serial port /dev/ttyACM1
|
||||||
|
Starting DFU upgrade of type 3, SoftDevice size: 152728, bootloader size: 39000, application size: 0
|
||||||
|
Sending DFU start packet
|
||||||
|
Sending DFU init packet
|
||||||
|
Sending firmware file
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
########################################
|
||||||
|
###############
|
||||||
|
Activating new firmware
|
||||||
|
|
||||||
|
DFU upgrade took 20.242434978485107s
|
||||||
|
Device programmed.
|
||||||
|
|
||||||
53
boards/heltec_mesh_node_t114.json
Normal file
53
boards/heltec_mesh_node_t114.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x4405"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"]
|
||||||
|
],
|
||||||
|
"usb_product": "HT-n5262",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "heltec_mesh_node_t114",
|
||||||
|
"variants_dir": "variants",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"onboard_tools": ["jlink"],
|
||||||
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Heltec nrf (Adafruit BSP)",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "FIXME",
|
||||||
|
"vendor": "Heltec"
|
||||||
|
}
|
||||||
42
boards/heltec_vision_master_e213.json
Normal file
42
boards/heltec_vision_master_e213.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "default_8MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=0",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
["0x303A", "0x1001"],
|
||||||
|
["0x303A", "0x0002"]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "heltec_vision_master_e213"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "Heltec Vision Master E213",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://heltec.org/project/vision-master-e213/",
|
||||||
|
"vendor": "Heltec"
|
||||||
|
}
|
||||||
42
boards/heltec_vision_master_e290.json
Normal file
42
boards/heltec_vision_master_e290.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "default_8MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=0",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
["0x303A", "0x1001"],
|
||||||
|
["0x303A", "0x0002"]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "heltec_vision_master_e290"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "Heltec Vision Master E290",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://heltec.org/project/vision-master-e290/",
|
||||||
|
"vendor": "Heltec"
|
||||||
|
}
|
||||||
42
boards/heltec_vision_master_t190.json
Normal file
42
boards/heltec_vision_master_t190.json
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "default_8MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-DARDUINO_USB_MODE=0",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [
|
||||||
|
["0x303A", "0x1001"],
|
||||||
|
["0x303A", "0x0002"]
|
||||||
|
],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "heltec_vision_master_t190"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "Heltec Vision Master t190",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "8MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 8388608,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://heltec.org/project/vision-master-t190/",
|
||||||
|
"vendor": "Heltec"
|
||||||
|
}
|
||||||
58
boards/me25ls01-4y10td.json
Normal file
58
boards/me25ls01-4y10td.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v7.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "ME25LS01-BOOT",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "MINEWSEMI_ME25LS01",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "7.3.0",
|
||||||
|
"sd_fwid": "0x0123"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Minesemi ME25LS01",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink",
|
||||||
|
"cmsis-dap",
|
||||||
|
"blackmagic"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://en.minewsemi.com/lora-module/lr1110-nrf52840-me25LS01l",
|
||||||
|
"vendor": "Minesemi"
|
||||||
|
}
|
||||||
52
boards/promicro-nrf52840.json
Normal file
52
boards/promicro-nrf52840.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x00B3"],
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "ProMicro compatible nRF52840",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "promicro_diy",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "ProMicro compatible nRF52840",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": ["nrfutil", "jlink", "nrfjprog", "stlink"],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.nologo.tech/product/otherboard/NRF52840.html",
|
||||||
|
"vendor": "Nologo"
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
"-DBOARD_HAS_PSRAM",
|
"-DBOARD_HAS_PSRAM",
|
||||||
"-DLILYGO_TBEAM_S3_CORE",
|
"-DLILYGO_TBEAM_S3_CORE",
|
||||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
"-DARDUINO_USB_MODE=1",
|
"-DARDUINO_USB_MODE=0",
|
||||||
"-DARDUINO_RUNNING_CORE=1",
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
],
|
],
|
||||||
|
|||||||
58
boards/tracker-t1000-e.json
Normal file
58
boards/tracker-t1000-e.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v7.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "T1000-E-BOOT",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "Seeed_T1000-E",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "7.3.0",
|
||||||
|
"sd_fwid": "0x0123"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Seeed T1000-E",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink",
|
||||||
|
"cmsis-dap",
|
||||||
|
"blackmagic"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html",
|
||||||
|
"vendor": "Seeed Studio"
|
||||||
|
}
|
||||||
51
boards/wio-sdk-wm1110.json
Normal file
51
boards/wio-sdk-wm1110.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v7.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "Seeed_WIO_WM1110",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "7.3.0",
|
||||||
|
"sd_fwid": "0x0123"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "freertos"],
|
||||||
|
"name": "Seeed WIO WM1110",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink",
|
||||||
|
"cmsis-dap",
|
||||||
|
"blackmagic"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.seeedstudio.com/Wio-WM1110-Dev-Kit-p-5677.html",
|
||||||
|
"vendor": "Seeed Studio"
|
||||||
|
}
|
||||||
58
boards/wio-t1000-s.json
Normal file
58
boards/wio-t1000-s.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v7.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "WIO-BOOT",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "Seeed_WIO_WM1110",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "7.3.0",
|
||||||
|
"sd_fwid": "0x0123"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Seeed WIO WM1110",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink",
|
||||||
|
"cmsis-dap",
|
||||||
|
"blackmagic"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.seeedstudio.com/LoRaWAN-Tracker-c-1938.html",
|
||||||
|
"vendor": "Seeed Studio"
|
||||||
|
}
|
||||||
58
boards/wio-tracker-wm1110.json
Normal file
58
boards/wio-tracker-wm1110.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v7.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_WIO_WM1110 -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x8029"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
|
["0x239A", "0x002A"],
|
||||||
|
["0x239A", "0x802A"]
|
||||||
|
],
|
||||||
|
"usb_product": "WIO-BOOT",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "Seeed_WIO_WM1110",
|
||||||
|
"bsp": {
|
||||||
|
"name": "adafruit"
|
||||||
|
},
|
||||||
|
"softdevice": {
|
||||||
|
"sd_flags": "-DS140",
|
||||||
|
"sd_name": "s140",
|
||||||
|
"sd_version": "7.3.0",
|
||||||
|
"sd_fwid": "0x0123"
|
||||||
|
},
|
||||||
|
"bootloader": {
|
||||||
|
"settings_addr": "0xFF000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"connectivity": ["bluetooth"],
|
||||||
|
"debug": {
|
||||||
|
"jlink_device": "nRF52840_xxAA",
|
||||||
|
"svd_path": "nrf52840.svd"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino"],
|
||||||
|
"name": "Seeed WIO WM1110",
|
||||||
|
"upload": {
|
||||||
|
"maximum_ram_size": 248832,
|
||||||
|
"maximum_size": 815104,
|
||||||
|
"speed": 115200,
|
||||||
|
"protocol": "nrfutil",
|
||||||
|
"protocols": [
|
||||||
|
"jlink",
|
||||||
|
"nrfjprog",
|
||||||
|
"nrfutil",
|
||||||
|
"stlink",
|
||||||
|
"cmsis-dap",
|
||||||
|
"blackmagic"
|
||||||
|
],
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"wait_for_upload_port": true
|
||||||
|
},
|
||||||
|
"url": "https://www.seeedstudio.com/Wio-Tracker-1110-Dev-Board-p-5799.html",
|
||||||
|
"vendor": "Seeed Studio"
|
||||||
|
}
|
||||||
34
boards/wiphone.json
Normal file
34
boards/wiphone.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32_out.ld",
|
||||||
|
"partitions": "default_16MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_WIPHONE14",
|
||||||
|
"-DBOARD_HAS_PSRAM",
|
||||||
|
"-mfix-esp32-psram-cache-issue",
|
||||||
|
"-mfix-esp32-psram-cache-strategy=memw"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "40000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"mcu": "esp32",
|
||||||
|
"variant": "wiphone",
|
||||||
|
"board": "WiPhone"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth"],
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "WIPhone Integrated 1.4",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 532480,
|
||||||
|
"maximum_size": 6553600,
|
||||||
|
"maximum_data_size": 4521984,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.wiphone.io/",
|
||||||
|
"vendor": "HackEDA"
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
"ldscript": "esp32_out.ld"
|
"ldscript": "esp32_out.ld"
|
||||||
},
|
},
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": "-DARDUINO_ESP32_DEV",
|
"extra_flags": ["-DBOARD_HAS_PSRAM", "-DARDUINO_ESP32_DEV"],
|
||||||
"f_cpu": "240000000L",
|
"f_cpu": "240000000L",
|
||||||
"f_flash": "40000000L",
|
"f_flash": "40000000L",
|
||||||
"flash_mode": "dio",
|
"flash_mode": "dio",
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"variant_h": "variant_RAK3172_MODULE.h"
|
||||||
|
},
|
||||||
"core": "stm32",
|
"core": "stm32",
|
||||||
"cpu": "cortex-m4",
|
"cpu": "cortex-m4",
|
||||||
"extra_flags": "-DSTM32WLxx -DSTM32WLE5xx -DARDUINO_GENERIC_WLE5CCUX",
|
"extra_flags": "-DSTM32WLxx -DSTM32WLE5xx -DARDUINO_GENERIC_WLE5CCUX",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"svd_path": "nrf52840.svd",
|
"svd_path": "nrf52840.svd",
|
||||||
"openocd_target": "nrf52840-mdk-rs"
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino", "freertos"],
|
||||||
"name": "WisCore RAK4631 Board",
|
"name": "WisCore RAK4631 Board",
|
||||||
"upload": {
|
"upload": {
|
||||||
"maximum_ram_size": 248832,
|
"maximum_ram_size": 248832,
|
||||||
|
|||||||
3
extra_scripts/README.md
Normal file
3
extra_scripts/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# extra_scripts
|
||||||
|
|
||||||
|
This directory contains special [scripts](https://docs.platformio.org/en/latest/scripting/index.html) that are used to modify the platformio environment in rare cases.
|
||||||
28
extra_scripts/disable_adafruit_usb.py
Normal file
28
extra_scripts/disable_adafruit_usb.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# trunk-ignore-all(flake8/F821)
|
||||||
|
# trunk-ignore-all(ruff/F821)
|
||||||
|
|
||||||
|
Import("env")
|
||||||
|
|
||||||
|
# NOTE: This is not currently used, but can serve as an example on how to write extra_scripts
|
||||||
|
|
||||||
|
# print("Current CLI targets", COMMAND_LINE_TARGETS)
|
||||||
|
# print("Current Build targets", BUILD_TARGETS)
|
||||||
|
# print("CPP defs", env.get("CPPDEFINES"))
|
||||||
|
# print(env.Dump())
|
||||||
|
|
||||||
|
# Adafruit.py in the platformio build tree is a bit naive and always enables their USB stack for building. We don't want this.
|
||||||
|
# So come in after that python script has run and disable it. This hack avoids us having to fork that big project and send in a PR
|
||||||
|
# which might not be accepted. -@geeksville
|
||||||
|
|
||||||
|
lib_builders = env.get("__PIO_LIB_BUILDERS", None)
|
||||||
|
if lib_builders is not None:
|
||||||
|
print("Disabling Adafruit USB stack")
|
||||||
|
for k in lib_builders:
|
||||||
|
if k.name == "Adafruit TinyUSB Library":
|
||||||
|
libenv = k.env
|
||||||
|
# print(f"{k.name }: { libenv.Dump() } ")
|
||||||
|
# libenv["CPPDEFINES"].remove("USBCON")
|
||||||
|
libenv["CPPDEFINES"].remove("USE_TINYUSB")
|
||||||
|
|
||||||
|
# Custom actions when building program/firmware
|
||||||
|
# env.AddPreAction("buildprog", callback...)
|
||||||
@@ -18,10 +18,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from platformio.project.exception import PlatformioException
|
from platformio.project.exception import PlatformioException
|
||||||
from platformio.public import (
|
from platformio.public import DeviceMonitorFilterBase, load_build_metadata
|
||||||
DeviceMonitorFilterBase,
|
|
||||||
load_build_metadata,
|
|
||||||
)
|
|
||||||
|
|
||||||
# By design, __init__ is called inside miniterm and we can't pass context to it.
|
# By design, __init__ is called inside miniterm and we can't pass context to it.
|
||||||
# pylint: disable=attribute-defined-outside-init
|
# pylint: disable=attribute-defined-outside-init
|
||||||
@@ -32,7 +29,7 @@ IS_WINDOWS = sys.platform.startswith("win")
|
|||||||
class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
|
class Esp32C3ExceptionDecoder(DeviceMonitorFilterBase):
|
||||||
NAME = "esp32_c3_exception_decoder"
|
NAME = "esp32_c3_exception_decoder"
|
||||||
|
|
||||||
PCADDR_PATTERN = re.compile(r'0x4[0-9a-f]{7}', re.IGNORECASE)
|
PCADDR_PATTERN = re.compile(r"0x4[0-9a-f]{7}", re.IGNORECASE)
|
||||||
|
|
||||||
def __call__(self):
|
def __call__(self):
|
||||||
self.buffer = ""
|
self.buffer = ""
|
||||||
@@ -75,14 +72,14 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
|
|||||||
% self.__class__.__name__
|
% self.__class__.__name__
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not os.path.isfile(self.addr2line_path):
|
if not os.path.isfile(self.addr2line_path):
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
"%s: disabling, addr2line at %s does not exist\n"
|
"%s: disabling, addr2line at %s does not exist\n"
|
||||||
% (self.__class__.__name__, self.addr2line_path)
|
% (self.__class__.__name__, self.addr2line_path)
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except PlatformioException as e:
|
except PlatformioException as e:
|
||||||
sys.stderr.write(
|
sys.stderr.write(
|
||||||
@@ -117,7 +114,7 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
|
|||||||
|
|
||||||
trace = self.get_backtrace(m)
|
trace = self.get_backtrace(m)
|
||||||
if len(trace) != "":
|
if len(trace) != "":
|
||||||
text = text[: last] + trace + text[last :]
|
text = text[:last] + trace + text[last:]
|
||||||
last += len(trace)
|
last += len(trace)
|
||||||
|
|
||||||
return text
|
return text
|
||||||
@@ -125,14 +122,10 @@ See https://docs.platformio.org/page/projectconf/build_configurations.html
|
|||||||
def get_backtrace(self, match):
|
def get_backtrace(self, match):
|
||||||
trace = "\n"
|
trace = "\n"
|
||||||
enc = "mbcs" if IS_WINDOWS else "utf-8"
|
enc = "mbcs" if IS_WINDOWS else "utf-8"
|
||||||
args = [self.addr2line_path, u"-fipC", u"-e", self.firmware_path]
|
args = [self.addr2line_path, "-fipC", "-e", self.firmware_path]
|
||||||
try:
|
try:
|
||||||
addr = match.group()
|
addr = match.group()
|
||||||
output = (
|
output = subprocess.check_output(args + [addr]).decode(enc).strip()
|
||||||
subprocess.check_output(args + [addr])
|
|
||||||
.decode(enc)
|
|
||||||
.strip()
|
|
||||||
)
|
|
||||||
output = output.replace(
|
output = output.replace(
|
||||||
"\n", "\n "
|
"\n", "\n "
|
||||||
) # newlines happen with inlined methods
|
) # newlines happen with inlined methods
|
||||||
|
|||||||
@@ -29,14 +29,24 @@ default_envs = tbeam
|
|||||||
;default_envs = meshtastic-dr-dev
|
;default_envs = meshtastic-dr-dev
|
||||||
;default_envs = m5stack-coreink
|
;default_envs = m5stack-coreink
|
||||||
;default_envs = rak4631
|
;default_envs = rak4631
|
||||||
|
;default_envs = rak2560
|
||||||
;default_envs = rak10701
|
;default_envs = rak10701
|
||||||
;default_envs = wio-e5
|
;default_envs = wio-e5
|
||||||
|
;default_envs = radiomaster_900_bandit_nano
|
||||||
|
;default_envs = radiomaster_900_bandit_micro
|
||||||
|
;default_envs = radiomaster_900_bandit
|
||||||
|
;default_envs = heltec_capsule_sensor_v3
|
||||||
|
;default_envs = heltec_vision_master_t190
|
||||||
|
;default_envs = heltec_vision_master_e213
|
||||||
|
;default_envs = heltec_vision_master_e290
|
||||||
|
;default_envs = heltec_mesh_node_t114
|
||||||
|
|
||||||
extra_configs =
|
extra_configs =
|
||||||
arch/*/*.ini
|
arch/*/*.ini
|
||||||
variants/*/platformio.ini
|
variants/*/platformio.ini
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
|
test_build_src = true
|
||||||
extra_scripts = bin/platformio-custom.py
|
extra_scripts = bin/platformio-custom.py
|
||||||
|
|
||||||
; note: we add src to our include search path so that lmic_project_config can override
|
; note: we add src to our include search path so that lmic_project_config can override
|
||||||
@@ -70,17 +80,19 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
-DRADIOLIB_EXCLUDE_FSK4
|
-DRADIOLIB_EXCLUDE_FSK4
|
||||||
-DRADIOLIB_EXCLUDE_APRS
|
-DRADIOLIB_EXCLUDE_APRS
|
||||||
-DRADIOLIB_EXCLUDE_LORAWAN
|
-DRADIOLIB_EXCLUDE_LORAWAN
|
||||||
|
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
monitor_filters = direct
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
jgromes/RadioLib@~6.5.0
|
jgromes/RadioLib@~6.6.0
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#ee628ee6c9588d4c56c9e3da35f0fc9448ad54a8 ; ESP8266_SSD1306
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git#e16cee124fe26490cb14880c679321ad8ac89c95 ; ESP8266_SSD1306
|
||||||
mathertel/OneButton@^2.5.0 ; OneButton library for non-blocking button debounce
|
https://github.com/mathertel/OneButton@~2.6.1 ; OneButton library for non-blocking button debounce
|
||||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||||
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||||
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
https://github.com/meshtastic/ArduinoThread.git#1ae8778c85d0a2a729f989e0b1e7d7c4dc84eef0
|
||||||
nanopb/Nanopb@^0.4.7
|
nanopb/Nanopb@^0.4.8
|
||||||
erriez/ErriezCRC32@^1.0.1
|
erriez/ErriezCRC32@^1.0.1
|
||||||
|
|
||||||
; Used for the code analysis in PIO Home / Inspect
|
; Used for the code analysis in PIO Home / Inspect
|
||||||
@@ -96,7 +108,6 @@ check_flags =
|
|||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
mprograms/QMC5883LCompass@^1.2.0
|
|
||||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da
|
||||||
|
|
||||||
@@ -119,10 +130,7 @@ lib_deps =
|
|||||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||||
adafruit/Adafruit BMP085 Library@^1.2.4
|
adafruit/Adafruit BMP085 Library@^1.2.4
|
||||||
adafruit/Adafruit BME280 Library@^2.2.2
|
adafruit/Adafruit BME280 Library@^2.2.2
|
||||||
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.5.2400
|
|
||||||
boschsensortec/BME68x Sensor Library@^1.1.40407
|
|
||||||
adafruit/Adafruit MCP9808 Library@^2.0.0
|
adafruit/Adafruit MCP9808 Library@^2.0.0
|
||||||
https://github.com/KodinLanewave/INA3221@^1.0.0
|
|
||||||
adafruit/Adafruit INA260 Library@^1.5.0
|
adafruit/Adafruit INA260 Library@^1.5.0
|
||||||
adafruit/Adafruit INA219@^1.2.0
|
adafruit/Adafruit INA219@^1.2.0
|
||||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||||
@@ -131,5 +139,22 @@ lib_deps =
|
|||||||
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
adafruit/Adafruit PM25 AQI Sensor@^1.0.6
|
||||||
adafruit/Adafruit MPU6050@^2.2.4
|
adafruit/Adafruit MPU6050@^2.2.4
|
||||||
adafruit/Adafruit LIS3DH@^1.2.4
|
adafruit/Adafruit LIS3DH@^1.2.4
|
||||||
https://github.com/lewisxhe/SensorLib#27fd0f721e20cd09e1f81383f0ba58a54fe84a17
|
adafruit/Adafruit AHTX0@^2.0.5
|
||||||
adafruit/Adafruit LSM6DS@^4.7.2
|
adafruit/Adafruit LSM6DS@^4.7.2
|
||||||
|
adafruit/Adafruit VEML7700 Library@^2.1.6
|
||||||
|
adafruit/Adafruit SHT4x Library@^1.0.4
|
||||||
|
adafruit/Adafruit TSL2591 Library@^1.4.5
|
||||||
|
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@^1.0.5
|
||||||
|
ClosedCube OPT3001@^1.1.2
|
||||||
|
emotibit/EmotiBit MLX90632@^1.0.8
|
||||||
|
dfrobot/DFRobot_RTU@^1.0.3
|
||||||
|
|
||||||
|
|
||||||
|
https://github.com/boschsensortec/Bosch-BSEC2-Library#v1.7.2502
|
||||||
|
boschsensortec/BME68x Sensor Library@^1.1.40407
|
||||||
|
https://github.com/KodinLanewave/INA3221@^1.0.0
|
||||||
|
lewisxhe/SensorLib@^0.2.0
|
||||||
|
mprograms/QMC5883LCompass@^1.2.0
|
||||||
|
|
||||||
|
|
||||||
|
https://github.com/meshtastic/DFRobot_LarkWeatherStation#dee914270dc7cb3e43fbf034edd85a63a16a12ee
|
||||||
|
|||||||
Submodule protobufs updated: e21899aa6b...52cfa2c1c2
7
pyocd.yaml
Normal file
7
pyocd.yaml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# This is a config file to control pyocd ICE debugger probe options (only used for NRF52 targets with hardware debugging connections)
|
||||||
|
# for more info see FIXMEURL
|
||||||
|
|
||||||
|
# console or telnet
|
||||||
|
semihost_console_type: telnet
|
||||||
|
enable_semihosting: True
|
||||||
|
telnet_port: 4444
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#if !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
|
||||||
|
|
||||||
#include "PowerFSM.h"
|
#include "PowerFSM.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
#include "configuration.h"
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "power.h"
|
#include "power.h"
|
||||||
|
|
||||||
@@ -10,14 +14,17 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SensorBMA423.hpp>
|
#include <SensorBMA423.hpp>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#ifdef RAK_4631
|
||||||
SensorBMA423 bmaSensor;
|
#include "Fusion/Fusion.h"
|
||||||
bool BMA_IRQ = false;
|
#include "graphics/Screen.h"
|
||||||
|
#include "graphics/ScreenFonts.h"
|
||||||
|
#include <Rak_BMX160.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
||||||
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
||||||
|
|
||||||
int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
static inline int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
Wire.beginTransmission(address);
|
Wire.beginTransmission(address);
|
||||||
Wire.write(reg);
|
Wire.write(reg);
|
||||||
@@ -30,7 +37,7 @@ int readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
|||||||
return 0; // Pass
|
return 0; // Pass
|
||||||
}
|
}
|
||||||
|
|
||||||
int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
static inline int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
||||||
{
|
{
|
||||||
Wire.beginTransmission(address);
|
Wire.beginTransmission(address);
|
||||||
Wire.write(reg);
|
Wire.write(reg);
|
||||||
@@ -38,8 +45,6 @@ int writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint8_t len)
|
|||||||
return (0 != Wire.endTransmission());
|
return (0 != Wire.endTransmission());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
class AccelerometerThread : public concurrency::OSThread
|
class AccelerometerThread : public concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -50,14 +55,129 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
acceleremoter_type = type;
|
||||||
|
#ifndef RAK_4631
|
||||||
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
|
if (!config.display.wake_on_tap_or_motion && !config.device.double_tap_as_button_press) {
|
||||||
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
|
LOG_DEBUG("AccelerometerThread disabling due to no interested configurations\n");
|
||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
acceleremoter_type = type;
|
void start()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
setIntervalFromNow(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t runOnce() override
|
||||||
|
{
|
||||||
|
canSleep = true; // Assume we should not keep the board awake
|
||||||
|
|
||||||
|
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
|
||||||
|
wakeScreen();
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
|
||||||
|
uint8_t click = lis.getClick();
|
||||||
|
if (!config.device.double_tap_as_button_press) {
|
||||||
|
wakeScreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.device.double_tap_as_button_press && (click & 0x20)) {
|
||||||
|
buttonPress();
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
|
||||||
|
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
|
||||||
|
wakeScreen();
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
#ifdef RAK_4631
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160) {
|
||||||
|
sBmx160SensorData_t magAccel;
|
||||||
|
sBmx160SensorData_t gAccel;
|
||||||
|
|
||||||
|
/* Get a new sensor event */
|
||||||
|
bmx160.getAllData(&magAccel, NULL, &gAccel);
|
||||||
|
|
||||||
|
// expirimental calibrate routine. Limited to between 10 and 30 seconds after boot
|
||||||
|
if (millis() > 12 * 1000 && millis() < 30 * 1000) {
|
||||||
|
if (!showingScreen) {
|
||||||
|
showingScreen = true;
|
||||||
|
screen->startAlert((FrameCallback)drawFrameCalibration);
|
||||||
|
}
|
||||||
|
if (magAccel.x > highestX)
|
||||||
|
highestX = magAccel.x;
|
||||||
|
if (magAccel.x < lowestX)
|
||||||
|
lowestX = magAccel.x;
|
||||||
|
if (magAccel.y > highestY)
|
||||||
|
highestY = magAccel.y;
|
||||||
|
if (magAccel.y < lowestY)
|
||||||
|
lowestY = magAccel.y;
|
||||||
|
if (magAccel.z > highestZ)
|
||||||
|
highestZ = magAccel.z;
|
||||||
|
if (magAccel.z < lowestZ)
|
||||||
|
lowestZ = magAccel.z;
|
||||||
|
} else if (showingScreen && millis() >= 30 * 1000) {
|
||||||
|
showingScreen = false;
|
||||||
|
screen->endAlert();
|
||||||
|
}
|
||||||
|
|
||||||
|
int highestRealX = highestX - (highestX + lowestX) / 2;
|
||||||
|
|
||||||
|
magAccel.x -= (highestX + lowestX) / 2;
|
||||||
|
magAccel.y -= (highestY + lowestY) / 2;
|
||||||
|
magAccel.z -= (highestZ + lowestZ) / 2;
|
||||||
|
FusionVector ga, ma;
|
||||||
|
ga.axis.x = -gAccel.x; // default location for the BMX160 is on the rear of the board
|
||||||
|
ga.axis.y = -gAccel.y;
|
||||||
|
ga.axis.z = gAccel.z;
|
||||||
|
ma.axis.x = -magAccel.x;
|
||||||
|
ma.axis.y = -magAccel.y;
|
||||||
|
ma.axis.z = magAccel.z * 3;
|
||||||
|
|
||||||
|
// If we're set to one of the inverted positions
|
||||||
|
if (config.display.compass_orientation > meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270) {
|
||||||
|
ma = FusionAxesSwap(ma, FusionAxesAlignmentNXNYPZ);
|
||||||
|
ga = FusionAxesSwap(ga, FusionAxesAlignmentNXNYPZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
float heading = FusionCompassCalculateHeading(FusionConventionNed, ga, ma);
|
||||||
|
|
||||||
|
switch (config.display.compass_orientation) {
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0_INVERTED:
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_0:
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90:
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_90_INVERTED:
|
||||||
|
heading += 90;
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180:
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_180_INVERTED:
|
||||||
|
heading += 180;
|
||||||
|
break;
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270:
|
||||||
|
case meshtastic_Config_DisplayConfig_CompassOrientation_DEGREES_270_INVERTED:
|
||||||
|
heading += 270;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
screen->setHeading(heading);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) {
|
||||||
|
wakeScreen();
|
||||||
|
return 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init()
|
||||||
|
{
|
||||||
LOG_DEBUG("AccelerometerThread initializing\n");
|
LOG_DEBUG("AccelerometerThread initializing\n");
|
||||||
|
|
||||||
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
||||||
@@ -109,6 +229,11 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
bmaSensor.enableTiltIRQ();
|
bmaSensor.enableTiltIRQ();
|
||||||
// It corresponds to isDoubleClick interrupt
|
// It corresponds to isDoubleClick interrupt
|
||||||
bmaSensor.enableWakeupIRQ();
|
bmaSensor.enableWakeupIRQ();
|
||||||
|
#ifdef RAK_4631
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::BMX160 && bmx160.begin()) {
|
||||||
|
bmx160.ODR_Config(BMX160_ACCEL_ODR_100HZ, BMX160_GYRO_ODR_100HZ); // set output data rate
|
||||||
|
|
||||||
|
#endif
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) {
|
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.begin_I2C(accelerometer_found.address)) {
|
||||||
LOG_DEBUG("LSM6DS3 initializing\n");
|
LOG_DEBUG("LSM6DS3 initializing\n");
|
||||||
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
|
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
|
||||||
@@ -120,38 +245,6 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
|
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
int32_t runOnce() override
|
|
||||||
{
|
|
||||||
canSleep = true; // Assume we should not keep the board awake
|
|
||||||
|
|
||||||
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.getMotionInterruptStatus()) {
|
|
||||||
wakeScreen();
|
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.getClick() > 0) {
|
|
||||||
uint8_t click = lis.getClick();
|
|
||||||
if (!config.device.double_tap_as_button_press) {
|
|
||||||
wakeScreen();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.device.double_tap_as_button_press && (click & 0x20)) {
|
|
||||||
buttonPress();
|
|
||||||
return 500;
|
|
||||||
}
|
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
|
|
||||||
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
|
|
||||||
wakeScreen();
|
|
||||||
return 500;
|
|
||||||
}
|
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LSM6DS3 && lsm.shake()) {
|
|
||||||
wakeScreen();
|
|
||||||
return 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void wakeScreen()
|
void wakeScreen()
|
||||||
{
|
{
|
||||||
if (powerFSM.getState() == &stateDARK) {
|
if (powerFSM.getState() == &stateDARK) {
|
||||||
@@ -170,6 +263,35 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
Adafruit_MPU6050 mpu;
|
Adafruit_MPU6050 mpu;
|
||||||
Adafruit_LIS3DH lis;
|
Adafruit_LIS3DH lis;
|
||||||
Adafruit_LSM6DS3TRC lsm;
|
Adafruit_LSM6DS3TRC lsm;
|
||||||
|
SensorBMA423 bmaSensor;
|
||||||
|
bool BMA_IRQ = false;
|
||||||
|
#ifdef RAK_4631
|
||||||
|
bool showingScreen = false;
|
||||||
|
RAK_BMX160 bmx160;
|
||||||
|
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||||
|
|
||||||
|
static void drawFrameCalibration(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||||
|
{
|
||||||
|
int x_offset = display->width() / 2;
|
||||||
|
int y_offset = display->height() <= 80 ? 0 : 32;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(FONT_MEDIUM);
|
||||||
|
display->drawString(x, y, "Calibrating\nCompass");
|
||||||
|
int16_t compassX = 0, compassY = 0;
|
||||||
|
uint16_t compassDiam = graphics::Screen::getCompassDiam(display->getWidth(), display->getHeight());
|
||||||
|
|
||||||
|
// coordinates for the center of the compass/circle
|
||||||
|
if (config.display.displaymode == meshtastic_Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||||
|
compassX = x + display->getWidth() - compassDiam / 2 - 5;
|
||||||
|
compassY = y + display->getHeight() / 2;
|
||||||
|
} else {
|
||||||
|
compassX = x + display->getWidth() - compassDiam / 2 - 5;
|
||||||
|
compassY = y + FONT_HEIGHT_SMALL + (display->getHeight() - FONT_HEIGHT_SMALL) / 2;
|
||||||
|
}
|
||||||
|
display->drawCircle(compassX, compassY, compassDiam / 2);
|
||||||
|
screen->drawCompassNorth(display, compassX, compassY, screen->getHeading() * PI / 180);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace concurrency
|
#endif
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#include "Observer.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
@@ -22,10 +23,18 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
public:
|
public:
|
||||||
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
||||||
{
|
{
|
||||||
|
notifyDeepSleepObserver.observe(¬ifyDeepSleep); // Let us know when shutdown() is issued.
|
||||||
|
|
||||||
|
// Enables Ambient Lighting by default if conditions are meet.
|
||||||
|
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||||
|
#ifdef ENABLE_AMBIENTLIGHTING
|
||||||
|
moduleConfig.ambient_lighting.led_state = true;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
// Uncomment to test module
|
// Uncomment to test module
|
||||||
// moduleConfig.ambient_lighting.led_state = true;
|
// moduleConfig.ambient_lighting.led_state = true;
|
||||||
// moduleConfig.ambient_lighting.current = 10;
|
// moduleConfig.ambient_lighting.current = 10;
|
||||||
// // Default to a color based on our node number
|
// Default to a color based on our node number
|
||||||
// moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
// moduleConfig.ambient_lighting.red = (myNodeInfo.my_node_num & 0xFF0000) >> 16;
|
||||||
// moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
// moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
|
||||||
// moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
// moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
|
||||||
@@ -82,9 +91,46 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
return disable();
|
return disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When shutdown() is issued, setLightingOff will be called.
|
||||||
|
CallbackObserver<AmbientLightingThread, void *> notifyDeepSleepObserver =
|
||||||
|
CallbackObserver<AmbientLightingThread, void *>(this, &AmbientLightingThread::setLightingOff);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
|
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
|
||||||
|
|
||||||
|
// Turn RGB lighting off, is used in junction to shutdown()
|
||||||
|
int setLightingOff(void *unused)
|
||||||
|
{
|
||||||
|
#ifdef HAS_NCP5623
|
||||||
|
rgb.setCurrent(0);
|
||||||
|
rgb.setRed(0);
|
||||||
|
rgb.setGreen(0);
|
||||||
|
rgb.setBlue(0);
|
||||||
|
LOG_INFO("Turn Off NCP5623 Ambient lighting.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_NEOPIXEL
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
LOG_INFO("Turn Off NeoPixel Ambient lighting.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef RGBLED_CA
|
||||||
|
analogWrite(RGBLED_RED, 255 - 0);
|
||||||
|
analogWrite(RGBLED_GREEN, 255 - 0);
|
||||||
|
analogWrite(RGBLED_BLUE, 255 - 0);
|
||||||
|
LOG_INFO("Turn Off Ambient lighting RGB Common Anode.\n");
|
||||||
|
#elif defined(RGBLED_RED)
|
||||||
|
analogWrite(RGBLED_RED, 0);
|
||||||
|
analogWrite(RGBLED_GREEN, 0);
|
||||||
|
analogWrite(RGBLED_BLUE, 0);
|
||||||
|
LOG_INFO("Turn Off Ambient lighting RGB Common Cathode.\n");
|
||||||
|
#endif
|
||||||
|
#ifdef UNPHONE
|
||||||
|
unphone.rgb(0, 0, 0);
|
||||||
|
LOG_INFO("Turn Off unPhone Ambient lighting.\n");
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void setLighting()
|
void setLighting()
|
||||||
{
|
{
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
@@ -100,6 +146,17 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||||
moduleConfig.ambient_lighting.blue),
|
moduleConfig.ambient_lighting.blue),
|
||||||
0, NEOPIXEL_COUNT);
|
0, NEOPIXEL_COUNT);
|
||||||
|
|
||||||
|
// RadioMaster Bandit has addressable LED at the two buttons
|
||||||
|
// this allow us to set different lighting for them in variant.h file.
|
||||||
|
#ifdef RADIOMASTER_900_BANDIT
|
||||||
|
#if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX)
|
||||||
|
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
|
||||||
|
#endif
|
||||||
|
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
|
||||||
|
pixels.fill(BUTTON2_COLOR, BUTTON1_COLOR_INDEX, 1);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
pixels.show();
|
pixels.show();
|
||||||
LOG_DEBUG("Initializing NeoPixel Ambient lighting w/ brightness(current)=%d, red=%d, green=%d, blue=%d\n",
|
LOG_DEBUG("Initializing NeoPixel Ambient lighting w/ brightness(current)=%d, red=%d, green=%d, blue=%d\n",
|
||||||
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||||
|
|||||||
@@ -10,4 +10,8 @@ const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd,
|
|||||||
const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
|
const uint8_t FROMRADIO_UUID_16[16u] = {0x02, 0x00, 0x12, 0xac, 0x42, 0x02, 0x78, 0xb8,
|
||||||
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
|
0xed, 0x11, 0x93, 0x49, 0x9e, 0xe6, 0x55, 0x2c};
|
||||||
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
||||||
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
||||||
|
const uint8_t LEGACY_LOGRADIO_UUID_16[16u] = {0xe2, 0xf2, 0x1e, 0xbe, 0xc5, 0x15, 0xcf, 0xaa,
|
||||||
|
0x6b, 0x43, 0xfa, 0x78, 0x38, 0xd2, 0x6f, 0x6c};
|
||||||
|
const uint8_t LOGRADIO_UUID_16[16u] = {0x47, 0x95, 0xDF, 0x8C, 0xDE, 0xE9, 0x44, 0x99,
|
||||||
|
0x23, 0x44, 0xE6, 0x06, 0x49, 0x6E, 0x3D, 0x5A};
|
||||||
@@ -11,10 +11,12 @@
|
|||||||
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||||
#define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
|
#define FROMRADIO_UUID "2c55e69e-4993-11ed-b878-0242ac120002"
|
||||||
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||||
|
#define LEGACY_LOGRADIO_UUID "6c6fd238-78fa-436b-aacf-15c5be1ef2e2"
|
||||||
|
#define LOGRADIO_UUID "5a3d6e49-06e6-4423-9944-e9de8cdf9547"
|
||||||
|
|
||||||
// NRF52 wants these constants as byte arrays
|
// NRF52 wants these constants as byte arrays
|
||||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||||
extern const uint8_t MESH_SERVICE_UUID_16[], TORADIO_UUID_16[16u], FROMRADIO_UUID_16[], FROMNUM_UUID_16[];
|
extern const uint8_t MESH_SERVICE_UUID_16[], TORADIO_UUID_16[16u], FROMRADIO_UUID_16[], FROMNUM_UUID_16[], LOGRADIO_UUID_16[];
|
||||||
|
|
||||||
/// Given a level between 0-100, update the BLE attribute
|
/// Given a level between 0-100, update the BLE attribute
|
||||||
void updateBatteryLevel(uint8_t level);
|
void updateBatteryLevel(uint8_t level);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BU
|
|||||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
OneButton ButtonThread::userButton; // Get reference to static member
|
OneButton ButtonThread::userButton; // Get reference to static member
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ButtonThread::ButtonThread() : OSThread("Button")
|
ButtonThread::ButtonThread() : OSThread("Button")
|
||||||
{
|
{
|
||||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
@@ -41,19 +40,29 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
|||||||
}
|
}
|
||||||
#elif defined(BUTTON_PIN)
|
#elif defined(BUTTON_PIN)
|
||||||
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
|
int pin = config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN; // Resolved button pin
|
||||||
|
#if defined(HELTEC_CAPSULE_SENSOR_V3)
|
||||||
|
this->userButton = OneButton(pin, false, false);
|
||||||
|
#elif defined(BUTTON_ACTIVE_LOW)
|
||||||
|
this->userButton = OneButton(pin, BUTTON_ACTIVE_LOW, BUTTON_ACTIVE_PULLUP);
|
||||||
|
#else
|
||||||
this->userButton = OneButton(pin, true, true);
|
this->userButton = OneButton(pin, true, true);
|
||||||
|
#endif
|
||||||
LOG_DEBUG("Using GPIO%02d for button\n", pin);
|
LOG_DEBUG("Using GPIO%02d for button\n", pin);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef INPUT_PULLUP_SENSE
|
#ifdef INPUT_PULLUP_SENSE
|
||||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||||
|
#ifdef BUTTON_SENSE_TYPE
|
||||||
|
pinMode(pin, BUTTON_SENSE_TYPE);
|
||||||
|
#else
|
||||||
pinMode(pin, INPUT_PULLUP_SENSE);
|
pinMode(pin, INPUT_PULLUP_SENSE);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
userButton.attachClick(userButtonPressed);
|
userButton.attachClick(userButtonPressed);
|
||||||
userButton.setClickMs(250);
|
userButton.setClickMs(BUTTON_CLICK_MS);
|
||||||
userButton.setPressMs(c_longPressTime);
|
userButton.setPressMs(BUTTON_LONGPRESS_MS);
|
||||||
userButton.setDebounceMs(1);
|
userButton.setDebounceMs(1);
|
||||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||||
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
|
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
|
||||||
@@ -70,8 +79,8 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
|||||||
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
||||||
#endif
|
#endif
|
||||||
userButtonAlt.attachClick(userButtonPressed);
|
userButtonAlt.attachClick(userButtonPressed);
|
||||||
userButtonAlt.setClickMs(250);
|
userButtonAlt.setClickMs(BUTTON_CLICK_MS);
|
||||||
userButtonAlt.setPressMs(c_longPressTime);
|
userButtonAlt.setPressMs(BUTTON_LONGPRESS_MS);
|
||||||
userButtonAlt.setDebounceMs(1);
|
userButtonAlt.setDebounceMs(1);
|
||||||
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
||||||
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
|
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
|
||||||
@@ -80,7 +89,7 @@ ButtonThread::ButtonThread() : OSThread("Button")
|
|||||||
|
|
||||||
#ifdef BUTTON_PIN_TOUCH
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
||||||
userButtonTouch.setPressMs(400);
|
userButtonTouch.setPressMs(BUTTON_TOUCH_MS);
|
||||||
userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click?
|
userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click?
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -135,8 +144,8 @@ int32_t ButtonThread::runOnce()
|
|||||||
|
|
||||||
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||||
LOG_BUTTON("Double press!\n");
|
LOG_BUTTON("Double press!\n");
|
||||||
service.refreshLocalMeshNode();
|
service->refreshLocalMeshNode();
|
||||||
auto sentPosition = service.trySendPosition(NODENUM_BROADCAST, true);
|
auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
|
||||||
if (screen) {
|
if (screen) {
|
||||||
if (sentPosition)
|
if (sentPosition)
|
||||||
screen->print("Sent ad-hoc position\n");
|
screen->print("Sent ad-hoc position\n");
|
||||||
@@ -177,8 +186,9 @@ int32_t ButtonThread::runOnce()
|
|||||||
case BUTTON_EVENT_LONG_PRESSED: {
|
case BUTTON_EVENT_LONG_PRESSED: {
|
||||||
LOG_BUTTON("Long press!\n");
|
LOG_BUTTON("Long press!\n");
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
if (screen)
|
if (screen) {
|
||||||
screen->startShutdownScreen();
|
screen->startAlert("Shutting down...");
|
||||||
|
}
|
||||||
playBeep();
|
playBeep();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -231,9 +241,10 @@ void ButtonThread::attachButtonInterrupts()
|
|||||||
attachInterrupt(
|
attachInterrupt(
|
||||||
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
|
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
|
||||||
[]() {
|
[]() {
|
||||||
|
ButtonThread::userButton.tick();
|
||||||
|
runASAP = true;
|
||||||
BaseType_t higherWake = 0;
|
BaseType_t higherWake = 0;
|
||||||
mainDelay.interruptFromISR(&higherWake);
|
mainDelay.interruptFromISR(&higherWake);
|
||||||
ButtonThread::userButton.tick();
|
|
||||||
},
|
},
|
||||||
CHANGE);
|
CHANGE);
|
||||||
#endif
|
#endif
|
||||||
@@ -280,6 +291,7 @@ void ButtonThread::wakeOnIrq(int irq, int mode)
|
|||||||
[] {
|
[] {
|
||||||
BaseType_t higherWake = 0;
|
BaseType_t higherWake = 0;
|
||||||
mainDelay.interruptFromISR(&higherWake);
|
mainDelay.interruptFromISR(&higherWake);
|
||||||
|
runASAP = true;
|
||||||
},
|
},
|
||||||
FALLING);
|
FALLING);
|
||||||
}
|
}
|
||||||
@@ -315,4 +327,4 @@ void ButtonThread::userButtonPressedLongStop()
|
|||||||
if (millis() > c_holdOffTime) {
|
if (millis() > c_holdOffTime) {
|
||||||
btnEvent = BUTTON_EVENT_LONG_RELEASED;
|
btnEvent = BUTTON_EVENT_LONG_RELEASED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,11 +4,22 @@
|
|||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
|
||||||
|
#ifndef BUTTON_CLICK_MS
|
||||||
|
#define BUTTON_CLICK_MS 250
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BUTTON_LONGPRESS_MS
|
||||||
|
#define BUTTON_LONGPRESS_MS 5000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BUTTON_TOUCH_MS
|
||||||
|
#define BUTTON_TOUCH_MS 400
|
||||||
|
#endif
|
||||||
|
|
||||||
class ButtonThread : public concurrency::OSThread
|
class ButtonThread : public concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const uint32_t c_longPressTime = 5000; // shutdown after 5s
|
static const uint32_t c_holdOffTime = 30000; // hold off 30s after boot
|
||||||
static const uint32_t c_holdOffTime = 30000; // hold off 30s after boot
|
|
||||||
|
|
||||||
enum ButtonEventType {
|
enum ButtonEventType {
|
||||||
BUTTON_EVENT_NONE,
|
BUTTON_EVENT_NONE,
|
||||||
|
|||||||
@@ -26,7 +26,21 @@ SOFTWARE.*/
|
|||||||
|
|
||||||
#include "DebugConfiguration.h"
|
#include "DebugConfiguration.h"
|
||||||
|
|
||||||
#if HAS_WIFI || HAS_ETHERNET
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "platform/portduino/PortduinoGlue.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
|
||||||
|
extern "C" void logLegacy(const char *level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
if (console)
|
||||||
|
console->vprintf(level, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAS_NETWORKING
|
||||||
|
|
||||||
Syslog::Syslog(UDP &client)
|
Syslog::Syslog(UDP &client)
|
||||||
{
|
{
|
||||||
@@ -129,6 +143,11 @@ bool Syslog::vlogf(uint16_t pri, const char *appName, const char *fmt, va_list a
|
|||||||
inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message)
|
inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *message)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
bool utf = !settingsMap[ascii_logs];
|
||||||
|
#else
|
||||||
|
bool utf = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!this->_enabled)
|
if (!this->_enabled)
|
||||||
return false;
|
return false;
|
||||||
@@ -159,7 +178,12 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
|||||||
this->_client->print(this->_deviceHostname);
|
this->_client->print(this->_deviceHostname);
|
||||||
this->_client->print(' ');
|
this->_client->print(' ');
|
||||||
this->_client->print(appName);
|
this->_client->print(appName);
|
||||||
this->_client->print(F(" - - - \xEF\xBB\xBF"));
|
this->_client->print(F(" - - - "));
|
||||||
|
if (utf) {
|
||||||
|
this->_client->print(F("\xEF\xBB\xBF"));
|
||||||
|
} else {
|
||||||
|
this->_client->print(F(" "));
|
||||||
|
}
|
||||||
this->_client->print(F("["));
|
this->_client->print(F("["));
|
||||||
this->_client->print(int(millis() / 1000));
|
this->_client->print(int(millis() / 1000));
|
||||||
this->_client->print(F("]: "));
|
this->_client->print(F("]: "));
|
||||||
@@ -169,4 +193,4 @@ inline bool Syslog::_sendLog(uint16_t pri, const char *appName, const char *mess
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
#ifndef SYSLOG_H
|
#pragma once
|
||||||
#define SYSLOG_H
|
|
||||||
|
#include "configuration.h"
|
||||||
|
|
||||||
// DEBUG LED
|
// DEBUG LED
|
||||||
#ifndef LED_INVERTED
|
#ifndef LED_STATE_ON
|
||||||
#define LED_INVERTED 0 // define as 1 if LED is active low (on)
|
#define LED_STATE_ON 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -25,6 +26,14 @@
|
|||||||
|
|
||||||
#include "SerialConsole.h"
|
#include "SerialConsole.h"
|
||||||
|
|
||||||
|
// If defined we will include support for ARM ICE "semihosting" for a virtual
|
||||||
|
// console over the JTAG port (to replace the normal serial port)
|
||||||
|
// Note: Normally this flag is passed into the gcc commandline by platformio.ini.
|
||||||
|
// for an example see env:rak4631_dap.
|
||||||
|
// #ifndef USE_SEMIHOSTING
|
||||||
|
// #define USE_SEMIHOSTING
|
||||||
|
// #endif
|
||||||
|
|
||||||
#define DEBUG_PORT (*console) // Serial debug port
|
#define DEBUG_PORT (*console) // Serial debug port
|
||||||
|
|
||||||
#ifdef USE_SEGGER
|
#ifdef USE_SEGGER
|
||||||
@@ -36,7 +45,7 @@
|
|||||||
#define LOG_CRIT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define LOG_CRIT(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#ifdef DEBUG_PORT
|
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE) && !defined(PIO_UNIT_TESTING)
|
||||||
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||||
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||||
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
||||||
@@ -53,6 +62,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/// A C wrapper for LOG_DEBUG that can be used from arduino C libs that don't know about C++ or meshtastic
|
||||||
|
extern "C" void logLegacy(const char *level, const char *fmt, ...);
|
||||||
|
|
||||||
#define SYSLOG_NILVALUE "-"
|
#define SYSLOG_NILVALUE "-"
|
||||||
|
|
||||||
#define SYSLOG_CRIT 2 /* critical conditions */
|
#define SYSLOG_CRIT 2 /* critical conditions */
|
||||||
@@ -117,7 +129,7 @@
|
|||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#endif // HAS_WIFI
|
#endif // HAS_WIFI
|
||||||
|
|
||||||
#if HAS_WIFI || HAS_ETHERNET
|
#if HAS_NETWORKING
|
||||||
|
|
||||||
class Syslog
|
class Syslog
|
||||||
{
|
{
|
||||||
@@ -152,6 +164,4 @@ class Syslog
|
|||||||
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HAS_ETHERNET || HAS_WIFI
|
#endif // HAS_ETHERNET || HAS_WIFI
|
||||||
|
|
||||||
#endif // SYSLOG_H
|
|
||||||
@@ -3,6 +3,9 @@
|
|||||||
const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName)
|
const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaConfig_ModemPreset preset, bool useShortName)
|
||||||
{
|
{
|
||||||
switch (preset) {
|
switch (preset) {
|
||||||
|
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_TURBO:
|
||||||
|
return useShortName ? "ShortT" : "ShortTurbo";
|
||||||
|
break;
|
||||||
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
case meshtastic_Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||||
return useShortName ? "ShortS" : "ShortSlow";
|
return useShortName ? "ShortS" : "ShortSlow";
|
||||||
break;
|
break;
|
||||||
|
|||||||
132
src/FSCommon.cpp
132
src/FSCommon.cpp
@@ -24,6 +24,39 @@ SPIClass SPI1(HSPI);
|
|||||||
|
|
||||||
#endif // HAS_SDCARD
|
#endif // HAS_SDCARD
|
||||||
|
|
||||||
|
#if defined(ARCH_STM32WL)
|
||||||
|
|
||||||
|
uint16_t OSFS::startOfEEPROM = 1;
|
||||||
|
uint16_t OSFS::endOfEEPROM = 2048;
|
||||||
|
|
||||||
|
// 3) How do I read from the medium?
|
||||||
|
void OSFS::readNBytes(uint16_t address, unsigned int num, byte *output)
|
||||||
|
{
|
||||||
|
for (uint16_t i = address; i < address + num; i++) {
|
||||||
|
*output = EEPROM.read(i);
|
||||||
|
output++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4) How to I write to the medium?
|
||||||
|
void OSFS::writeNBytes(uint16_t address, unsigned int num, const byte *input)
|
||||||
|
{
|
||||||
|
for (uint16_t i = address; i < address + num; i++) {
|
||||||
|
EEPROM.update(i, *input);
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool lfs_assert_failed =
|
||||||
|
false; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our modified lfs_util.h)
|
||||||
|
|
||||||
|
extern "C" void lfs_assert(const char *reason)
|
||||||
|
{
|
||||||
|
LOG_ERROR("LFS assert: %s\n", reason);
|
||||||
|
lfs_assert_failed = true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Copies a file from one location to another.
|
* @brief Copies a file from one location to another.
|
||||||
*
|
*
|
||||||
@@ -33,7 +66,33 @@ SPIClass SPI1(HSPI);
|
|||||||
*/
|
*/
|
||||||
bool copyFile(const char *from, const char *to)
|
bool copyFile(const char *from, const char *to)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef ARCH_STM32WL
|
||||||
|
unsigned char cbuffer[2048];
|
||||||
|
|
||||||
|
// Var to hold the result of actions
|
||||||
|
OSFS::result r;
|
||||||
|
|
||||||
|
r = OSFS::getFile(from, cbuffer);
|
||||||
|
|
||||||
|
if (r == notfound) {
|
||||||
|
LOG_ERROR("Failed to open source file %s\n", from);
|
||||||
|
return false;
|
||||||
|
} else if (r == noerr) {
|
||||||
|
r = OSFS::newFile(to, cbuffer, true);
|
||||||
|
if (r == noerr) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("OSFS Error %d\n", r);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("OSFS Error %d\n", r);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#elif defined(FSCom)
|
||||||
unsigned char cbuffer[16];
|
unsigned char cbuffer[16];
|
||||||
|
|
||||||
File f1 = FSCom.open(from, FILE_O_READ);
|
File f1 = FSCom.open(from, FILE_O_READ);
|
||||||
@@ -70,7 +129,13 @@ bool copyFile(const char *from, const char *to)
|
|||||||
*/
|
*/
|
||||||
bool renameFile(const char *pathFrom, const char *pathTo)
|
bool renameFile(const char *pathFrom, const char *pathTo)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef ARCH_STM32WL
|
||||||
|
if (copyFile(pathFrom, pathTo) && (OSFS::deleteFile(pathFrom) == OSFS::result::NO_ERROR)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#elif defined(FSCom)
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
// rename was fixed for ESP32 IDF LittleFS in April
|
// rename was fixed for ESP32 IDF LittleFS in April
|
||||||
return FSCom.rename(pathFrom, pathTo);
|
return FSCom.rename(pathFrom, pathTo);
|
||||||
@@ -84,6 +149,58 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the list of files in a directory.
|
||||||
|
*
|
||||||
|
* This function returns a list of files in a directory. The list includes the full path of each file.
|
||||||
|
*
|
||||||
|
* @param dirname The name of the directory.
|
||||||
|
* @param levels The number of levels of subdirectories to list.
|
||||||
|
* @return A vector of strings containing the full path of each file in the directory.
|
||||||
|
*/
|
||||||
|
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels)
|
||||||
|
{
|
||||||
|
std::vector<meshtastic_FileInfo> filenames = {};
|
||||||
|
#ifdef FSCom
|
||||||
|
File root = FSCom.open(dirname, FILE_O_READ);
|
||||||
|
if (!root)
|
||||||
|
return filenames;
|
||||||
|
if (!root.isDirectory())
|
||||||
|
return filenames;
|
||||||
|
|
||||||
|
File file = root.openNextFile();
|
||||||
|
while (file) {
|
||||||
|
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||||
|
if (levels) {
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.path(), levels - 1);
|
||||||
|
#else
|
||||||
|
std::vector<meshtastic_FileInfo> subDirFilenames = getFiles(file.name(), levels - 1);
|
||||||
|
#endif
|
||||||
|
filenames.insert(filenames.end(), subDirFilenames.begin(), subDirFilenames.end());
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
meshtastic_FileInfo fileInfo = {"", file.size()};
|
||||||
|
#ifdef ARCH_ESP32
|
||||||
|
strcpy(fileInfo.file_name, file.path());
|
||||||
|
#else
|
||||||
|
strcpy(fileInfo.file_name, file.name());
|
||||||
|
#endif
|
||||||
|
if (!String(fileInfo.file_name).endsWith(".")) {
|
||||||
|
filenames.push_back(fileInfo);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
file = root.openNextFile();
|
||||||
|
}
|
||||||
|
root.close();
|
||||||
|
#endif
|
||||||
|
return filenames;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists the contents of a directory.
|
* Lists the contents of a directory.
|
||||||
*
|
*
|
||||||
@@ -91,7 +208,7 @@ bool renameFile(const char *pathFrom, const char *pathTo)
|
|||||||
* @param levels The number of levels of subdirectories to list.
|
* @param levels The number of levels of subdirectories to list.
|
||||||
* @param del Whether or not to delete the contents of the directory after listing.
|
* @param del Whether or not to delete the contents of the directory after listing.
|
||||||
*/
|
*/
|
||||||
void listDir(const char *dirname, uint8_t levels, bool del = false)
|
void listDir(const char *dirname, uint8_t levels, bool del)
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
#if (defined(ARCH_ESP32) || defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||||
@@ -106,7 +223,9 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
|
|||||||
}
|
}
|
||||||
|
|
||||||
File file = root.openNextFile();
|
File file = root.openNextFile();
|
||||||
while (file) {
|
while (
|
||||||
|
file &&
|
||||||
|
file.name()[0]) { // This file.name() check is a workaround for a bug in the Adafruit LittleFS nrf52 glue (see issue 4395)
|
||||||
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
if (file.isDirectory() && !String(file.name()).endsWith(".")) {
|
||||||
if (levels) {
|
if (levels) {
|
||||||
#ifdef ARCH_ESP32
|
#ifdef ARCH_ESP32
|
||||||
@@ -130,6 +249,7 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
|
|||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
LOG_DEBUG(" %s (directory)\n", file.name());
|
||||||
listDir(file.name(), levels - 1, del);
|
listDir(file.name(), levels - 1, del);
|
||||||
file.close();
|
file.close();
|
||||||
#endif
|
#endif
|
||||||
@@ -156,7 +276,7 @@ void listDir(const char *dirname, uint8_t levels, bool del = false)
|
|||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
|
LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||||
file.close();
|
file.close();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -212,7 +332,7 @@ void fsInit()
|
|||||||
LOG_ERROR("Filesystem mount Failed.\n");
|
LOG_ERROR("Filesystem mount Failed.\n");
|
||||||
// assert(0); This auto-formats the partition, so no need to fail here.
|
// assert(0); This auto-formats the partition, so no need to fail here.
|
||||||
}
|
}
|
||||||
#ifdef ARCH_ESP32
|
#if defined(ARCH_ESP32)
|
||||||
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
|
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
|
||||||
#else
|
#else
|
||||||
LOG_DEBUG("Filesystem files:\n");
|
LOG_DEBUG("Filesystem files:\n");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
// Cross platform filesystem API
|
// Cross platform filesystem API
|
||||||
|
|
||||||
@@ -14,10 +15,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_STM32WL)
|
#if defined(ARCH_STM32WL)
|
||||||
#include "platform/stm32wl/InternalFileSystem.h" // STM32WL version
|
// STM32WL series 2 Kbytes (8 rows of 256 bytes)
|
||||||
#define FSCom InternalFS
|
#include <EEPROM.h>
|
||||||
#define FSBegin() FSCom.begin()
|
#include <OSFS.h>
|
||||||
using namespace LittleFS_Namespace;
|
|
||||||
|
// Useful consts
|
||||||
|
const OSFS::result noerr = OSFS::result::NO_ERROR;
|
||||||
|
const OSFS::result notfound = OSFS::result::FILE_NOT_FOUND;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(ARCH_RP2040)
|
#if defined(ARCH_RP2040)
|
||||||
@@ -47,8 +51,13 @@ using namespace Adafruit_LittleFS_Namespace;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void fsInit();
|
void fsInit();
|
||||||
|
void fsListFiles();
|
||||||
bool copyFile(const char *from, const char *to);
|
bool copyFile(const char *from, const char *to);
|
||||||
bool renameFile(const char *pathFrom, const char *pathTo);
|
bool renameFile(const char *pathFrom, const char *pathTo);
|
||||||
void listDir(const char *dirname, uint8_t levels, bool del);
|
std::vector<meshtastic_FileInfo> getFiles(const char *dirname, uint8_t levels);
|
||||||
|
void listDir(const char *dirname, uint8_t levels, bool del = false);
|
||||||
void rmDir(const char *dirname);
|
void rmDir(const char *dirname);
|
||||||
void setupSDCard();
|
void setupSDCard();
|
||||||
|
|
||||||
|
extern bool lfs_assert_failed; // Note: we use this global on all platforms, though it can only be set true on nrf52 (in our
|
||||||
|
// modified lfs_util.h)
|
||||||
|
|||||||
32
src/Fusion/Fusion.h
Normal file
32
src/Fusion/Fusion.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* @file Fusion.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Main header file for the Fusion library. This is the only file that
|
||||||
|
* needs to be included when using the library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_H
|
||||||
|
#define FUSION_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "FusionAhrs.h"
|
||||||
|
#include "FusionAxes.h"
|
||||||
|
#include "FusionCalibration.h"
|
||||||
|
#include "FusionCompass.h"
|
||||||
|
#include "FusionConvention.h"
|
||||||
|
#include "FusionMath.h"
|
||||||
|
#include "FusionOffset.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
542
src/Fusion/FusionAhrs.c
Normal file
542
src/Fusion/FusionAhrs.c
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionAhrs.c
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief AHRS algorithm to combine gyroscope, accelerometer, and magnetometer
|
||||||
|
* measurements into a single measurement of orientation relative to the Earth.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionAhrs.h"
|
||||||
|
#include <float.h> // FLT_MAX
|
||||||
|
#include <math.h> // atan2f, cosf, fabsf, powf, sinf
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initial gain used during the initialisation.
|
||||||
|
*/
|
||||||
|
#define INITIAL_GAIN (10.0f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialisation period in seconds.
|
||||||
|
*/
|
||||||
|
#define INITIALISATION_PERIOD (3.0f)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Function declarations
|
||||||
|
|
||||||
|
static inline FusionVector HalfGravity(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
static inline FusionVector HalfMagnetic(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
static inline FusionVector Feedback(const FusionVector sensor, const FusionVector reference);
|
||||||
|
|
||||||
|
static inline int Clamp(const int value, const int min, const int max);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialises the AHRS algorithm structure.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
*/
|
||||||
|
void FusionAhrsInitialise(FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
const FusionAhrsSettings settings = {
|
||||||
|
.convention = FusionConventionNwu,
|
||||||
|
.gain = 0.5f,
|
||||||
|
.gyroscopeRange = 0.0f,
|
||||||
|
.accelerationRejection = 90.0f,
|
||||||
|
.magneticRejection = 90.0f,
|
||||||
|
.recoveryTriggerPeriod = 0,
|
||||||
|
};
|
||||||
|
FusionAhrsSetSettings(ahrs, &settings);
|
||||||
|
FusionAhrsReset(ahrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets the AHRS algorithm. This is equivalent to reinitialising the
|
||||||
|
* algorithm while maintaining the current settings.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
*/
|
||||||
|
void FusionAhrsReset(FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
ahrs->quaternion = FUSION_IDENTITY_QUATERNION;
|
||||||
|
ahrs->accelerometer = FUSION_VECTOR_ZERO;
|
||||||
|
ahrs->initialising = true;
|
||||||
|
ahrs->rampedGain = INITIAL_GAIN;
|
||||||
|
ahrs->angularRateRecovery = false;
|
||||||
|
ahrs->halfAccelerometerFeedback = FUSION_VECTOR_ZERO;
|
||||||
|
ahrs->halfMagnetometerFeedback = FUSION_VECTOR_ZERO;
|
||||||
|
ahrs->accelerometerIgnored = false;
|
||||||
|
ahrs->accelerationRecoveryTrigger = 0;
|
||||||
|
ahrs->accelerationRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
ahrs->magnetometerIgnored = false;
|
||||||
|
ahrs->magneticRecoveryTrigger = 0;
|
||||||
|
ahrs->magneticRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the AHRS algorithm settings.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param settings Settings.
|
||||||
|
*/
|
||||||
|
void FusionAhrsSetSettings(FusionAhrs *const ahrs, const FusionAhrsSettings *const settings)
|
||||||
|
{
|
||||||
|
ahrs->settings.convention = settings->convention;
|
||||||
|
ahrs->settings.gain = settings->gain;
|
||||||
|
ahrs->settings.gyroscopeRange = settings->gyroscopeRange == 0.0f ? FLT_MAX : 0.98f * settings->gyroscopeRange;
|
||||||
|
ahrs->settings.accelerationRejection = settings->accelerationRejection == 0.0f
|
||||||
|
? FLT_MAX
|
||||||
|
: powf(0.5f * sinf(FusionDegreesToRadians(settings->accelerationRejection)), 2);
|
||||||
|
ahrs->settings.magneticRejection =
|
||||||
|
settings->magneticRejection == 0.0f ? FLT_MAX : powf(0.5f * sinf(FusionDegreesToRadians(settings->magneticRejection)), 2);
|
||||||
|
ahrs->settings.recoveryTriggerPeriod = settings->recoveryTriggerPeriod;
|
||||||
|
ahrs->accelerationRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
ahrs->magneticRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
if ((settings->gain == 0.0f) ||
|
||||||
|
(settings->recoveryTriggerPeriod == 0)) { // disable acceleration and magnetic rejection features if gain is zero
|
||||||
|
ahrs->settings.accelerationRejection = FLT_MAX;
|
||||||
|
ahrs->settings.magneticRejection = FLT_MAX;
|
||||||
|
}
|
||||||
|
if (ahrs->initialising == false) {
|
||||||
|
ahrs->rampedGain = ahrs->settings.gain;
|
||||||
|
}
|
||||||
|
ahrs->rampedGainStep = (INITIAL_GAIN - ahrs->settings.gain) / INITIALISATION_PERIOD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates the AHRS algorithm using the gyroscope, accelerometer, and
|
||||||
|
* magnetometer measurements.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param gyroscope Gyroscope measurement in degrees per second.
|
||||||
|
* @param accelerometer Accelerometer measurement in g.
|
||||||
|
* @param magnetometer Magnetometer measurement in arbitrary units.
|
||||||
|
* @param deltaTime Delta time in seconds.
|
||||||
|
*/
|
||||||
|
void FusionAhrsUpdate(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const FusionVector magnetometer, const float deltaTime)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
|
||||||
|
// Store accelerometer
|
||||||
|
ahrs->accelerometer = accelerometer;
|
||||||
|
|
||||||
|
// Reinitialise if gyroscope range exceeded
|
||||||
|
if ((fabsf(gyroscope.axis.x) > ahrs->settings.gyroscopeRange) || (fabsf(gyroscope.axis.y) > ahrs->settings.gyroscopeRange) ||
|
||||||
|
(fabsf(gyroscope.axis.z) > ahrs->settings.gyroscopeRange)) {
|
||||||
|
const FusionQuaternion quaternion = ahrs->quaternion;
|
||||||
|
FusionAhrsReset(ahrs);
|
||||||
|
ahrs->quaternion = quaternion;
|
||||||
|
ahrs->angularRateRecovery = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ramp down gain during initialisation
|
||||||
|
if (ahrs->initialising) {
|
||||||
|
ahrs->rampedGain -= ahrs->rampedGainStep * deltaTime;
|
||||||
|
if ((ahrs->rampedGain < ahrs->settings.gain) || (ahrs->settings.gain == 0.0f)) {
|
||||||
|
ahrs->rampedGain = ahrs->settings.gain;
|
||||||
|
ahrs->initialising = false;
|
||||||
|
ahrs->angularRateRecovery = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate direction of gravity indicated by algorithm
|
||||||
|
const FusionVector halfGravity = HalfGravity(ahrs);
|
||||||
|
|
||||||
|
// Calculate accelerometer feedback
|
||||||
|
FusionVector halfAccelerometerFeedback = FUSION_VECTOR_ZERO;
|
||||||
|
ahrs->accelerometerIgnored = true;
|
||||||
|
if (FusionVectorIsZero(accelerometer) == false) {
|
||||||
|
|
||||||
|
// Calculate accelerometer feedback scaled by 0.5
|
||||||
|
ahrs->halfAccelerometerFeedback = Feedback(FusionVectorNormalise(accelerometer), halfGravity);
|
||||||
|
|
||||||
|
// Don't ignore accelerometer if acceleration error below threshold
|
||||||
|
if (ahrs->initialising ||
|
||||||
|
((FusionVectorMagnitudeSquared(ahrs->halfAccelerometerFeedback) <= ahrs->settings.accelerationRejection))) {
|
||||||
|
ahrs->accelerometerIgnored = false;
|
||||||
|
ahrs->accelerationRecoveryTrigger -= 9;
|
||||||
|
} else {
|
||||||
|
ahrs->accelerationRecoveryTrigger += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't ignore accelerometer during acceleration recovery
|
||||||
|
if (ahrs->accelerationRecoveryTrigger > ahrs->accelerationRecoveryTimeout) {
|
||||||
|
ahrs->accelerationRecoveryTimeout = 0;
|
||||||
|
ahrs->accelerometerIgnored = false;
|
||||||
|
} else {
|
||||||
|
ahrs->accelerationRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
}
|
||||||
|
ahrs->accelerationRecoveryTrigger = Clamp(ahrs->accelerationRecoveryTrigger, 0, ahrs->settings.recoveryTriggerPeriod);
|
||||||
|
|
||||||
|
// Apply accelerometer feedback
|
||||||
|
if (ahrs->accelerometerIgnored == false) {
|
||||||
|
halfAccelerometerFeedback = ahrs->halfAccelerometerFeedback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate magnetometer feedback
|
||||||
|
FusionVector halfMagnetometerFeedback = FUSION_VECTOR_ZERO;
|
||||||
|
ahrs->magnetometerIgnored = true;
|
||||||
|
if (FusionVectorIsZero(magnetometer) == false) {
|
||||||
|
|
||||||
|
// Calculate direction of magnetic field indicated by algorithm
|
||||||
|
const FusionVector halfMagnetic = HalfMagnetic(ahrs);
|
||||||
|
|
||||||
|
// Calculate magnetometer feedback scaled by 0.5
|
||||||
|
ahrs->halfMagnetometerFeedback =
|
||||||
|
Feedback(FusionVectorNormalise(FusionVectorCrossProduct(halfGravity, magnetometer)), halfMagnetic);
|
||||||
|
|
||||||
|
// Don't ignore magnetometer if magnetic error below threshold
|
||||||
|
if (ahrs->initialising ||
|
||||||
|
((FusionVectorMagnitudeSquared(ahrs->halfMagnetometerFeedback) <= ahrs->settings.magneticRejection))) {
|
||||||
|
ahrs->magnetometerIgnored = false;
|
||||||
|
ahrs->magneticRecoveryTrigger -= 9;
|
||||||
|
} else {
|
||||||
|
ahrs->magneticRecoveryTrigger += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't ignore magnetometer during magnetic recovery
|
||||||
|
if (ahrs->magneticRecoveryTrigger > ahrs->magneticRecoveryTimeout) {
|
||||||
|
ahrs->magneticRecoveryTimeout = 0;
|
||||||
|
ahrs->magnetometerIgnored = false;
|
||||||
|
} else {
|
||||||
|
ahrs->magneticRecoveryTimeout = ahrs->settings.recoveryTriggerPeriod;
|
||||||
|
}
|
||||||
|
ahrs->magneticRecoveryTrigger = Clamp(ahrs->magneticRecoveryTrigger, 0, ahrs->settings.recoveryTriggerPeriod);
|
||||||
|
|
||||||
|
// Apply magnetometer feedback
|
||||||
|
if (ahrs->magnetometerIgnored == false) {
|
||||||
|
halfMagnetometerFeedback = ahrs->halfMagnetometerFeedback;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert gyroscope to radians per second scaled by 0.5
|
||||||
|
const FusionVector halfGyroscope = FusionVectorMultiplyScalar(gyroscope, FusionDegreesToRadians(0.5f));
|
||||||
|
|
||||||
|
// Apply feedback to gyroscope
|
||||||
|
const FusionVector adjustedHalfGyroscope = FusionVectorAdd(
|
||||||
|
halfGyroscope,
|
||||||
|
FusionVectorMultiplyScalar(FusionVectorAdd(halfAccelerometerFeedback, halfMagnetometerFeedback), ahrs->rampedGain));
|
||||||
|
|
||||||
|
// Integrate rate of change of quaternion
|
||||||
|
ahrs->quaternion = FusionQuaternionAdd(
|
||||||
|
ahrs->quaternion,
|
||||||
|
FusionQuaternionMultiplyVector(ahrs->quaternion, FusionVectorMultiplyScalar(adjustedHalfGyroscope, deltaTime)));
|
||||||
|
|
||||||
|
// Normalise quaternion
|
||||||
|
ahrs->quaternion = FusionQuaternionNormalise(ahrs->quaternion);
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the direction of gravity scaled by 0.5.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return Direction of gravity scaled by 0.5.
|
||||||
|
*/
|
||||||
|
static inline FusionVector HalfGravity(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
switch (ahrs->settings.convention) {
|
||||||
|
case FusionConventionNwu:
|
||||||
|
case FusionConventionEnu: {
|
||||||
|
const FusionVector halfGravity = {.axis = {
|
||||||
|
.x = Q.x * Q.z - Q.w * Q.y,
|
||||||
|
.y = Q.y * Q.z + Q.w * Q.x,
|
||||||
|
.z = Q.w * Q.w - 0.5f + Q.z * Q.z,
|
||||||
|
}}; // third column of transposed rotation matrix scaled by 0.5
|
||||||
|
return halfGravity;
|
||||||
|
}
|
||||||
|
case FusionConventionNed: {
|
||||||
|
const FusionVector halfGravity = {.axis = {
|
||||||
|
.x = Q.w * Q.y - Q.x * Q.z,
|
||||||
|
.y = -1.0f * (Q.y * Q.z + Q.w * Q.x),
|
||||||
|
.z = 0.5f - Q.w * Q.w - Q.z * Q.z,
|
||||||
|
}}; // third column of transposed rotation matrix scaled by -0.5
|
||||||
|
return halfGravity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FUSION_VECTOR_ZERO; // avoid compiler warning
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the direction of the magnetic field scaled by 0.5.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return Direction of the magnetic field scaled by 0.5.
|
||||||
|
*/
|
||||||
|
static inline FusionVector HalfMagnetic(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
switch (ahrs->settings.convention) {
|
||||||
|
case FusionConventionNwu: {
|
||||||
|
const FusionVector halfMagnetic = {.axis = {
|
||||||
|
.x = Q.x * Q.y + Q.w * Q.z,
|
||||||
|
.y = Q.w * Q.w - 0.5f + Q.y * Q.y,
|
||||||
|
.z = Q.y * Q.z - Q.w * Q.x,
|
||||||
|
}}; // second column of transposed rotation matrix scaled by 0.5
|
||||||
|
return halfMagnetic;
|
||||||
|
}
|
||||||
|
case FusionConventionEnu: {
|
||||||
|
const FusionVector halfMagnetic = {.axis = {
|
||||||
|
.x = 0.5f - Q.w * Q.w - Q.x * Q.x,
|
||||||
|
.y = Q.w * Q.z - Q.x * Q.y,
|
||||||
|
.z = -1.0f * (Q.x * Q.z + Q.w * Q.y),
|
||||||
|
}}; // first column of transposed rotation matrix scaled by -0.5
|
||||||
|
return halfMagnetic;
|
||||||
|
}
|
||||||
|
case FusionConventionNed: {
|
||||||
|
const FusionVector halfMagnetic = {.axis = {
|
||||||
|
.x = -1.0f * (Q.x * Q.y + Q.w * Q.z),
|
||||||
|
.y = 0.5f - Q.w * Q.w - Q.y * Q.y,
|
||||||
|
.z = Q.w * Q.x - Q.y * Q.z,
|
||||||
|
}}; // second column of transposed rotation matrix scaled by -0.5
|
||||||
|
return halfMagnetic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FUSION_VECTOR_ZERO; // avoid compiler warning
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the feedback.
|
||||||
|
* @param sensor Sensor.
|
||||||
|
* @param reference Reference.
|
||||||
|
* @return Feedback.
|
||||||
|
*/
|
||||||
|
static inline FusionVector Feedback(const FusionVector sensor, const FusionVector reference)
|
||||||
|
{
|
||||||
|
if (FusionVectorDotProduct(sensor, reference) < 0.0f) { // if error is >90 degrees
|
||||||
|
return FusionVectorNormalise(FusionVectorCrossProduct(sensor, reference));
|
||||||
|
}
|
||||||
|
return FusionVectorCrossProduct(sensor, reference);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns a value limited to maximum and minimum.
|
||||||
|
* @param value Value.
|
||||||
|
* @param min Minimum value.
|
||||||
|
* @param max Maximum value.
|
||||||
|
* @return Value limited to maximum and minimum.
|
||||||
|
*/
|
||||||
|
static inline int Clamp(const int value, const int min, const int max)
|
||||||
|
{
|
||||||
|
if (value < min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
if (value > max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates the AHRS algorithm using the gyroscope and accelerometer
|
||||||
|
* measurements only.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param gyroscope Gyroscope measurement in degrees per second.
|
||||||
|
* @param accelerometer Accelerometer measurement in g.
|
||||||
|
* @param deltaTime Delta time in seconds.
|
||||||
|
*/
|
||||||
|
void FusionAhrsUpdateNoMagnetometer(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const float deltaTime)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Update AHRS algorithm
|
||||||
|
FusionAhrsUpdate(ahrs, gyroscope, accelerometer, FUSION_VECTOR_ZERO, deltaTime);
|
||||||
|
|
||||||
|
// Zero heading during initialisation
|
||||||
|
if (ahrs->initialising) {
|
||||||
|
FusionAhrsSetHeading(ahrs, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates the AHRS algorithm using the gyroscope, accelerometer, and
|
||||||
|
* heading measurements.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param gyroscope Gyroscope measurement in degrees per second.
|
||||||
|
* @param accelerometer Accelerometer measurement in g.
|
||||||
|
* @param heading Heading measurement in degrees.
|
||||||
|
* @param deltaTime Delta time in seconds.
|
||||||
|
*/
|
||||||
|
void FusionAhrsUpdateExternalHeading(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const float heading, const float deltaTime)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
|
||||||
|
// Calculate roll
|
||||||
|
const float roll = atan2f(Q.w * Q.x + Q.y * Q.z, 0.5f - Q.y * Q.y - Q.x * Q.x);
|
||||||
|
|
||||||
|
// Calculate magnetometer
|
||||||
|
const float headingRadians = FusionDegreesToRadians(heading);
|
||||||
|
const float sinHeadingRadians = sinf(headingRadians);
|
||||||
|
const FusionVector magnetometer = {.axis = {
|
||||||
|
.x = cosf(headingRadians),
|
||||||
|
.y = -1.0f * cosf(roll) * sinHeadingRadians,
|
||||||
|
.z = sinHeadingRadians * sinf(roll),
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Update AHRS algorithm
|
||||||
|
FusionAhrsUpdate(ahrs, gyroscope, accelerometer, magnetometer, deltaTime);
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the quaternion describing the sensor relative to the Earth.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return Quaternion describing the sensor relative to the Earth.
|
||||||
|
*/
|
||||||
|
FusionQuaternion FusionAhrsGetQuaternion(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
return ahrs->quaternion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the quaternion describing the sensor relative to the Earth.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param quaternion Quaternion describing the sensor relative to the Earth.
|
||||||
|
*/
|
||||||
|
void FusionAhrsSetQuaternion(FusionAhrs *const ahrs, const FusionQuaternion quaternion)
|
||||||
|
{
|
||||||
|
ahrs->quaternion = quaternion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the linear acceleration measurement equal to the accelerometer
|
||||||
|
* measurement with the 1 g of gravity removed.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return Linear acceleration measurement in g.
|
||||||
|
*/
|
||||||
|
FusionVector FusionAhrsGetLinearAcceleration(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
|
||||||
|
// Calculate gravity in the sensor coordinate frame
|
||||||
|
const FusionVector gravity = {.axis = {
|
||||||
|
.x = 2.0f * (Q.x * Q.z - Q.w * Q.y),
|
||||||
|
.y = 2.0f * (Q.y * Q.z + Q.w * Q.x),
|
||||||
|
.z = 2.0f * (Q.w * Q.w - 0.5f + Q.z * Q.z),
|
||||||
|
}}; // third column of transposed rotation matrix
|
||||||
|
|
||||||
|
// Remove gravity from accelerometer measurement
|
||||||
|
switch (ahrs->settings.convention) {
|
||||||
|
case FusionConventionNwu:
|
||||||
|
case FusionConventionEnu: {
|
||||||
|
return FusionVectorSubtract(ahrs->accelerometer, gravity);
|
||||||
|
}
|
||||||
|
case FusionConventionNed: {
|
||||||
|
return FusionVectorAdd(ahrs->accelerometer, gravity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return FUSION_VECTOR_ZERO; // avoid compiler warning
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the Earth acceleration measurement equal to accelerometer
|
||||||
|
* measurement in the Earth coordinate frame with the 1 g of gravity removed.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return Earth acceleration measurement in g.
|
||||||
|
*/
|
||||||
|
FusionVector FusionAhrsGetEarthAcceleration(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
#define A ahrs->accelerometer.axis
|
||||||
|
|
||||||
|
// Calculate accelerometer measurement in the Earth coordinate frame
|
||||||
|
const float qwqw = Q.w * Q.w; // calculate common terms to avoid repeated operations
|
||||||
|
const float qwqx = Q.w * Q.x;
|
||||||
|
const float qwqy = Q.w * Q.y;
|
||||||
|
const float qwqz = Q.w * Q.z;
|
||||||
|
const float qxqy = Q.x * Q.y;
|
||||||
|
const float qxqz = Q.x * Q.z;
|
||||||
|
const float qyqz = Q.y * Q.z;
|
||||||
|
FusionVector accelerometer = {.axis = {
|
||||||
|
.x = 2.0f * ((qwqw - 0.5f + Q.x * Q.x) * A.x + (qxqy - qwqz) * A.y + (qxqz + qwqy) * A.z),
|
||||||
|
.y = 2.0f * ((qxqy + qwqz) * A.x + (qwqw - 0.5f + Q.y * Q.y) * A.y + (qyqz - qwqx) * A.z),
|
||||||
|
.z = 2.0f * ((qxqz - qwqy) * A.x + (qyqz + qwqx) * A.y + (qwqw - 0.5f + Q.z * Q.z) * A.z),
|
||||||
|
}}; // rotation matrix multiplied with the accelerometer
|
||||||
|
|
||||||
|
// Remove gravity from accelerometer measurement
|
||||||
|
switch (ahrs->settings.convention) {
|
||||||
|
case FusionConventionNwu:
|
||||||
|
case FusionConventionEnu:
|
||||||
|
accelerometer.axis.z -= 1.0f;
|
||||||
|
break;
|
||||||
|
case FusionConventionNed:
|
||||||
|
accelerometer.axis.z += 1.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return accelerometer;
|
||||||
|
#undef Q
|
||||||
|
#undef A
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the AHRS algorithm internal states.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return AHRS algorithm internal states.
|
||||||
|
*/
|
||||||
|
FusionAhrsInternalStates FusionAhrsGetInternalStates(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
const FusionAhrsInternalStates internalStates = {
|
||||||
|
.accelerationError = FusionRadiansToDegrees(FusionAsin(2.0f * FusionVectorMagnitude(ahrs->halfAccelerometerFeedback))),
|
||||||
|
.accelerometerIgnored = ahrs->accelerometerIgnored,
|
||||||
|
.accelerationRecoveryTrigger =
|
||||||
|
ahrs->settings.recoveryTriggerPeriod == 0
|
||||||
|
? 0.0f
|
||||||
|
: (float)ahrs->accelerationRecoveryTrigger / (float)ahrs->settings.recoveryTriggerPeriod,
|
||||||
|
.magneticError = FusionRadiansToDegrees(FusionAsin(2.0f * FusionVectorMagnitude(ahrs->halfMagnetometerFeedback))),
|
||||||
|
.magnetometerIgnored = ahrs->magnetometerIgnored,
|
||||||
|
.magneticRecoveryTrigger = ahrs->settings.recoveryTriggerPeriod == 0
|
||||||
|
? 0.0f
|
||||||
|
: (float)ahrs->magneticRecoveryTrigger / (float)ahrs->settings.recoveryTriggerPeriod,
|
||||||
|
};
|
||||||
|
return internalStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the AHRS algorithm flags.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @return AHRS algorithm flags.
|
||||||
|
*/
|
||||||
|
FusionAhrsFlags FusionAhrsGetFlags(const FusionAhrs *const ahrs)
|
||||||
|
{
|
||||||
|
const FusionAhrsFlags flags = {
|
||||||
|
.initialising = ahrs->initialising,
|
||||||
|
.angularRateRecovery = ahrs->angularRateRecovery,
|
||||||
|
.accelerationRecovery = ahrs->accelerationRecoveryTrigger > ahrs->accelerationRecoveryTimeout,
|
||||||
|
.magneticRecovery = ahrs->magneticRecoveryTrigger > ahrs->magneticRecoveryTimeout,
|
||||||
|
};
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the heading of the orientation measurement provided by the AHRS
|
||||||
|
* algorithm. This function can be used to reset drift in heading when the AHRS
|
||||||
|
* algorithm is being used without a magnetometer.
|
||||||
|
* @param ahrs AHRS algorithm structure.
|
||||||
|
* @param heading Heading angle in degrees.
|
||||||
|
*/
|
||||||
|
void FusionAhrsSetHeading(FusionAhrs *const ahrs, const float heading)
|
||||||
|
{
|
||||||
|
#define Q ahrs->quaternion.element
|
||||||
|
const float yaw = atan2f(Q.w * Q.z + Q.x * Q.y, 0.5f - Q.y * Q.y - Q.z * Q.z);
|
||||||
|
const float halfYawMinusHeading = 0.5f * (yaw - FusionDegreesToRadians(heading));
|
||||||
|
const FusionQuaternion rotation = {.element = {
|
||||||
|
.w = cosf(halfYawMinusHeading),
|
||||||
|
.x = 0.0f,
|
||||||
|
.y = 0.0f,
|
||||||
|
.z = -1.0f * sinf(halfYawMinusHeading),
|
||||||
|
}};
|
||||||
|
ahrs->quaternion = FusionQuaternionMultiply(rotation, ahrs->quaternion);
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
112
src/Fusion/FusionAhrs.h
Normal file
112
src/Fusion/FusionAhrs.h
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionAhrs.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief AHRS algorithm to combine gyroscope, accelerometer, and magnetometer
|
||||||
|
* measurements into a single measurement of orientation relative to the Earth.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_AHRS_H
|
||||||
|
#define FUSION_AHRS_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionConvention.h"
|
||||||
|
#include "FusionMath.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AHRS algorithm settings.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
FusionConvention convention;
|
||||||
|
float gain;
|
||||||
|
float gyroscopeRange;
|
||||||
|
float accelerationRejection;
|
||||||
|
float magneticRejection;
|
||||||
|
unsigned int recoveryTriggerPeriod;
|
||||||
|
} FusionAhrsSettings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AHRS algorithm structure. Structure members are used internally and
|
||||||
|
* must not be accessed by the application.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
FusionAhrsSettings settings;
|
||||||
|
FusionQuaternion quaternion;
|
||||||
|
FusionVector accelerometer;
|
||||||
|
bool initialising;
|
||||||
|
float rampedGain;
|
||||||
|
float rampedGainStep;
|
||||||
|
bool angularRateRecovery;
|
||||||
|
FusionVector halfAccelerometerFeedback;
|
||||||
|
FusionVector halfMagnetometerFeedback;
|
||||||
|
bool accelerometerIgnored;
|
||||||
|
int accelerationRecoveryTrigger;
|
||||||
|
int accelerationRecoveryTimeout;
|
||||||
|
bool magnetometerIgnored;
|
||||||
|
int magneticRecoveryTrigger;
|
||||||
|
int magneticRecoveryTimeout;
|
||||||
|
} FusionAhrs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AHRS algorithm internal states.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
float accelerationError;
|
||||||
|
bool accelerometerIgnored;
|
||||||
|
float accelerationRecoveryTrigger;
|
||||||
|
float magneticError;
|
||||||
|
bool magnetometerIgnored;
|
||||||
|
float magneticRecoveryTrigger;
|
||||||
|
} FusionAhrsInternalStates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief AHRS algorithm flags.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
bool initialising;
|
||||||
|
bool angularRateRecovery;
|
||||||
|
bool accelerationRecovery;
|
||||||
|
bool magneticRecovery;
|
||||||
|
} FusionAhrsFlags;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Function declarations
|
||||||
|
|
||||||
|
void FusionAhrsInitialise(FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
void FusionAhrsReset(FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
void FusionAhrsSetSettings(FusionAhrs *const ahrs, const FusionAhrsSettings *const settings);
|
||||||
|
|
||||||
|
void FusionAhrsUpdate(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const FusionVector magnetometer, const float deltaTime);
|
||||||
|
|
||||||
|
void FusionAhrsUpdateNoMagnetometer(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const float deltaTime);
|
||||||
|
|
||||||
|
void FusionAhrsUpdateExternalHeading(FusionAhrs *const ahrs, const FusionVector gyroscope, const FusionVector accelerometer,
|
||||||
|
const float heading, const float deltaTime);
|
||||||
|
|
||||||
|
FusionQuaternion FusionAhrsGetQuaternion(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
void FusionAhrsSetQuaternion(FusionAhrs *const ahrs, const FusionQuaternion quaternion);
|
||||||
|
|
||||||
|
FusionVector FusionAhrsGetLinearAcceleration(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
FusionVector FusionAhrsGetEarthAcceleration(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
FusionAhrsInternalStates FusionAhrsGetInternalStates(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
FusionAhrsFlags FusionAhrsGetFlags(const FusionAhrs *const ahrs);
|
||||||
|
|
||||||
|
void FusionAhrsSetHeading(FusionAhrs *const ahrs, const float heading);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
188
src/Fusion/FusionAxes.h
Normal file
188
src/Fusion/FusionAxes.h
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionAxes.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Swaps sensor axes for alignment with the body axes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_AXES_H
|
||||||
|
#define FUSION_AXES_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionMath.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Axes alignment describing the sensor axes relative to the body axes.
|
||||||
|
* For example, if the body X axis is aligned with the sensor Y axis and the
|
||||||
|
* body Y axis is aligned with sensor X axis but pointing the opposite direction
|
||||||
|
* then alignment is +Y-X+Z.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
FusionAxesAlignmentPXPYPZ, /* +X+Y+Z */
|
||||||
|
FusionAxesAlignmentPXNZPY, /* +X-Z+Y */
|
||||||
|
FusionAxesAlignmentPXNYNZ, /* +X-Y-Z */
|
||||||
|
FusionAxesAlignmentPXPZNY, /* +X+Z-Y */
|
||||||
|
FusionAxesAlignmentNXPYNZ, /* -X+Y-Z */
|
||||||
|
FusionAxesAlignmentNXPZPY, /* -X+Z+Y */
|
||||||
|
FusionAxesAlignmentNXNYPZ, /* -X-Y+Z */
|
||||||
|
FusionAxesAlignmentNXNZNY, /* -X-Z-Y */
|
||||||
|
FusionAxesAlignmentPYNXPZ, /* +Y-X+Z */
|
||||||
|
FusionAxesAlignmentPYNZNX, /* +Y-Z-X */
|
||||||
|
FusionAxesAlignmentPYPXNZ, /* +Y+X-Z */
|
||||||
|
FusionAxesAlignmentPYPZPX, /* +Y+Z+X */
|
||||||
|
FusionAxesAlignmentNYPXPZ, /* -Y+X+Z */
|
||||||
|
FusionAxesAlignmentNYNZPX, /* -Y-Z+X */
|
||||||
|
FusionAxesAlignmentNYNXNZ, /* -Y-X-Z */
|
||||||
|
FusionAxesAlignmentNYPZNX, /* -Y+Z-X */
|
||||||
|
FusionAxesAlignmentPZPYNX, /* +Z+Y-X */
|
||||||
|
FusionAxesAlignmentPZPXPY, /* +Z+X+Y */
|
||||||
|
FusionAxesAlignmentPZNYPX, /* +Z-Y+X */
|
||||||
|
FusionAxesAlignmentPZNXNY, /* +Z-X-Y */
|
||||||
|
FusionAxesAlignmentNZPYPX, /* -Z+Y+X */
|
||||||
|
FusionAxesAlignmentNZNXPY, /* -Z-X+Y */
|
||||||
|
FusionAxesAlignmentNZNYNX, /* -Z-Y-X */
|
||||||
|
FusionAxesAlignmentNZPXNY, /* -Z+X-Y */
|
||||||
|
} FusionAxesAlignment;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Swaps sensor axes for alignment with the body axes.
|
||||||
|
* @param sensor Sensor axes.
|
||||||
|
* @param alignment Axes alignment.
|
||||||
|
* @return Sensor axes aligned with the body axes.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionAxesSwap(const FusionVector sensor, const FusionAxesAlignment alignment)
|
||||||
|
{
|
||||||
|
FusionVector result;
|
||||||
|
switch (alignment) {
|
||||||
|
case FusionAxesAlignmentPXPYPZ:
|
||||||
|
break;
|
||||||
|
case FusionAxesAlignmentPXNZPY:
|
||||||
|
result.axis.x = +sensor.axis.x;
|
||||||
|
result.axis.y = -sensor.axis.z;
|
||||||
|
result.axis.z = +sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPXNYNZ:
|
||||||
|
result.axis.x = +sensor.axis.x;
|
||||||
|
result.axis.y = -sensor.axis.y;
|
||||||
|
result.axis.z = -sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPXPZNY:
|
||||||
|
result.axis.x = +sensor.axis.x;
|
||||||
|
result.axis.y = +sensor.axis.z;
|
||||||
|
result.axis.z = -sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNXPYNZ:
|
||||||
|
result.axis.x = -sensor.axis.x;
|
||||||
|
result.axis.y = +sensor.axis.y;
|
||||||
|
result.axis.z = -sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNXPZPY:
|
||||||
|
result.axis.x = -sensor.axis.x;
|
||||||
|
result.axis.y = +sensor.axis.z;
|
||||||
|
result.axis.z = +sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNXNYPZ:
|
||||||
|
result.axis.x = -sensor.axis.x;
|
||||||
|
result.axis.y = -sensor.axis.y;
|
||||||
|
result.axis.z = +sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNXNZNY:
|
||||||
|
result.axis.x = -sensor.axis.x;
|
||||||
|
result.axis.y = -sensor.axis.z;
|
||||||
|
result.axis.z = -sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPYNXPZ:
|
||||||
|
result.axis.x = +sensor.axis.y;
|
||||||
|
result.axis.y = -sensor.axis.x;
|
||||||
|
result.axis.z = +sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPYNZNX:
|
||||||
|
result.axis.x = +sensor.axis.y;
|
||||||
|
result.axis.y = -sensor.axis.z;
|
||||||
|
result.axis.z = -sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPYPXNZ:
|
||||||
|
result.axis.x = +sensor.axis.y;
|
||||||
|
result.axis.y = +sensor.axis.x;
|
||||||
|
result.axis.z = -sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPYPZPX:
|
||||||
|
result.axis.x = +sensor.axis.y;
|
||||||
|
result.axis.y = +sensor.axis.z;
|
||||||
|
result.axis.z = +sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNYPXPZ:
|
||||||
|
result.axis.x = -sensor.axis.y;
|
||||||
|
result.axis.y = +sensor.axis.x;
|
||||||
|
result.axis.z = +sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNYNZPX:
|
||||||
|
result.axis.x = -sensor.axis.y;
|
||||||
|
result.axis.y = -sensor.axis.z;
|
||||||
|
result.axis.z = +sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNYNXNZ:
|
||||||
|
result.axis.x = -sensor.axis.y;
|
||||||
|
result.axis.y = -sensor.axis.x;
|
||||||
|
result.axis.z = -sensor.axis.z;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNYPZNX:
|
||||||
|
result.axis.x = -sensor.axis.y;
|
||||||
|
result.axis.y = +sensor.axis.z;
|
||||||
|
result.axis.z = -sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPZPYNX:
|
||||||
|
result.axis.x = +sensor.axis.z;
|
||||||
|
result.axis.y = +sensor.axis.y;
|
||||||
|
result.axis.z = -sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPZPXPY:
|
||||||
|
result.axis.x = +sensor.axis.z;
|
||||||
|
result.axis.y = +sensor.axis.x;
|
||||||
|
result.axis.z = +sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPZNYPX:
|
||||||
|
result.axis.x = +sensor.axis.z;
|
||||||
|
result.axis.y = -sensor.axis.y;
|
||||||
|
result.axis.z = +sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentPZNXNY:
|
||||||
|
result.axis.x = +sensor.axis.z;
|
||||||
|
result.axis.y = -sensor.axis.x;
|
||||||
|
result.axis.z = -sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNZPYPX:
|
||||||
|
result.axis.x = -sensor.axis.z;
|
||||||
|
result.axis.y = +sensor.axis.y;
|
||||||
|
result.axis.z = +sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNZNXPY:
|
||||||
|
result.axis.x = -sensor.axis.z;
|
||||||
|
result.axis.y = -sensor.axis.x;
|
||||||
|
result.axis.z = +sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNZNYNX:
|
||||||
|
result.axis.x = -sensor.axis.z;
|
||||||
|
result.axis.y = -sensor.axis.y;
|
||||||
|
result.axis.z = -sensor.axis.x;
|
||||||
|
return result;
|
||||||
|
case FusionAxesAlignmentNZPXNY:
|
||||||
|
result.axis.x = -sensor.axis.z;
|
||||||
|
result.axis.y = +sensor.axis.x;
|
||||||
|
result.axis.z = -sensor.axis.y;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return sensor; // avoid compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
49
src/Fusion/FusionCalibration.h
Normal file
49
src/Fusion/FusionCalibration.h
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionCalibration.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Gyroscope, accelerometer, and magnetometer calibration models.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_CALIBRATION_H
|
||||||
|
#define FUSION_CALIBRATION_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionMath.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gyroscope and accelerometer calibration model.
|
||||||
|
* @param uncalibrated Uncalibrated measurement.
|
||||||
|
* @param misalignment Misalignment matrix.
|
||||||
|
* @param sensitivity Sensitivity.
|
||||||
|
* @param offset Offset.
|
||||||
|
* @return Calibrated measurement.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionCalibrationInertial(const FusionVector uncalibrated, const FusionMatrix misalignment,
|
||||||
|
const FusionVector sensitivity, const FusionVector offset)
|
||||||
|
{
|
||||||
|
return FusionMatrixMultiplyVector(misalignment,
|
||||||
|
FusionVectorHadamardProduct(FusionVectorSubtract(uncalibrated, offset), sensitivity));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Magnetometer calibration model.
|
||||||
|
* @param uncalibrated Uncalibrated measurement.
|
||||||
|
* @param softIronMatrix Soft-iron matrix.
|
||||||
|
* @param hardIronOffset Hard-iron offset.
|
||||||
|
* @return Calibrated measurement.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionCalibrationMagnetic(const FusionVector uncalibrated, const FusionMatrix softIronMatrix,
|
||||||
|
const FusionVector hardIronOffset)
|
||||||
|
{
|
||||||
|
return FusionMatrixMultiplyVector(softIronMatrix, FusionVectorSubtract(uncalibrated, hardIronOffset));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
51
src/Fusion/FusionCompass.c
Normal file
51
src/Fusion/FusionCompass.c
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionCompass.c
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Tilt-compensated compass to calculate the magnetic heading using
|
||||||
|
* accelerometer and magnetometer measurements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionCompass.h"
|
||||||
|
#include "FusionAxes.h"
|
||||||
|
#include <math.h> // atan2f
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates the magnetic heading.
|
||||||
|
* @param convention Earth axes convention.
|
||||||
|
* @param accelerometer Accelerometer measurement in any calibrated units.
|
||||||
|
* @param magnetometer Magnetometer measurement in any calibrated units.
|
||||||
|
* @return Heading angle in degrees.
|
||||||
|
*/
|
||||||
|
float FusionCompassCalculateHeading(const FusionConvention convention, const FusionVector accelerometer,
|
||||||
|
const FusionVector magnetometer)
|
||||||
|
{
|
||||||
|
switch (convention) {
|
||||||
|
case FusionConventionNwu: {
|
||||||
|
const FusionVector west = FusionVectorNormalise(FusionVectorCrossProduct(accelerometer, magnetometer));
|
||||||
|
const FusionVector north = FusionVectorNormalise(FusionVectorCrossProduct(west, accelerometer));
|
||||||
|
return FusionRadiansToDegrees(atan2f(west.axis.x, north.axis.x));
|
||||||
|
}
|
||||||
|
case FusionConventionEnu: {
|
||||||
|
const FusionVector west = FusionVectorNormalise(FusionVectorCrossProduct(accelerometer, magnetometer));
|
||||||
|
const FusionVector north = FusionVectorNormalise(FusionVectorCrossProduct(west, accelerometer));
|
||||||
|
const FusionVector east = FusionVectorMultiplyScalar(west, -1.0f);
|
||||||
|
return FusionRadiansToDegrees(atan2f(north.axis.x, east.axis.x));
|
||||||
|
}
|
||||||
|
case FusionConventionNed: {
|
||||||
|
const FusionVector up = FusionVectorMultiplyScalar(accelerometer, -1.0f);
|
||||||
|
const FusionVector west = FusionVectorNormalise(FusionVectorCrossProduct(up, magnetometer));
|
||||||
|
const FusionVector north = FusionVectorNormalise(FusionVectorCrossProduct(west, up));
|
||||||
|
return FusionRadiansToDegrees(atan2f(west.axis.x, north.axis.x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0; // avoid compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
26
src/Fusion/FusionCompass.h
Normal file
26
src/Fusion/FusionCompass.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionCompass.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Tilt-compensated compass to calculate the magnetic heading using
|
||||||
|
* accelerometer and magnetometer measurements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_COMPASS_H
|
||||||
|
#define FUSION_COMPASS_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionConvention.h"
|
||||||
|
#include "FusionMath.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Function declarations
|
||||||
|
|
||||||
|
float FusionCompassCalculateHeading(const FusionConvention convention, const FusionVector accelerometer,
|
||||||
|
const FusionVector magnetometer);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
25
src/Fusion/FusionConvention.h
Normal file
25
src/Fusion/FusionConvention.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionConvention.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Earth axes convention.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_CONVENTION_H
|
||||||
|
#define FUSION_CONVENTION_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Earth axes convention.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
FusionConventionNwu, /* North-West-Up */
|
||||||
|
FusionConventionEnu, /* East-North-Up */
|
||||||
|
FusionConventionNed, /* North-East-Down */
|
||||||
|
} FusionConvention;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
503
src/Fusion/FusionMath.h
Normal file
503
src/Fusion/FusionMath.h
Normal file
@@ -0,0 +1,503 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionMath.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Math library.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_MATH_H
|
||||||
|
#define FUSION_MATH_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include <math.h> // M_PI, sqrtf, atan2f, asinf
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 3D vector.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
float array[3];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} axis;
|
||||||
|
} FusionVector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Quaternion.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
float array[4];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float w;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float z;
|
||||||
|
} element;
|
||||||
|
} FusionQuaternion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 3x3 matrix in row-major order.
|
||||||
|
* See http://en.wikipedia.org/wiki/Row-major_order
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
float array[3][3];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float xx;
|
||||||
|
float xy;
|
||||||
|
float xz;
|
||||||
|
float yx;
|
||||||
|
float yy;
|
||||||
|
float yz;
|
||||||
|
float zx;
|
||||||
|
float zy;
|
||||||
|
float zz;
|
||||||
|
} element;
|
||||||
|
} FusionMatrix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Euler angles. Roll, pitch, and yaw correspond to rotations around
|
||||||
|
* X, Y, and Z respectively.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
float array[3];
|
||||||
|
|
||||||
|
struct {
|
||||||
|
float roll;
|
||||||
|
float pitch;
|
||||||
|
float yaw;
|
||||||
|
} angle;
|
||||||
|
} FusionEuler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vector of zeros.
|
||||||
|
*/
|
||||||
|
#define FUSION_VECTOR_ZERO ((FusionVector){.array = {0.0f, 0.0f, 0.0f}})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Vector of ones.
|
||||||
|
*/
|
||||||
|
#define FUSION_VECTOR_ONES ((FusionVector){.array = {1.0f, 1.0f, 1.0f}})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identity quaternion.
|
||||||
|
*/
|
||||||
|
#define FUSION_IDENTITY_QUATERNION ((FusionQuaternion){.array = {1.0f, 0.0f, 0.0f, 0.0f}})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Identity matrix.
|
||||||
|
*/
|
||||||
|
#define FUSION_IDENTITY_MATRIX ((FusionMatrix){.array = {{1.0f, 0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}}})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Euler angles of zero.
|
||||||
|
*/
|
||||||
|
#define FUSION_EULER_ZERO ((FusionEuler){.array = {0.0f, 0.0f, 0.0f}})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Pi. May not be defined in math.h.
|
||||||
|
*/
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI (3.14159265358979323846)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Include this definition or add as a preprocessor definition to use
|
||||||
|
* normal square root operations.
|
||||||
|
*/
|
||||||
|
// #define FUSION_USE_NORMAL_SQRT
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Degrees and radians conversion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts degrees to radians.
|
||||||
|
* @param degrees Degrees.
|
||||||
|
* @return Radians.
|
||||||
|
*/
|
||||||
|
static inline float FusionDegreesToRadians(const float degrees)
|
||||||
|
{
|
||||||
|
return degrees * ((float)M_PI / 180.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts radians to degrees.
|
||||||
|
* @param radians Radians.
|
||||||
|
* @return Degrees.
|
||||||
|
*/
|
||||||
|
static inline float FusionRadiansToDegrees(const float radians)
|
||||||
|
{
|
||||||
|
return radians * (180.0f / (float)M_PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Arc sine
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the arc sine of the value.
|
||||||
|
* @param value Value.
|
||||||
|
* @return Arc sine of the value.
|
||||||
|
*/
|
||||||
|
static inline float FusionAsin(const float value)
|
||||||
|
{
|
||||||
|
if (value <= -1.0f) {
|
||||||
|
return (float)M_PI / -2.0f;
|
||||||
|
}
|
||||||
|
if (value >= 1.0f) {
|
||||||
|
return (float)M_PI / 2.0f;
|
||||||
|
}
|
||||||
|
return asinf(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Fast inverse square root
|
||||||
|
|
||||||
|
#ifndef FUSION_USE_NORMAL_SQRT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates the reciprocal of the square root.
|
||||||
|
* See https://pizer.wordpress.com/2008/10/12/fast-inverse-square-root/
|
||||||
|
* @param x Operand.
|
||||||
|
* @return Reciprocal of the square root of x.
|
||||||
|
*/
|
||||||
|
static inline float FusionFastInverseSqrt(const float x)
|
||||||
|
{
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
float f;
|
||||||
|
int32_t i;
|
||||||
|
} Union32;
|
||||||
|
|
||||||
|
Union32 union32 = {.f = x};
|
||||||
|
union32.i = 0x5F1F1412 - (union32.i >> 1);
|
||||||
|
return union32.f * (1.69000231f - 0.714158168f * x * union32.f * union32.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Vector operations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the vector is zero.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return True if the vector is zero.
|
||||||
|
*/
|
||||||
|
static inline bool FusionVectorIsZero(const FusionVector vector)
|
||||||
|
{
|
||||||
|
return (vector.axis.x == 0.0f) && (vector.axis.y == 0.0f) && (vector.axis.z == 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the sum of two vectors.
|
||||||
|
* @param vectorA Vector A.
|
||||||
|
* @param vectorB Vector B.
|
||||||
|
* @return Sum of two vectors.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorAdd(const FusionVector vectorA, const FusionVector vectorB)
|
||||||
|
{
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = vectorA.axis.x + vectorB.axis.x,
|
||||||
|
.y = vectorA.axis.y + vectorB.axis.y,
|
||||||
|
.z = vectorA.axis.z + vectorB.axis.z,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns vector B subtracted from vector A.
|
||||||
|
* @param vectorA Vector A.
|
||||||
|
* @param vectorB Vector B.
|
||||||
|
* @return Vector B subtracted from vector A.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorSubtract(const FusionVector vectorA, const FusionVector vectorB)
|
||||||
|
{
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = vectorA.axis.x - vectorB.axis.x,
|
||||||
|
.y = vectorA.axis.y - vectorB.axis.y,
|
||||||
|
.z = vectorA.axis.z - vectorB.axis.z,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the sum of the elements.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Sum of the elements.
|
||||||
|
*/
|
||||||
|
static inline float FusionVectorSum(const FusionVector vector)
|
||||||
|
{
|
||||||
|
return vector.axis.x + vector.axis.y + vector.axis.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the multiplication of a vector by a scalar.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @param scalar Scalar.
|
||||||
|
* @return Multiplication of a vector by a scalar.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorMultiplyScalar(const FusionVector vector, const float scalar)
|
||||||
|
{
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = vector.axis.x * scalar,
|
||||||
|
.y = vector.axis.y * scalar,
|
||||||
|
.z = vector.axis.z * scalar,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculates the Hadamard product (element-wise multiplication).
|
||||||
|
* @param vectorA Vector A.
|
||||||
|
* @param vectorB Vector B.
|
||||||
|
* @return Hadamard product.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorHadamardProduct(const FusionVector vectorA, const FusionVector vectorB)
|
||||||
|
{
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = vectorA.axis.x * vectorB.axis.x,
|
||||||
|
.y = vectorA.axis.y * vectorB.axis.y,
|
||||||
|
.z = vectorA.axis.z * vectorB.axis.z,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the cross product.
|
||||||
|
* @param vectorA Vector A.
|
||||||
|
* @param vectorB Vector B.
|
||||||
|
* @return Cross product.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorCrossProduct(const FusionVector vectorA, const FusionVector vectorB)
|
||||||
|
{
|
||||||
|
#define A vectorA.axis
|
||||||
|
#define B vectorB.axis
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = A.y * B.z - A.z * B.y,
|
||||||
|
.y = A.z * B.x - A.x * B.z,
|
||||||
|
.z = A.x * B.y - A.y * B.x,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
#undef A
|
||||||
|
#undef B
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the dot product.
|
||||||
|
* @param vectorA Vector A.
|
||||||
|
* @param vectorB Vector B.
|
||||||
|
* @return Dot product.
|
||||||
|
*/
|
||||||
|
static inline float FusionVectorDotProduct(const FusionVector vectorA, const FusionVector vectorB)
|
||||||
|
{
|
||||||
|
return FusionVectorSum(FusionVectorHadamardProduct(vectorA, vectorB));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the vector magnitude squared.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Vector magnitude squared.
|
||||||
|
*/
|
||||||
|
static inline float FusionVectorMagnitudeSquared(const FusionVector vector)
|
||||||
|
{
|
||||||
|
return FusionVectorSum(FusionVectorHadamardProduct(vector, vector));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the vector magnitude.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Vector magnitude.
|
||||||
|
*/
|
||||||
|
static inline float FusionVectorMagnitude(const FusionVector vector)
|
||||||
|
{
|
||||||
|
return sqrtf(FusionVectorMagnitudeSquared(vector));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the normalised vector.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Normalised vector.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionVectorNormalise(const FusionVector vector)
|
||||||
|
{
|
||||||
|
#ifdef FUSION_USE_NORMAL_SQRT
|
||||||
|
const float magnitudeReciprocal = 1.0f / sqrtf(FusionVectorMagnitudeSquared(vector));
|
||||||
|
#else
|
||||||
|
const float magnitudeReciprocal = FusionFastInverseSqrt(FusionVectorMagnitudeSquared(vector));
|
||||||
|
#endif
|
||||||
|
return FusionVectorMultiplyScalar(vector, magnitudeReciprocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Quaternion operations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the sum of two quaternions.
|
||||||
|
* @param quaternionA Quaternion A.
|
||||||
|
* @param quaternionB Quaternion B.
|
||||||
|
* @return Sum of two quaternions.
|
||||||
|
*/
|
||||||
|
static inline FusionQuaternion FusionQuaternionAdd(const FusionQuaternion quaternionA, const FusionQuaternion quaternionB)
|
||||||
|
{
|
||||||
|
const FusionQuaternion result = {.element = {
|
||||||
|
.w = quaternionA.element.w + quaternionB.element.w,
|
||||||
|
.x = quaternionA.element.x + quaternionB.element.x,
|
||||||
|
.y = quaternionA.element.y + quaternionB.element.y,
|
||||||
|
.z = quaternionA.element.z + quaternionB.element.z,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the multiplication of two quaternions.
|
||||||
|
* @param quaternionA Quaternion A (to be post-multiplied).
|
||||||
|
* @param quaternionB Quaternion B (to be pre-multiplied).
|
||||||
|
* @return Multiplication of two quaternions.
|
||||||
|
*/
|
||||||
|
static inline FusionQuaternion FusionQuaternionMultiply(const FusionQuaternion quaternionA, const FusionQuaternion quaternionB)
|
||||||
|
{
|
||||||
|
#define A quaternionA.element
|
||||||
|
#define B quaternionB.element
|
||||||
|
const FusionQuaternion result = {.element = {
|
||||||
|
.w = A.w * B.w - A.x * B.x - A.y * B.y - A.z * B.z,
|
||||||
|
.x = A.w * B.x + A.x * B.w + A.y * B.z - A.z * B.y,
|
||||||
|
.y = A.w * B.y - A.x * B.z + A.y * B.w + A.z * B.x,
|
||||||
|
.z = A.w * B.z + A.x * B.y - A.y * B.x + A.z * B.w,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
#undef A
|
||||||
|
#undef B
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the multiplication of a quaternion with a vector. This is a
|
||||||
|
* normal quaternion multiplication where the vector is treated a
|
||||||
|
* quaternion with a W element value of zero. The quaternion is post-
|
||||||
|
* multiplied by the vector.
|
||||||
|
* @param quaternion Quaternion.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Multiplication of a quaternion with a vector.
|
||||||
|
*/
|
||||||
|
static inline FusionQuaternion FusionQuaternionMultiplyVector(const FusionQuaternion quaternion, const FusionVector vector)
|
||||||
|
{
|
||||||
|
#define Q quaternion.element
|
||||||
|
#define V vector.axis
|
||||||
|
const FusionQuaternion result = {.element = {
|
||||||
|
.w = -Q.x * V.x - Q.y * V.y - Q.z * V.z,
|
||||||
|
.x = Q.w * V.x + Q.y * V.z - Q.z * V.y,
|
||||||
|
.y = Q.w * V.y - Q.x * V.z + Q.z * V.x,
|
||||||
|
.z = Q.w * V.z + Q.x * V.y - Q.y * V.x,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
#undef Q
|
||||||
|
#undef V
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the normalised quaternion.
|
||||||
|
* @param quaternion Quaternion.
|
||||||
|
* @return Normalised quaternion.
|
||||||
|
*/
|
||||||
|
static inline FusionQuaternion FusionQuaternionNormalise(const FusionQuaternion quaternion)
|
||||||
|
{
|
||||||
|
#define Q quaternion.element
|
||||||
|
#ifdef FUSION_USE_NORMAL_SQRT
|
||||||
|
const float magnitudeReciprocal = 1.0f / sqrtf(Q.w * Q.w + Q.x * Q.x + Q.y * Q.y + Q.z * Q.z);
|
||||||
|
#else
|
||||||
|
const float magnitudeReciprocal = FusionFastInverseSqrt(Q.w * Q.w + Q.x * Q.x + Q.y * Q.y + Q.z * Q.z);
|
||||||
|
#endif
|
||||||
|
const FusionQuaternion result = {.element = {
|
||||||
|
.w = Q.w * magnitudeReciprocal,
|
||||||
|
.x = Q.x * magnitudeReciprocal,
|
||||||
|
.y = Q.y * magnitudeReciprocal,
|
||||||
|
.z = Q.z * magnitudeReciprocal,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Matrix operations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the multiplication of a matrix with a vector.
|
||||||
|
* @param matrix Matrix.
|
||||||
|
* @param vector Vector.
|
||||||
|
* @return Multiplication of a matrix with a vector.
|
||||||
|
*/
|
||||||
|
static inline FusionVector FusionMatrixMultiplyVector(const FusionMatrix matrix, const FusionVector vector)
|
||||||
|
{
|
||||||
|
#define R matrix.element
|
||||||
|
const FusionVector result = {.axis = {
|
||||||
|
.x = R.xx * vector.axis.x + R.xy * vector.axis.y + R.xz * vector.axis.z,
|
||||||
|
.y = R.yx * vector.axis.x + R.yy * vector.axis.y + R.yz * vector.axis.z,
|
||||||
|
.z = R.zx * vector.axis.x + R.zy * vector.axis.y + R.zz * vector.axis.z,
|
||||||
|
}};
|
||||||
|
return result;
|
||||||
|
#undef R
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Inline functions - Conversion operations
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts a quaternion to a rotation matrix.
|
||||||
|
* @param quaternion Quaternion.
|
||||||
|
* @return Rotation matrix.
|
||||||
|
*/
|
||||||
|
static inline FusionMatrix FusionQuaternionToMatrix(const FusionQuaternion quaternion)
|
||||||
|
{
|
||||||
|
#define Q quaternion.element
|
||||||
|
const float qwqw = Q.w * Q.w; // calculate common terms to avoid repeated operations
|
||||||
|
const float qwqx = Q.w * Q.x;
|
||||||
|
const float qwqy = Q.w * Q.y;
|
||||||
|
const float qwqz = Q.w * Q.z;
|
||||||
|
const float qxqy = Q.x * Q.y;
|
||||||
|
const float qxqz = Q.x * Q.z;
|
||||||
|
const float qyqz = Q.y * Q.z;
|
||||||
|
const FusionMatrix matrix = {.element = {
|
||||||
|
.xx = 2.0f * (qwqw - 0.5f + Q.x * Q.x),
|
||||||
|
.xy = 2.0f * (qxqy - qwqz),
|
||||||
|
.xz = 2.0f * (qxqz + qwqy),
|
||||||
|
.yx = 2.0f * (qxqy + qwqz),
|
||||||
|
.yy = 2.0f * (qwqw - 0.5f + Q.y * Q.y),
|
||||||
|
.yz = 2.0f * (qyqz - qwqx),
|
||||||
|
.zx = 2.0f * (qxqz - qwqy),
|
||||||
|
.zy = 2.0f * (qyqz + qwqx),
|
||||||
|
.zz = 2.0f * (qwqw - 0.5f + Q.z * Q.z),
|
||||||
|
}};
|
||||||
|
return matrix;
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts a quaternion to ZYX Euler angles in degrees.
|
||||||
|
* @param quaternion Quaternion.
|
||||||
|
* @return Euler angles in degrees.
|
||||||
|
*/
|
||||||
|
static inline FusionEuler FusionQuaternionToEuler(const FusionQuaternion quaternion)
|
||||||
|
{
|
||||||
|
#define Q quaternion.element
|
||||||
|
const float halfMinusQySquared = 0.5f - Q.y * Q.y; // calculate common terms to avoid repeated operations
|
||||||
|
const FusionEuler euler = {.angle = {
|
||||||
|
.roll = FusionRadiansToDegrees(atan2f(Q.w * Q.x + Q.y * Q.z, halfMinusQySquared - Q.x * Q.x)),
|
||||||
|
.pitch = FusionRadiansToDegrees(FusionAsin(2.0f * (Q.w * Q.y - Q.z * Q.x))),
|
||||||
|
.yaw = FusionRadiansToDegrees(atan2f(Q.w * Q.z + Q.x * Q.y, halfMinusQySquared - Q.z * Q.z)),
|
||||||
|
}};
|
||||||
|
return euler;
|
||||||
|
#undef Q
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
80
src/Fusion/FusionOffset.c
Normal file
80
src/Fusion/FusionOffset.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionOffset.c
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Gyroscope offset correction algorithm for run-time calibration of the
|
||||||
|
* gyroscope offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionOffset.h"
|
||||||
|
#include <math.h> // fabsf
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cutoff frequency in Hz.
|
||||||
|
*/
|
||||||
|
#define CUTOFF_FREQUENCY (0.02f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Timeout in seconds.
|
||||||
|
*/
|
||||||
|
#define TIMEOUT (5)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Threshold in degrees per second.
|
||||||
|
*/
|
||||||
|
#define THRESHOLD (3.0f)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Functions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialises the gyroscope offset algorithm.
|
||||||
|
* @param offset Gyroscope offset algorithm structure.
|
||||||
|
* @param sampleRate Sample rate in Hz.
|
||||||
|
*/
|
||||||
|
void FusionOffsetInitialise(FusionOffset *const offset, const unsigned int sampleRate)
|
||||||
|
{
|
||||||
|
offset->filterCoefficient = 2.0f * (float)M_PI * CUTOFF_FREQUENCY * (1.0f / (float)sampleRate);
|
||||||
|
offset->timeout = TIMEOUT * sampleRate;
|
||||||
|
offset->timer = 0;
|
||||||
|
offset->gyroscopeOffset = FUSION_VECTOR_ZERO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Updates the gyroscope offset algorithm and returns the corrected
|
||||||
|
* gyroscope measurement.
|
||||||
|
* @param offset Gyroscope offset algorithm structure.
|
||||||
|
* @param gyroscope Gyroscope measurement in degrees per second.
|
||||||
|
* @return Corrected gyroscope measurement in degrees per second.
|
||||||
|
*/
|
||||||
|
FusionVector FusionOffsetUpdate(FusionOffset *const offset, FusionVector gyroscope)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Subtract offset from gyroscope measurement
|
||||||
|
gyroscope = FusionVectorSubtract(gyroscope, offset->gyroscopeOffset);
|
||||||
|
|
||||||
|
// Reset timer if gyroscope not stationary
|
||||||
|
if ((fabsf(gyroscope.axis.x) > THRESHOLD) || (fabsf(gyroscope.axis.y) > THRESHOLD) || (fabsf(gyroscope.axis.z) > THRESHOLD)) {
|
||||||
|
offset->timer = 0;
|
||||||
|
return gyroscope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment timer while gyroscope stationary
|
||||||
|
if (offset->timer < offset->timeout) {
|
||||||
|
offset->timer++;
|
||||||
|
return gyroscope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust offset if timer has elapsed
|
||||||
|
offset->gyroscopeOffset =
|
||||||
|
FusionVectorAdd(offset->gyroscopeOffset, FusionVectorMultiplyScalar(gyroscope, offset->filterCoefficient));
|
||||||
|
return gyroscope;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user