mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-21 02:02:23 +00:00
Compare commits
1030 Commits
v2.2.12.09
...
v2.3.13.83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83f5ba0161 | ||
|
|
12b8dc1918 | ||
|
|
1f214211ba | ||
|
|
96853aeeea | ||
|
|
af36ee3a05 | ||
|
|
c593e7ce56 | ||
|
|
15250a566a | ||
|
|
7afa8107ae | ||
|
|
c2097d38fd | ||
|
|
163a732ddc | ||
|
|
ea69b999f9 | ||
|
|
7aea056ac0 | ||
|
|
369d379720 | ||
|
|
02050a4775 | ||
|
|
aca0807acf | ||
|
|
4fe281cf7f | ||
|
|
11c3ca541f | ||
|
|
ceb884cf18 | ||
|
|
e546220a80 | ||
|
|
f50073ed9f | ||
|
|
0c45c99b15 | ||
|
|
abdb7f52bc | ||
|
|
471ee78a5e | ||
|
|
85d621d9c6 | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
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 | ||
|
|
3719ddac03 | ||
|
|
4a05874dba | ||
|
|
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 | ||
|
|
d490a332a7 | ||
|
|
5dfa4b837f | ||
|
|
9501f3bda9 | ||
|
|
b69a1cada9 | ||
|
|
06e7d2b845 | ||
|
|
71400103b3 | ||
|
|
40e361e6d0 | ||
|
|
d1b6f11429 | ||
|
|
0527fb10ce | ||
|
|
5f929a8024 | ||
|
|
4f54862d63 | ||
|
|
0f4ac94559 | ||
|
|
45c1b46bd0 | ||
|
|
5095efc55f | ||
|
|
ec92f7a5a3 | ||
|
|
57da37cfbc | ||
|
|
3619ac87b8 | ||
|
|
e51ee91c39 | ||
|
|
21311bbeda | ||
|
|
472db5b237 | ||
|
|
18e69a0906 | ||
|
|
93f77ea7d2 | ||
|
|
ee4c4ae6c9 | ||
|
|
6cc7dee95c | ||
|
|
38c4d35a7b | ||
|
|
e683d8f552 | ||
|
|
e66aec8223 | ||
|
|
a06a01d25e | ||
|
|
f8c3f43ea6 | ||
|
|
dfcabba0b2 | ||
|
|
827bacdfc8 | ||
|
|
5806a266d3 | ||
|
|
30fbcabf84 | ||
|
|
c14043f196 | ||
|
|
e3610a2eb1 | ||
|
|
9baccc80d8 | ||
|
|
ac16ccf40c | ||
|
|
1c0227f90c | ||
|
|
57d296e0db | ||
|
|
9c9d126f6b | ||
|
|
27f0e42d2f | ||
|
|
4599534616 | ||
|
|
7acaec8ef5 | ||
|
|
d0e81b9151 | ||
|
|
c6e940af81 | ||
|
|
3302fbcc53 | ||
|
|
ccbf635eef | ||
|
|
6669b22db3 | ||
|
|
ec2b854ea2 | ||
|
|
378a2d723e | ||
|
|
5dd08e9533 | ||
|
|
125add9792 | ||
|
|
250cf16bf8 | ||
|
|
8b5fad21b0 | ||
|
|
30d4c3a945 | ||
|
|
45fd5e25ac | ||
|
|
ac6a668362 | ||
|
|
f47b40cf68 | ||
|
|
fd9461505f | ||
|
|
84edaabfe9 | ||
|
|
048f0a1601 | ||
|
|
4a48a3fb52 | ||
|
|
39bbf0d352 | ||
|
|
675d8fe089 | ||
|
|
0406be82d2 | ||
|
|
679e068e19 | ||
|
|
952393ca0f | ||
|
|
a231cd2ad0 | ||
|
|
ac87c0065f | ||
|
|
9822a85274 | ||
|
|
a957065fe8 | ||
|
|
41f3557491 | ||
|
|
402b0d7e0b | ||
|
|
13ebda6b2f | ||
|
|
1dd19cec6e | ||
|
|
df718ab294 | ||
|
|
dfc43bae18 | ||
|
|
f6cfdfe881 | ||
|
|
820c5dc8c5 | ||
|
|
1f9c295c9e | ||
|
|
5218aaafcf | ||
|
|
c480f0870c | ||
|
|
9e4ef92e6d | ||
|
|
cf65661c7c | ||
|
|
fb7a878d94 | ||
|
|
e72792afc8 | ||
|
|
ec39e1136a | ||
|
|
94e1f016e5 | ||
|
|
9170fe0580 | ||
|
|
ef9808cdd6 | ||
|
|
0972a8dccb | ||
|
|
419eb13968 | ||
|
|
e7828c4c64 | ||
|
|
44aa248099 | ||
|
|
e0513d4078 | ||
|
|
2100f3135e | ||
|
|
2f36d4990e | ||
|
|
65bde8538f | ||
|
|
7a3570aecf | ||
|
|
4a471ded79 | ||
|
|
eea85d26ca | ||
|
|
64edfb76e0 | ||
|
|
8ac308e73b | ||
|
|
0ae7674982 | ||
|
|
e4b5f2ce14 | ||
|
|
7d77b23eb6 | ||
|
|
a149999cec | ||
|
|
78d915b454 | ||
|
|
4c0b7ea409 | ||
|
|
425a715995 | ||
|
|
2e13aeeacb | ||
|
|
747c713ba9 | ||
|
|
4b5549be8f | ||
|
|
172d271b0b | ||
|
|
2e14234b77 | ||
|
|
d47e9bed19 | ||
|
|
bc085ab840 | ||
|
|
2450031b1b | ||
|
|
2cd877d2eb | ||
|
|
c34956e9d8 | ||
|
|
afb4de21d9 | ||
|
|
86223d8806 | ||
|
|
0632b96fcb | ||
|
|
dcfc9c9f03 | ||
|
|
8a3322fbcb | ||
|
|
55c9c3b298 | ||
|
|
9599549477 | ||
|
|
e813703bf5 | ||
|
|
699ea74672 | ||
|
|
a01069a549 | ||
|
|
3413b9da41 | ||
|
|
7d3175dc83 | ||
|
|
441638c2eb | ||
|
|
2f9b68e08b | ||
|
|
27ae4399bc | ||
|
|
385d7296fe | ||
|
|
d1cd686644 | ||
|
|
1291da746b | ||
|
|
2803fa964e | ||
|
|
1d97544041 | ||
|
|
5b52c31a76 | ||
|
|
00d4c011c7 | ||
|
|
1447148811 | ||
|
|
4f205718f0 | ||
|
|
5047468d9f | ||
|
|
ec3971bce5 | ||
|
|
0a246bfe9b | ||
|
|
f1a1834ee2 | ||
|
|
2a6e26620e | ||
|
|
3f45c2d4f0 | ||
|
|
11adfe05ce | ||
|
|
b4009f9f2f | ||
|
|
917b739e62 | ||
|
|
2c4db16336 | ||
|
|
4c9646f7d9 | ||
|
|
8fd32f3452 | ||
|
|
178877f2d9 | ||
|
|
6de0363eea | ||
|
|
f4a2023dba | ||
|
|
927d07e2c6 | ||
|
|
a4a8556aa2 | ||
|
|
8e29efcb50 | ||
|
|
3bee6ce9c3 | ||
|
|
fcab20fb3b | ||
|
|
2d81c97b98 | ||
|
|
cfd98b2c91 | ||
|
|
6e7405e56b | ||
|
|
77082e35f5 | ||
|
|
daa64b055a | ||
|
|
ec74fba2bd | ||
|
|
e89575bfd1 | ||
|
|
ea61808fd9 | ||
|
|
b14ac777f1 | ||
|
|
65e5bdc212 | ||
|
|
aa3280c18c | ||
|
|
68e657fd07 | ||
|
|
47b8f7b6c6 | ||
|
|
fde20db95f | ||
|
|
40a7fd145a | ||
|
|
33842b67e8 | ||
|
|
2db061ded9 | ||
|
|
1baad2875a | ||
|
|
0e9f1beb40 | ||
|
|
03f60dcb49 | ||
|
|
5b5f9c62b5 | ||
|
|
577de1e517 | ||
|
|
f6e6f975c0 | ||
|
|
902f38238d | ||
|
|
9b2d862b7d | ||
|
|
4cdfae71cf | ||
|
|
be889015f7 | ||
|
|
f0b6ff9b2d | ||
|
|
30ebb6ae46 | ||
|
|
d1db51830b | ||
|
|
eb0e705ba9 | ||
|
|
46ad4bf0e5 | ||
|
|
a570e50aca | ||
|
|
2caed6d29c | ||
|
|
f2ed0f7c8c | ||
|
|
8bb562c5fa | ||
|
|
15501e84dd | ||
|
|
a4c22321fc | ||
|
|
46a63bf293 | ||
|
|
279464f96d | ||
|
|
3cf6c47bab | ||
|
|
64fd866494 | ||
|
|
7b391d1a9f | ||
|
|
8187fa7115 | ||
|
|
daa4d387c6 | ||
|
|
4c2d5c6a89 | ||
|
|
b5ec35ec78 | ||
|
|
5732eed86b | ||
|
|
1542afb847 | ||
|
|
acc32916c3 | ||
|
|
728b58fb94 | ||
|
|
77fb230baa | ||
|
|
b960dc1b41 | ||
|
|
5f529f7ca3 | ||
|
|
b4dbc2b4bf | ||
|
|
63df972d42 | ||
|
|
c87fdfece7 | ||
|
|
381d5230b8 | ||
|
|
a7c005ccdf | ||
|
|
71ca6f768f | ||
|
|
4cce4c7c93 | ||
|
|
9e8860d188 | ||
|
|
d30d6bd3eb | ||
|
|
94e4301f2f | ||
|
|
54818b5f8d | ||
|
|
c77c58d656 | ||
|
|
794e99c2f9 | ||
|
|
7aa013a716 | ||
|
|
a57f7730ea | ||
|
|
35754d661d | ||
|
|
79cfb1e876 | ||
|
|
155df45d92 | ||
|
|
907d075917 | ||
|
|
9c88906acc | ||
|
|
defeb8e52b | ||
|
|
6dd337a651 | ||
|
|
0a7ddb7594 | ||
|
|
4debcd5ccd | ||
|
|
fd26914d88 | ||
|
|
dfcd0d14f6 | ||
|
|
f4095ce00d | ||
|
|
7aa21f6e3f | ||
|
|
5e832e2fc6 | ||
|
|
4fa7f5a748 | ||
|
|
a6625998f5 | ||
|
|
711b85cfe8 | ||
|
|
b98176e73e | ||
|
|
aae49f5ecf | ||
|
|
0d1d79b6d1 | ||
|
|
bb57ccfc9e | ||
|
|
e27f029d09 | ||
|
|
13cc1b0252 | ||
|
|
54a2a4bcc6 | ||
|
|
611f291d4d | ||
|
|
9586606229 | ||
|
|
0de36fbfb0 | ||
|
|
0dda20bc35 | ||
|
|
52cfec29fc | ||
|
|
4d0d82f7e7 | ||
|
|
34bc22f94d | ||
|
|
cb3740708b | ||
|
|
e8ec167854 | ||
|
|
b900415218 | ||
|
|
2eb78fec53 | ||
|
|
da7cd5fc7f | ||
|
|
b06c77d46f | ||
|
|
cbc0aa16c5 | ||
|
|
876a0520a9 | ||
|
|
50cc4cfcf1 | ||
|
|
ec6bdeed81 | ||
|
|
a085c3ddb3 | ||
|
|
58cdf360f8 | ||
|
|
9c37e57e75 | ||
|
|
9d2fcbe1e1 | ||
|
|
3995e2f708 | ||
|
|
216f85ff22 | ||
|
|
2efe436102 | ||
|
|
fb16390205 | ||
|
|
333c3c1c9e | ||
|
|
724fa38a55 | ||
|
|
38ea681433 | ||
|
|
ee685b4ed7 | ||
|
|
cf11807f97 | ||
|
|
7f063fbf81 | ||
|
|
6215495ccc | ||
|
|
045dda64e7 | ||
|
|
affbd7f2b9 | ||
|
|
f9bf9e2dcc | ||
|
|
5f47ca1f32 | ||
|
|
6a27e62bcf | ||
|
|
2d5a6c1a20 | ||
|
|
c7839b469b | ||
|
|
95967a01b8 | ||
|
|
e16689a0d6 | ||
|
|
c80098f517 | ||
|
|
1f766a04aa | ||
|
|
1d31be939f | ||
|
|
4b4bd07d5c | ||
|
|
cf4753f7fd | ||
|
|
892223a297 | ||
|
|
658ed6fd28 | ||
|
|
3a8f623f8a | ||
|
|
f09e5c96fc | ||
|
|
a493ab526f | ||
|
|
b3ec3c20fb | ||
|
|
b65b9e5d65 | ||
|
|
766beefbc5 | ||
|
|
eb372c190e | ||
|
|
70df36b5db | ||
|
|
e33d014257 | ||
|
|
26691c0be7 | ||
|
|
09e08e0091 | ||
|
|
73c77b663c | ||
|
|
fb4faf790b | ||
|
|
cb7407e06b | ||
|
|
b45a912409 | ||
|
|
c7d5698dbc | ||
|
|
d1a25947e3 | ||
|
|
69dcc948b9 | ||
|
|
084b01715e | ||
|
|
af9d14c370 | ||
|
|
1032e16ea4 | ||
|
|
3da1b74a10 | ||
|
|
c0a3b20aa3 | ||
|
|
3daae24d29 | ||
|
|
dced888492 | ||
|
|
7167f1e04f | ||
|
|
dfbb4cd913 | ||
|
|
3da7c0dba7 | ||
|
|
7b70324435 | ||
|
|
94eb837ee8 | ||
|
|
a9c07a4c01 | ||
|
|
e232e3462c | ||
|
|
94794edd43 | ||
|
|
95b6f27d2a | ||
|
|
efd818fe90 | ||
|
|
576f582cd9 | ||
|
|
d5c11d1892 | ||
|
|
aaa5d61162 | ||
|
|
3efd606ea7 | ||
|
|
42286edc81 | ||
|
|
29335a18f5 | ||
|
|
51df4fc775 | ||
|
|
0f1bc98305 | ||
|
|
23926210d1 | ||
|
|
7275c21f6b | ||
|
|
ac89bb3387 | ||
|
|
07da130586 | ||
|
|
5d4d91f775 | ||
|
|
7da1153c2c | ||
|
|
585805c3b9 | ||
|
|
a4830e0ab1 | ||
|
|
763ae9f2e2 | ||
|
|
7f12505716 | ||
|
|
b4940b476d | ||
|
|
c860493e68 | ||
|
|
2dd751e339 | ||
|
|
bfce3938d2 | ||
|
|
46ad623785 | ||
|
|
e174328de3 | ||
|
|
9d37a8d17f | ||
|
|
f5ff77c2b9 | ||
|
|
72050530f1 | ||
|
|
e5bf07d4fb | ||
|
|
7ab9a94edb | ||
|
|
3c3d391044 | ||
|
|
e3063a2785 | ||
|
|
6dbb6583ef | ||
|
|
9b3e519487 | ||
|
|
495840c777 | ||
|
|
5865add857 | ||
|
|
c659292836 | ||
|
|
905718e2ac | ||
|
|
a58348369d | ||
|
|
d20fa6e927 | ||
|
|
bf88773b6b | ||
|
|
6acc63729b | ||
|
|
7aee014f5e | ||
|
|
2786db499d | ||
|
|
4ffb906fe8 | ||
|
|
f7758b4e44 | ||
|
|
e6a2c06346 | ||
|
|
ce0e5c0ce7 | ||
|
|
59bbd1ad00 | ||
|
|
4796c8edc4 | ||
|
|
f708e41ba7 | ||
|
|
d556d59308 | ||
|
|
146b5b557a | ||
|
|
0dcd3584e4 | ||
|
|
d434117ffd | ||
|
|
0f27992c5a | ||
|
|
824991c178 | ||
|
|
02192e1163 | ||
|
|
d47f55289f | ||
|
|
b98ddbddf4 | ||
|
|
6932f07310 | ||
|
|
a8d37475b6 | ||
|
|
8726cb830e | ||
|
|
8c7ee1a7bb | ||
|
|
1fe230a065 | ||
|
|
74714bf0c5 | ||
|
|
8bfe5a2bd4 | ||
|
|
9c4d1b5ac8 | ||
|
|
c2085c2c88 | ||
|
|
730429fc9b | ||
|
|
f1b314251c | ||
|
|
b2ea1e23be | ||
|
|
3ad34f8759 | ||
|
|
f95b90364a | ||
|
|
7706786541 | ||
|
|
eb2fa727a7 | ||
|
|
790f100620 | ||
|
|
0153daa8ba | ||
|
|
880afb9477 | ||
|
|
78b4a65635 | ||
|
|
eb8a12e5a2 | ||
|
|
9784758c7b | ||
|
|
e0c7f7207b | ||
|
|
23df6ddf01 | ||
|
|
7a1c565701 | ||
|
|
0bfac7b5f9 | ||
|
|
5a3180a525 | ||
|
|
5672e6825d | ||
|
|
143ee9cdf6 | ||
|
|
998013aff3 | ||
|
|
1bacd8641d | ||
|
|
7c9d1b0abf | ||
|
|
e3c4bc5473 | ||
|
|
fdc27fe08b | ||
|
|
cb4e1840e3 | ||
|
|
007ecd0604 | ||
|
|
d9bd9bdfb0 | ||
|
|
d2a74a5329 | ||
|
|
0b466fdca9 | ||
|
|
30507f5125 | ||
|
|
c43cbb5795 | ||
|
|
124be247c7 | ||
|
|
4d18bc0658 | ||
|
|
c8dae33e2f | ||
|
|
bac7c708bf | ||
|
|
96bd898a38 | ||
|
|
36cf9b9ef4 | ||
|
|
ce8673b6dc | ||
|
|
d52cfc294b | ||
|
|
f11def4246 | ||
|
|
13c8dca6b4 | ||
|
|
404d0dda79 | ||
|
|
514c19a68e | ||
|
|
1085b54069 | ||
|
|
bcbc2f229d | ||
|
|
74b90d3505 | ||
|
|
d246c47ae7 | ||
|
|
54e52ae05f | ||
|
|
8130b1cf43 | ||
|
|
9d4c4f8bd1 | ||
|
|
3b0169ba7a | ||
|
|
996e72a816 | ||
|
|
a40b4e4d69 | ||
|
|
f4151a7108 | ||
|
|
a3755dfce5 | ||
|
|
ca5795d3e7 | ||
|
|
990ee5dacf | ||
|
|
4c55d5d9e4 | ||
|
|
7db02ad722 | ||
|
|
7f7c5cbd62 | ||
|
|
0c0a3c4b55 | ||
|
|
bf762bc58d | ||
|
|
84e578323e | ||
|
|
bdbe42dfd0 | ||
|
|
4f64c4f7b9 | ||
|
|
af5ac32048 | ||
|
|
9586c68c65 | ||
|
|
ca45888f3e | ||
|
|
1e4ecea6fc | ||
|
|
d1ea589757 | ||
|
|
af52dcecdf | ||
|
|
0ae4622393 | ||
|
|
a49740cd56 | ||
|
|
417feee47f | ||
|
|
d604a76c73 | ||
|
|
ac9c5f81b9 | ||
|
|
d6fa190025 | ||
|
|
f2c04c5504 | ||
|
|
4ae5443c3b | ||
|
|
6b5101ec67 | ||
|
|
062c646814 | ||
|
|
bccc0d47eb | ||
|
|
8f6a2836b8 | ||
|
|
4f76239d48 | ||
|
|
486bf79690 | ||
|
|
2efaaea625 | ||
|
|
af157d276a | ||
|
|
b489ee08c8 | ||
|
|
751bdf94aa | ||
|
|
e2a3b0306f | ||
|
|
a8b7490b6e | ||
|
|
4056d34bed | ||
|
|
fd8b1687a1 | ||
|
|
8b362dee3a | ||
|
|
30e3a28014 | ||
|
|
14736775e2 | ||
|
|
a7019b7206 | ||
|
|
6284f4ffe6 | ||
|
|
e4e9a1559e | ||
|
|
92110276d7 | ||
|
|
c22340eaf7 | ||
|
|
6f96fbfb74 | ||
|
|
4a867c81c0 | ||
|
|
7e53a96ee5 | ||
|
|
3e21e05a2c | ||
|
|
e9bde80b57 | ||
|
|
ccb5485510 | ||
|
|
0d85069bec | ||
|
|
77ff1704db | ||
|
|
613a2bfb70 | ||
|
|
ea651c2f8f | ||
|
|
c2afa879b8 | ||
|
|
59253d9c78 | ||
|
|
be46f9ea24 | ||
|
|
674fd32349 | ||
|
|
bacc525d0a | ||
|
|
aa10a3ec40 | ||
|
|
e3c768bf10 | ||
|
|
943367edd0 | ||
|
|
4577646f8b | ||
|
|
1ae02a9a28 | ||
|
|
28951ea1e0 | ||
|
|
2e9cc73ebb | ||
|
|
dbac2b1cad | ||
|
|
2b7eb1e489 | ||
|
|
d401040e51 | ||
|
|
5110de4838 | ||
|
|
2d35f72d85 | ||
|
|
d318d34c3c | ||
|
|
06b4638f6b | ||
|
|
16c18d0da9 | ||
|
|
8d37d93e05 | ||
|
|
7334ee7349 | ||
|
|
ba98da55a7 | ||
|
|
db8f8db8e8 | ||
|
|
d88baea627 | ||
|
|
16a3a32f2a | ||
|
|
a138e9cb6b | ||
|
|
86475a1719 | ||
|
|
c5a2dc758f | ||
|
|
add78a459b | ||
|
|
f1b380882d | ||
|
|
bbe21766be | ||
|
|
dfa537415d | ||
|
|
24c4ee9bfa | ||
|
|
71c0726838 | ||
|
|
45f90fb39b | ||
|
|
1c6acfd734 | ||
|
|
c6ae66dcaa | ||
|
|
fc365a1fee | ||
|
|
6c1db94ae7 | ||
|
|
ded1cbf4dd | ||
|
|
399b9f8f6d | ||
|
|
4720b2874f | ||
|
|
1af3e0ddaa | ||
|
|
9f85279e74 | ||
|
|
dd96848bec | ||
|
|
4932e277f1 | ||
|
|
dad05d7873 | ||
|
|
4b7fbeca29 | ||
|
|
2ebaea317a | ||
|
|
d14d2c89c3 | ||
|
|
35938392f1 | ||
|
|
d952da8b1e | ||
|
|
385b29c977 | ||
|
|
dc309f61e8 | ||
|
|
512399c8f5 | ||
|
|
5d94bb601a | ||
|
|
796592b586 | ||
|
|
d552ee3556 | ||
|
|
14b31d4d14 | ||
|
|
4de6eb2e1d | ||
|
|
abaa37133d | ||
|
|
5eac227550 | ||
|
|
671112f47d | ||
|
|
8ea19d665a | ||
|
|
8f57cfaaf4 | ||
|
|
a54e3826e9 | ||
|
|
9188a9a1f2 | ||
|
|
17f1a450b2 | ||
|
|
ba021c97b2 | ||
|
|
b4ad6b0f41 | ||
|
|
28502a762f | ||
|
|
89f0464233 | ||
|
|
46d02affe8 | ||
|
|
62329ad11f | ||
|
|
72b4fe51b1 | ||
|
|
07fc5df9c1 | ||
|
|
1c22d2c885 | ||
|
|
1f931a5e55 | ||
|
|
31c4693c66 | ||
|
|
6ff61b3e04 | ||
|
|
9e90b4af02 | ||
|
|
2544733ad4 | ||
|
|
1b6c11c5f1 | ||
|
|
4c69d06ac0 | ||
|
|
85cbde75fe | ||
|
|
5e70fb9851 | ||
|
|
6e967421a5 | ||
|
|
a05bab35ad | ||
|
|
ac506a581c | ||
|
|
def4ec5822 | ||
|
|
209fb585b0 | ||
|
|
fb89482129 | ||
|
|
8e742f2f80 | ||
|
|
238cf8cdeb | ||
|
|
5df7f07f95 | ||
|
|
6fa026a78b | ||
|
|
39743832ad | ||
|
|
bd2675caf1 | ||
|
|
c489c251ab | ||
|
|
14d03a2bda | ||
|
|
423b8ad603 | ||
|
|
ce8342d3e5 | ||
|
|
57227c0f85 | ||
|
|
1ca2923658 | ||
|
|
d10b1e1d00 | ||
|
|
d3e64350d9 | ||
|
|
102efd4954 | ||
|
|
18cf8ca4fa | ||
|
|
c7f6071f70 | ||
|
|
c7e3485dd7 | ||
|
|
603e564db3 | ||
|
|
ac318a9850 | ||
|
|
1feb74f525 | ||
|
|
d6fc1c314f | ||
|
|
b3852322ef | ||
|
|
cbb8eb65ba | ||
|
|
4712b1ca65 | ||
|
|
57542ce9e6 | ||
|
|
1b20a82b55 | ||
|
|
195706e0e5 | ||
|
|
c1f5878648 | ||
|
|
7380f3b170 | ||
|
|
a9d846c1b3 | ||
|
|
cfb09ee115 | ||
|
|
8f0ce606db | ||
|
|
d04ff29c2a | ||
|
|
8e92754b59 | ||
|
|
dad824c0e9 | ||
|
|
31d7c6826d | ||
|
|
d33521ee86 | ||
|
|
5ad12fed60 | ||
|
|
4af90eeb39 | ||
|
|
08297bb0b7 | ||
|
|
16ef40b21f | ||
|
|
7ef4abb974 | ||
|
|
297267d037 | ||
|
|
f8e766ebc7 | ||
|
|
7bd2b07024 | ||
|
|
b6ddbd0087 | ||
|
|
dc8903ec42 | ||
|
|
46bd6ca7ba | ||
|
|
9d4af1146e | ||
|
|
5ce6ca25f2 | ||
|
|
f2210d8f8d | ||
|
|
5d917885df | ||
|
|
e99ae64ece | ||
|
|
61f888e952 | ||
|
|
a144d5d6cc | ||
|
|
c3e3569c14 | ||
|
|
b1b5bafdda | ||
|
|
91e399a2b6 | ||
|
|
8b16367597 | ||
|
|
0b9accc3b6 | ||
|
|
590b0bbff4 | ||
|
|
19be230b24 | ||
|
|
8df16ad6a6 | ||
|
|
2d62f00ac3 | ||
|
|
9f93b9ab9d | ||
|
|
fc3200134d | ||
|
|
470264b7f9 | ||
|
|
600541ac25 | ||
|
|
298b383127 | ||
|
|
f57020412e | ||
|
|
4a6cc8fd8c | ||
|
|
45c5e0e730 | ||
|
|
527bffb7e0 | ||
|
|
4c35a7fb7d | ||
|
|
0f9936a0e0 | ||
|
|
40395bef01 | ||
|
|
8b8fffda81 | ||
|
|
4052194dfe | ||
|
|
b36ffe5200 | ||
|
|
a60b4d08bf | ||
|
|
227467f638 | ||
|
|
b388f8edcd | ||
|
|
5075849ec0 | ||
|
|
7f16b6b342 | ||
|
|
762166495f | ||
|
|
00ea6ef5ad | ||
|
|
b5b66f43f2 | ||
|
|
1e71d346ae | ||
|
|
919b2d1e48 | ||
|
|
171cca435e | ||
|
|
e878f55ed3 | ||
|
|
d74cbdaa8b | ||
|
|
3a5b79e4c1 | ||
|
|
9bee35118f | ||
|
|
80f029aa32 | ||
|
|
b75aa79da5 | ||
|
|
49febc0d9d | ||
|
|
85818b8dfd | ||
|
|
7d299b06a7 | ||
|
|
14080d4667 | ||
|
|
8a806efb95 | ||
|
|
ef2d0cb830 | ||
|
|
5e779bfb33 | ||
|
|
498964e04e | ||
|
|
7d0bea267a | ||
|
|
ed1aa9ddb0 | ||
|
|
97a0b164be | ||
|
|
82706a961f | ||
|
|
06a1b079da | ||
|
|
56afed84df | ||
|
|
945fd7a05c | ||
|
|
e9a55fc296 | ||
|
|
472c43aace | ||
|
|
8b5937892b | ||
|
|
8c20fe5ec4 |
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
|
||||||
|
|||||||
11
.github/actions/setup-base/action.yml
vendored
11
.github/actions/setup-base/action.yml
vendored
@@ -5,24 +5,25 @@ 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
|
||||||
|
sudo apt-get install -y cppcheck libbluetooth-dev libgpiod-dev 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
|
||||||
|
|||||||
10
.github/workflows/build_esp32.yml
vendored
10
.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
|
||||||
@@ -35,12 +35,13 @@ jobs:
|
|||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||||
|
|
||||||
- name: Build ESP32
|
- name: Build ESP32
|
||||||
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
|
||||||
@@ -53,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
|
||||||
|
|||||||
63
.github/workflows/build_esp32_c3.yml
vendored
Normal file
63
.github/workflows/build_esp32_c3.yml
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
name: Build ESP32-C3
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
board:
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
permissions: read-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-esp32-c3:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Build base
|
||||||
|
id: base
|
||||||
|
uses: ./.github/actions/setup-base
|
||||||
|
|
||||||
|
- 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: Unpack web ui
|
||||||
|
run: |
|
||||||
|
tar -xf build.tar -C data/static
|
||||||
|
rm build.tar
|
||||||
|
- name: Remove debug flags for release
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
run: |
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||||
|
- name: Build ESP32
|
||||||
|
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||||
|
|
||||||
|
- name: Pull OTA Firmware
|
||||||
|
uses: dsaltares/fetch-gh-release-asset@master
|
||||||
|
with:
|
||||||
|
repo: meshtastic/firmware-ota
|
||||||
|
file: firmware-c3.bin
|
||||||
|
target: release/bleota-c3.bin
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Get release version string
|
||||||
|
shell: bash
|
||||||
|
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/*.bin
|
||||||
|
release/*.elf
|
||||||
10
.github/workflows/build_esp32_s3.yml
vendored
10
.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
|
||||||
@@ -34,11 +34,12 @@ jobs:
|
|||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32.ini
|
||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s2.ini
|
||||||
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32s3.ini
|
||||||
|
sed -i '/DDEBUG_HEAP/d' ./arch/esp32/esp32c3.ini
|
||||||
- name: Build ESP32
|
- name: Build ESP32
|
||||||
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
|
||||||
@@ -51,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
|
||||||
|
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
|
||||||
5
.github/workflows/build_nrf52.yml
vendored
5
.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,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
|
||||||
|
|||||||
51
.github/workflows/build_raspbian.yml
vendored
Normal file
51
.github/workflows/build_raspbian.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: Build Raspbian
|
||||||
|
|
||||||
|
on: workflow_call
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-raspbian:
|
||||||
|
runs-on: [self-hosted, linux, ARM64]
|
||||||
|
steps:
|
||||||
|
- name: Install libbluetooth
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
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-${{ steps.version.outputs.version }}.zip
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
release/meshtasticd_linux_aarch64
|
||||||
|
bin/config-dist.yaml
|
||||||
51
.github/workflows/build_raspbian_armv7l.yml
vendored
Normal file
51
.github/workflows/build_raspbian_armv7l.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
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 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
|
||||||
|
|||||||
281
.github/workflows/main_matrix.yml
vendored
281
.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,224 +20,168 @@ 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, 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-g1
|
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 }}
|
||||||
|
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_8
|
|
||||||
- board: tbeam
|
|
||||||
- board: heltec-v1
|
|
||||||
- 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
|
|
||||||
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-paper
|
|
||||||
- board: tbeam-s3-core
|
|
||||||
- board: tlora-t3s3-v1
|
|
||||||
- board: t-watch-s3
|
|
||||||
- board: t-deck
|
|
||||||
- board: picomputer-s3
|
|
||||||
uses: ./.github/workflows/build_esp32_s3.yml
|
uses: ./.github/workflows/build_esp32_s3.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-nrf52:
|
build-esp32-c3:
|
||||||
|
needs: setup
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
max-parallel: 2
|
matrix: ${{ fromJson(needs.setup.outputs.esp32c3) }}
|
||||||
matrix:
|
uses: ./.github/workflows/build_esp32_c3.yml
|
||||||
include:
|
with:
|
||||||
- board: rak4631
|
board: ${{ matrix.board }}
|
||||||
- board: rak4631_eink
|
|
||||||
- board: monteops_hw1
|
build-nrf52:
|
||||||
- board: t-echo
|
needs: setup
|
||||||
- board: pca10059_diy_eink
|
strategy:
|
||||||
- board: feather_diy
|
fail-fast: false
|
||||||
- board: nano-g2-ultra
|
matrix: ${{ fromJson(needs.setup.outputs.nrf52840) }}
|
||||||
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
|
||||||
max-parallel: 2
|
matrix: ${{ fromJson(needs.setup.outputs.rp2040) }}
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- board: pico
|
|
||||||
- board: rak11310
|
|
||||||
uses: ./.github/workflows/build_rpi2040.yml
|
uses: ./.github/workflows/build_rpi2040.yml
|
||||||
with:
|
with:
|
||||||
board: ${{ matrix.board }}
|
board: ${{ matrix.board }}
|
||||||
|
|
||||||
build-native:
|
package-raspbian:
|
||||||
runs-on: ubuntu-latest
|
uses: ./.github/workflows/package_raspbian.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-raspbian-armv7l:
|
||||||
#- name: Build for native
|
uses: ./.github/workflows/package_raspbian_armv7l.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
|
package-native:
|
||||||
run: bin/build-native.sh
|
uses: ./.github/workflows/package_amd64.yml
|
||||||
|
|
||||||
- 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}}
|
||||||
|
|
||||||
gather-artifacts:
|
gather-artifacts:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
[build-esp32, build-esp32-s3, build-nrf52, build-native, build-rpi2040]
|
[
|
||||||
|
build-esp32,
|
||||||
|
build-esp32-s3,
|
||||||
|
build-esp32-c3,
|
||||||
|
build-nrf52,
|
||||||
|
build-rpi2040,
|
||||||
|
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
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
- name: Get release version string
|
- name: Get release version string
|
||||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||||
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 ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
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-*-ota.zip
|
./firmware-*-ota.zip
|
||||||
./device-*.sh
|
./device-*.sh
|
||||||
./device-*.bat
|
./device-*.bat
|
||||||
|
./meshtasticd_linux_*
|
||||||
|
./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
|
||||||
@@ -253,23 +197,23 @@ 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
|
||||||
|
|
||||||
- name: Create request artifacts
|
- name: Create request artifacts
|
||||||
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
continue-on-error: true # FIXME: Why are we getting 502, but things still work?
|
||||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||||
uses: gavv/pull-request-artifacts@v1.1.0
|
uses: gavv/pull-request-artifacts@v2.1.0
|
||||||
with:
|
with:
|
||||||
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
commit: ${{ (github.event.pull_request_target || github.event.pull_request).head.sha }}
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
artifacts-token: ${{ secrets.ARTIFACTS_TOKEN }}
|
||||||
artifacts-repo: meshtastic/artifacts
|
artifacts-repo: meshtastic/artifacts
|
||||||
artifacts-branch: device
|
artifacts-branch: device
|
||||||
artifacts-dir: pr
|
|
||||||
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
artifacts: ./firmware-${{ steps.version.outputs.version }}.zip
|
||||||
|
|
||||||
release-artifacts:
|
release-artifacts:
|
||||||
@@ -278,10 +222,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
|
||||||
|
|
||||||
@@ -289,22 +233,33 @@ 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@v4
|
||||||
|
with:
|
||||||
|
pattern: meshtasticd_${{ steps.version.outputs.version }}_*.deb
|
||||||
|
merge-multiple: true
|
||||||
|
path: ./output
|
||||||
|
|
||||||
|
- name: Display structure of downloaded files
|
||||||
|
run: ls -R
|
||||||
|
|
||||||
- name: Device scripts permissions
|
- name: Device scripts permissions
|
||||||
run: |
|
run: |
|
||||||
chmod +x ./output/device-install.sh
|
chmod +x ./output/device-install.sh
|
||||||
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
|
||||||
@@ -347,12 +302,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 aarch64 .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 }}_arm64.deb
|
||||||
|
asset_name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||||
|
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
|
||||||
78
.github/workflows/package_raspbian.yml
vendored
Normal file
78
.github/workflows/package_raspbian.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
name: Package Raspbian
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-raspbian:
|
||||||
|
uses: ./.github/workflows/build_raspbian.yml
|
||||||
|
|
||||||
|
package-raspbian:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build-raspbian
|
||||||
|
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-${{ 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_aarch64 .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: arm64
|
||||||
|
depends: libyaml-cpp0.7, openssl, libulfius2.7
|
||||||
|
desc: Native Linux Meshtastic binary.
|
||||||
|
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb
|
||||||
|
overwrite: true
|
||||||
|
path: |
|
||||||
|
./*.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
|
||||||
|
|
||||||
|
|||||||
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
|
||||||
|
|||||||
10
.github/workflows/update_protobufs.yml
vendored
10
.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
|
||||||
|
|
||||||
@@ -17,16 +17,16 @@ jobs:
|
|||||||
|
|
||||||
- name: Download nanopb
|
- name: Download nanopb
|
||||||
run: |
|
run: |
|
||||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz
|
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.8-linux-x86.tar.gz
|
||||||
tar xvzf nanopb-0.4.7-linux-x86.tar.gz
|
tar xvzf nanopb-0.4.8-linux-x86.tar.gz
|
||||||
mv nanopb-0.4.7-linux-x86 nanopb-0.4.7
|
mv nanopb-0.4.8-linux-x86 nanopb-0.4.8
|
||||||
|
|
||||||
- name: Re-generate protocol buffers
|
- name: Re-generate protocol buffers
|
||||||
run: |
|
run: |
|
||||||
./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
.gitignore
vendored
2
.gitignore
vendored
@@ -31,3 +31,5 @@ venv/
|
|||||||
release/
|
release/
|
||||||
.vscode/extensions.json
|
.vscode/extensions.json
|
||||||
/compile_commands.json
|
/compile_commands.json
|
||||||
|
src/mesh/raspihttp/certificate.pem
|
||||||
|
src/mesh/raspihttp/private_key.pem
|
||||||
1
.trunk/.gitignore
vendored
1
.trunk/.gitignore
vendored
@@ -6,3 +6,4 @@
|
|||||||
plugins
|
plugins
|
||||||
user_trunk.yaml
|
user_trunk.yaml
|
||||||
user.yaml
|
user.yaml
|
||||||
|
tmp
|
||||||
|
|||||||
2
.trunk/configs/.bandit
Normal file
2
.trunk/configs/.bandit
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[bandit]
|
||||||
|
skips = B101
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
enable=all
|
enable=all
|
||||||
source-path=SCRIPTDIR
|
source-path=SCRIPTDIR
|
||||||
disable=SC2154
|
disable=SC2154
|
||||||
|
disable=SC2248
|
||||||
|
disable=SC2250
|
||||||
|
|
||||||
# If you're having issues with shellcheck following source, disable the errors via:
|
# If you're having issues with shellcheck following source, disable the errors via:
|
||||||
# disable=SC1090
|
# disable=SC1090
|
||||||
# disable=SC1091
|
# disable=SC1091
|
||||||
|
#
|
||||||
@@ -3,7 +3,7 @@ rules:
|
|||||||
required: only-when-needed
|
required: only-when-needed
|
||||||
extra-allowed: ["{|}"]
|
extra-allowed: ["{|}"]
|
||||||
empty-values:
|
empty-values:
|
||||||
forbid-in-block-mappings: true
|
forbid-in-block-mappings: false
|
||||||
forbid-in-flow-mappings: true
|
forbid-in-flow-mappings: true
|
||||||
key-duplicates: {}
|
key-duplicates: {}
|
||||||
octal-values:
|
octal-values:
|
||||||
|
|||||||
@@ -1,44 +1,36 @@
|
|||||||
version: 0.1
|
version: 0.1
|
||||||
cli:
|
cli:
|
||||||
version: 1.17.0
|
version: 1.22.1
|
||||||
plugins:
|
plugins:
|
||||||
sources:
|
sources:
|
||||||
- id: trunk
|
- id: trunk
|
||||||
ref: v1.2.5
|
ref: v1.5.0
|
||||||
uri: https://github.com/trunk-io/plugins
|
uri: https://github.com/trunk-io/plugins
|
||||||
lint:
|
lint:
|
||||||
enabled:
|
enabled:
|
||||||
- bandit@1.7.5
|
- trufflehog@3.76.3
|
||||||
- checkov@2.5.0
|
- yamllint@1.35.1
|
||||||
- terrascan@1.18.3
|
- bandit@1.7.8
|
||||||
- trivy@0.45.1
|
- checkov@3.2.95
|
||||||
- trufflehog@3.59.0
|
- terrascan@1.19.1
|
||||||
|
- trivy@0.51.1
|
||||||
|
#- trufflehog@3.63.2-rc0
|
||||||
- taplo@0.8.1
|
- taplo@0.8.1
|
||||||
- ruff@0.0.292
|
- ruff@0.4.4
|
||||||
- yamllint@1.32.0
|
- isort@5.13.2
|
||||||
- isort@5.12.0
|
- markdownlint@0.40.0
|
||||||
- markdownlint@0.37.0
|
- oxipng@9.1.1
|
||||||
- oxipng@8.0.0
|
- svgo@3.3.2
|
||||||
- svgo@3.0.2
|
- actionlint@1.7.0
|
||||||
- actionlint@1.6.26
|
- flake8@7.0.0
|
||||||
- flake8@6.1.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@23.9.1
|
- black@24.4.2
|
||||||
- git-diff-check
|
- git-diff-check
|
||||||
- gitleaks@8.18.0
|
- gitleaks@8.18.2
|
||||||
- clang-format@16.0.3
|
- clang-format@16.0.3
|
||||||
- prettier@3.0.3
|
- prettier@3.2.5
|
||||||
disabled:
|
|
||||||
- taplo@0.8.1
|
|
||||||
- shellcheck@0.9.0
|
|
||||||
- shfmt@3.6.0
|
|
||||||
- oxipng@8.0.0
|
|
||||||
- actionlint@1.6.22
|
|
||||||
- markdownlint@0.37.0
|
|
||||||
- hadolint@2.12.0
|
|
||||||
- svgo@3.0.2
|
|
||||||
runtimes:
|
runtimes:
|
||||||
enabled:
|
enabled:
|
||||||
- python@3.10.8
|
- python@3.10.8
|
||||||
|
|||||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.defaultFormatter": "trunk.io",
|
"editor.defaultFormatter": "trunk.io",
|
||||||
"trunk.enableWindows": true
|
"trunk.enableWindows": true,
|
||||||
|
"files.insertFinalNewline": false,
|
||||||
|
"files.trimFinalNewlines": false,
|
||||||
|
"cmake.configureOnOpen": false
|
||||||
}
|
}
|
||||||
|
|||||||
59
Dockerfile
59
Dockerfile
@@ -1,4 +1,4 @@
|
|||||||
FROM debian:bullseye-slim AS builder
|
FROM debian:bookworm-slim AS builder
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND=noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
ENV TZ=Etc/UTC
|
ENV TZ=Etc/UTC
|
||||||
@@ -11,31 +11,46 @@ SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
|||||||
|
|
||||||
# Install build deps
|
# Install build deps
|
||||||
USER root
|
USER root
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates
|
|
||||||
|
|
||||||
# create a non-priveleged user & group
|
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||||
|
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||||
|
RUN apt-get update && apt-get install --no-install-recommends -y wget python3 python3-pip python3-wheel python3-venv g++ zip git \
|
||||||
|
ca-certificates libgpiod-dev libyaml-cpp-dev libbluetooth-dev \
|
||||||
|
libulfius-dev liborcania-dev libssl-dev pkg-config && \
|
||||||
|
apt-get clean && rm -rf /var/lib/apt/lists/* && mkdir /tmp/firmware
|
||||||
|
|
||||||
|
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh && chown mesh:mesh /tmp/firmware
|
||||||
|
USER mesh
|
||||||
|
|
||||||
|
WORKDIR /tmp/firmware
|
||||||
|
RUN python3 -m venv /tmp/firmware
|
||||||
|
RUN source ./bin/activate && pip3 install --no-cache-dir -U platformio==6.1.14
|
||||||
|
# trunk-ignore(terrascan/AC_DOCKER_00024): We would actually like these files to be owned by mesh tyvm
|
||||||
|
COPY --chown=mesh:mesh . /tmp/firmware
|
||||||
|
RUN source ./bin/activate && chmod +x /tmp/firmware/bin/build-native.sh && ./bin/build-native.sh
|
||||||
|
RUN cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
|
||||||
|
|
||||||
|
|
||||||
|
##### PRODUCTION BUILD #############
|
||||||
|
|
||||||
|
FROM debian:bookworm-slim
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV TZ=Etc/UTC
|
||||||
|
|
||||||
|
# trunk-ignore(terrascan/AC_DOCKER_0002): Known terrascan issue
|
||||||
|
# trunk-ignore(hadolint/DL3008): Use latest version of packages for buildchain
|
||||||
|
RUN apt-get update && apt-get --no-install-recommends -y install libc-bin libc6 libgpiod2 libyaml-cpp0.7 libulfius2.7 liborcania2.3 libssl3 && \
|
||||||
|
apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||||
|
|
||||||
USER mesh
|
USER mesh
|
||||||
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \
|
|
||||||
chmod +x /tmp/get-platformio.py && \
|
|
||||||
python3 /tmp/get-platformio.py && \
|
|
||||||
git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \
|
|
||||||
cd /tmp/firmware && \
|
|
||||||
chmod +x /tmp/firmware/bin/build-native.sh && \
|
|
||||||
source ~/.platformio/penv/bin/activate && \
|
|
||||||
./bin/build-native.sh
|
|
||||||
|
|
||||||
FROM frolvlad/alpine-glibc
|
|
||||||
|
|
||||||
RUN apk --update add --no-cache g++ shadow && \
|
|
||||||
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
|
||||||
|
|
||||||
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_amd64 /home/mesh/
|
|
||||||
|
|
||||||
USER mesh
|
|
||||||
WORKDIR /home/mesh
|
WORKDIR /home/mesh
|
||||||
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'"
|
COPY --from=builder /tmp/firmware/release/meshtasticd /home/mesh/
|
||||||
|
|
||||||
|
RUN mkdir data
|
||||||
|
VOLUME /home/mesh/data
|
||||||
|
|
||||||
|
CMD [ "sh", "-cx", "./meshtasticd -d /home/mesh/data --hwid=${HWID:-$RANDOM}" ]
|
||||||
|
|
||||||
HEALTHCHECK NONE
|
HEALTHCHECK NONE
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
; 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/>
|
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<mesh/raspihttp>
|
||||||
|
|
||||||
upload_speed = 921600
|
upload_speed = 921600
|
||||||
debug_init_break = tbreak setup
|
debug_init_break = tbreak setup
|
||||||
@@ -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
|
||||||
@@ -31,6 +34,9 @@ build_flags =
|
|||||||
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
-DCONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=5120
|
||||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||||
-DSERIAL_BUFFER_SIZE=4096
|
-DSERIAL_BUFFER_SIZE=4096
|
||||||
|
-DLIBPAX_ARDUINO
|
||||||
|
-DLIBPAX_WIFI
|
||||||
|
-DLIBPAX_BLE
|
||||||
;-DDEBUG_HEAP
|
;-DDEBUG_HEAP
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
@@ -39,7 +45,7 @@ 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.1
|
||||||
jgromes/RadioLib@^6.1.0
|
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
|
||||||
|
|
||||||
|
|||||||
@@ -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,16 +1,19 @@
|
|||||||
[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} -<nimble/>
|
${esp32_base.build_src_filter} - <libpax/> -<nimble/> -<mesh/raspihttp>
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${esp32_base.build_flags}
|
${esp32_base.build_flags}
|
||||||
-DHAS_BLUETOOTH=0
|
-DHAS_BLUETOOTH=0
|
||||||
|
-DMESHTASTIC_EXCLUDE_PAXCOUNTER
|
||||||
|
-DMESHTASTIC_EXCLUDE_BLUETOOTH
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
${esp32_base.lib_ignore}
|
${esp32_base.lib_ignore}
|
||||||
NimBLE-Arduino
|
NimBLE-Arduino
|
||||||
|
libpax
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
[esp32s3_base]
|
[esp32s3_base]
|
||||||
extends = esp32_base
|
extends = esp32_base
|
||||||
|
custom_esp32_kind = esp32s3
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
[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.1.0
|
platform = platformio/nordicnrf52@^10.5.0
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
|
|
||||||
build_type = debug ; I'm debugging with ICE a lot now
|
build_type = debug
|
||||||
build_flags =
|
build_flags =
|
||||||
${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/api/> -<mesh/http/> -<modules/esp32> -<platform/rp2040> -<mesh/eth/>
|
${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}
|
||||||
jgromes/RadioLib@^6.1.0
|
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
||||||
@@ -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#489ff929dca0bb768256ba2de45f95815111490f
|
platform = https://github.com/meshtastic/platform-native.git#ad8112adf82ce1f5b917092cf32be07a077801a0
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
@@ -10,7 +10,9 @@ build_src_filter =
|
|||||||
-<platform/nrf52/>
|
-<platform/nrf52/>
|
||||||
-<platform/stm32wl/>
|
-<platform/stm32wl/>
|
||||||
-<platform/rp2040>
|
-<platform/rp2040>
|
||||||
|
-<mesh/wifi/>
|
||||||
-<mesh/http/>
|
-<mesh/http/>
|
||||||
|
+<mesh/raspihttp/>
|
||||||
-<mesh/eth/>
|
-<mesh/eth/>
|
||||||
-<modules/esp32>
|
-<modules/esp32>
|
||||||
-<modules/Telemetry/EnvironmentTelemetry.cpp>
|
-<modules/Telemetry/EnvironmentTelemetry.cpp>
|
||||||
@@ -22,9 +24,14 @@ lib_deps =
|
|||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
${networking_base.lib_deps}
|
${networking_base.lib_deps}
|
||||||
rweather/Crypto@^0.4.0
|
rweather/Crypto@^0.4.0
|
||||||
jgromes/RadioLib@6.1.0
|
https://github.com/lovyan03/LovyanGFX.git#5a39989aa2c9492572255b22f033843ec8900233
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
${arduino_base.build_flags}
|
${arduino_base.build_flags}
|
||||||
-fPIC
|
-fPIC
|
||||||
-Isrc/platform/portduino
|
-Isrc/platform/portduino
|
||||||
|
-DRADIOLIB_EEPROM_UNSUPPORTED
|
||||||
|
-DPORTDUINO_LINUX_HARDWARE
|
||||||
|
-lbluetooth
|
||||||
|
-lgpiod
|
||||||
|
-lyaml-cpp
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
; Common settings for rp2040 Processor based targets
|
; Common settings for rp2040 Processor based targets
|
||||||
[rp2040_base]
|
[rp2040_base]
|
||||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#0c33219f53faa035e188925ea1324f472e8b93d2
|
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#60d6ae81fcc73c34b1493ca9e261695e471bc0c2
|
||||||
extends = arduino_base
|
extends = arduino_base
|
||||||
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.2.2
|
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#3.7.2
|
||||||
|
|
||||||
board_build.core = earlephilhower
|
board_build.core = earlephilhower
|
||||||
board_build.filesystem_size = 0.5m
|
board_build.filesystem_size = 0.5m
|
||||||
@@ -12,7 +12,7 @@ build_flags =
|
|||||||
-D__PLAT_RP2040__
|
-D__PLAT_RP2040__
|
||||||
# -D _POSIX_THREADS
|
# -D _POSIX_THREADS
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<modules/esp32> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/> -<mesh/wifi/> -<mesh/http/> -<mesh/raspihttp>
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
BluetoothOTA
|
BluetoothOTA
|
||||||
@@ -20,5 +20,4 @@ lib_ignore =
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
${arduino_base.lib_deps}
|
${arduino_base.lib_deps}
|
||||||
${environmental_base.lib_deps}
|
${environmental_base.lib_deps}
|
||||||
jgromes/RadioLib@^6.1.0
|
rweather/Crypto
|
||||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
|
||||||
@@ -13,17 +13,16 @@ build_flags =
|
|||||||
-DVECT_TAB_OFFSET=0x08000000
|
-DVECT_TAB_OFFSET=0x08000000
|
||||||
|
|
||||||
build_src_filter =
|
build_src_filter =
|
||||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
${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
|
board_upload.offset_address = 0x08000000
|
||||||
upload_protocol = stlink
|
upload_protocol = stlink
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${env.lib_deps}
|
${env.lib_deps}
|
||||||
jgromes/RadioLib@^6.1.0
|
|
||||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||||
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
https://github.com/littlefs-project/littlefs.git#v2.5.1
|
||||||
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
https://github.com/stm32duino/STM32FreeRTOS.git#10.3.1
|
||||||
|
|
||||||
lib_ignore =
|
lib_ignore =
|
||||||
https://github.com/mathertel/OneButton#2.1.0
|
mathertel/OneButton
|
||||||
Binary file not shown.
BIN
bin/Meshtastic_nRF52_factory_erase_v2.uf2
Normal file
BIN
bin/Meshtastic_nRF52_factory_erase_v2.uf2
Normal file
Binary file not shown.
@@ -2,8 +2,19 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
VERSION=`bin/buildinfo.py long`
|
platformioFailed() {
|
||||||
SHORT_VERSION=`bin/buildinfo.py short`
|
[[ $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)
|
||||||
|
SHORT_VERSION=$(bin/buildinfo.py short)
|
||||||
|
|
||||||
OUTDIR=release/
|
OUTDIR=release/
|
||||||
|
|
||||||
@@ -13,11 +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
|
platformio pkg update --environment native || platformioFailed
|
||||||
|
pio run --environment native || platformioFailed
|
||||||
pio run --environment native
|
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
|
||||||
cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64
|
|
||||||
|
|
||||||
cp bin/device-install.* $OUTDIR
|
cp bin/device-install.* $OUTDIR
|
||||||
cp bin/device-update.* $OUTDIR
|
cp bin/device-update.* $OUTDIR
|
||||||
|
|
||||||
|
|||||||
@@ -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]}")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ if [[ $# -gt 0 ]]; then
|
|||||||
# can override which environment by passing arg
|
# can override which environment by passing arg
|
||||||
BOARDS="$@"
|
BOARDS="$@"
|
||||||
else
|
else
|
||||||
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo pca10059_diy_eink"
|
BOARDS="tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 rak4631 rak4631_eink rak11200 t-echo canaryone pca10059_diy_eink"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "BOARDS:${BOARDS}"
|
echo "BOARDS:${BOARDS}"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ if [[ $# -gt 0 ]]; then
|
|||||||
# can override which environment by passing arg
|
# can override which environment by passing arg
|
||||||
BOARDS="$@"
|
BOARDS="$@"
|
||||||
else
|
else
|
||||||
BOARDS="rak4631 rak4631_eink t-echo pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
|
BOARDS="rak4631 rak4631_eink t-echo canaryone pca10059_diy_eink pico rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink tbeam-s3-core"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "BOARDS:${BOARDS}"
|
echo "BOARDS:${BOARDS}"
|
||||||
|
|||||||
144
bin/config-dist.yaml
Normal file
144
bin/config-dist.yaml
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
### Define your devices here using Broadcom pin numbering
|
||||||
|
### Uncomment the block that corresponds to your hardware
|
||||||
|
### Including the "Module:" line!
|
||||||
|
---
|
||||||
|
Lora:
|
||||||
|
# Module: sx1262 # Waveshare SX126X XXXM
|
||||||
|
# DIO2_AS_RF_SWITCH: true
|
||||||
|
# CS: 21
|
||||||
|
# IRQ: 16
|
||||||
|
# Busy: 20
|
||||||
|
# Reset: 18
|
||||||
|
|
||||||
|
# Module: sx1262 # Waveshare SX1302 LISTEN ONLY AT THIS TIME!
|
||||||
|
# CS: 7
|
||||||
|
# IRQ: 17
|
||||||
|
# Reset: 22
|
||||||
|
|
||||||
|
# Module: sx1262 # pinedio
|
||||||
|
# CS: 0
|
||||||
|
# IRQ: 10
|
||||||
|
# Busy: 11
|
||||||
|
# spidev: spidev0.1
|
||||||
|
|
||||||
|
# Module: RF95 # Adafruit RFM9x
|
||||||
|
# Reset: 25
|
||||||
|
# CS: 7
|
||||||
|
# IRQ: 22
|
||||||
|
# Busy: 23
|
||||||
|
|
||||||
|
# Module: RF95 # Elecrow Lora RFM95 IOT https://www.elecrow.com/lora-rfm95-iot-board-for-rpi.html
|
||||||
|
# Reset: 22
|
||||||
|
# CS: 7
|
||||||
|
# IRQ: 25
|
||||||
|
|
||||||
|
# Module: sx1280 # SX1280
|
||||||
|
# CS: 21
|
||||||
|
# IRQ: 16
|
||||||
|
# Busy: 20
|
||||||
|
# Reset: 18
|
||||||
|
|
||||||
|
# Module: sx1268 # SX1268-based modules, tested with Ebyte E22 400M33S
|
||||||
|
# CS: 21
|
||||||
|
# IRQ: 16
|
||||||
|
# Busy: 20
|
||||||
|
# Reset: 18
|
||||||
|
# TXen: 6
|
||||||
|
# RXen: 12
|
||||||
|
# DIO3_TCXO_VOLTAGE: true
|
||||||
|
|
||||||
|
# DIO3_TCXO_VOLTAGE: true # the Waveshare Core1262 and others are known to need this setting
|
||||||
|
|
||||||
|
# TXen: x # TX and RX enable pins
|
||||||
|
# RXen: x
|
||||||
|
|
||||||
|
# ch341_quirk: true # Uncomment this to use the chunked SPI transfer that seems to fix the ch341
|
||||||
|
|
||||||
|
### Set gpio chip to use in /dev/. Defaults to 0.
|
||||||
|
### Notably the Raspberry Pi 5 puts the GPIO header on gpiochip4
|
||||||
|
# gpiochip: 4
|
||||||
|
|
||||||
|
### Specify the SPI device to use in /dev/. Defaults to spidev0.0
|
||||||
|
### Some devices, like the pinedio, may require spidev0.1 as a workaround.
|
||||||
|
# spidev: spidev0.0
|
||||||
|
|
||||||
|
### Define GPIO buttons here:
|
||||||
|
|
||||||
|
GPIO:
|
||||||
|
# User: 6
|
||||||
|
|
||||||
|
### Define GPS
|
||||||
|
|
||||||
|
GPS:
|
||||||
|
# SerialPath: /dev/ttyS0
|
||||||
|
|
||||||
|
### Specify I2C device, or leave blank for none
|
||||||
|
|
||||||
|
I2C:
|
||||||
|
# I2CDevice: /dev/i2c-1
|
||||||
|
|
||||||
|
### Set up SPI displays here. Note that I2C displays are generally auto-detected.
|
||||||
|
|
||||||
|
Display:
|
||||||
|
|
||||||
|
### Waveshare 2.8inch RPi LCD
|
||||||
|
# Panel: ST7789
|
||||||
|
# CS: 8
|
||||||
|
# DC: 22 # Data/Command pin
|
||||||
|
# Backlight: 18
|
||||||
|
# Width: 240
|
||||||
|
# Height: 320
|
||||||
|
# Reset: 27
|
||||||
|
# Rotate: true
|
||||||
|
# Invert: true
|
||||||
|
|
||||||
|
### Waveshare 1.44inch LCD HAT
|
||||||
|
# Panel: ST7735S
|
||||||
|
# CS: 8 #Chip Select
|
||||||
|
# DC: 25 # Data/Command pin
|
||||||
|
# Backlight: 24
|
||||||
|
# Width: 128
|
||||||
|
# Height: 128
|
||||||
|
# Reset: 27
|
||||||
|
# OffsetX: 0
|
||||||
|
# OffsetY: 0
|
||||||
|
|
||||||
|
### Adafruit PiTFT 2.8 TFT+Touchscreen
|
||||||
|
# Panel: ILI9341
|
||||||
|
# CS: 8
|
||||||
|
# DC: 25
|
||||||
|
# Width: 240
|
||||||
|
# Height: 320
|
||||||
|
# Rotate: true
|
||||||
|
|
||||||
|
Touchscreen:
|
||||||
|
### Note, at least for now, the touchscreen must have a CS pin defined, even if you let Linux manage the CS switching.
|
||||||
|
|
||||||
|
# Module: STMPE610 # Option 1 for Adafruit PiTFT 2.8
|
||||||
|
# CS: 7
|
||||||
|
# IRQ: 24
|
||||||
|
|
||||||
|
# Module: FT5x06 # Option 2 for Adafruit PiTFT 2.8
|
||||||
|
# IRQ: 24
|
||||||
|
# I2CAddr: 0x38
|
||||||
|
|
||||||
|
# Module: XPT2046 # Waveshare 2.8inch
|
||||||
|
# CS: 7
|
||||||
|
# IRQ: 17
|
||||||
|
|
||||||
|
### Configure device for direct keyboard input
|
||||||
|
|
||||||
|
Input:
|
||||||
|
# KeyboardDevice: /dev/input/by-id/usb-_Raspberry_Pi_Internal_Keyboard-event-kbd
|
||||||
|
|
||||||
|
###
|
||||||
|
|
||||||
|
Logging:
|
||||||
|
LogLevel: info # debug, info, warn, error
|
||||||
|
|
||||||
|
Webserver:
|
||||||
|
# Port: 443 # Port for Webserver & Webservices
|
||||||
|
# RootPath: /usr/share/doc/meshtasticd/web # Root Dir of WebServer
|
||||||
|
|
||||||
|
General:
|
||||||
|
MaxNodes: 200
|
||||||
@@ -31,9 +31,13 @@ IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
|||||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||||
|
|
||||||
@REM Account for S3 board's different OTA partition
|
@REM Account for S3 and C3 board's different OTA partition
|
||||||
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% (
|
IF x%FILENAME:s3=%==x%FILENAME% IF x%FILENAME:v3=%==x%FILENAME% IF x%FILENAME:t-deck=%==x%FILENAME% IF x%FILENAME:wireless-paper=%==x%FILENAME% IF x%FILENAME:wireless-tracker=%==x%FILENAME% IF x%FILENAME:station-g2=%==x%FILENAME% IF x%FILENAME:unphone=%==x%FILENAME% (
|
||||||
|
IF x%FILENAME:esp32c3=%==x%FILENAME% (
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota.bin
|
||||||
|
) else (
|
||||||
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-c3.bin
|
||||||
|
)
|
||||||
) else (
|
) else (
|
||||||
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
%PYTHON% -m esptool --baud 115200 write_flash 0x260000 bleota-s3.bin
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
|
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Usage info
|
# Usage info
|
||||||
show_help() {
|
show_help() {
|
||||||
cat << EOF
|
cat <<EOF
|
||||||
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
|
||||||
Flash image file to device, but first erasing and writing system information"
|
Flash image file to device, but first erasing and writing system information"
|
||||||
|
|
||||||
@@ -18,18 +18,20 @@ Flash image file to device, but first erasing and writing system information"
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while getopts ":hp:P:f:" opt; do
|
while getopts ":hp:P:f:" opt; do
|
||||||
case "${opt}" in
|
case "${opt}" in
|
||||||
h)
|
h)
|
||||||
show_help
|
show_help
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
p) export ESPTOOL_PORT=${OPTARG}
|
p)
|
||||||
|
export ESPTOOL_PORT=${OPTARG}
|
||||||
;;
|
;;
|
||||||
P) PYTHON=${OPTARG}
|
P)
|
||||||
|
PYTHON=${OPTARG}
|
||||||
;;
|
;;
|
||||||
f) FILENAME=${OPTARG}
|
f)
|
||||||
|
FILENAME=${OPTARG}
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Invalid flag."
|
echo "Invalid flag."
|
||||||
@@ -38,20 +40,24 @@ while getopts ":hp:P:f:" opt; do
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
shift "$((OPTIND-1))"
|
shift "$((OPTIND - 1))"
|
||||||
|
|
||||||
[ -z "$FILENAME" -a -n "$1" ] && {
|
[ -z "$FILENAME" -a -n "$1" ] && {
|
||||||
FILENAME=$1
|
FILENAME=$1
|
||||||
shift
|
shift
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
|
||||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||||
"$PYTHON" -m esptool erase_flash
|
"$PYTHON" -m esptool erase_flash
|
||||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||||
# Account for S3 board's different OTA partition
|
# Account for S3 board's different OTA partition
|
||||||
if [ ! -z "${FILENAME##*"s3"*}" ] && [ ! -z "${FILENAME##*"-v3"*}" ] && [ ! -z "${FILENAME##*"t-deck"*}" ] && [ ! -z "${FILENAME##*"wireless-paper"*}" ] && [ ! -z "${FILENAME##*"wireless-tracker"*}" ]; then
|
if [ -n "${FILENAME##*"s3"*}" ] && [ -n "${FILENAME##*"-v3"*}" ] && [ -n "${FILENAME##*"t-deck"*}" ] && [ -n "${FILENAME##*"wireless-paper"*}" ] && [ -n "${FILENAME##*"wireless-tracker"*}" ] && [ -n "${FILENAME##*"station-g2"*}" ] && [ -n "${FILENAME##*"unphone"*}" ]; then
|
||||||
|
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
|
||||||
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
"$PYTHON" -m esptool write_flash 0x260000 bleota.bin
|
||||||
|
else
|
||||||
|
"$PYTHON" -m esptool write_flash 0x260000 bleota-c3.bin
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
"$PYTHON" -m esptool write_flash 0x260000 bleota-s3.bin
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -11,19 +11,22 @@ Meshtastic notes:
|
|||||||
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
|
* version that's checked into meshtastic repo is based on: https://github.com/me21/EspArduinoExceptionDecoder
|
||||||
which adds in ESP32 Backtrace decoding.
|
which adds in ESP32 Backtrace decoding.
|
||||||
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin
|
* this also updates the defaults to use ESP32, instead of ESP8266 and defaults to the built firmware.bin
|
||||||
|
* also updated the toolchain name, which will be set according to the platform
|
||||||
|
|
||||||
To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
|
To use, copy the "Backtrace: 0x...." line to a file, e.g., backtrace.txt, then run:
|
||||||
$ bin/exception_decoder.py backtrace.txt
|
$ bin/exception_decoder.py backtrace.txt
|
||||||
|
For a platform other than ESP32, use the -p option, e.g.:
|
||||||
|
$ bin/exception_decoder.py -p ESP32S3 backtrace.txt
|
||||||
|
To specify a specific .elf file, use the -e option, e.g.:
|
||||||
|
$ bin/exception_decoder.py -e firmware.elf backtrace.txt
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
from collections import namedtuple
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
from collections import namedtuple
|
||||||
import os
|
|
||||||
|
|
||||||
EXCEPTIONS = [
|
EXCEPTIONS = [
|
||||||
"Illegal instruction",
|
"Illegal instruction",
|
||||||
@@ -55,24 +58,39 @@ EXCEPTIONS = [
|
|||||||
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
|
"LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",
|
||||||
"reserved",
|
"reserved",
|
||||||
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads",
|
"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads",
|
||||||
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores"
|
"StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores",
|
||||||
]
|
]
|
||||||
|
|
||||||
PLATFORMS = {
|
PLATFORMS = {
|
||||||
"ESP8266": "lx106",
|
"ESP8266": "xtensa-lx106",
|
||||||
"ESP32": "esp32"
|
"ESP32": "xtensa-esp32",
|
||||||
|
"ESP32S3": "xtensa-esp32s3",
|
||||||
|
"ESP32C3": "riscv32-esp",
|
||||||
|
}
|
||||||
|
TOOLS = {
|
||||||
|
"ESP8266": "xtensa",
|
||||||
|
"ESP32": "xtensa-esp32",
|
||||||
|
"ESP32S3": "xtensa-esp32s3",
|
||||||
|
"ESP32C3": "riscv32-esp",
|
||||||
}
|
}
|
||||||
|
|
||||||
BACKTRACE_REGEX = re.compile(r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b")
|
BACKTRACE_REGEX = re.compile(
|
||||||
|
r"(?:\s+(0x40[0-2](?:\d|[a-f]|[A-F]){5}):0x(?:\d|[a-f]|[A-F]){8})\b"
|
||||||
|
)
|
||||||
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
|
EXCEPTION_REGEX = re.compile("^Exception \\((?P<exc>[0-9]*)\\):$")
|
||||||
COUNTER_REGEX = re.compile('^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) '
|
COUNTER_REGEX = re.compile(
|
||||||
'excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$')
|
"^epc1=(?P<epc1>0x[0-9a-f]+) epc2=(?P<epc2>0x[0-9a-f]+) epc3=(?P<epc3>0x[0-9a-f]+) "
|
||||||
|
"excvaddr=(?P<excvaddr>0x[0-9a-f]+) depc=(?P<depc>0x[0-9a-f]+)$"
|
||||||
|
)
|
||||||
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
|
CTX_REGEX = re.compile("^ctx: (?P<ctx>.+)$")
|
||||||
POINTER_REGEX = re.compile('^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$')
|
POINTER_REGEX = re.compile(
|
||||||
STACK_BEGIN = '>>>stack>>>'
|
"^sp: (?P<sp>[0-9a-f]+) end: (?P<end>[0-9a-f]+) offset: (?P<offset>[0-9a-f]+)$"
|
||||||
STACK_END = '<<<stack<<<'
|
)
|
||||||
|
STACK_BEGIN = ">>>stack>>>"
|
||||||
|
STACK_END = "<<<stack<<<"
|
||||||
STACK_REGEX = re.compile(
|
STACK_REGEX = re.compile(
|
||||||
'^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$')
|
"^(?P<off>[0-9a-f]+):\W+(?P<c1>[0-9a-f]+) (?P<c2>[0-9a-f]+) (?P<c3>[0-9a-f]+) (?P<c4>[0-9a-f]+)(\W.*)?$"
|
||||||
|
)
|
||||||
|
|
||||||
StackLine = namedtuple("StackLine", ["offset", "content"])
|
StackLine = namedtuple("StackLine", ["offset", "content"])
|
||||||
|
|
||||||
@@ -96,15 +114,18 @@ class ExceptionDataParser(object):
|
|||||||
self.stack = []
|
self.stack = []
|
||||||
|
|
||||||
def _parse_backtrace(self, line):
|
def _parse_backtrace(self, line):
|
||||||
if line.startswith('Backtrace:'):
|
if line.startswith("Backtrace:"):
|
||||||
self.stack = [StackLine(offset=0, content=(addr,)) for addr in BACKTRACE_REGEX.findall(line)]
|
self.stack = [
|
||||||
|
StackLine(offset=0, content=(addr,))
|
||||||
|
for addr in BACKTRACE_REGEX.findall(line)
|
||||||
|
]
|
||||||
return None
|
return None
|
||||||
return self._parse_backtrace
|
return self._parse_backtrace
|
||||||
|
|
||||||
def _parse_exception(self, line):
|
def _parse_exception(self, line):
|
||||||
match = EXCEPTION_REGEX.match(line)
|
match = EXCEPTION_REGEX.match(line)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
self.exception = int(match.group('exc'))
|
self.exception = int(match.group("exc"))
|
||||||
return self._parse_counters
|
return self._parse_counters
|
||||||
return self._parse_exception
|
return self._parse_exception
|
||||||
|
|
||||||
@@ -144,14 +165,22 @@ class ExceptionDataParser(object):
|
|||||||
if line != STACK_END:
|
if line != STACK_END:
|
||||||
match = STACK_REGEX.match(line)
|
match = STACK_REGEX.match(line)
|
||||||
if match is not None:
|
if match is not None:
|
||||||
self.stack.append(StackLine(offset=match.group("off"),
|
self.stack.append(
|
||||||
content=(match.group("c1"), match.group("c2"), match.group("c3"),
|
StackLine(
|
||||||
match.group("c4"))))
|
offset=match.group("off"),
|
||||||
|
content=(
|
||||||
|
match.group("c1"),
|
||||||
|
match.group("c2"),
|
||||||
|
match.group("c3"),
|
||||||
|
match.group("c4"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
return self._parse_stack_line
|
return self._parse_stack_line
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def parse_file(self, file, platform, stack_only=False):
|
def parse_file(self, file, platform, stack_only=False):
|
||||||
if platform == 'ESP32':
|
if platform != "ESP8266":
|
||||||
func = self._parse_backtrace
|
func = self._parse_backtrace
|
||||||
else:
|
else:
|
||||||
func = self._parse_exception
|
func = self._parse_exception
|
||||||
@@ -175,7 +204,9 @@ class AddressResolver(object):
|
|||||||
self._address_map = {}
|
self._address_map = {}
|
||||||
|
|
||||||
def _lookup(self, addresses):
|
def _lookup(self, addresses):
|
||||||
cmd = [self._tool, "-aipfC", "-e", self._elf] + [addr for addr in addresses if addr is not None]
|
cmd = [self._tool, "-aipfC", "-e", self._elf] + [
|
||||||
|
addr for addr in addresses if addr is not None
|
||||||
|
]
|
||||||
|
|
||||||
if sys.version_info[0] < 3:
|
if sys.version_info[0] < 3:
|
||||||
output = subprocess.check_output(cmd)
|
output = subprocess.check_output(cmd)
|
||||||
@@ -190,19 +221,27 @@ class AddressResolver(object):
|
|||||||
match = line_regex.match(line)
|
match = line_regex.match(line)
|
||||||
|
|
||||||
if match is None:
|
if match is None:
|
||||||
if last is not None and line.startswith('(inlined by)'):
|
if last is not None and line.startswith("(inlined by)"):
|
||||||
line = line [12:].strip()
|
line = line[12:].strip()
|
||||||
self._address_map[last] += ("\n \-> inlined by: " + line)
|
self._address_map[last] += "\n \-> inlined by: " + line
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if match.group("result") == '?? ??:0':
|
if match.group("result") == "?? ??:0":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
self._address_map[match.group("addr")] = match.group("result")
|
self._address_map[match.group("addr")] = match.group("result")
|
||||||
last = match.group("addr")
|
last = match.group("addr")
|
||||||
|
|
||||||
def fill(self, parser):
|
def fill(self, parser):
|
||||||
addresses = [parser.epc1, parser.epc2, parser.epc3, parser.excvaddr, parser.sp, parser.end, parser.offset]
|
addresses = [
|
||||||
|
parser.epc1,
|
||||||
|
parser.epc2,
|
||||||
|
parser.epc3,
|
||||||
|
parser.excvaddr,
|
||||||
|
parser.sp,
|
||||||
|
parser.end,
|
||||||
|
parser.offset,
|
||||||
|
]
|
||||||
for line in parser.stack:
|
for line in parser.stack:
|
||||||
addresses.extend(line.content)
|
addresses.extend(line.content)
|
||||||
|
|
||||||
@@ -257,8 +296,10 @@ def print_stack(lines, resolver):
|
|||||||
|
|
||||||
|
|
||||||
def print_result(parser, resolver, platform, full=True, stack_only=False):
|
def print_result(parser, resolver, platform, full=True, stack_only=False):
|
||||||
if platform == 'ESP8266' and not stack_only:
|
if platform == "ESP8266" and not stack_only:
|
||||||
print('Exception: {} ({})'.format(parser.exception, EXCEPTIONS[parser.exception]))
|
print(
|
||||||
|
"Exception: {} ({})".format(parser.exception, EXCEPTIONS[parser.exception])
|
||||||
|
)
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
print_addr("epc1", parser.epc1, resolver)
|
print_addr("epc1", parser.epc1, resolver)
|
||||||
@@ -285,15 +326,33 @@ def print_result(parser, resolver, platform, full=True, stack_only=False):
|
|||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
|
parser = argparse.ArgumentParser(description="decode ESP Stacktraces.")
|
||||||
|
|
||||||
parser.add_argument("-p", "--platform", help="The platform to decode from", choices=PLATFORMS.keys(),
|
parser.add_argument(
|
||||||
default="ESP32")
|
"-p",
|
||||||
parser.add_argument("-t", "--tool", help="Path to the xtensa toolchain",
|
"--platform",
|
||||||
default="~/.platformio/packages/toolchain-xtensa32/")
|
help="The platform to decode from",
|
||||||
parser.add_argument("-e", "--elf", help="path to elf file",
|
choices=PLATFORMS.keys(),
|
||||||
default=".pio/build/esp32/firmware.elf")
|
default="ESP32",
|
||||||
parser.add_argument("-f", "--full", help="Print full stack dump", action="store_true")
|
)
|
||||||
parser.add_argument("-s", "--stack_only", help="Decode only a stractrace", action="store_true")
|
parser.add_argument(
|
||||||
parser.add_argument("file", help="The file to read the exception data from ('-' for STDIN)", default="-")
|
"-t",
|
||||||
|
"--tool",
|
||||||
|
help="Path to the toolchain (without specific platform)",
|
||||||
|
default="~/.platformio/packages/toolchain-",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-e", "--elf", help="path to elf file", default=".pio/build/tbeam/firmware.elf"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-f", "--full", help="Print full stack dump", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s", "--stack_only", help="Decode only a stractrace", action="store_true"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"file",
|
||||||
|
help="The file to read the exception data from ('-' for STDIN)",
|
||||||
|
default="-",
|
||||||
|
)
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
@@ -309,10 +368,12 @@ if __name__ == "__main__":
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
file = open(args.file, "r")
|
file = open(args.file, "r")
|
||||||
|
|
||||||
addr2line = os.path.join(os.path.abspath(os.path.expanduser(args.tool)),
|
addr2line = os.path.join(
|
||||||
"bin/xtensa-" + PLATFORMS[args.platform] + "-elf-addr2line")
|
os.path.abspath(os.path.expanduser(args.tool + TOOLS[args.platform])),
|
||||||
if os.name == 'nt':
|
"bin/" + PLATFORMS[args.platform] + "-elf-addr2line",
|
||||||
addr2line += '.exe'
|
)
|
||||||
|
if os.name == "nt":
|
||||||
|
addr2line += ".exe"
|
||||||
if not os.path.exists(addr2line):
|
if not os.path.exists(addr2line):
|
||||||
print("ERROR: addr2line not found (" + addr2line + ")")
|
print("ERROR: addr2line not found (" + addr2line + ")")
|
||||||
|
|
||||||
|
|||||||
@@ -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/lilygo_techo_bootloader-0.6.1.zip
Normal file
BIN
bin/lilygo_techo_bootloader-0.6.1.zip
Normal file
Binary file not shown.
12
bin/meshtasticd.service
Normal file
12
bin/meshtasticd.service
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Meshtastic Native Daemon
|
||||||
|
After=network-online.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
User=root
|
||||||
|
Group=root
|
||||||
|
Type=simple
|
||||||
|
ExecStart=/usr/sbin/meshtasticd
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
10
bin/native-install.sh
Executable file
10
bin/native-install.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
|
||||||
|
mkdir /etc/meshtasticd
|
||||||
|
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
|
||||||
|
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
|
||||||
|
else
|
||||||
|
cp bin/config-dist.yaml /etc/meshtasticd/config.yaml
|
||||||
|
fi
|
||||||
|
cp bin/meshtasticd.service /usr/lib/systemd/system/meshtasticd.service
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
import subprocess
|
# trunk-ignore-all(ruff/F821)
|
||||||
import configparser
|
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
||||||
import traceback
|
|
||||||
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 +21,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 +52,42 @@ 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"])
|
||||||
|
|
||||||
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 +1 @@
|
|||||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --experimental_allow_proto3_optional --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs ..\protobufs\meshtastic\*.proto
|
cd protobufs && ..\nanopb-0.4.8\generator-bin\protoc.exe --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:..\src\mesh\generated" -I=..\protobufs\ ..\protobufs\meshtastic\*.proto
|
||||||
|
|||||||
@@ -2,19 +2,10 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
|
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.8 to be located in the"
|
||||||
echo "firmware root directory if the following step fails, you should download the correct"
|
echo "firmware root directory if the following step fails, you should download the correct"
|
||||||
echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
echo "prebuilt binaries for your computer into nanopb-0.4.8"
|
||||||
|
|
||||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||||
cd protobufs
|
cd protobufs
|
||||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated/ -I=../protobufs meshtastic/*.proto --experimental_allow_proto3_optional
|
../nanopb-0.4.8/generator-bin/protoc --experimental_allow_proto3_optional "--nanopb_out=-S.cpp -v:../src/mesh/generated/" -I=../protobufs meshtastic/*.proto
|
||||||
|
|
||||||
# cd ../src/mesh/generated/meshtastic
|
|
||||||
# sed -i 's/#include "meshtastic/#include "./g' -- *
|
|
||||||
|
|
||||||
# sed -i 's/meshtastic_//g' -- *
|
|
||||||
|
|
||||||
#echo "Regenerating protobuf documentation - if you see an error message"
|
|
||||||
#echo "you can ignore it unless doing a new protobuf release to github."
|
|
||||||
#bin/regen-docs.sh
|
|
||||||
|
|||||||
BIN
bin/update-lilygo_techo_bootloader-0.6.1_nosd.uf2
Normal file
BIN
bin/update-lilygo_techo_bootloader-0.6.1_nosd.uf2
Normal file
Binary file not shown.
38
boards/CDEBYTE_EoRa-S3.json
Normal file
38
boards/CDEBYTE_EoRa-S3.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-D CDEBYTE_EORA_S3",
|
||||||
|
"-D ARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
|
"-D ARDUINO_USB_MODE=0",
|
||||||
|
"-D ARDUINO_RUNNING_CORE=1",
|
||||||
|
"-D ARDUINO_EVENT_RUNNING_CORE=1",
|
||||||
|
"-D BOARD_HAS_PSRAM"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "dio",
|
||||||
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "CDEBYTE_EoRa-S3"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi"],
|
||||||
|
"debug": {
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "CDEBYTE EoRa-S3",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.cdebyte.com/Module-Testkits-EoRaPI",
|
||||||
|
"vendor": "CDEBYTE"
|
||||||
|
}
|
||||||
39
boards/ESP32-S3-WROOM-1-N4.json
Normal file
39
boards/ESP32-S3-WROOM-1-N4.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-D ARDUINO_USB_CDC_ON_BOOT=0",
|
||||||
|
"-D ARDUINO_USB_MSC_ON_BOOT=0",
|
||||||
|
"-D ARDUINO_USB_DFU_ON_BOOT=0",
|
||||||
|
"-D ARDUINO_USB_MODE=0",
|
||||||
|
"-D ARDUINO_RUNNING_CORE=1",
|
||||||
|
"-D ARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "ESP32-S3-WROOM-1-N4"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi"],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": ["esp-builtin"],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "ESP32-S3-WROOM-1-N4 (4 MB Flash, No PSRAM)",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "4MB",
|
||||||
|
"maximum_ram_size": 524288,
|
||||||
|
"maximum_size": 4194304,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
|
||||||
|
"vendor": "Espressif"
|
||||||
|
}
|
||||||
52
boards/canaryone.json
Normal file
52
boards/canaryone.json
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.ld"
|
||||||
|
},
|
||||||
|
"core": "nRF5",
|
||||||
|
"cpu": "cortex-m4",
|
||||||
|
"extra_flags": "-DARDUINO_NRF52840_CANARY -DNRF52840_XXAA",
|
||||||
|
"f_cpu": "64000000L",
|
||||||
|
"hwids": [
|
||||||
|
["0x239A", "0x4405"],
|
||||||
|
["0x239A", "0x009F"]
|
||||||
|
],
|
||||||
|
"usb_product": "CanaryOne",
|
||||||
|
"mcu": "nrf52840",
|
||||||
|
"variant": "canaryone",
|
||||||
|
"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": "Canary (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": "https://canaryradio.io/",
|
||||||
|
"vendor": "Canary Radio Company"
|
||||||
|
}
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "TTGO eink (Adafruit BSP)",
|
"name": "TTGO eink (Adafruit BSP)",
|
||||||
|
|||||||
40
boards/esp32-s3-pico.json
Normal file
40
boards/esp32-s3-pico.json
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"partitions": "default_16MB.csv"
|
||||||
|
},
|
||||||
|
"core": "esp32",
|
||||||
|
"extra_flags": [
|
||||||
|
"-DARDUINO_ESP32S3_DEV",
|
||||||
|
"-DARDUINO_USB_MODE=1",
|
||||||
|
"-DARDUINO_RUNNING_CORE=1",
|
||||||
|
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "esp32s3"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": ["esp-builtin"],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "Waveshare ESP32-S3-Pico (16 MB FLASH, 2 MB PSRAM)",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://www.waveshare.com/esp32-s3-pico.htm",
|
||||||
|
"vendor": "Waveshare"
|
||||||
|
}
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
"connectivity": ["bluetooth"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52832_xxAA",
|
"jlink_device": "nRF52832_xxAA",
|
||||||
"svd_path": "nrf52.svd"
|
"svd_path": "nrf52.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "lora ISP4520",
|
"name": "lora ISP4520",
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"connectivity": ["bluetooth"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "nRF52840 Dongle",
|
"name": "nRF52840 Dongle",
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "Meshtastic PPR (Adafruit BSP)",
|
"name": "Meshtastic PPR (Adafruit BSP)",
|
||||||
|
|||||||
@@ -29,7 +29,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52833_xxAA",
|
"jlink_device": "nRF52833_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52833.svd"
|
"svd_path": "nrf52833.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "Meshtastic PPR1 (Adafruit BSP)",
|
"name": "Meshtastic PPR1 (Adafruit BSP)",
|
||||||
|
|||||||
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"
|
||||||
|
}
|
||||||
41
boards/station-g2.json
Executable file
41
boards/station-g2.json
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "esp32s3_out.ld",
|
||||||
|
"memory_type": "qio_opi"
|
||||||
|
},
|
||||||
|
"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=0"
|
||||||
|
],
|
||||||
|
"f_cpu": "240000000L",
|
||||||
|
"f_flash": "80000000L",
|
||||||
|
"flash_mode": "qio",
|
||||||
|
"hwids": [["0x303A", "0x1001"]],
|
||||||
|
"mcu": "esp32s3",
|
||||||
|
"variant": "station-g2"
|
||||||
|
},
|
||||||
|
"connectivity": ["wifi", "bluetooth", "lora"],
|
||||||
|
"debug": {
|
||||||
|
"default_tool": "esp-builtin",
|
||||||
|
"onboard_tools": ["esp-builtin"],
|
||||||
|
"openocd_target": "esp32s3.cfg"
|
||||||
|
},
|
||||||
|
"frameworks": ["arduino", "espidf"],
|
||||||
|
"name": "BQ Station G2",
|
||||||
|
"upload": {
|
||||||
|
"flash_size": "16MB",
|
||||||
|
"maximum_ram_size": 327680,
|
||||||
|
"maximum_size": 16777216,
|
||||||
|
"use_1200bps_touch": true,
|
||||||
|
"wait_for_upload_port": true,
|
||||||
|
"require_upload_port": true,
|
||||||
|
"speed": 921600
|
||||||
|
},
|
||||||
|
"url": "https://wiki.uniteng.com/en/meshtastic/station-g2",
|
||||||
|
"vendor": "BQ Consulting"
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
"f_cpu": "64000000L",
|
"f_cpu": "64000000L",
|
||||||
"hwids": [
|
"hwids": [
|
||||||
["0x239A", "0x4405"],
|
["0x239A", "0x4405"],
|
||||||
|
["0x239A", "0x0029"],
|
||||||
["0x239A", "0x002A"]
|
["0x239A", "0x002A"]
|
||||||
],
|
],
|
||||||
"usb_product": "TTGO_eink",
|
"usb_product": "TTGO_eink",
|
||||||
@@ -32,7 +33,8 @@
|
|||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"onboard_tools": ["jlink"],
|
"onboard_tools": ["jlink"],
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "TTGO eink (Adafruit BSP)",
|
"name": "TTGO eink (Adafruit BSP)",
|
||||||
|
|||||||
@@ -16,7 +16,10 @@
|
|||||||
"f_cpu": "240000000L",
|
"f_cpu": "240000000L",
|
||||||
"f_flash": "80000000L",
|
"f_flash": "80000000L",
|
||||||
"flash_mode": "qio",
|
"flash_mode": "qio",
|
||||||
"hwids": [["0x303A", "0x1001"]],
|
"hwids": [
|
||||||
|
["0x303A", "0x1001"],
|
||||||
|
["0x303A", "0x0002"]
|
||||||
|
],
|
||||||
"mcu": "esp32s3",
|
"mcu": "esp32s3",
|
||||||
"variant": "t-watch-s3"
|
"variant": "t-watch-s3"
|
||||||
},
|
},
|
||||||
|
|||||||
58
boards/wio-sdk-wm1110.json
Normal file
58
boards/wio-sdk-wm1110.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"build": {
|
||||||
|
"arduino": {
|
||||||
|
"ldscript": "nrf52840_s140_v6.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": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"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-WM1110-Dev-Kit-p-5677.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_v6.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": "6.1.1",
|
||||||
|
"sd_fwid": "0x00B6"
|
||||||
|
},
|
||||||
|
"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-WM1110-Dev-Kit-p-5677.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",
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"connectivity": ["bluetooth"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52832_xxAA",
|
"jlink_device": "nRF52832_xxAA",
|
||||||
"svd_path": "nrf52.svd"
|
"svd_path": "nrf52.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino", "zephyr"],
|
"frameworks": ["arduino", "zephyr"],
|
||||||
"name": "Adafruit Bluefruit nRF52832 Feather",
|
"name": "Adafruit Bluefruit nRF52832 Feather",
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"connectivity": ["bluetooth"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "WisCore RAK4631 Board",
|
"name": "WisCore RAK4631 Board",
|
||||||
|
|||||||
@@ -31,7 +31,8 @@
|
|||||||
"connectivity": ["bluetooth"],
|
"connectivity": ["bluetooth"],
|
||||||
"debug": {
|
"debug": {
|
||||||
"jlink_device": "nRF52840_xxAA",
|
"jlink_device": "nRF52840_xxAA",
|
||||||
"svd_path": "nrf52840.svd"
|
"svd_path": "nrf52840.svd",
|
||||||
|
"openocd_target": "nrf52840-mdk-rs"
|
||||||
},
|
},
|
||||||
"frameworks": ["arduino"],
|
"frameworks": ["arduino"],
|
||||||
"name": "Seeed Xiao BLE Sense",
|
"name": "Seeed Xiao BLE Sense",
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
;default_envs = tbeam
|
default_envs = tbeam
|
||||||
;default_envs = pico
|
;default_envs = pico
|
||||||
;default_envs = tbeam-s3-core
|
;default_envs = tbeam-s3-core
|
||||||
;default_envs = tbeam0.7
|
;default_envs = tbeam0.7
|
||||||
@@ -10,13 +10,16 @@
|
|||||||
;default_envs = heltec-v2_0
|
;default_envs = heltec-v2_0
|
||||||
;default_envs = heltec-v2_1
|
;default_envs = heltec-v2_1
|
||||||
;default_envs = heltec-wireless-tracker
|
;default_envs = heltec-wireless-tracker
|
||||||
|
;default_envs = chatter2
|
||||||
;default_envs = tlora-v1
|
;default_envs = tlora-v1
|
||||||
;default_envs = tlora_v1_3
|
;default_envs = tlora_v1_3
|
||||||
;default_envs = tlora-v2
|
;default_envs = tlora-v2
|
||||||
;default_envs = tlora-v2-1-1_6
|
;default_envs = tlora-v2-1-1_6
|
||||||
|
;default_envs = tlora-v2-1-1_6-tcxo
|
||||||
;default_envs = tlora-t3s3-v1
|
;default_envs = tlora-t3s3-v1
|
||||||
;default_envs = lora-relay-v1 # nrf board
|
;default_envs = lora-relay-v1 # nrf board
|
||||||
;default_envs = t-echo
|
;default_envs = t-echo
|
||||||
|
;default_envs = canaryone
|
||||||
;default_envs = nrf52840dk-geeksville
|
;default_envs = nrf52840dk-geeksville
|
||||||
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
;default_envs = native # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||||
;default_envs = nano-g1
|
;default_envs = nano-g1
|
||||||
@@ -26,7 +29,12 @@
|
|||||||
;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 = wio-e5
|
;default_envs = rak2560
|
||||||
|
;default_envs = rak10701
|
||||||
|
;default_envs = wio-e5
|
||||||
|
;default_envs = radiomaster_900_bandit_nano
|
||||||
|
;default_envs = radiomaster_900_bandit_micro
|
||||||
|
;default_envs = heltec_capsule_sensor_v3
|
||||||
|
|
||||||
extra_configs =
|
extra_configs =
|
||||||
arch/*/*.ini
|
arch/*/*.ini
|
||||||
@@ -50,9 +58,11 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
-DRADIOLIB_EXCLUDE_NRF24
|
-DRADIOLIB_EXCLUDE_NRF24
|
||||||
-DRADIOLIB_EXCLUDE_RF69
|
-DRADIOLIB_EXCLUDE_RF69
|
||||||
-DRADIOLIB_EXCLUDE_SX1231
|
-DRADIOLIB_EXCLUDE_SX1231
|
||||||
|
-DRADIOLIB_EXCLUDE_SX1233
|
||||||
-DRADIOLIB_EXCLUDE_SI443X
|
-DRADIOLIB_EXCLUDE_SI443X
|
||||||
-DRADIOLIB_EXCLUDE_RFM2X
|
-DRADIOLIB_EXCLUDE_RFM2X
|
||||||
-DRADIOLIB_EXCLUDE_AFSK
|
-DRADIOLIB_EXCLUDE_AFSK
|
||||||
|
-DRADIOLIB_EXCLUDE_BELL
|
||||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
|
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
|
||||||
-DRADIOLIB_EXCLUDE_MORSE
|
-DRADIOLIB_EXCLUDE_MORSE
|
||||||
-DRADIOLIB_EXCLUDE_RTTY
|
-DRADIOLIB_EXCLUDE_RTTY
|
||||||
@@ -63,16 +73,19 @@ build_flags = -Wno-missing-field-initializers
|
|||||||
-DRADIOLIB_EXCLUDE_PAGER
|
-DRADIOLIB_EXCLUDE_PAGER
|
||||||
-DRADIOLIB_EXCLUDE_FSK4
|
-DRADIOLIB_EXCLUDE_FSK4
|
||||||
-DRADIOLIB_EXCLUDE_APRS
|
-DRADIOLIB_EXCLUDE_APRS
|
||||||
|
-DRADIOLIB_EXCLUDE_LORAWAN
|
||||||
|
-DMESHTASTIC_EXCLUDE_DROPZONE=1
|
||||||
|
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#b38094e03dfa964fbc0e799bc374e91a605c1223 ; ESP8266_SSD1306
|
jgromes/RadioLib@~6.6.0
|
||||||
https://github.com/mathertel/OneButton#2.1.0 ; OneButton library for non-blocking button debounce
|
https://github.com/meshtastic/esp8266-oled-ssd1306.git#dcacac5d2c7942376bc17f7079cced6a73cb659f ; ESP8266_SSD1306
|
||||||
|
mathertel/OneButton@^2.5.0 ; 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#076e8d2c8fb702d9be5b08c55b93ff76f8af7e61
|
https://github.com/meshtastic/TinyGPSPlus.git#71a82db35f3b973440044c476d4bcdc673b104f4
|
||||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
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
|
||||||
@@ -88,11 +101,10 @@ 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
|
||||||
|
|
||||||
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
|
build_flags = ${env.build_flags} -Os
|
||||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||||
|
|
||||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||||
@@ -106,12 +118,11 @@ lib_deps =
|
|||||||
; (not included in native / portduino)
|
; (not included in native / portduino)
|
||||||
[environmental_base]
|
[environmental_base]
|
||||||
lib_deps =
|
lib_deps =
|
||||||
adafruit/Adafruit BusIO@^1.11.4
|
adafruit/Adafruit BusIO@^1.15.0
|
||||||
adafruit/Adafruit Unified Sensor@^1.1.11
|
adafruit/Adafruit Unified Sensor@^1.1.11
|
||||||
adafruit/Adafruit BMP280 Library@^2.6.8
|
adafruit/Adafruit BMP280 Library@^2.6.8
|
||||||
|
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
|
||||||
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
|
||||||
@@ -121,4 +132,23 @@ 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/BMA423_Library@^0.0.1
|
adafruit/Adafruit AHTX0@^2.0.5
|
||||||
|
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: 6290ee0f6a...0c90a6814f
@@ -1,22 +1,28 @@
|
|||||||
|
#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"
|
||||||
|
|
||||||
#include <Adafruit_LIS3DH.h>
|
#include <Adafruit_LIS3DH.h>
|
||||||
|
#include <Adafruit_LSM6DS3TRC.h>
|
||||||
#include <Adafruit_MPU6050.h>
|
#include <Adafruit_MPU6050.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#include <SensorBMA423.hpp>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
#include <bma.h>
|
#ifdef RAK_4631
|
||||||
|
#include "Fusion/Fusion.h"
|
||||||
BMA423 bmaSensor;
|
#include <Rak_BMX160.h>
|
||||||
bool BMA_IRQ = false;
|
#endif
|
||||||
|
|
||||||
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
#define ACCELEROMETER_CHECK_INTERVAL_MS 100
|
||||||
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
#define ACCELEROMETER_CLICK_THRESHOLD 40
|
||||||
|
|
||||||
uint16_t readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_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);
|
||||||
@@ -29,7 +35,7 @@ uint16_t readRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len)
|
|||||||
return 0; // Pass
|
return 0; // Pass
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_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);
|
||||||
@@ -37,93 +43,33 @@ uint16_t writeRegister(uint8_t address, uint8_t reg, uint8_t *data, uint16_t len
|
|||||||
return (0 != Wire.endTransmission());
|
return (0 != Wire.endTransmission());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace concurrency
|
|
||||||
{
|
|
||||||
class AccelerometerThread : public concurrency::OSThread
|
class AccelerometerThread : public concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AccelerometerThread(ScanI2C::DeviceType type = ScanI2C::DeviceType::NONE) : OSThread("AccelerometerThread")
|
explicit AccelerometerThread(ScanI2C::DeviceType type) : OSThread("AccelerometerThread")
|
||||||
{
|
{
|
||||||
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
if (accelerometer_found.port == ScanI2C::I2CPort::NO_I2C) {
|
||||||
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
LOG_DEBUG("AccelerometerThread disabling due to no sensors found\n");
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
acceleremoter_type = type;
|
|
||||||
LOG_DEBUG("AccelerometerThread initializing\n");
|
|
||||||
|
|
||||||
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
|
||||||
LOG_DEBUG("MPU6050 initializing\n");
|
|
||||||
// setup motion detection
|
|
||||||
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
|
|
||||||
mpu.setMotionDetectionThreshold(1);
|
|
||||||
mpu.setMotionDetectionDuration(20);
|
|
||||||
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
|
|
||||||
mpu.setInterruptPinPolarity(true);
|
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
|
|
||||||
LOG_DEBUG("LIS3DH initializing\n");
|
|
||||||
lis.setRange(LIS3DH_RANGE_2_G);
|
|
||||||
// Adjust threshold, higher numbers are less sensitive
|
|
||||||
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
|
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.begin(readRegister, writeRegister, delay)) {
|
|
||||||
LOG_DEBUG("BMA423 initializing\n");
|
|
||||||
Acfg cfg;
|
|
||||||
cfg.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
|
|
||||||
cfg.range = BMA4_ACCEL_RANGE_2G;
|
|
||||||
cfg.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
|
|
||||||
cfg.perf_mode = BMA4_CONTINUOUS_MODE;
|
|
||||||
bmaSensor.setAccelConfig(cfg);
|
|
||||||
bmaSensor.enableAccel();
|
|
||||||
|
|
||||||
struct bma4_int_pin_config pin_config;
|
|
||||||
pin_config.edge_ctrl = BMA4_LEVEL_TRIGGER;
|
|
||||||
pin_config.lvl = BMA4_ACTIVE_HIGH;
|
|
||||||
pin_config.od = BMA4_PUSH_PULL;
|
|
||||||
pin_config.output_en = BMA4_OUTPUT_ENABLE;
|
|
||||||
pin_config.input_en = BMA4_INPUT_DISABLE;
|
|
||||||
// The correct trigger interrupt needs to be configured as needed
|
|
||||||
bmaSensor.setINTPinConfig(pin_config, BMA4_INTR1_MAP);
|
|
||||||
|
|
||||||
#ifdef BMA423_INT
|
|
||||||
pinMode(BMA4XX_INT, INPUT);
|
|
||||||
attachInterrupt(
|
|
||||||
BMA4XX_INT,
|
|
||||||
[] {
|
|
||||||
// Set interrupt to set irq value to true
|
|
||||||
BMA_IRQ = true;
|
|
||||||
},
|
|
||||||
RISING); // Select the interrupt mode according to the actual circuit
|
|
||||||
#endif
|
#endif
|
||||||
|
init();
|
||||||
struct bma423_axes_remap remap_data;
|
|
||||||
remap_data.x_axis = 0;
|
|
||||||
remap_data.x_axis_sign = 1;
|
|
||||||
remap_data.y_axis = 1;
|
|
||||||
remap_data.y_axis_sign = 0;
|
|
||||||
remap_data.z_axis = 2;
|
|
||||||
remap_data.z_axis_sign = 1;
|
|
||||||
// Need to raise the wrist function, need to set the correct axis
|
|
||||||
bmaSensor.setRemapAxes(&remap_data);
|
|
||||||
// sensor.enableFeature(BMA423_STEP_CNTR, true);
|
|
||||||
bmaSensor.enableFeature(BMA423_TILT, true);
|
|
||||||
bmaSensor.enableFeature(BMA423_WAKEUP, true);
|
|
||||||
// sensor.resetStepCounter();
|
|
||||||
|
|
||||||
// Turn on feature interrupt
|
|
||||||
bmaSensor.enableStepCountInterrupt();
|
|
||||||
bmaSensor.enableTiltInterrupt();
|
|
||||||
// It corresponds to isDoubleClick interrupt
|
|
||||||
bmaSensor.enableWakeupInterrupt();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void start()
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
setIntervalFromNow(0);
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int32_t runOnce() override
|
int32_t runOnce() override
|
||||||
{
|
{
|
||||||
@@ -141,17 +87,155 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
buttonPress();
|
buttonPress();
|
||||||
return 500;
|
return 500;
|
||||||
}
|
}
|
||||||
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.getINT()) {
|
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 && bmaSensor.readIrqStatus() != DEV_WIRE_NONE) {
|
||||||
if (bmaSensor.isTilt() || bmaSensor.isDoubleClick()) {
|
if (bmaSensor.isTilt() || bmaSensor.isDoubleTap()) {
|
||||||
wakeScreen();
|
wakeScreen();
|
||||||
return 500;
|
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() > 10 * 1000 && millis() < 30 * 1000) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return ACCELEROMETER_CHECK_INTERVAL_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void init()
|
||||||
|
{
|
||||||
|
LOG_DEBUG("AccelerometerThread initializing\n");
|
||||||
|
|
||||||
|
if (acceleremoter_type == ScanI2C::DeviceType::MPU6050 && mpu.begin(accelerometer_found.address)) {
|
||||||
|
LOG_DEBUG("MPU6050 initializing\n");
|
||||||
|
// setup motion detection
|
||||||
|
mpu.setHighPassFilter(MPU6050_HIGHPASS_0_63_HZ);
|
||||||
|
mpu.setMotionDetectionThreshold(1);
|
||||||
|
mpu.setMotionDetectionDuration(20);
|
||||||
|
mpu.setInterruptPinLatch(true); // Keep it latched. Will turn off when reinitialized.
|
||||||
|
mpu.setInterruptPinPolarity(true);
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::LIS3DH && lis.begin(accelerometer_found.address)) {
|
||||||
|
LOG_DEBUG("LIS3DH initializing\n");
|
||||||
|
lis.setRange(LIS3DH_RANGE_2_G);
|
||||||
|
// Adjust threshold, higher numbers are less sensitive
|
||||||
|
lis.setClick(config.device.double_tap_as_button_press ? 2 : 1, ACCELEROMETER_CLICK_THRESHOLD);
|
||||||
|
} else if (acceleremoter_type == ScanI2C::DeviceType::BMA423 &&
|
||||||
|
bmaSensor.begin(accelerometer_found.address, &readRegister, &writeRegister)) {
|
||||||
|
LOG_DEBUG("BMA423 initializing\n");
|
||||||
|
bmaSensor.configAccelerometer(bmaSensor.RANGE_2G, bmaSensor.ODR_100HZ, bmaSensor.BW_NORMAL_AVG4,
|
||||||
|
bmaSensor.PERF_CONTINUOUS_MODE);
|
||||||
|
bmaSensor.enableAccelerometer();
|
||||||
|
bmaSensor.configInterrupt(BMA4_LEVEL_TRIGGER, BMA4_ACTIVE_HIGH, BMA4_PUSH_PULL, BMA4_OUTPUT_ENABLE,
|
||||||
|
BMA4_INPUT_DISABLE);
|
||||||
|
|
||||||
|
#ifdef BMA423_INT
|
||||||
|
pinMode(BMA4XX_INT, INPUT);
|
||||||
|
attachInterrupt(
|
||||||
|
BMA4XX_INT,
|
||||||
|
[] {
|
||||||
|
// Set interrupt to set irq value to true
|
||||||
|
BMA_IRQ = true;
|
||||||
|
},
|
||||||
|
RISING); // Select the interrupt mode according to the actual circuit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef T_WATCH_S3
|
||||||
|
// Need to raise the wrist function, need to set the correct axis
|
||||||
|
bmaSensor.setReampAxes(bmaSensor.REMAP_TOP_LAYER_RIGHT_CORNER);
|
||||||
|
#else
|
||||||
|
bmaSensor.setReampAxes(bmaSensor.REMAP_BOTTOM_LAYER_BOTTOM_LEFT_CORNER);
|
||||||
|
#endif
|
||||||
|
// bmaSensor.enableFeature(bmaSensor.FEATURE_STEP_CNTR, true);
|
||||||
|
bmaSensor.enableFeature(bmaSensor.FEATURE_TILT, true);
|
||||||
|
bmaSensor.enableFeature(bmaSensor.FEATURE_WAKEUP, true);
|
||||||
|
// bmaSensor.resetPedometer();
|
||||||
|
|
||||||
|
// Turn on feature interrupt
|
||||||
|
bmaSensor.enablePedometerIRQ();
|
||||||
|
bmaSensor.enableTiltIRQ();
|
||||||
|
// It corresponds to isDoubleClick interrupt
|
||||||
|
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)) {
|
||||||
|
LOG_DEBUG("LSM6DS3 initializing\n");
|
||||||
|
// Default threshold of 2G, less sensitive options are 4, 8 or 16G
|
||||||
|
lsm.setAccelRange(LSM6DS_ACCEL_RANGE_2_G);
|
||||||
|
#ifndef LSM6DS3_WAKE_THRESH
|
||||||
|
#define LSM6DS3_WAKE_THRESH 20
|
||||||
|
#endif
|
||||||
|
lsm.enableWakeup(config.display.wake_on_tap_or_motion, 1, LSM6DS3_WAKE_THRESH);
|
||||||
|
// Duration is number of occurances needed to trigger, higher threshold is less sensitive
|
||||||
|
}
|
||||||
|
}
|
||||||
void wakeScreen()
|
void wakeScreen()
|
||||||
{
|
{
|
||||||
if (powerFSM.getState() == &stateDARK) {
|
if (powerFSM.getState() == &stateDARK) {
|
||||||
@@ -169,6 +253,13 @@ class AccelerometerThread : public concurrency::OSThread
|
|||||||
ScanI2C::DeviceType acceleremoter_type;
|
ScanI2C::DeviceType acceleremoter_type;
|
||||||
Adafruit_MPU6050 mpu;
|
Adafruit_MPU6050 mpu;
|
||||||
Adafruit_LIS3DH lis;
|
Adafruit_LIS3DH lis;
|
||||||
|
Adafruit_LSM6DS3TRC lsm;
|
||||||
|
SensorBMA423 bmaSensor;
|
||||||
|
#ifdef RAK_4631
|
||||||
|
RAK_BMX160 bmx160;
|
||||||
|
float highestX = 0, lowestX = 0, highestY = 0, lowestY = 0, highestZ = 0, lowestZ = 0;
|
||||||
|
#endif
|
||||||
|
bool BMA_IRQ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace concurrency
|
#endif
|
||||||
@@ -5,12 +5,22 @@
|
|||||||
NCP5623 rgb;
|
NCP5623 rgb;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAS_NEOPIXEL
|
||||||
|
#include <graphics/NeoPixel.h>
|
||||||
|
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNPHONE
|
||||||
|
#include "unPhone.h"
|
||||||
|
extern unPhone unphone;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace concurrency
|
namespace concurrency
|
||||||
{
|
{
|
||||||
class AmbientLightingThread : public concurrency::OSThread
|
class AmbientLightingThread : public concurrency::OSThread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
explicit AmbientLightingThread(ScanI2C::DeviceType type) : OSThread("AmbientLightingThread")
|
||||||
{
|
{
|
||||||
// Uncomment to test module
|
// Uncomment to test module
|
||||||
// moduleConfig.ambient_lighting.led_state = true;
|
// moduleConfig.ambient_lighting.led_state = true;
|
||||||
@@ -27,15 +37,31 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||||
if (!moduleConfig.ambient_lighting.led_state) {
|
if (!moduleConfig.ambient_lighting.led_state) {
|
||||||
LOG_DEBUG("AmbientLightingThread disabling due to moduleConfig.ambient_lighting.led_state OFF\n");
|
LOG_DEBUG("AmbientLightingThread disabling due to moduleConfig.ambient_lighting.led_state OFF\n");
|
||||||
disable();
|
disable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_DEBUG("AmbientLightingThread initializing\n");
|
LOG_DEBUG("AmbientLightingThread initializing\n");
|
||||||
|
#ifdef HAS_NCP5623
|
||||||
if (_type == ScanI2C::NCP5623) {
|
if (_type == ScanI2C::NCP5623) {
|
||||||
rgb.begin();
|
rgb.begin();
|
||||||
|
#endif
|
||||||
|
#ifdef RGBLED_RED
|
||||||
|
pinMode(RGBLED_RED, OUTPUT);
|
||||||
|
pinMode(RGBLED_GREEN, OUTPUT);
|
||||||
|
pinMode(RGBLED_BLUE, OUTPUT);
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_NEOPIXEL
|
||||||
|
pixels.begin(); // Initialise the pixel(s)
|
||||||
|
pixels.clear(); // Set all pixel colors to 'off'
|
||||||
|
pixels.setBrightness(moduleConfig.ambient_lighting.current);
|
||||||
|
#endif
|
||||||
setLighting();
|
setLighting();
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_NCP5623
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -43,16 +69,17 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
protected:
|
protected:
|
||||||
int32_t runOnce() override
|
int32_t runOnce() override
|
||||||
{
|
{
|
||||||
|
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
|
||||||
#ifdef HAS_NCP5623
|
#ifdef HAS_NCP5623
|
||||||
if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) {
|
if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) {
|
||||||
|
#endif
|
||||||
setLighting();
|
setLighting();
|
||||||
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
|
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
|
||||||
} else {
|
#ifdef HAS_NCP5623
|
||||||
return disable();
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
return disable();
|
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
return disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -65,9 +92,36 @@ class AmbientLightingThread : public concurrency::OSThread
|
|||||||
rgb.setRed(moduleConfig.ambient_lighting.red);
|
rgb.setRed(moduleConfig.ambient_lighting.red);
|
||||||
rgb.setGreen(moduleConfig.ambient_lighting.green);
|
rgb.setGreen(moduleConfig.ambient_lighting.green);
|
||||||
rgb.setBlue(moduleConfig.ambient_lighting.blue);
|
rgb.setBlue(moduleConfig.ambient_lighting.blue);
|
||||||
LOG_DEBUG("Initializing Ambient lighting w/ current=%d, red=%d, green=%d, blue=%d\n",
|
LOG_DEBUG("Initializing NCP5623 Ambient lighting w/ 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,
|
||||||
moduleConfig.ambient_lighting.blue);
|
moduleConfig.ambient_lighting.blue);
|
||||||
|
#endif
|
||||||
|
#ifdef HAS_NEOPIXEL
|
||||||
|
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
|
||||||
|
moduleConfig.ambient_lighting.blue),
|
||||||
|
0, NEOPIXEL_COUNT);
|
||||||
|
pixels.show();
|
||||||
|
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.blue);
|
||||||
|
#endif
|
||||||
|
#ifdef RGBLED_CA
|
||||||
|
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
|
||||||
|
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
|
||||||
|
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
|
||||||
|
LOG_DEBUG("Initializing Ambient lighting RGB Common Anode w/ red=%d, green=%d, blue=%d\n",
|
||||||
|
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||||
|
#elif defined(RGBLED_RED)
|
||||||
|
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
|
||||||
|
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
|
||||||
|
analogWrite(RGBLED_BLUE, moduleConfig.ambient_lighting.blue);
|
||||||
|
LOG_DEBUG("Initializing Ambient lighting RGB Common Cathode w/ red=%d, green=%d, blue=%d\n",
|
||||||
|
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||||
|
#endif
|
||||||
|
#ifdef UNPHONE
|
||||||
|
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||||
|
LOG_DEBUG("Initializing unPhone Ambient lighting w/ red=%d, green=%d, blue=%d\n", moduleConfig.ambient_lighting.red,
|
||||||
|
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
77
src/AudioThread.h
Normal file
77
src/AudioThread.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "concurrency/OSThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "sleep.h"
|
||||||
|
|
||||||
|
#ifdef HAS_I2S
|
||||||
|
#include <AudioFileSourcePROGMEM.h>
|
||||||
|
#include <AudioGeneratorRTTTL.h>
|
||||||
|
#include <AudioOutputI2S.h>
|
||||||
|
#include <ESP8266SAM.h>
|
||||||
|
|
||||||
|
#define AUDIO_THREAD_INTERVAL_MS 100
|
||||||
|
|
||||||
|
class AudioThread : public concurrency::OSThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AudioThread() : OSThread("AudioThread") { initOutput(); }
|
||||||
|
|
||||||
|
void beginRttl(const void *data, uint32_t len)
|
||||||
|
{
|
||||||
|
setCPUFast(true);
|
||||||
|
rtttlFile = new AudioFileSourcePROGMEM(data, len);
|
||||||
|
i2sRtttl = new AudioGeneratorRTTTL();
|
||||||
|
i2sRtttl->begin(rtttlFile, audioOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isPlaying()
|
||||||
|
{
|
||||||
|
if (i2sRtttl != nullptr) {
|
||||||
|
return i2sRtttl->isRunning() && i2sRtttl->loop();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop()
|
||||||
|
{
|
||||||
|
if (i2sRtttl != nullptr) {
|
||||||
|
i2sRtttl->stop();
|
||||||
|
delete i2sRtttl;
|
||||||
|
i2sRtttl = nullptr;
|
||||||
|
}
|
||||||
|
if (rtttlFile != nullptr) {
|
||||||
|
delete rtttlFile;
|
||||||
|
rtttlFile = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCPUFast(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int32_t runOnce() override
|
||||||
|
{
|
||||||
|
canSleep = true; // Assume we should not keep the board awake
|
||||||
|
|
||||||
|
// if (i2sRtttl != nullptr && i2sRtttl->isRunning()) {
|
||||||
|
// i2sRtttl->loop();
|
||||||
|
// }
|
||||||
|
return AUDIO_THREAD_INTERVAL_MS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void initOutput()
|
||||||
|
{
|
||||||
|
audioOut = new AudioOutputI2S(1, AudioOutputI2S::EXTERNAL_I2S);
|
||||||
|
audioOut->SetPinout(DAC_I2S_BCK, DAC_I2S_WS, DAC_I2S_DOUT);
|
||||||
|
audioOut->SetGain(0.2);
|
||||||
|
};
|
||||||
|
|
||||||
|
AudioGeneratorRTTTL *i2sRtttl = nullptr;
|
||||||
|
AudioOutputI2S *audioOut;
|
||||||
|
|
||||||
|
AudioFileSourcePROGMEM *rtttlFile;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
325
src/ButtonThread.cpp
Normal file
325
src/ButtonThread.cpp
Normal file
@@ -0,0 +1,325 @@
|
|||||||
|
#include "ButtonThread.h"
|
||||||
|
#include "configuration.h"
|
||||||
|
#if !MESHTASTIC_EXCLUDE_GPS
|
||||||
|
#include "GPS.h"
|
||||||
|
#endif
|
||||||
|
#include "MeshService.h"
|
||||||
|
#include "PowerFSM.h"
|
||||||
|
#include "RadioLibInterface.h"
|
||||||
|
#include "buzz.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "modules/ExternalNotificationModule.h"
|
||||||
|
#include "power.h"
|
||||||
|
#ifdef ARCH_PORTDUINO
|
||||||
|
#include "platform/portduino/PortduinoGlue.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEBUG_BUTTONS 0
|
||||||
|
#if DEBUG_BUTTONS
|
||||||
|
#define LOG_BUTTON(...) LOG_DEBUG(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define LOG_BUTTON(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace concurrency;
|
||||||
|
|
||||||
|
ButtonThread *buttonThread; // Declared extern in header
|
||||||
|
volatile ButtonThread::ButtonEventType ButtonThread::btnEvent = ButtonThread::BUTTON_EVENT_NONE;
|
||||||
|
|
||||||
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
|
OneButton ButtonThread::userButton; // Get reference to static member
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ButtonThread::ButtonThread() : OSThread("Button")
|
||||||
|
{
|
||||||
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
|
|
||||||
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||||
|
this->userButton = OneButton(settingsMap[user], true, true);
|
||||||
|
LOG_DEBUG("Using GPIO%02d for button\n", settingsMap[user]);
|
||||||
|
}
|
||||||
|
#elif defined(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);
|
||||||
|
#else
|
||||||
|
this->userButton = OneButton(pin, true, true);
|
||||||
|
#endif
|
||||||
|
LOG_DEBUG("Using GPIO%02d for button\n", pin);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef INPUT_PULLUP_SENSE
|
||||||
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||||
|
pinMode(pin, INPUT_PULLUP_SENSE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
|
userButton.attachClick(userButtonPressed);
|
||||||
|
userButton.setClickMs(BUTTON_CLICK_MS);
|
||||||
|
userButton.setPressMs(BUTTON_LONGPRESS_MS);
|
||||||
|
userButton.setDebounceMs(1);
|
||||||
|
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||||
|
userButton.attachMultiClick(userButtonMultiPressed, this); // Reference to instance: get click count from non-static OneButton
|
||||||
|
#ifndef T_DECK // T-Deck immediately wakes up after shutdown, so disable this function
|
||||||
|
userButton.attachLongPressStart(userButtonPressedLongStart);
|
||||||
|
userButton.attachLongPressStop(userButtonPressedLongStop);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
||||||
|
#ifdef INPUT_PULLUP_SENSE
|
||||||
|
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
||||||
|
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
||||||
|
#endif
|
||||||
|
userButtonAlt.attachClick(userButtonPressed);
|
||||||
|
userButtonAlt.setClickMs(BUTTON_CLICK_MS);
|
||||||
|
userButtonAlt.setPressMs(BUTTON_LONGPRESS_MS);
|
||||||
|
userButtonAlt.setDebounceMs(1);
|
||||||
|
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
||||||
|
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
|
||||||
|
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
|
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
||||||
|
userButtonTouch.setPressMs(BUTTON_TOUCH_MS);
|
||||||
|
userButtonTouch.attachLongPressStart(touchPressedLongStart); // Better handling with longpress than click?
|
||||||
|
#endif
|
||||||
|
|
||||||
|
attachButtonInterrupts();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ButtonThread::runOnce()
|
||||||
|
{
|
||||||
|
// If the button is pressed we suppress CPU sleep until release
|
||||||
|
canSleep = true; // Assume we should not keep the board awake
|
||||||
|
|
||||||
|
#if defined(BUTTON_PIN)
|
||||||
|
userButton.tick();
|
||||||
|
canSleep &= userButton.isIdle();
|
||||||
|
#elif defined(ARCH_PORTDUINO)
|
||||||
|
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) {
|
||||||
|
userButton.tick();
|
||||||
|
canSleep &= userButton.isIdle();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
userButtonAlt.tick();
|
||||||
|
canSleep &= userButtonAlt.isIdle();
|
||||||
|
#endif
|
||||||
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
|
userButtonTouch.tick();
|
||||||
|
canSleep &= userButtonTouch.isIdle();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (btnEvent != BUTTON_EVENT_NONE) {
|
||||||
|
switch (btnEvent) {
|
||||||
|
case BUTTON_EVENT_PRESSED: {
|
||||||
|
LOG_BUTTON("press!\n");
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
||||||
|
moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||||
|
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
|
||||||
|
!moduleConfig.canned_message.enabled) {
|
||||||
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
|
||||||
|
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||||
|
!moduleConfig.canned_message.enabled) {
|
||||||
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_EVENT_DOUBLE_PRESSED: {
|
||||||
|
LOG_BUTTON("Double press!\n");
|
||||||
|
service.refreshLocalMeshNode();
|
||||||
|
auto sentPosition = service.trySendPosition(NODENUM_BROADCAST, true);
|
||||||
|
if (screen) {
|
||||||
|
if (sentPosition)
|
||||||
|
screen->print("Sent ad-hoc position\n");
|
||||||
|
else
|
||||||
|
screen->print("Sent ad-hoc nodeinfo\n");
|
||||||
|
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case BUTTON_EVENT_MULTI_PRESSED: {
|
||||||
|
LOG_BUTTON("Mulitipress! %hux\n", multipressClickCount);
|
||||||
|
switch (multipressClickCount) {
|
||||||
|
#if HAS_GPS
|
||||||
|
// 3 clicks: toggle GPS
|
||||||
|
case 3:
|
||||||
|
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
||||||
|
gps->toggleGpsMode();
|
||||||
|
if (screen)
|
||||||
|
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo
|
||||||
|
// 4 clicks: toggle backlight
|
||||||
|
case 4:
|
||||||
|
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
// No valid multipress action
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
} // end switch: click count
|
||||||
|
|
||||||
|
break;
|
||||||
|
} // end multipress event
|
||||||
|
|
||||||
|
case BUTTON_EVENT_LONG_PRESSED: {
|
||||||
|
LOG_BUTTON("Long press!\n");
|
||||||
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
if (screen)
|
||||||
|
screen->startShutdownScreen();
|
||||||
|
playBeep();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do actual shutdown when button released, otherwise the button release
|
||||||
|
// may wake the board immediatedly.
|
||||||
|
case BUTTON_EVENT_LONG_RELEASED: {
|
||||||
|
LOG_INFO("Shutdown from long press\n");
|
||||||
|
playShutdownMelody();
|
||||||
|
delay(3000);
|
||||||
|
power->shutdown();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
|
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
|
||||||
|
LOG_BUTTON("Touch press!\n");
|
||||||
|
if (screen) {
|
||||||
|
// Wake if asleep
|
||||||
|
if (powerFSM.getState() == &stateDARK)
|
||||||
|
powerFSM.trigger(EVENT_PRESS);
|
||||||
|
|
||||||
|
// Update display (legacy behaviour)
|
||||||
|
screen->forceDisplay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // BUTTON_PIN_TOUCH
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
btnEvent = BUTTON_EVENT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
runASAP = false;
|
||||||
|
return 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attach (or re-attach) hardware interrupts for buttons
|
||||||
|
* Public method. Used outside class when waking from MCU sleep
|
||||||
|
*/
|
||||||
|
void ButtonThread::attachButtonInterrupts()
|
||||||
|
{
|
||||||
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||||
|
wakeOnIrq(settingsMap[user], FALLING);
|
||||||
|
#elif defined(BUTTON_PIN)
|
||||||
|
// Interrupt for user button, during normal use. Improves responsiveness.
|
||||||
|
attachInterrupt(
|
||||||
|
config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN,
|
||||||
|
[]() {
|
||||||
|
ButtonThread::userButton.tick();
|
||||||
|
runASAP = true;
|
||||||
|
BaseType_t higherWake = 0;
|
||||||
|
mainDelay.interruptFromISR(&higherWake);
|
||||||
|
},
|
||||||
|
CHANGE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
|
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detach the "normal" button interrupts.
|
||||||
|
* Public method. Used before attaching a "wake-on-button" interrupt for MCU sleep
|
||||||
|
*/
|
||||||
|
void ButtonThread::detachButtonInterrupts()
|
||||||
|
{
|
||||||
|
#if defined(ARCH_PORTDUINO)
|
||||||
|
if (settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC)
|
||||||
|
detachInterrupt(settingsMap[user]);
|
||||||
|
#elif defined(BUTTON_PIN)
|
||||||
|
detachInterrupt(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_ALT
|
||||||
|
detachInterrupt(BUTTON_PIN_ALT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
|
detachInterrupt(BUTTON_PIN_TOUCH);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch a GPIO and if we get an IRQ, wake the main thread.
|
||||||
|
* Use to add wake on button press
|
||||||
|
*/
|
||||||
|
void ButtonThread::wakeOnIrq(int irq, int mode)
|
||||||
|
{
|
||||||
|
attachInterrupt(
|
||||||
|
irq,
|
||||||
|
[] {
|
||||||
|
BaseType_t higherWake = 0;
|
||||||
|
mainDelay.interruptFromISR(&higherWake);
|
||||||
|
runASAP = true;
|
||||||
|
},
|
||||||
|
FALLING);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static callback
|
||||||
|
void ButtonThread::userButtonMultiPressed(void *callerThread)
|
||||||
|
{
|
||||||
|
// Grab click count from non-static button, while the info is still valid
|
||||||
|
ButtonThread *thread = (ButtonThread *)callerThread;
|
||||||
|
thread->storeClickCount();
|
||||||
|
|
||||||
|
// Then handle later, in the usual way
|
||||||
|
btnEvent = BUTTON_EVENT_MULTI_PRESSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-static method, runs during callback. Grabs info while still valid
|
||||||
|
void ButtonThread::storeClickCount()
|
||||||
|
{
|
||||||
|
#ifdef BUTTON_PIN
|
||||||
|
multipressClickCount = userButton.getNumberClicks();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonThread::userButtonPressedLongStart()
|
||||||
|
{
|
||||||
|
if (millis() > c_holdOffTime) {
|
||||||
|
btnEvent = BUTTON_EVENT_LONG_PRESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ButtonThread::userButtonPressedLongStop()
|
||||||
|
{
|
||||||
|
if (millis() > c_holdOffTime) {
|
||||||
|
btnEvent = BUTTON_EVENT_LONG_RELEASED;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,45 @@
|
|||||||
#include "PowerFSM.h"
|
#pragma once
|
||||||
#include "RadioLibInterface.h"
|
|
||||||
#include "buzz.h"
|
#include "OneButton.h"
|
||||||
#include "concurrency/OSThread.h"
|
#include "concurrency/OSThread.h"
|
||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include "graphics/Screen.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "power.h"
|
|
||||||
#include <OneButton.h>
|
|
||||||
|
|
||||||
namespace concurrency
|
#ifndef BUTTON_CLICK_MS
|
||||||
{
|
#define BUTTON_CLICK_MS 250
|
||||||
/**
|
#endif
|
||||||
* Watch a GPIO and if we get an IRQ, wake the main thread.
|
|
||||||
* Use to add wake on button press
|
#ifndef BUTTON_LONGPRESS_MS
|
||||||
*/
|
#define BUTTON_LONGPRESS_MS 5000
|
||||||
void wakeOnIrq(int irq, int mode)
|
#endif
|
||||||
{
|
|
||||||
attachInterrupt(
|
#ifndef BUTTON_TOUCH_MS
|
||||||
irq,
|
#define BUTTON_TOCH_MS 400
|
||||||
[] {
|
#endif
|
||||||
BaseType_t higherWake = 0;
|
|
||||||
mainDelay.interruptFromISR(&higherWake);
|
|
||||||
},
|
|
||||||
FALLING);
|
|
||||||
}
|
|
||||||
|
|
||||||
class ButtonThread : public concurrency::OSThread
|
class ButtonThread : public concurrency::OSThread
|
||||||
{
|
{
|
||||||
// Prepare for button presses
|
public:
|
||||||
#ifdef BUTTON_PIN
|
static const uint32_t c_holdOffTime = 30000; // hold off 30s after boot
|
||||||
OneButton userButton;
|
|
||||||
|
enum ButtonEventType {
|
||||||
|
BUTTON_EVENT_NONE,
|
||||||
|
BUTTON_EVENT_PRESSED,
|
||||||
|
BUTTON_EVENT_DOUBLE_PRESSED,
|
||||||
|
BUTTON_EVENT_MULTI_PRESSED,
|
||||||
|
BUTTON_EVENT_LONG_PRESSED,
|
||||||
|
BUTTON_EVENT_LONG_RELEASED,
|
||||||
|
BUTTON_EVENT_TOUCH_LONG_PRESSED,
|
||||||
|
};
|
||||||
|
|
||||||
|
ButtonThread();
|
||||||
|
int32_t runOnce() override;
|
||||||
|
void attachButtonInterrupts();
|
||||||
|
void detachButtonInterrupts();
|
||||||
|
void storeClickCount();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#if defined(BUTTON_PIN) || defined(ARCH_PORTDUINO)
|
||||||
|
static OneButton userButton; // Static - accessed from an interrupt
|
||||||
#endif
|
#endif
|
||||||
#ifdef BUTTON_PIN_ALT
|
#ifdef BUTTON_PIN_ALT
|
||||||
OneButton userButtonAlt;
|
OneButton userButtonAlt;
|
||||||
@@ -37,166 +47,22 @@ class ButtonThread : public concurrency::OSThread
|
|||||||
#ifdef BUTTON_PIN_TOUCH
|
#ifdef BUTTON_PIN_TOUCH
|
||||||
OneButton userButtonTouch;
|
OneButton userButtonTouch;
|
||||||
#endif
|
#endif
|
||||||
static bool shutdown_on_long_stop;
|
|
||||||
|
|
||||||
public:
|
// set during IRQ
|
||||||
static uint32_t longPressTime;
|
static volatile ButtonEventType btnEvent;
|
||||||
|
|
||||||
// callback returns the period for the next callback invocation (or 0 if we should no longer be called)
|
// Store click count during callback, for later use
|
||||||
ButtonThread() : OSThread("Button")
|
volatile int multipressClickCount = 0;
|
||||||
{
|
|
||||||
#ifdef BUTTON_PIN
|
|
||||||
userButton = OneButton(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, true, true);
|
|
||||||
#ifdef INPUT_PULLUP_SENSE
|
|
||||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
|
||||||
pinMode(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, INPUT_PULLUP_SENSE);
|
|
||||||
#endif
|
|
||||||
userButton.attachClick(userButtonPressed);
|
|
||||||
userButton.setClickMs(300);
|
|
||||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
|
||||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
|
||||||
userButton.attachMultiClick(userButtonMultiPressed);
|
|
||||||
userButton.attachLongPressStart(userButtonPressedLongStart);
|
|
||||||
userButton.attachLongPressStop(userButtonPressedLongStop);
|
|
||||||
wakeOnIrq(config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN, FALLING);
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_ALT
|
|
||||||
userButtonAlt = OneButton(BUTTON_PIN_ALT, true, true);
|
|
||||||
#ifdef INPUT_PULLUP_SENSE
|
|
||||||
// Some platforms (nrf52) have a SENSE variant which allows wake from sleep - override what OneButton did
|
|
||||||
pinMode(BUTTON_PIN_ALT, INPUT_PULLUP_SENSE);
|
|
||||||
#endif
|
|
||||||
userButtonAlt.attachClick(userButtonPressed);
|
|
||||||
userButtonAlt.attachDuringLongPress(userButtonPressedLong);
|
|
||||||
userButtonAlt.attachDoubleClick(userButtonDoublePressed);
|
|
||||||
userButtonAlt.attachLongPressStart(userButtonPressedLongStart);
|
|
||||||
userButtonAlt.attachLongPressStop(userButtonPressedLongStop);
|
|
||||||
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BUTTON_PIN_TOUCH
|
static void wakeOnIrq(int irq, int mode);
|
||||||
userButtonTouch = OneButton(BUTTON_PIN_TOUCH, true, true);
|
|
||||||
userButtonTouch.attachClick(touchPressed);
|
|
||||||
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
// IRQ callbacks
|
||||||
/// If the button is pressed we suppress CPU sleep until release
|
static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; }
|
||||||
int32_t runOnce() override
|
static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; }
|
||||||
{
|
static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid
|
||||||
canSleep = true; // Assume we should not keep the board awake
|
static void userButtonPressedLongStart();
|
||||||
|
static void userButtonPressedLongStop();
|
||||||
#ifdef BUTTON_PIN
|
static void touchPressedLongStart() { btnEvent = BUTTON_EVENT_TOUCH_LONG_PRESSED; }
|
||||||
userButton.tick();
|
|
||||||
canSleep &= userButton.isIdle();
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_ALT
|
|
||||||
userButtonAlt.tick();
|
|
||||||
canSleep &= userButtonAlt.isIdle();
|
|
||||||
#endif
|
|
||||||
#ifdef BUTTON_PIN_TOUCH
|
|
||||||
userButtonTouch.tick();
|
|
||||||
canSleep &= userButtonTouch.isIdle();
|
|
||||||
#endif
|
|
||||||
// if (!canSleep) LOG_DEBUG("Suppressing sleep!\n");
|
|
||||||
// else LOG_DEBUG("sleep ok\n");
|
|
||||||
|
|
||||||
return 50;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static void touchPressed()
|
|
||||||
{
|
|
||||||
screen->forceDisplay();
|
|
||||||
LOG_DEBUG("touch press!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void userButtonPressed()
|
|
||||||
{
|
|
||||||
// LOG_DEBUG("press!\n");
|
|
||||||
#ifdef BUTTON_PIN
|
|
||||||
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
|
|
||||||
moduleConfig.canned_message.inputbroker_pin_press) ||
|
|
||||||
!moduleConfig.canned_message.enabled) {
|
|
||||||
powerFSM.trigger(EVENT_PRESS);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
static void userButtonPressedLong()
|
|
||||||
{
|
|
||||||
// LOG_DEBUG("Long press!\n");
|
|
||||||
// If user button is held down for 5 seconds, shutdown the device.
|
|
||||||
if ((millis() - longPressTime > 5000) && (longPressTime > 0)) {
|
|
||||||
#if defined(ARCH_NRF52) || defined(ARCH_ESP32)
|
|
||||||
// Do actual shutdown when button released, otherwise the button release
|
|
||||||
// may wake the board immediatedly.
|
|
||||||
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
|
|
||||||
screen->startShutdownScreen();
|
|
||||||
LOG_INFO("Shutdown from long press");
|
|
||||||
playBeep();
|
|
||||||
#ifdef PIN_LED1
|
|
||||||
ledOff(PIN_LED1);
|
|
||||||
#endif
|
|
||||||
#ifdef PIN_LED2
|
|
||||||
ledOff(PIN_LED2);
|
|
||||||
#endif
|
|
||||||
#ifdef PIN_LED3
|
|
||||||
ledOff(PIN_LED3);
|
|
||||||
#endif
|
|
||||||
shutdown_on_long_stop = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
|
||||||
// LOG_DEBUG("Long press %u\n", (millis() - longPressTime));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void userButtonDoublePressed()
|
|
||||||
{
|
|
||||||
#if defined(USE_EINK) && defined(PIN_EINK_EN)
|
|
||||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
|
||||||
#endif
|
|
||||||
screen->print("Sent ad-hoc ping\n");
|
|
||||||
service.refreshLocalMeshNode();
|
|
||||||
service.sendNetworkPing(NODENUM_BROADCAST, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void userButtonMultiPressed()
|
|
||||||
{
|
|
||||||
if (!config.device.disable_triple_click && (gps != nullptr)) {
|
|
||||||
config.position.gps_enabled = !(config.position.gps_enabled);
|
|
||||||
if (config.position.gps_enabled) {
|
|
||||||
LOG_DEBUG("Flag set to true to restore power\n");
|
|
||||||
gps->enable();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
LOG_DEBUG("Flag set to false for gps power\n");
|
|
||||||
gps->disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void userButtonPressedLongStart()
|
|
||||||
{
|
|
||||||
if (millis() > 30 * 1000) {
|
|
||||||
LOG_DEBUG("Long press start!\n");
|
|
||||||
longPressTime = millis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void userButtonPressedLongStop()
|
|
||||||
{
|
|
||||||
if (millis() > 30 * 1000) {
|
|
||||||
LOG_DEBUG("Long press stop!\n");
|
|
||||||
longPressTime = 0;
|
|
||||||
if (shutdown_on_long_stop) {
|
|
||||||
playShutdownMelody();
|
|
||||||
delay(3000);
|
|
||||||
power->shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace concurrency
|
extern ButtonThread *buttonThread;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#define DEBUG_PORT (*console) // Serial debug port
|
#define DEBUG_PORT (*console) // Serial debug port
|
||||||
|
|
||||||
#ifdef USE_SEGGER
|
#ifdef USE_SEGGER
|
||||||
#define DEBUG_PORT
|
// #undef DEBUG_PORT
|
||||||
#define LOG_DEBUG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define LOG_DEBUG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
#define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
#define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
#define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||||
@@ -36,7 +36,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)
|
||||||
#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__)
|
||||||
|
|||||||
@@ -205,6 +205,62 @@ void rmDir(const char *dirname)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fsCheck()
|
||||||
|
{
|
||||||
|
#if defined(ARCH_NRF52)
|
||||||
|
size_t write_size = 0;
|
||||||
|
size_t read_size = 0;
|
||||||
|
char buf[32] = {0};
|
||||||
|
|
||||||
|
Adafruit_LittleFS_Namespace::File file(FSCom);
|
||||||
|
const char *text = "meshtastic fs test";
|
||||||
|
size_t text_length = strlen(text);
|
||||||
|
const char *filename = "/meshtastic.txt";
|
||||||
|
|
||||||
|
LOG_DEBUG("Try create file .\n");
|
||||||
|
if (file.open(filename, FILE_O_WRITE)) {
|
||||||
|
write_size = file.write(text);
|
||||||
|
} else {
|
||||||
|
LOG_DEBUG("Open file failed .\n");
|
||||||
|
goto FORMAT_FS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_size != text_length) {
|
||||||
|
LOG_DEBUG("Text bytes do not match .\n");
|
||||||
|
file.close();
|
||||||
|
goto FORMAT_FS;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
if (!file.open(filename, FILE_O_READ)) {
|
||||||
|
LOG_DEBUG("Open file failed .\n");
|
||||||
|
goto FORMAT_FS;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_size = file.readBytes(buf, text_length);
|
||||||
|
if (read_size != text_length) {
|
||||||
|
LOG_DEBUG("Text bytes do not match .\n");
|
||||||
|
file.close();
|
||||||
|
goto FORMAT_FS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(buf, text, text_length) != 0) {
|
||||||
|
LOG_DEBUG("The written bytes do not match the read bytes .\n");
|
||||||
|
file.close();
|
||||||
|
goto FORMAT_FS;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
FORMAT_FS:
|
||||||
|
LOG_DEBUG("Format FS ....\n");
|
||||||
|
FSCom.format();
|
||||||
|
FSCom.begin();
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void fsInit()
|
void fsInit()
|
||||||
{
|
{
|
||||||
#ifdef FSCom
|
#ifdef FSCom
|
||||||
@@ -212,8 +268,37 @@ 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());
|
||||||
|
#elif defined(ARCH_NRF52)
|
||||||
|
/*
|
||||||
|
* nRF52840 has a certain chance of automatic formatting failure.
|
||||||
|
* Try to create a file after initializing the file system. If the creation fails,
|
||||||
|
* it means that the file system is not working properly. Please format it manually again.
|
||||||
|
* To check the normality of the file system, you need to disable the LFS_NO_ASSERT assertion.
|
||||||
|
* Otherwise, the assertion will be entered at the moment of reading or opening, and the FS will not be formatted.
|
||||||
|
* */
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t retry = 3;
|
||||||
|
|
||||||
|
while (retry--) {
|
||||||
|
ret = fsCheck();
|
||||||
|
if (ret) {
|
||||||
|
LOG_DEBUG("File system check is OK.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// It may not be possible to reach this step.
|
||||||
|
// Add a loop here to prevent unpredictable situations from happening.
|
||||||
|
// Can add a screen to display error status later.
|
||||||
|
if (!ret) {
|
||||||
|
while (1) {
|
||||||
|
LOG_ERROR("The file system is damaged and cannot proceed to the next step.\n");
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
LOG_DEBUG("Filesystem files:\n");
|
LOG_DEBUG("Filesystem files:\n");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
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
|
||||||
40
src/Fusion/FusionOffset.h
Normal file
40
src/Fusion/FusionOffset.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* @file FusionOffset.h
|
||||||
|
* @author Seb Madgwick
|
||||||
|
* @brief Gyroscope offset correction algorithm for run-time calibration of the
|
||||||
|
* gyroscope offset.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FUSION_OFFSET_H
|
||||||
|
#define FUSION_OFFSET_H
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Includes
|
||||||
|
|
||||||
|
#include "FusionMath.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Definitions
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gyroscope offset algorithm structure. Structure members are used
|
||||||
|
* internally and must not be accessed by the application.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
float filterCoefficient;
|
||||||
|
unsigned int timeout;
|
||||||
|
unsigned int timer;
|
||||||
|
FusionVector gyroscopeOffset;
|
||||||
|
} FusionOffset;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Function declarations
|
||||||
|
|
||||||
|
void FusionOffsetInitialise(FusionOffset *const offset, const unsigned int sampleRate);
|
||||||
|
|
||||||
|
FusionVector FusionOffsetUpdate(FusionOffset *const offset, FusionVector gyroscope);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// End of file
|
||||||
@@ -4,8 +4,6 @@
|
|||||||
#include "configuration.h"
|
#include "configuration.h"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
extern NodeDB nodeDB;
|
|
||||||
|
|
||||||
namespace meshtastic
|
namespace meshtastic
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -55,7 +53,7 @@ class GPSStatus : public Status
|
|||||||
#ifdef GPS_EXTRAVERBOSE
|
#ifdef GPS_EXTRAVERBOSE
|
||||||
LOG_WARN("Using fixed latitude\n");
|
LOG_WARN("Using fixed latitude\n");
|
||||||
#endif
|
#endif
|
||||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
return node->position.latitude_i;
|
return node->position.latitude_i;
|
||||||
} else {
|
} else {
|
||||||
return p.latitude_i;
|
return p.latitude_i;
|
||||||
@@ -68,7 +66,7 @@ class GPSStatus : public Status
|
|||||||
#ifdef GPS_EXTRAVERBOSE
|
#ifdef GPS_EXTRAVERBOSE
|
||||||
LOG_WARN("Using fixed longitude\n");
|
LOG_WARN("Using fixed longitude\n");
|
||||||
#endif
|
#endif
|
||||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
return node->position.longitude_i;
|
return node->position.longitude_i;
|
||||||
} else {
|
} else {
|
||||||
return p.longitude_i;
|
return p.longitude_i;
|
||||||
@@ -81,27 +79,18 @@ class GPSStatus : public Status
|
|||||||
#ifdef GPS_EXTRAVERBOSE
|
#ifdef GPS_EXTRAVERBOSE
|
||||||
LOG_WARN("Using fixed altitude\n");
|
LOG_WARN("Using fixed altitude\n");
|
||||||
#endif
|
#endif
|
||||||
meshtastic_NodeInfoLite *node = nodeDB.getMeshNode(nodeDB.getNodeNum());
|
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum());
|
||||||
return node->position.altitude;
|
return node->position.altitude;
|
||||||
} else {
|
} else {
|
||||||
return p.altitude;
|
return p.altitude;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getDOP() const
|
uint32_t getDOP() const { return p.PDOP; }
|
||||||
{
|
|
||||||
return p.PDOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getHeading() const
|
uint32_t getHeading() const { return p.ground_track; }
|
||||||
{
|
|
||||||
return p.ground_track;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t getNumSatellites() const
|
uint32_t getNumSatellites() const { return p.sats_in_view; }
|
||||||
{
|
|
||||||
return p.sats_in_view;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool matches(const GPSStatus *newStatus) const
|
bool matches(const GPSStatus *newStatus) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,12 +10,12 @@ template <class T> class Observable;
|
|||||||
*/
|
*/
|
||||||
template <class T> class Observer
|
template <class T> class Observer
|
||||||
{
|
{
|
||||||
std::list<Observable<T> *> observed;
|
std::list<Observable<T> *> observables;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~Observer();
|
virtual ~Observer();
|
||||||
|
|
||||||
/// Stop watching the obserable
|
/// Stop watching the observable
|
||||||
void unobserve(Observable<T> *o);
|
void unobserve(Observable<T> *o);
|
||||||
|
|
||||||
/// Start watching a specified observable
|
/// Start watching a specified observable
|
||||||
@@ -86,21 +86,21 @@ template <class T> class Observable
|
|||||||
|
|
||||||
template <class T> Observer<T>::~Observer()
|
template <class T> Observer<T>::~Observer()
|
||||||
{
|
{
|
||||||
for (typename std::list<Observable<T> *>::const_iterator iterator = observed.begin(); iterator != observed.end();
|
for (typename std::list<Observable<T> *>::const_iterator iterator = observables.begin(); iterator != observables.end();
|
||||||
++iterator) {
|
++iterator) {
|
||||||
(*iterator)->removeObserver(this);
|
(*iterator)->removeObserver(this);
|
||||||
}
|
}
|
||||||
observed.clear();
|
observables.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> void Observer<T>::unobserve(Observable<T> *o)
|
template <class T> void Observer<T>::unobserve(Observable<T> *o)
|
||||||
{
|
{
|
||||||
o->removeObserver(this);
|
o->removeObserver(this);
|
||||||
observed.remove(o);
|
observables.remove(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T> void Observer<T>::observe(Observable<T> *o)
|
template <class T> void Observer<T>::observe(Observable<T> *o)
|
||||||
{
|
{
|
||||||
observed.push_back(o);
|
observables.push_back(o);
|
||||||
o->addObserver(this);
|
o->addObserver(this);
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user