mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 12:42:30 +04:00
Compare commits
1609 Commits
subghz_pro
...
readme_upd
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
226e300a16 | ||
|
|
d49246048d | ||
|
|
a90ebd7b53 | ||
|
|
b1b35e87f9 | ||
|
|
1df2fc035f | ||
|
|
45fd5ef9d8 | ||
|
|
cfa95c757e | ||
|
|
600b2ce627 | ||
|
|
fdb9748acc | ||
|
|
d40f664342 | ||
|
|
8cbb757533 | ||
|
|
452e27b05e | ||
|
|
b3cce2351a | ||
|
|
1859b06b6a | ||
|
|
1653abe0ef | ||
|
|
c7b2e85e13 | ||
|
|
b24fba6ad7 | ||
|
|
ffc6f726f0 | ||
|
|
0eb06ba2b7 | ||
|
|
2a789ae1c1 | ||
|
|
062faa4a84 | ||
|
|
1cafa9a46b | ||
|
|
654b3245c2 | ||
|
|
99eb10d6e7 | ||
|
|
e878ed7547 | ||
|
|
ac4177c248 | ||
|
|
e6f9563bbc | ||
|
|
2b383ebcee | ||
|
|
cfc5caca63 | ||
|
|
9c6e20356f | ||
|
|
0b806c2360 | ||
|
|
ce89240f6f | ||
|
|
686fab7296 | ||
|
|
7d2deb5939 | ||
|
|
06a528f497 | ||
|
|
265d2592e7 | ||
|
|
72e6f5f59e | ||
|
|
3898e6e71d | ||
|
|
17269a5386 | ||
|
|
a2bcf67f7f | ||
|
|
bd2cfb55df | ||
|
|
0c7689831e | ||
|
|
ec9df8711a | ||
|
|
15c480b68a | ||
|
|
a8456208da | ||
|
|
7ecd5684cb | ||
|
|
832d861b9d | ||
|
|
7a0c896626 | ||
|
|
52b5966262 | ||
|
|
e5fdb2e069 | ||
|
|
5eeb672dd4 | ||
|
|
d8d2b360cb | ||
|
|
7531e18020 | ||
|
|
f218c41d83 | ||
|
|
7aa55ebc6c | ||
|
|
809418b9da | ||
|
|
b91f8d009e | ||
|
|
aa1c1fd905 | ||
|
|
cb5c5c08f6 | ||
|
|
c6be6f487a | ||
|
|
5eb045e25f | ||
|
|
04b2771e3b | ||
|
|
5bd868665e | ||
|
|
46e74b3823 | ||
|
|
a772408ee6 | ||
|
|
416a02fc5b | ||
|
|
cf74dd2599 | ||
|
|
66d26c16cd | ||
|
|
c3aa151712 | ||
|
|
ce1336c0ed | ||
|
|
32fb94f5db | ||
|
|
f93aab9b22 | ||
|
|
742c4ae834 | ||
|
|
6609a64307 | ||
|
|
09aabff55b | ||
|
|
0660329ae5 | ||
|
|
b5426197f5 | ||
|
|
940ec36a0b | ||
|
|
60182aa2cd | ||
|
|
56b5b35236 | ||
|
|
b368660d48 | ||
|
|
091d32ed7a | ||
|
|
52654d018e | ||
|
|
8df9947d42 | ||
|
|
d808884b97 | ||
|
|
6042254861 | ||
|
|
beeeb9bbdc | ||
|
|
4ade0fc76d | ||
|
|
15f92f765d | ||
|
|
821f03b230 | ||
|
|
ad723217e6 | ||
|
|
df5b2cbddd | ||
|
|
dc7517e5fd | ||
|
|
20593d56c0 | ||
|
|
27b2808ade | ||
|
|
ace0901125 | ||
|
|
991e58e405 | ||
|
|
e353433cd8 | ||
|
|
200c44bdca | ||
|
|
67a0136e81 | ||
|
|
2b5ad4f5af | ||
|
|
35cdefa1ca | ||
|
|
f14ed73dfd | ||
|
|
9bf1433334 | ||
|
|
35c413b8a6 | ||
|
|
34712b0c3b | ||
|
|
486542fe14 | ||
|
|
69debc36a0 | ||
|
|
2fabb0b589 | ||
|
|
c05a766651 | ||
|
|
ac9234563a | ||
|
|
b07b6dc857 | ||
|
|
c70edf6dc9 | ||
|
|
8a3d8bdee7 | ||
|
|
535bf35e23 | ||
|
|
362aa68038 | ||
|
|
f17b941f7d | ||
|
|
830eb0e5f6 | ||
|
|
38607d8dbe | ||
|
|
fe095df06a | ||
|
|
d728c140d8 | ||
|
|
4f6fd2e9bc | ||
|
|
d7a579e713 | ||
|
|
26e5ae7476 | ||
|
|
2458cb2b96 | ||
|
|
3da9cb1b81 | ||
|
|
5924c3dd2c | ||
|
|
5cfc8fc536 | ||
|
|
03d3482357 | ||
|
|
0af8bd1e8b | ||
|
|
6330012b1d | ||
|
|
b1b00d4fa7 | ||
|
|
7a80aaa5c8 | ||
|
|
3584e0da46 | ||
|
|
e1c83692c3 | ||
|
|
3507c89dbb | ||
|
|
6e2bcd9d00 | ||
|
|
f73f369952 | ||
|
|
3990c93013 | ||
|
|
4d5a900352 | ||
|
|
e830dc1636 | ||
|
|
2d6bd46326 | ||
|
|
0805754589 | ||
|
|
d627b53510 | ||
|
|
69cabfb496 | ||
|
|
b235c8abe9 | ||
|
|
0934b3f791 | ||
|
|
fec80da3f4 | ||
|
|
e892c977f3 | ||
|
|
15ac511dea | ||
|
|
b90e2ca342 | ||
|
|
aad06fdd43 | ||
|
|
d4bc0cc10c | ||
|
|
0ecec8a711 | ||
|
|
9d7396ee63 | ||
|
|
a7f0f5ad27 | ||
|
|
146ae8c3bf | ||
|
|
aeadaef7c9 | ||
|
|
fb2c65721b | ||
|
|
830e202bb1 | ||
|
|
9e3868887c | ||
|
|
f18df25a96 | ||
|
|
7bd8846288 | ||
|
|
196edb5d05 | ||
|
|
8c0e0c78f2 | ||
|
|
71b610c87e | ||
|
|
4f148079d5 | ||
|
|
80c0301316 | ||
|
|
4d772ed67e | ||
|
|
ff17f33a36 | ||
|
|
9fb20438c7 | ||
|
|
28a05d8f6b | ||
|
|
773a5e382f | ||
|
|
4164932044 | ||
|
|
751cb9f5d6 | ||
|
|
8d8102b4f9 | ||
|
|
4b81046b6f | ||
|
|
f069cdb7e6 | ||
|
|
43ba76a37f | ||
|
|
3aad84aa70 | ||
|
|
dc2d12d468 | ||
|
|
09d5b3b1ed | ||
|
|
5f48968a05 | ||
|
|
3a36d5ea6d | ||
|
|
12d9b1069c | ||
|
|
7178bd20cf | ||
|
|
f75fcd4e34 | ||
|
|
498aee20a2 | ||
|
|
ee64a962d9 | ||
|
|
c40e4ba01e | ||
|
|
2702c00ba4 | ||
|
|
c976ff11bf | ||
|
|
fb63e53d9a | ||
|
|
1078625775 | ||
|
|
7027f6a4c4 | ||
|
|
a39ef50fdb | ||
|
|
d9e931b7b7 | ||
|
|
98d4309b61 | ||
|
|
00cdc3d1cb | ||
|
|
8936c02487 | ||
|
|
e9f1af44f2 | ||
|
|
ab006361cc | ||
|
|
1e4af1d550 | ||
|
|
4c771b66dc | ||
|
|
20a6aa078c | ||
|
|
3c298d7d83 | ||
|
|
e01e6f163c | ||
|
|
6f37f01b20 | ||
|
|
d11fdca903 | ||
|
|
e50cab3da1 | ||
|
|
49d2b31446 | ||
|
|
c1438ce850 | ||
|
|
0f61a8eb46 | ||
|
|
6ef1847e4d | ||
|
|
f70d2b5ae7 | ||
|
|
4951efff4d | ||
|
|
07f6859a80 | ||
|
|
d30510f700 | ||
|
|
becc8edd8c | ||
|
|
d09cf6c692 | ||
|
|
afa7bd7f79 | ||
|
|
eb54fef384 | ||
|
|
fe630362a8 | ||
|
|
66deaad4f4 | ||
|
|
74ffb02b56 | ||
|
|
c7648eb932 | ||
|
|
cf6706c42e | ||
|
|
a7aef0bfc2 | ||
|
|
3e8e999909 | ||
|
|
3a5ed704fd | ||
|
|
7a45db3881 | ||
|
|
9fd9dd85e3 | ||
|
|
313e9c3d89 | ||
|
|
c72531edc6 | ||
|
|
035e447009 | ||
|
|
be86b0f38a | ||
|
|
a677b2bcc2 | ||
|
|
17bcfee224 | ||
|
|
1536f7a643 | ||
|
|
67ca96ea96 | ||
|
|
fe7a1c2fcc | ||
|
|
aadb72af53 | ||
|
|
68eb1ecebb | ||
|
|
a2a4fa8cda | ||
|
|
5d21da1737 | ||
|
|
7413f707ed | ||
|
|
c6b6aec057 | ||
|
|
c3f7a0d128 | ||
|
|
2c656f9c49 | ||
|
|
913efab179 | ||
|
|
03b950999c | ||
|
|
62e817f183 | ||
|
|
0f9c6ba847 | ||
|
|
e698d6274f | ||
|
|
ff2e1acfdb | ||
|
|
d4ff1e3a50 | ||
|
|
58beca313d | ||
|
|
99b203e25c | ||
|
|
2446c5c02b | ||
|
|
8e20aa6780 | ||
|
|
6f40a06869 | ||
|
|
8a249c48c5 | ||
|
|
e686561c77 | ||
|
|
3fcf0da1ec | ||
|
|
2c8ac7f775 | ||
|
|
dbb1ab8693 | ||
|
|
eed85f019c | ||
|
|
f1a353d942 | ||
|
|
9fa45850d2 | ||
|
|
2dc5d49be1 | ||
|
|
8c3d648814 | ||
|
|
5cfcbe1a2a | ||
|
|
73fc7146c8 | ||
|
|
5d14f6048a | ||
|
|
725d623855 | ||
|
|
c447dc45f1 | ||
|
|
14e44b6f88 | ||
|
|
a0f59f6094 | ||
|
|
bb4bd28fe1 | ||
|
|
171e147a9d | ||
|
|
7933bd9788 | ||
|
|
b7b03f2108 | ||
|
|
a7304bd9a8 | ||
|
|
9b88bda88b | ||
|
|
823094bf79 | ||
|
|
0470d681a2 | ||
|
|
5c5e68a5ce | ||
|
|
0d84dceaae | ||
|
|
b58be2bf1e | ||
|
|
27dc328614 | ||
|
|
8dc6a3c113 | ||
|
|
906de7d9e7 | ||
|
|
3f08d861e9 | ||
|
|
be358f98eb | ||
|
|
9ec25a2681 | ||
|
|
7d0c62f726 | ||
|
|
2ab7548175 | ||
|
|
99d8164065 | ||
|
|
676c59cd31 | ||
|
|
0bb1e8902e | ||
|
|
0b29fb4ffa | ||
|
|
92b280291d | ||
|
|
9fa3375b0a | ||
|
|
0835124a02 | ||
|
|
44721727af | ||
|
|
80df63ce29 | ||
|
|
3635a3b71f | ||
|
|
7d81d3bee0 | ||
|
|
c0eebcb540 | ||
|
|
3c32075919 | ||
|
|
2f532a547e | ||
|
|
76e97b8d35 | ||
|
|
309f65e401 | ||
|
|
12f7edb56a | ||
|
|
bb6d3cb796 | ||
|
|
e2028eb731 | ||
|
|
6870304a73 | ||
|
|
2c8350818c | ||
|
|
9bb04832a8 | ||
|
|
20f6394ad8 | ||
|
|
da919372e2 | ||
|
|
3ad10aaa48 | ||
|
|
6afbd97d81 | ||
|
|
bb9ba09b6d | ||
|
|
b663726576 | ||
|
|
635c824b1b | ||
|
|
d74dc11775 | ||
|
|
f2324e4d1c | ||
|
|
61a66c52c6 | ||
|
|
af64ae0e40 | ||
|
|
8e2371d0c9 | ||
|
|
b3810ec573 | ||
|
|
f49cad314e | ||
|
|
521ef5659f | ||
|
|
e073c603a4 | ||
|
|
523f522de0 | ||
|
|
dd26ec22c3 | ||
|
|
fe95845fa0 | ||
|
|
52c30f50ec | ||
|
|
0a45cba2bf | ||
|
|
af23870d3b | ||
|
|
090a912f93 | ||
|
|
ec588935b5 | ||
|
|
fd778be03c | ||
|
|
0cbbe1ac0a | ||
|
|
3f7337cd13 | ||
|
|
53b27e18c3 | ||
|
|
015350c692 | ||
|
|
65bbaca380 | ||
|
|
705d6265d1 | ||
|
|
d64d797bcc | ||
|
|
59d56186aa | ||
|
|
34abfcb454 | ||
|
|
a7b3f9df4c | ||
|
|
6605740ce9 | ||
|
|
8dc1edac18 | ||
|
|
b55d97f827 | ||
|
|
d3c0fbef3b | ||
|
|
ea357b8eaf | ||
|
|
f998948623 | ||
|
|
c4b04a06bb | ||
|
|
92c0baa461 | ||
|
|
a4b4802897 | ||
|
|
dcb49c540f | ||
|
|
25ec09c7eb | ||
|
|
bf15d3ce74 | ||
|
|
b1e13d44b8 | ||
|
|
a319a6fdf2 | ||
|
|
b7d2fe769c | ||
|
|
4a2cae23ca | ||
|
|
4ccfd5ba63 | ||
|
|
8ab3308553 | ||
|
|
b41ffd887d | ||
|
|
44baa84cf6 | ||
|
|
8bccfd6fd8 | ||
|
|
bc0722fe25 | ||
|
|
9d98724dcb | ||
|
|
14fc960246 | ||
|
|
136114890f | ||
|
|
978fecf242 | ||
|
|
e7439272e6 | ||
|
|
5a6c168b68 | ||
|
|
640fd92d3b | ||
|
|
73737fb94a | ||
|
|
342c7dc5b5 | ||
|
|
8e0029586b | ||
|
|
9a7d5189d8 | ||
|
|
88391c8392 | ||
|
|
1e8a58c224 | ||
|
|
f91a73159f | ||
|
|
5897b8278b | ||
|
|
9f9664f6ca | ||
|
|
171fd947e9 | ||
|
|
0e1a54141e | ||
|
|
76ddb5de76 | ||
|
|
5398fb806e | ||
|
|
dab2e6e39c | ||
|
|
5fa0706d70 | ||
|
|
bb7ffd6ff5 | ||
|
|
9c6d0e7f21 | ||
|
|
b451fa91de | ||
|
|
e56b970eb4 | ||
|
|
9b2d80d6b7 | ||
|
|
4736fa876d | ||
|
|
0195f8bf00 | ||
|
|
b148e396d7 | ||
|
|
27259c0cff | ||
|
|
8369f72afb | ||
|
|
0109361fe9 | ||
|
|
64732d25fc | ||
|
|
3fad9a2437 | ||
|
|
9494cc01a9 | ||
|
|
7e14f997e7 | ||
|
|
3f4887e8d3 | ||
|
|
2211314900 | ||
|
|
49cce65018 | ||
|
|
79bcd5a1c6 | ||
|
|
cef59887ed | ||
|
|
f81f4edad3 | ||
|
|
55149f6d4c | ||
|
|
2c9ddd5a90 | ||
|
|
dd2cad0c20 | ||
|
|
b1850fd700 | ||
|
|
cb08b84197 | ||
|
|
d8500510be | ||
|
|
2be6e330eb | ||
|
|
1a283cde3e | ||
|
|
a6978bfd2d | ||
|
|
d9b95fd156 | ||
|
|
45f3a77548 | ||
|
|
cebc56dc23 | ||
|
|
0f5fc11f8f | ||
|
|
4876e03932 | ||
|
|
e83764ef4e | ||
|
|
e6ae2c03ca | ||
|
|
550edc3666 | ||
|
|
ab6c1d0d8c | ||
|
|
a9d4897dfb | ||
|
|
93acba9ae3 | ||
|
|
3d1d5f5b77 | ||
|
|
e6b0494d4d | ||
|
|
906cca8f24 | ||
|
|
94efd48cd0 | ||
|
|
ad33162d81 | ||
|
|
f3ae09cc16 | ||
|
|
f6d0b1d399 | ||
|
|
0cff0d603e | ||
|
|
000bc845a8 | ||
|
|
255830ffab | ||
|
|
c00d758c1b | ||
|
|
97fbd84e08 | ||
|
|
c7de6509bc | ||
|
|
0980424bb9 | ||
|
|
ae545cdb09 | ||
|
|
bbbb371d35 | ||
|
|
9e67fe6794 | ||
|
|
08bafc478e | ||
|
|
0af14d3f1d | ||
|
|
d4300a10dd | ||
|
|
bb16997809 | ||
|
|
d208b69f42 | ||
|
|
90ed11e5e1 | ||
|
|
2ef07a7a6c | ||
|
|
01d7beef4e | ||
|
|
0d6e6c4d85 | ||
|
|
2fb57529a0 | ||
|
|
c1f056cf93 | ||
|
|
a9948003b1 | ||
|
|
24dffe4436 | ||
|
|
9d09aa4313 | ||
|
|
c611c2d1bb | ||
|
|
167576e0f7 | ||
|
|
9b86e7d2f1 | ||
|
|
d4f4a720fe | ||
|
|
a8dd326fdc | ||
|
|
c547781ba0 | ||
|
|
ad12071f4c | ||
|
|
394224b3a3 | ||
|
|
8c5931a62d | ||
|
|
e7bd547d05 | ||
|
|
88f8f68e29 | ||
|
|
8c93695d01 | ||
|
|
79d585323e | ||
|
|
6d9de25494 | ||
|
|
980e5061f3 | ||
|
|
5d40193308 | ||
|
|
b51f0b2c78 | ||
|
|
95c1585df6 | ||
|
|
ab323c53a6 | ||
|
|
052a55fe96 | ||
|
|
3aa44d9e44 | ||
|
|
e5ae3e22b3 | ||
|
|
293e01b800 | ||
|
|
259979a76a | ||
|
|
380734f804 | ||
|
|
5e2d01f159 | ||
|
|
b0988e4d86 | ||
|
|
c10c45616d | ||
|
|
d1c27b6457 | ||
|
|
feebf2cd77 | ||
|
|
dcf105994b | ||
|
|
a595231d25 | ||
|
|
bf975ad786 | ||
|
|
6f1c46e11d | ||
|
|
ee96e34767 | ||
|
|
e52fdcf109 | ||
|
|
645a7c5989 | ||
|
|
92c1bb83bf | ||
|
|
e680cf59b6 | ||
|
|
0a5508a8a1 | ||
|
|
75354ec5ba | ||
|
|
168fa72d53 | ||
|
|
0b68487519 | ||
|
|
3d1ef1aae3 | ||
|
|
7aa15ada30 | ||
|
|
a466885df3 | ||
|
|
190d47e528 | ||
|
|
eb282d20b7 | ||
|
|
300bd2c16b | ||
|
|
35f95336ed | ||
|
|
34ff4c7dfa | ||
|
|
fef90f1ec5 | ||
|
|
b92f7c669b | ||
|
|
6f3f2fa1e7 | ||
|
|
8e126112f0 | ||
|
|
ae47b9888f | ||
|
|
0540c2743f | ||
|
|
8ae952f499 | ||
|
|
e3a7dbdcec | ||
|
|
3ee2223cbd | ||
|
|
761a14e6e2 | ||
|
|
2149859719 | ||
|
|
62da715f75 | ||
|
|
91ab2fd984 | ||
|
|
1e76c2d840 | ||
|
|
7bd0273fd5 | ||
|
|
6e26de3763 | ||
|
|
e2e9e53b6a | ||
|
|
f9472effe3 | ||
|
|
a519a242d6 | ||
|
|
ab12c8c339 | ||
|
|
72712d9f07 | ||
|
|
2817913e63 | ||
|
|
5eb677aa55 | ||
|
|
3000b8fd0d | ||
|
|
a191631c32 | ||
|
|
1c06ac1a82 | ||
|
|
851aabdcb5 | ||
|
|
bd743dc1d8 | ||
|
|
44136b7d98 | ||
|
|
a414318605 | ||
|
|
34b5535e00 | ||
|
|
d816220596 | ||
|
|
c2fbc8a846 | ||
|
|
8f996f9267 | ||
|
|
491e368535 | ||
|
|
4ddfe05a59 | ||
|
|
5334a0ab92 | ||
|
|
3c2d56e46b | ||
|
|
1f3e621a31 | ||
|
|
5d9f4b1333 | ||
|
|
f078a48b7d | ||
|
|
ee8bbdcfe0 | ||
|
|
8f835597ba | ||
|
|
2ba1f80f7b | ||
|
|
8088c52551 | ||
|
|
b6dbf25f85 | ||
|
|
e2104bd6cf | ||
|
|
8bb3092002 | ||
|
|
417dedd317 | ||
|
|
f22624399c | ||
|
|
cd9874970a | ||
|
|
7b44221d9a | ||
|
|
c4baf3194e | ||
|
|
392bd3cde0 | ||
|
|
d1c970b019 | ||
|
|
6aed650bcc | ||
|
|
4f0d201269 | ||
|
|
63b350aedc | ||
|
|
ef66a62a88 | ||
|
|
6256f0c46e | ||
|
|
b1af5bb6e5 | ||
|
|
b80fc6caf1 | ||
|
|
451aa86c91 | ||
|
|
26e38bc792 | ||
|
|
f7195adbda | ||
|
|
d87745f2be | ||
|
|
75859e9a7e | ||
|
|
fef5efb38a | ||
|
|
c97412f9bd | ||
|
|
3ebca1327f | ||
|
|
1a6b2010ba | ||
|
|
b61a84313a | ||
|
|
de626626de | ||
|
|
4900e8b7a2 | ||
|
|
2312fe5bfc | ||
|
|
49d842e213 | ||
|
|
53f6205766 | ||
|
|
e9fc5f62a5 | ||
|
|
0e4344a83c | ||
|
|
62939dd28b | ||
|
|
af4a48a4bc | ||
|
|
f4cc929a99 | ||
|
|
d8ae931b7c | ||
|
|
fd6b8cd99a | ||
|
|
253478dba5 | ||
|
|
bff5921266 | ||
|
|
1c306a04fc | ||
|
|
18220515b5 | ||
|
|
ce25d6339e | ||
|
|
e3e64e5e83 | ||
|
|
e5343fdc9a | ||
|
|
3226254876 | ||
|
|
c186d2b0cc | ||
|
|
436194e6c7 | ||
|
|
5496fa2958 | ||
|
|
98e0f5a8f6 | ||
|
|
4e92f88b36 | ||
|
|
c5f062be9a | ||
|
|
bd9d831b56 | ||
|
|
016249c982 | ||
|
|
ffda6ad321 | ||
|
|
47734f2459 | ||
|
|
af2ecbc3ed | ||
|
|
87f70655a2 | ||
|
|
9af3c22a6a | ||
|
|
35ea46fd13 | ||
|
|
09fae620d9 | ||
|
|
5fc6659e50 | ||
|
|
82de8145b0 | ||
|
|
c763ae6d5c | ||
|
|
6ce098064a | ||
|
|
754e640c8d | ||
|
|
58338ff51f | ||
|
|
ac15621e74 | ||
|
|
0d394a6f87 | ||
|
|
d86eb870d4 | ||
|
|
28f4cd3d3c | ||
|
|
6f6ead1726 | ||
|
|
dbd48a04d4 | ||
|
|
3e1f209d64 | ||
|
|
e4a2e9a920 | ||
|
|
a284d21e1c | ||
|
|
61394b8be4 | ||
|
|
b0555d96e9 | ||
|
|
76c70bdf2c | ||
|
|
1e512b6add | ||
|
|
7c172c7c06 | ||
|
|
caab7c8e10 | ||
|
|
d2b0aa8513 | ||
|
|
a063858842 | ||
|
|
237d2ba1a0 | ||
|
|
b346487e76 | ||
|
|
6a9f396663 | ||
|
|
d3eb43ce35 | ||
|
|
6eed74c716 | ||
|
|
b95620cdd0 | ||
|
|
3bd08ab31c | ||
|
|
5b4bb66848 | ||
|
|
2b677c83e3 | ||
|
|
d3a260e441 | ||
|
|
70edcf3f6a | ||
|
|
e31a0c4d6d | ||
|
|
321f2d8d50 | ||
|
|
ab86f58643 | ||
|
|
72ad22bb91 | ||
|
|
73d4fc6d2f | ||
|
|
b16357494d | ||
|
|
2e47c5a2ac | ||
|
|
0f8ca0a563 | ||
|
|
a7a51b76f3 | ||
|
|
a12f563d1c | ||
|
|
6d433edc38 | ||
|
|
75ee4efa31 | ||
|
|
5a2fbf4af3 | ||
|
|
a0e39ddb67 | ||
|
|
2008247e65 | ||
|
|
263c94d167 | ||
|
|
fa997bdf4a | ||
|
|
d16ba6c4c8 | ||
|
|
67e661ec95 | ||
|
|
d9a9fa0c10 | ||
|
|
cec82e4ffb | ||
|
|
13a1cd32a7 | ||
|
|
e990e58177 | ||
|
|
0aba59501a | ||
|
|
7c86e53bd2 | ||
|
|
05b6ae7b20 | ||
|
|
2dc0059b1c | ||
|
|
ad83095959 | ||
|
|
a5bf97fbb2 | ||
|
|
b0c322ec90 | ||
|
|
ca49da3c83 | ||
|
|
4c134d8fdc | ||
|
|
1d7966f74e | ||
|
|
3a7203e32e | ||
|
|
f5692ea1f0 | ||
|
|
774156a78a | ||
|
|
b18bf3eddb | ||
|
|
86a64487cb | ||
|
|
d09c59fd2f | ||
|
|
87aca2874f | ||
|
|
b4ccf00722 | ||
|
|
53dbf8de72 | ||
|
|
e60707d7ef | ||
|
|
6374474b25 | ||
|
|
c0d80a4f83 | ||
|
|
fabbfc3979 | ||
|
|
0a0109e2aa | ||
|
|
5b487bab85 | ||
|
|
6ad58276f8 | ||
|
|
a260465721 | ||
|
|
8273c946de | ||
|
|
96e3d7f076 | ||
|
|
c70a13015b | ||
|
|
a312aa422a | ||
|
|
b3e8b2c487 | ||
|
|
15a33a58d3 | ||
|
|
a783612076 | ||
|
|
4609d7ed93 | ||
|
|
5db3d1ed7c | ||
|
|
a76c189ca5 | ||
|
|
81023875d5 | ||
|
|
da4a8eb5c1 | ||
|
|
48a2b0ab49 | ||
|
|
b25e98ffbb | ||
|
|
121526f521 | ||
|
|
2e70470d12 | ||
|
|
70cda48632 | ||
|
|
953bbabff3 | ||
|
|
a4c1ad22ef | ||
|
|
e474b851bf | ||
|
|
467f3265e0 | ||
|
|
0ab530e750 | ||
|
|
8d2ea14f06 | ||
|
|
b3aaffc95d | ||
|
|
3de856f8d5 | ||
|
|
b17125c65c | ||
|
|
23ff7d913a | ||
|
|
363f555ed7 | ||
|
|
18a895310c | ||
|
|
04f9811c6e | ||
|
|
66961dab06 | ||
|
|
f9390e0cbd | ||
|
|
44426c7612 | ||
|
|
7b426b936e | ||
|
|
0d1fea9861 | ||
|
|
1e1b85a575 | ||
|
|
a11b6e72dc | ||
|
|
c8d396f94b | ||
|
|
70a7ab7f2e | ||
|
|
adb236d8b6 | ||
|
|
6208337f61 | ||
|
|
9af6616882 | ||
|
|
b4558b2db1 | ||
|
|
2f35e980ef | ||
|
|
71a2d56ad3 | ||
|
|
858ab99cec | ||
|
|
c4cba38559 | ||
|
|
e6790e50c6 | ||
|
|
6dc1a0b6e8 | ||
|
|
9c520c5188 | ||
|
|
3e09793b54 | ||
|
|
2f284cdb18 | ||
|
|
c1eb968144 | ||
|
|
14a12b02ef | ||
|
|
3c452e6ddb | ||
|
|
5f52382098 | ||
|
|
cce0485e75 | ||
|
|
612d58b4b2 | ||
|
|
4f054ed535 | ||
|
|
5a7cd203cd | ||
|
|
b9397693a2 | ||
|
|
24ad48d390 | ||
|
|
12f9b6a89e | ||
|
|
36102b8ee0 | ||
|
|
490447bbd4 | ||
|
|
77bb997b0b | ||
|
|
a472ff7a0f | ||
|
|
12dc5b186f | ||
|
|
ed1ebf9b93 | ||
|
|
faa14cfa1c | ||
|
|
080324f7e0 | ||
|
|
d094bfaa12 | ||
|
|
88f0b63577 | ||
|
|
3eac6ccd48 | ||
|
|
d83d898cdc | ||
|
|
035bb57c56 | ||
|
|
977c9e706e | ||
|
|
d597211161 | ||
|
|
5c234c2106 | ||
|
|
b12fc114c7 | ||
|
|
bce12a4048 | ||
|
|
1e5a8f4391 | ||
|
|
712bdc7df8 | ||
|
|
1d5a4240b9 | ||
|
|
3217f286f0 | ||
|
|
711f0fef40 | ||
|
|
c82ed71b6f | ||
|
|
a821a2fcc0 | ||
|
|
e40620fd10 | ||
|
|
6779eab44e | ||
|
|
5f1ac6e1b1 | ||
|
|
1bd7d25973 | ||
|
|
544b6fea8a | ||
|
|
451ba8da9f | ||
|
|
1d11bc64a9 | ||
|
|
2a6749a56d | ||
|
|
ca0147e814 | ||
|
|
aab4d2bd34 | ||
|
|
16f3cb0189 | ||
|
|
03d8804209 | ||
|
|
889a45eaca | ||
|
|
ace9e03fe7 | ||
|
|
46832ff77f | ||
|
|
51df11886a | ||
|
|
8597169e14 | ||
|
|
58b21f2a49 | ||
|
|
e71a66535d | ||
|
|
311533a0ac | ||
|
|
d9fc408d96 | ||
|
|
ef19fa9b51 | ||
|
|
d7db7b8b67 | ||
|
|
26bcebd575 | ||
|
|
b11b0a4911 | ||
|
|
f6786d5a59 | ||
|
|
2414346ec3 | ||
|
|
47b1cadbb6 | ||
|
|
d949b010d8 | ||
|
|
2bda0820bf | ||
|
|
8ee959e1af | ||
|
|
1ea138f795 | ||
|
|
87ebbc9901 | ||
|
|
561b54ce36 | ||
|
|
2af8f00d0d | ||
|
|
2309656120 | ||
|
|
09527c3ab6 | ||
|
|
a4d72e0fee | ||
|
|
47f6d78737 | ||
|
|
e295c7aac2 | ||
|
|
1f97e9be34 | ||
|
|
0b25cc5a5c | ||
|
|
43a7b50b74 | ||
|
|
1d79e149cf | ||
|
|
d062ce73d7 | ||
|
|
e7965c6d95 | ||
|
|
de5afa1304 | ||
|
|
10d926de0d | ||
|
|
4e767c9872 | ||
|
|
481a8e0f33 | ||
|
|
324186dad2 | ||
|
|
a7ee5fea93 | ||
|
|
276020c482 | ||
|
|
99dde674ca | ||
|
|
6f205edd9a | ||
|
|
6f9f3e9496 | ||
|
|
e8264dc6e7 | ||
|
|
9da2e4fae8 | ||
|
|
64817ac216 | ||
|
|
11d4ad1e23 | ||
|
|
e3cf9a0306 | ||
|
|
2b01766460 | ||
|
|
f7d9ef0c97 | ||
|
|
78a2b12be0 | ||
|
|
5b4ec05dbe | ||
|
|
0164e061a4 | ||
|
|
9c3d2d736d | ||
|
|
f214f58269 | ||
|
|
f8c4b6ba59 | ||
|
|
15da25759e | ||
|
|
ce7517d5ce | ||
|
|
27028471bb | ||
|
|
d539b948a0 | ||
|
|
51ba8b66b6 | ||
|
|
35d72d82b4 | ||
|
|
95d6465dac | ||
|
|
fc18cea875 | ||
|
|
c9ddecff87 | ||
|
|
d620285e0a | ||
|
|
c760bca4a9 | ||
|
|
24e4c65221 | ||
|
|
45ae0c097b | ||
|
|
075dfe8109 | ||
|
|
e011c844de | ||
|
|
88e47e9251 | ||
|
|
90f18075cb | ||
|
|
320d58ea8c | ||
|
|
9069bb6f6e | ||
|
|
e0cb823ed0 | ||
|
|
174c00a8e7 | ||
|
|
26a113292b | ||
|
|
7fc8f6b3b8 | ||
|
|
c10cef3336 | ||
|
|
c2cf37145e | ||
|
|
cdf8daff86 | ||
|
|
3f33fe8cb0 | ||
|
|
9dedcd07b6 | ||
|
|
89ca69b111 | ||
|
|
07c0889d10 | ||
|
|
89c69ed622 | ||
|
|
575f863942 | ||
|
|
8c3fe81edd | ||
|
|
62fa698e2d | ||
|
|
d4bfc3f225 | ||
|
|
341cd5e860 | ||
|
|
8d1f5b04b3 | ||
|
|
c496962f95 | ||
|
|
523c63fec7 | ||
|
|
c2713eff87 | ||
|
|
bdc720ac7d | ||
|
|
c0b3a18316 | ||
|
|
43e5daded2 | ||
|
|
21d4dba03b | ||
|
|
2efecc25a7 | ||
|
|
f08dd2fd03 | ||
|
|
d87df3e6c2 | ||
|
|
71f48ea39e | ||
|
|
cb3d6f73ce | ||
|
|
6b56de5c93 | ||
|
|
07b2f0109a | ||
|
|
a74461d903 | ||
|
|
23a24c42c1 | ||
|
|
c0a26cf1eb | ||
|
|
e5c2e8e5d7 | ||
|
|
5c259fa0e2 | ||
|
|
849f14e480 | ||
|
|
8012f9cd44 | ||
|
|
fe212228e2 | ||
|
|
a7691b2d3b | ||
|
|
de73ee8bfc | ||
|
|
b2e55d7d84 | ||
|
|
ec7e6a0ac1 | ||
|
|
aa8a369e2a | ||
|
|
9862876f06 | ||
|
|
9914aa40bd | ||
|
|
3881de74eb | ||
|
|
d5100476ac | ||
|
|
a1fa5224a3 | ||
|
|
654a622607 | ||
|
|
c4010a6c78 | ||
|
|
054245c980 | ||
|
|
02610abd40 | ||
|
|
bc93de0f03 | ||
|
|
3531caaa0b | ||
|
|
b38a593c4f | ||
|
|
e7707b31f0 | ||
|
|
a941ed8c2a | ||
|
|
3e3538b9bc | ||
|
|
735fe31f3b | ||
|
|
cca6606c78 | ||
|
|
6f10990386 | ||
|
|
88bd5aef40 | ||
|
|
a3cf592f29 | ||
|
|
0019baaa00 | ||
|
|
85d44c5f6c | ||
|
|
5b447d0a56 | ||
|
|
e817a4cdba | ||
|
|
def4ae395e | ||
|
|
1d2d05cfdf | ||
|
|
02a22086a1 | ||
|
|
42a415e449 | ||
|
|
752a11ba26 | ||
|
|
21cd94cc79 | ||
|
|
c69b2086b0 | ||
|
|
d7f3b8a425 | ||
|
|
4693af74e7 | ||
|
|
face4bd3c7 | ||
|
|
9b3654c1f0 | ||
|
|
8ae2cb1d32 | ||
|
|
a2fbe7fab8 | ||
|
|
4cbdbd9ef5 | ||
|
|
076f6785cb | ||
|
|
07203f0989 | ||
|
|
f71900694b | ||
|
|
b99d309feb | ||
|
|
eebc6241b7 | ||
|
|
d5403a089c | ||
|
|
e1c6e78b2e | ||
|
|
f57f0efc48 | ||
|
|
241b4ef6e4 | ||
|
|
417343e3dd | ||
|
|
268b88be0d | ||
|
|
ee85541d2a | ||
|
|
538f96f0ac | ||
|
|
f7dd77795a | ||
|
|
2b2be1789f | ||
|
|
954780ed24 | ||
|
|
e65a5e2b7c | ||
|
|
1567225a64 | ||
|
|
1387d8d5d6 | ||
|
|
d8631d1489 | ||
|
|
c98e76f31e | ||
|
|
cb8c77ee2c | ||
|
|
ff24bf6829 | ||
|
|
1feb876a32 | ||
|
|
6b186622cb | ||
|
|
7ddde7e6ca | ||
|
|
914129a0d9 | ||
|
|
b0b9e507e7 | ||
|
|
4e78367ec4 | ||
|
|
c36b788b2d | ||
|
|
1f0c2c1266 | ||
|
|
ac05387803 | ||
|
|
a7d1ec03e8 | ||
|
|
d2ca67d261 | ||
|
|
3a51b3f70c | ||
|
|
6874b3b429 | ||
|
|
9d58b492a8 | ||
|
|
1b72acd68e | ||
|
|
30f79f838e | ||
|
|
22c514575c | ||
|
|
d110a3ef26 | ||
|
|
cae4790ef2 | ||
|
|
71e85ac367 | ||
|
|
c3ececcf96 | ||
|
|
015ab4a024 | ||
|
|
59386f9fa9 | ||
|
|
dfbacd1a47 | ||
|
|
c5b460b416 | ||
|
|
5c09bc5b2d | ||
|
|
23c946ef50 | ||
|
|
238005890e | ||
|
|
dd6c031a31 | ||
|
|
79566b7fa3 | ||
|
|
7ba96ad653 | ||
|
|
bf0e853413 | ||
|
|
259855e788 | ||
|
|
11a39927ef | ||
|
|
356db794b5 | ||
|
|
2e162c1131 | ||
|
|
311cbf709c | ||
|
|
2852990566 | ||
|
|
b801f70f3a | ||
|
|
e24cb944ff | ||
|
|
fe6bf3c7d6 | ||
|
|
0ef37df4ae | ||
|
|
2eac821f7f | ||
|
|
f9e5ef2aa9 | ||
|
|
d01600ea0f | ||
|
|
13a65d45a3 | ||
|
|
099f907972 | ||
|
|
b65f666578 | ||
|
|
3b40696c9e | ||
|
|
a9e47454d5 | ||
|
|
512fe8aead | ||
|
|
d1456929ec | ||
|
|
b86d155e8e | ||
|
|
999a2c7134 | ||
|
|
947dd1b754 | ||
|
|
5085a17bcb | ||
|
|
e42aec68c5 | ||
|
|
2aad416cc2 | ||
|
|
e87256e01f | ||
|
|
96375e8244 | ||
|
|
c0de75367f | ||
|
|
7b21dd7082 | ||
|
|
b31e955744 | ||
|
|
41895118bd | ||
|
|
d85e097ee5 | ||
|
|
6ed182013d | ||
|
|
1afa3916ac | ||
|
|
de3ad734f9 | ||
|
|
408edb3e99 | ||
|
|
a2b2e486ea | ||
|
|
5881ad9685 | ||
|
|
243edf7e13 | ||
|
|
6119d6e102 | ||
|
|
f967e75819 | ||
|
|
3b02dd316d | ||
|
|
102dd690b7 | ||
|
|
0a32cd2528 | ||
|
|
f48a2713bc | ||
|
|
10c4cd0f41 | ||
|
|
451ec9cba0 | ||
|
|
6c0c0bd0be | ||
|
|
0ec8fc4c55 | ||
|
|
a5f86b3025 | ||
|
|
f682053174 | ||
|
|
b49314deb0 | ||
|
|
3bb5763b1b | ||
|
|
35d876b816 | ||
|
|
ff45b425e3 | ||
|
|
d70ba2b740 | ||
|
|
6b09dfca76 | ||
|
|
9caedb422d | ||
|
|
6a9bdeae3e | ||
|
|
30447d7660 | ||
|
|
d7f9cbf9ca | ||
|
|
6271409e5a | ||
|
|
ab669b26da | ||
|
|
87a023c75d | ||
|
|
afe109ce27 | ||
|
|
1ef70c0bb4 | ||
|
|
8cb3b67295 | ||
|
|
69530cd50f | ||
|
|
02c4b6d7e2 | ||
|
|
5d98d2703b | ||
|
|
a0597a9e6e | ||
|
|
ba0efda2aa | ||
|
|
f693d4a8de | ||
|
|
05fab99f42 | ||
|
|
082db67373 | ||
|
|
963b19e2e0 | ||
|
|
10efb9590a | ||
|
|
1092cc92be | ||
|
|
ffae861bc2 | ||
|
|
a782a5ad29 | ||
|
|
7aa6716892 | ||
|
|
d537e21c65 | ||
|
|
b0fa913fa2 | ||
|
|
3561f79cf4 | ||
|
|
ad0db706c0 | ||
|
|
4671f8ca64 | ||
|
|
8a785993ed | ||
|
|
47ece05592 | ||
|
|
b46d9e09eb | ||
|
|
c1292d08de | ||
|
|
3a2240f2e1 | ||
|
|
eb3a4bfa6e | ||
|
|
458979293d | ||
|
|
67c0c9fd73 | ||
|
|
cbbdf0f6de | ||
|
|
f2a7172a84 | ||
|
|
40a5306ed4 | ||
|
|
7514bc8b49 | ||
|
|
634c37fb23 | ||
|
|
831fc9c361 | ||
|
|
1c65ec9ef2 | ||
|
|
e8bd435fe3 | ||
|
|
7747f45be3 | ||
|
|
f0e866cb56 | ||
|
|
d92833284e | ||
|
|
806b6d5a37 | ||
|
|
1bb3ab8715 | ||
|
|
0825db36ff | ||
|
|
15f204bbc5 | ||
|
|
2b6eee1848 | ||
|
|
67a457dd1f | ||
|
|
95e3b7d42b | ||
|
|
fd40a77089 | ||
|
|
19becd9985 | ||
|
|
57d9cdb3c4 | ||
|
|
8cfb37c12f | ||
|
|
4d015a1106 | ||
|
|
dd1a92803e | ||
|
|
40e435a961 | ||
|
|
2de476b11d | ||
|
|
3932503660 | ||
|
|
e0fa2e7b12 | ||
|
|
74fe003f8b | ||
|
|
7dfae0fb61 | ||
|
|
c6e5ca1fec | ||
|
|
2c7eb53cac | ||
|
|
059053b9b8 | ||
|
|
ab921a6f0d | ||
|
|
4a03e12636 | ||
|
|
198e67b1fc | ||
|
|
de24d6dc14 | ||
|
|
f68c3b2a65 | ||
|
|
a304e9c3fa | ||
|
|
d1df16a2bf | ||
|
|
62da755431 | ||
|
|
2eafc0ddff | ||
|
|
de02a0a25a | ||
|
|
1a17699356 | ||
|
|
591a36246f | ||
|
|
59c87c819a | ||
|
|
0717061212 | ||
|
|
0f48a14181 | ||
|
|
a81ba240be | ||
|
|
3ac478dfda | ||
|
|
c1fc152251 | ||
|
|
3fc43e8ebd | ||
|
|
ab5364232f | ||
|
|
8a468fccf0 | ||
|
|
afab1bdaad | ||
|
|
addf909287 | ||
|
|
0f6c2bff06 | ||
|
|
731c752e94 | ||
|
|
3191b32708 | ||
|
|
bd199c63ab | ||
|
|
3c4cbf2a05 | ||
|
|
21b7df9ab7 | ||
|
|
7922e3bb16 | ||
|
|
c7637a0fda | ||
|
|
6b70e37ae3 | ||
|
|
9ede95954b | ||
|
|
37fb330b36 | ||
|
|
39186004cc | ||
|
|
0a844e0b62 | ||
|
|
5d7bdca835 | ||
|
|
33e8bae78b | ||
|
|
206eb7946b | ||
|
|
243fbfc19a | ||
|
|
c2fa8a2b18 | ||
|
|
7ac7b70884 | ||
|
|
8f752b7eee | ||
|
|
93035f07aa | ||
|
|
114e8d5b6a | ||
|
|
b9ccb274a7 | ||
|
|
4c7fa05bfe | ||
|
|
c2997bb1fc | ||
|
|
d8378e6819 | ||
|
|
6cc5f30c84 | ||
|
|
4adcc763e5 | ||
|
|
5a7cddfb69 | ||
|
|
b8dba0fd0c | ||
|
|
9de6b6355e | ||
|
|
b9bc34afbf | ||
|
|
bf29f55205 | ||
|
|
a5a95847ea | ||
|
|
011c0b1914 | ||
|
|
a116dbc358 | ||
|
|
89161a7a1e | ||
|
|
0d8518d31d | ||
|
|
2e32d716aa | ||
|
|
51d52c213b | ||
|
|
8aed2375f3 | ||
|
|
53f6ae7a39 | ||
|
|
aac7654ca3 | ||
|
|
d1ad924216 | ||
|
|
b4ceb55fd2 | ||
|
|
a91d319839 | ||
|
|
8a021ae48c | ||
|
|
2a26680acb | ||
|
|
9e74ca3442 | ||
|
|
563ec6c2ab | ||
|
|
3cdb05364b | ||
|
|
a938b4ea18 | ||
|
|
4c488bd970 | ||
|
|
2b590f323a | ||
|
|
70eefe6de3 | ||
|
|
85aabe7c0c | ||
|
|
1923c15907 | ||
|
|
ef9dd5975b | ||
|
|
61ec8818db | ||
|
|
b122db27cc | ||
|
|
3b7b48be4a | ||
|
|
d4b32dc143 | ||
|
|
2fe4508db8 | ||
|
|
862f89a57c | ||
|
|
bb8e1d8ee2 | ||
|
|
494002505e | ||
|
|
efc52ab469 | ||
|
|
f98ac4c48a | ||
|
|
95bd038d8a | ||
|
|
b9c253e4c2 | ||
|
|
3d5701614f | ||
|
|
dce5bfd723 | ||
|
|
6b7b95e888 | ||
|
|
cb12369b1c | ||
|
|
656e328a55 | ||
|
|
52944370e6 | ||
|
|
aaeb0278b1 | ||
|
|
bd78c3b3ea | ||
|
|
01719eceb1 | ||
|
|
5603ed7ebb | ||
|
|
7b1d7904c1 | ||
|
|
f0d94e2757 | ||
|
|
8a21b7c5a1 | ||
|
|
d4a20bc37a | ||
|
|
d207e3f889 | ||
|
|
f192ccce2c | ||
|
|
ae3a3d6336 | ||
|
|
e7cada7ac7 | ||
|
|
cae1a6cc08 | ||
|
|
37bacdd83d | ||
|
|
e381951ecc | ||
|
|
bac1859432 | ||
|
|
b5ed26ad70 | ||
|
|
fe6d44d273 | ||
|
|
9382ed5451 | ||
|
|
910e4f3217 | ||
|
|
fdcec4315a | ||
|
|
b7b4bc7fab | ||
|
|
70a91aff40 | ||
|
|
e3c4a4b47f | ||
|
|
33b12d26cc | ||
|
|
b03018965a | ||
|
|
81bee794f8 | ||
|
|
ae3481ef6c | ||
|
|
e0928432ef | ||
|
|
0161d49d80 | ||
|
|
8b2dfea925 | ||
|
|
3617ad33e4 | ||
|
|
35442d14e2 | ||
|
|
4d21e23de9 | ||
|
|
5340ebe9ab | ||
|
|
85d3ecb729 | ||
|
|
74ec9760da | ||
|
|
bb600218b6 | ||
|
|
ce430ff7f6 | ||
|
|
0f06991391 | ||
|
|
438664f5da | ||
|
|
130181614a | ||
|
|
27341fc193 | ||
|
|
ae9659d32d | ||
|
|
001e00d84a | ||
|
|
5b39e80f6a | ||
|
|
6e507df2b9 | ||
|
|
74e928eb00 | ||
|
|
22406f8aca | ||
|
|
474897d644 | ||
|
|
5391b694d1 | ||
|
|
6a29984e18 | ||
|
|
fad24efdf0 | ||
|
|
b11161abb0 | ||
|
|
2ff07a0b54 | ||
|
|
831999f5e1 | ||
|
|
2bb704b6be | ||
|
|
4d7232d5ed | ||
|
|
9a14699aa0 | ||
|
|
73c7dce45a | ||
|
|
5ab574d7f2 | ||
|
|
9165b819f4 | ||
|
|
6057262c18 | ||
|
|
8002c6465d | ||
|
|
795c8eeef7 | ||
|
|
7bf0a4786c | ||
|
|
9daa51eda4 | ||
|
|
a81b794475 | ||
|
|
8b224ecb15 | ||
|
|
1f236ede0e | ||
|
|
973287b09b | ||
|
|
acc32f66e8 | ||
|
|
204b50381a | ||
|
|
94d238c611 | ||
|
|
5b6b081664 | ||
|
|
df766b1476 | ||
|
|
8373a21af2 | ||
|
|
c9cc2b5e20 | ||
|
|
0d03039c19 | ||
|
|
f5b818541e | ||
|
|
6089e9210f | ||
|
|
db54c463e6 | ||
|
|
ce50b09b28 | ||
|
|
bf70f4b71a | ||
|
|
fd8607398d | ||
|
|
08a2e51feb | ||
|
|
e62ac748ad | ||
|
|
1f881c6e47 | ||
|
|
127f436315 | ||
|
|
f62de11de7 | ||
|
|
6e810aacb4 | ||
|
|
2ff1e22ca9 | ||
|
|
c80405f880 | ||
|
|
b3ddca1aee | ||
|
|
df8a57c972 | ||
|
|
0444a80f19 | ||
|
|
3d90e6151c | ||
|
|
5660111b28 | ||
|
|
445a1aa7b0 | ||
|
|
0917494a80 | ||
|
|
1d91a572cc | ||
|
|
60ac2e9881 | ||
|
|
f7024cff78 | ||
|
|
6ec62f48f9 | ||
|
|
d14364a86c | ||
|
|
76d3f84a5e | ||
|
|
56c11c70b3 | ||
|
|
9e94b1fae0 | ||
|
|
682ac85e0a | ||
|
|
9a93551a2d | ||
|
|
147a1c7aaa | ||
|
|
58d4f3b531 | ||
|
|
eb355d4a16 | ||
|
|
3444c5245e | ||
|
|
9941457cdb | ||
|
|
54cefb7884 | ||
|
|
7de7fa293b | ||
|
|
b0928fb3cd | ||
|
|
559b0e9b40 | ||
|
|
67e7325f43 | ||
|
|
2cefc9aab0 | ||
|
|
cda605f578 | ||
|
|
25fd3c3400 | ||
|
|
771c47f809 | ||
|
|
3c3ac216dc | ||
|
|
5de507b0c8 | ||
|
|
bb9ac1389b | ||
|
|
49378f0893 | ||
|
|
6aa0c08f3a | ||
|
|
e90042368f | ||
|
|
9fbf327028 | ||
|
|
353adf4fb7 | ||
|
|
968d6d578f | ||
|
|
2046ac6604 | ||
|
|
2a040f245f | ||
|
|
d8385b7f91 | ||
|
|
c27d4d78f9 | ||
|
|
a69ae93871 | ||
|
|
e22668e196 | ||
|
|
3a242e5fc3 | ||
|
|
d12f76dacb | ||
|
|
fe403c6994 | ||
|
|
05e53cac26 | ||
|
|
8b8b78d001 | ||
|
|
dd99c22792 | ||
|
|
ccaa3864d5 | ||
|
|
53435579b3 | ||
|
|
84b2242636 | ||
|
|
d5ea5168a0 | ||
|
|
c560394358 | ||
|
|
5ddb9bd444 | ||
|
|
eb57f4c7e4 | ||
|
|
027ae3f3f6 | ||
|
|
d32c73ad57 | ||
|
|
f67a02203b | ||
|
|
4bd3dca16f | ||
|
|
c5db1aaaf5 | ||
|
|
a04c01a2fd | ||
|
|
a48adfbaf7 | ||
|
|
68fed0e03d | ||
|
|
0190a161ba | ||
|
|
5b05aeea82 | ||
|
|
780da7d4d5 | ||
|
|
c68a9f325d | ||
|
|
4fd043398a | ||
|
|
dfc45eb0f9 | ||
|
|
50ef5deefc | ||
|
|
319108b11c | ||
|
|
ee41413c6a | ||
|
|
71daa3e0f8 | ||
|
|
1249ce9b94 | ||
|
|
da9b968fc9 | ||
|
|
b0af6f4b53 | ||
|
|
7a413f390d | ||
|
|
16df48bac6 | ||
|
|
3b2d0486a0 | ||
|
|
ed06aa48e9 | ||
|
|
e941ef5952 | ||
|
|
5d9174ac9d | ||
|
|
5be15152eb | ||
|
|
90958a6d23 | ||
|
|
ab91dc1882 | ||
|
|
cad2f2a065 | ||
|
|
086be92f69 | ||
|
|
28eb4d1060 | ||
|
|
2ff937a278 | ||
|
|
cdc44c502e | ||
|
|
b37c3ccf92 | ||
|
|
74259c2276 | ||
|
|
3dcd5538d0 | ||
|
|
eb5dae1cda | ||
|
|
f0471a62e5 | ||
|
|
9819306731 | ||
|
|
b872a12517 | ||
|
|
eefca9f498 | ||
|
|
e0905597fc | ||
|
|
6511252140 | ||
|
|
27000f1763 | ||
|
|
ada343b7df | ||
|
|
9dd1fb64b7 | ||
|
|
c0e0403b44 | ||
|
|
6d0c3eb3b6 | ||
|
|
f25af91d23 | ||
|
|
507c8582ca | ||
|
|
d780752d9e | ||
|
|
2f567f3c3f | ||
|
|
f612357150 | ||
|
|
f1f2718598 | ||
|
|
4ab832cc46 | ||
|
|
920bee0532 | ||
|
|
1a9544778b | ||
|
|
dbee87a6c6 | ||
|
|
7e80ed6693 | ||
|
|
db0c34f63e | ||
|
|
056f2eb7d5 | ||
|
|
fe84e9521c | ||
|
|
91e2b466d3 | ||
|
|
b90060e574 | ||
|
|
5d4057f722 | ||
|
|
0b7d205253 | ||
|
|
72ca6b25e9 | ||
|
|
4be64b6206 | ||
|
|
6cc5119c64 | ||
|
|
42d27d04f6 | ||
|
|
fed4c28925 | ||
|
|
24f084d282 | ||
|
|
12b760e2e3 | ||
|
|
43ef3d9bff | ||
|
|
3bdd171ce2 | ||
|
|
6ff0a5f318 | ||
|
|
f3ab4bc292 | ||
|
|
806428efeb | ||
|
|
4359e2eaa9 | ||
|
|
777a4d109d | ||
|
|
f8dc1939cd | ||
|
|
1b8cf6a5b1 | ||
|
|
1f6382e93d | ||
|
|
ab6b3f8ed3 | ||
|
|
cc52253e22 | ||
|
|
cf6dc9f895 | ||
|
|
8deb29a8ff | ||
|
|
e0f9697750 | ||
|
|
c3a6ba3c02 | ||
|
|
75a8f0a7b4 | ||
|
|
caa4ba67d6 | ||
|
|
9f6f391354 | ||
|
|
24726ab8a3 | ||
|
|
6bd5e22872 | ||
|
|
cbb09b6812 | ||
|
|
9c9688dd5b | ||
|
|
21c52df090 | ||
|
|
2c95a7cba4 | ||
|
|
568176d775 | ||
|
|
04250632d7 | ||
|
|
9ae58f5462 | ||
|
|
e6d1bcc421 | ||
|
|
4439a83733 | ||
|
|
0f8d7dd6db | ||
|
|
182296d8af | ||
|
|
cd14380dba | ||
|
|
5b0c5a82c0 | ||
|
|
478390de19 | ||
|
|
b054912167 | ||
|
|
09edf66a2a | ||
|
|
1d55aee39c | ||
|
|
3efb7d4050 | ||
|
|
0c06e54831 | ||
|
|
a61286bd43 | ||
|
|
9bda3e62ee | ||
|
|
905273e066 | ||
|
|
16fe62e98d | ||
|
|
958797062d | ||
|
|
2bb76e09c6 | ||
|
|
33dd256dfb | ||
|
|
295fd3d0c0 | ||
|
|
efdf24d711 | ||
|
|
12c1ec37a2 | ||
|
|
03f889962b | ||
|
|
0bc995bfab | ||
|
|
a19768e376 | ||
|
|
0bf0267edd | ||
|
|
b3559bf058 | ||
|
|
2b8f55322e | ||
|
|
b15a15411f | ||
|
|
39329eb422 | ||
|
|
115257ea59 | ||
|
|
a71abedd25 | ||
|
|
b53924c27a | ||
|
|
543346f885 | ||
|
|
a435959ee3 | ||
|
|
d33b092a9d | ||
|
|
f676072e15 | ||
|
|
098d6944c4 | ||
|
|
172c0e077f | ||
|
|
4dbb55d740 | ||
|
|
ba09da107a | ||
|
|
eaf965c66f | ||
|
|
e999c35749 | ||
|
|
203adabc46 | ||
|
|
82ad44a863 | ||
|
|
86da6a7ffe | ||
|
|
36e7b9185a | ||
|
|
f8eda660d2 | ||
|
|
f3e3e828aa | ||
|
|
c230d09dad | ||
|
|
72fd448541 | ||
|
|
07ff0c7d97 | ||
|
|
76f84b50e6 | ||
|
|
1f3e937471 | ||
|
|
32f11f59b0 | ||
|
|
202a97eb74 | ||
|
|
f9db06b781 | ||
|
|
5132b16305 | ||
|
|
a0b02b0110 | ||
|
|
36debf25fb | ||
|
|
d16d1f43fc | ||
|
|
11b3484f4b | ||
|
|
2bcb15b8bc | ||
|
|
9690dba7fe | ||
|
|
663eb6cd6d | ||
|
|
e9aa2d3449 | ||
|
|
7d4bffb575 | ||
|
|
b89902942b | ||
|
|
0a3ff7f85a | ||
|
|
b15c4afea1 | ||
|
|
738e0df4f4 | ||
|
|
3de6ae07b7 | ||
|
|
78afaab7e8 | ||
|
|
80a64d8e1a | ||
|
|
c7fbc8323b | ||
|
|
335f8b9aff | ||
|
|
009c9b1b71 | ||
|
|
ab515aeebb | ||
|
|
487d03eca4 | ||
|
|
32b74b968e | ||
|
|
1e98361299 | ||
|
|
ee2f6581bb | ||
|
|
5b0f74bffa | ||
|
|
faac423772 | ||
|
|
aae37121d6 | ||
|
|
660f97f241 | ||
|
|
387e9431f5 | ||
|
|
fd46bd1886 | ||
|
|
883f67d6d1 | ||
|
|
a52f64acfd | ||
|
|
4f4ccaa727 | ||
|
|
85f6ee2870 | ||
|
|
d81653461c | ||
|
|
55cfccafaf | ||
|
|
58e9acc19e | ||
|
|
6bcb9a60f7 | ||
|
|
5a02a51bd9 | ||
|
|
4aae197cf7 | ||
|
|
2fdebb639b | ||
|
|
25e8947282 | ||
|
|
34f0aced2f |
@@ -36,13 +36,6 @@ Min level: 1
|
|||||||
Max level: 1
|
Max level: 1
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Happy_holidays_128x64
|
|
||||||
Min butthurt: 0
|
|
||||||
Max butthurt: 14
|
|
||||||
Min level: 1
|
|
||||||
Max level: 3
|
|
||||||
Weight: 4
|
|
||||||
|
|
||||||
Name: L1_Read_books_128x64
|
Name: L1_Read_books_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 8
|
Max butthurt: 8
|
||||||
@@ -92,6 +85,20 @@ Min level: 1
|
|||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L1_Kaiju_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 10
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
|
Name: L1_My_dude_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 8
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
Name: L2_Wake_up_128x64
|
Name: L2_Wake_up_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 12
|
Max butthurt: 12
|
||||||
@@ -120,6 +127,13 @@ Min level: 2
|
|||||||
Max level: 2
|
Max level: 2
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L2_Dj_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 8
|
||||||
|
Min level: 2
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
Name: L3_Furippa3_128x64
|
Name: L3_Furippa3_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 6
|
Max butthurt: 6
|
||||||
@@ -141,9 +155,16 @@ Min level: 3
|
|||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Sleigh_ride_128x64
|
Name: L1_Senpai_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 14
|
Max butthurt: 5
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|
||||||
|
Name: L1_Sad_song_128x64
|
||||||
|
Min butthurt: 8
|
||||||
|
Max butthurt: 13
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 4
|
||||||
|
|||||||
538
.ci_files/rgb.patch
Normal file
538
.ci_files/rgb.patch
Normal file
@@ -0,0 +1,538 @@
|
|||||||
|
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||||
|
index 2f947fe..03c4c76 100644
|
||||||
|
--- a/applications/services/notification/notification_app.c
|
||||||
|
+++ b/applications/services/notification/notification_app.c
|
||||||
|
@@ -9,6 +9,7 @@
|
||||||
|
#include "notification.h"
|
||||||
|
#include "notification_messages.h"
|
||||||
|
#include "notification_app.h"
|
||||||
|
+#include "applications/settings/notification_settings/rgb_backlight.h"
|
||||||
|
|
||||||
|
#define TAG "NotificationSrv"
|
||||||
|
|
||||||
|
@@ -579,6 +580,7 @@ int32_t notification_srv(void* p) {
|
||||||
|
break;
|
||||||
|
case SaveSettingsMessage:
|
||||||
|
notification_save_settings(app);
|
||||||
|
+ rgb_backlight_save_settings();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
|
index 565d4f1..bae9299 100644
|
||||||
|
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||||
|
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
|
@@ -3,6 +3,7 @@
|
||||||
|
#include <gui/modules/variable_item_list.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <lib/toolbox/value_index.h>
|
||||||
|
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||||
|
|
||||||
|
#define MAX_NOTIFICATION_SETTINGS 4
|
||||||
|
|
||||||
|
@@ -162,6 +163,14 @@ static void vibro_changed(VariableItem* item) {
|
||||||
|
notification_message(app->notification, &sequence_single_vibro);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void color_changed(VariableItem* item) {
|
||||||
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
+ rgb_backlight_set_color(index);
|
||||||
|
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
||||||
|
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static uint32_t notification_app_settings_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
return VIEW_NONE;
|
||||||
|
@@ -187,7 +196,13 @@ static NotificationAppSettings* alloc_settings() {
|
||||||
|
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||||
|
|
||||||
|
item = variable_item_list_add(
|
||||||
|
- app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
|
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
||||||
|
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
||||||
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
|
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(value_index));
|
||||||
|
+
|
||||||
|
+ item = variable_item_list_add(
|
||||||
|
+ app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
|
value_index = value_index_float(
|
||||||
|
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||||
|
variable_item_set_current_value_index(item, value_index);
|
||||||
|
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..269b544
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
|
@@ -0,0 +1,171 @@
|
||||||
|
+/*
|
||||||
|
+ RGB backlight FlipperZero driver
|
||||||
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
|
+
|
||||||
|
+ This program is free software: you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#include "rgb_backlight.h"
|
||||||
|
+#include <furi_hal.h>
|
||||||
|
+#include <storage/storage.h>
|
||||||
|
+
|
||||||
|
+#define RGB_BACKLIGHT_SETTINGS_VERSION 5
|
||||||
|
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||||
|
+#define RGB_BACKLIGHT_SETTINGS_PATH EXT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||||
|
+
|
||||||
|
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||||
|
+
|
||||||
|
+#define TAG "RGB Backlight"
|
||||||
|
+
|
||||||
|
+static RGBBacklightSettings rgb_settings = {
|
||||||
|
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||||
|
+ .display_color_index = 0,
|
||||||
|
+ .settings_is_loaded = false};
|
||||||
|
+
|
||||||
|
+static const RGBBacklightColor colors[] = {
|
||||||
|
+ {"Orange", 255, 60, 0},
|
||||||
|
+ {"Yellow", 255, 150, 0},
|
||||||
|
+ {"Spring", 167, 255, 0},
|
||||||
|
+ {"Lime", 0, 255, 0},
|
||||||
|
+ {"Aqua", 0, 255, 127},
|
||||||
|
+ {"Cyan", 0, 210, 210},
|
||||||
|
+ {"Azure", 0, 127, 255},
|
||||||
|
+ {"Blue", 0, 0, 255},
|
||||||
|
+ {"Purple", 127, 0, 255},
|
||||||
|
+ {"Magenta", 210, 0, 210},
|
||||||
|
+ {"Pink", 255, 0, 127},
|
||||||
|
+ {"Red", 255, 0, 0},
|
||||||
|
+ {"White", 150, 150, 110},
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+uint8_t rgb_backlight_get_color_count(void) {
|
||||||
|
+ return COLOR_COUNT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+const char* rgb_backlight_get_color_text(uint8_t index) {
|
||||||
|
+ return colors[index].name;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void rgb_backlight_load_settings(void) {
|
||||||
|
+ //Не загружать данные из внутренней памяти при загрузке в режиме DFU
|
||||||
|
+ FuriHalRtcBootMode bm = furi_hal_rtc_get_boot_mode();
|
||||||
|
+ if(bm == FuriHalRtcBootModeDfu) {
|
||||||
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ RGBBacklightSettings settings;
|
||||||
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
|
+
|
||||||
|
+ FURI_LOG_I(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
|
+ bool fs_result =
|
||||||
|
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
|
+
|
||||||
|
+ if(fs_result) {
|
||||||
|
+ uint16_t bytes_count = storage_file_read(file, &settings, settings_size);
|
||||||
|
+
|
||||||
|
+ if(bytes_count != settings_size) {
|
||||||
|
+ fs_result = false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(fs_result) {
|
||||||
|
+ FURI_LOG_I(TAG, "load success");
|
||||||
|
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
||||||
|
+ FURI_LOG_E(
|
||||||
|
+ TAG,
|
||||||
|
+ "version(%d != %d) mismatch",
|
||||||
|
+ settings.version,
|
||||||
|
+ RGB_BACKLIGHT_SETTINGS_VERSION);
|
||||||
|
+ } else {
|
||||||
|
+ memcpy(&rgb_settings, &settings, settings_size);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ storage_file_close(file);
|
||||||
|
+ storage_file_free(file);
|
||||||
|
+ furi_record_close(RECORD_STORAGE);
|
||||||
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+void rgb_backlight_save_settings(void) {
|
||||||
|
+ RGBBacklightSettings settings;
|
||||||
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
|
+
|
||||||
|
+ FURI_LOG_I(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
|
+
|
||||||
|
+ memcpy(&settings, &rgb_settings, settings_size);
|
||||||
|
+
|
||||||
|
+ bool fs_result =
|
||||||
|
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||||
|
+
|
||||||
|
+ if(fs_result) {
|
||||||
|
+ uint16_t bytes_count = storage_file_write(file, &settings, settings_size);
|
||||||
|
+
|
||||||
|
+ if(bytes_count != settings_size) {
|
||||||
|
+ fs_result = false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if(fs_result) {
|
||||||
|
+ FURI_LOG_I(TAG, "save success");
|
||||||
|
+ } else {
|
||||||
|
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ storage_file_close(file);
|
||||||
|
+ storage_file_free(file);
|
||||||
|
+ furi_record_close(RECORD_STORAGE);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
||||||
|
+ if(!rgb_settings.settings_is_loaded) {
|
||||||
|
+ rgb_backlight_load_settings();
|
||||||
|
+ }
|
||||||
|
+ return &rgb_settings;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void rgb_backlight_set_color(uint8_t color_index) {
|
||||||
|
+ if(color_index > (rgb_backlight_get_color_count() - 1)) color_index = 0;
|
||||||
|
+ rgb_settings.display_color_index = color_index;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void rgb_backlight_update(uint8_t brightness) {
|
||||||
|
+ if(!rgb_settings.settings_is_loaded) {
|
||||||
|
+ rgb_backlight_load_settings();
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ static uint8_t last_color_index = 255;
|
||||||
|
+ static uint8_t last_brightness = 123;
|
||||||
|
+
|
||||||
|
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ last_brightness = brightness;
|
||||||
|
+ last_color_index = rgb_settings.display_color_index;
|
||||||
|
+
|
||||||
|
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||||
|
+ uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
|
||||||
|
+ uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
|
||||||
|
+ uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
|
||||||
|
+
|
||||||
|
+ SK6805_set_led_color(i, r, g, b);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ SK6805_update();
|
||||||
|
+}
|
||||||
|
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..b63d223
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
|
@@ -0,0 +1,79 @@
|
||||||
|
+/*
|
||||||
|
+ RGB backlight FlipperZero driver
|
||||||
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
|
+
|
||||||
|
+ This program is free software: you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#include <furi.h>
|
||||||
|
+#include "SK6805.h"
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ char* name;
|
||||||
|
+ uint8_t red;
|
||||||
|
+ uint8_t green;
|
||||||
|
+ uint8_t blue;
|
||||||
|
+} RGBBacklightColor;
|
||||||
|
+
|
||||||
|
+typedef struct {
|
||||||
|
+ uint8_t version;
|
||||||
|
+ uint8_t display_color_index;
|
||||||
|
+ bool settings_is_loaded;
|
||||||
|
+} RGBBacklightSettings;
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Получить текущие настройки RGB-подсветки
|
||||||
|
+ *
|
||||||
|
+ * @return Указатель на структуру настроек
|
||||||
|
+ */
|
||||||
|
+RGBBacklightSettings* rgb_backlight_get_settings(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Загрузить настройки подсветки с SD-карты
|
||||||
|
+ */
|
||||||
|
+void rgb_backlight_load_settings(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Сохранить текущие настройки RGB-подсветки
|
||||||
|
+ */
|
||||||
|
+void rgb_backlight_save_settings(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Применить текущие настройки RGB-подсветки
|
||||||
|
+ *
|
||||||
|
+ * @param brightness Яркость свечения (0-255)
|
||||||
|
+ */
|
||||||
|
+void rgb_backlight_update(uint8_t brightness);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Установить цвет RGB-подсветки
|
||||||
|
+ *
|
||||||
|
+ * @param color_index Индекс цвета (0 - rgb_backlight_get_color_count())
|
||||||
|
+ */
|
||||||
|
+void rgb_backlight_set_color(uint8_t color_index);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Получить количество доступных цветов
|
||||||
|
+ *
|
||||||
|
+ * @return Число доступных вариантов цвета
|
||||||
|
+ */
|
||||||
|
+uint8_t rgb_backlight_get_color_count(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Получить текстовое название цвета
|
||||||
|
+ *
|
||||||
|
+ * @param index Индекс из доступных вариантов цвета
|
||||||
|
+ * @return Указатель на строку с названием цвета
|
||||||
|
+ */
|
||||||
|
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||||
|
\ No newline at end of file
|
||||||
|
diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
|
index 83e1603..cad5b86 100644
|
||||||
|
--- a/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
|
+++ b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
|
@@ -3,6 +3,7 @@
|
||||||
|
#include <furi_hal_light.h>
|
||||||
|
#include <lp5562.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||||
|
|
||||||
|
#define LED_CURRENT_RED 50
|
||||||
|
#define LED_CURRENT_GREEN 50
|
||||||
|
@@ -31,22 +32,21 @@ void furi_hal_light_init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_light_set(Light light, uint8_t value) {
|
||||||
|
- furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
|
- if(light & LightRed) {
|
||||||
|
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||||
|
- }
|
||||||
|
- if(light & LightGreen) {
|
||||||
|
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||||
|
- }
|
||||||
|
- if(light & LightBlue) {
|
||||||
|
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||||
|
- }
|
||||||
|
if(light & LightBacklight) {
|
||||||
|
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
||||||
|
- lp5562_execute_ramp(
|
||||||
|
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
||||||
|
+ rgb_backlight_update(value);
|
||||||
|
+ } else {
|
||||||
|
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
|
+ if(light & LightRed) {
|
||||||
|
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||||
|
+ }
|
||||||
|
+ if(light & LightGreen) {
|
||||||
|
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||||
|
+ }
|
||||||
|
+ if(light & LightBlue) {
|
||||||
|
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||||
|
+ }
|
||||||
|
+ furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||||
|
}
|
||||||
|
- furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||||
|
}
|
||||||
|
|
||||||
|
void furi_hal_light_blink_start(Light light, uint8_t brightness, uint16_t on_time, uint16_t period) {
|
||||||
|
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..572e1df
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/drivers/SK6805.c
|
||||||
|
@@ -0,0 +1,101 @@
|
||||||
|
+/*
|
||||||
|
+ SK6805 FlipperZero driver
|
||||||
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
|
+
|
||||||
|
+ This program is free software: you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#include "SK6805.h"
|
||||||
|
+#include <furi_hal.h>
|
||||||
|
+
|
||||||
|
+/* Настройки */
|
||||||
|
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||||
|
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||||
|
+
|
||||||
|
+#ifdef FURI_DEBUG
|
||||||
|
+#define DEBUG_PIN &gpio_ext_pa7
|
||||||
|
+#define DEBUG_INIT() \
|
||||||
|
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
||||||
|
+#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
|
||||||
|
+#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
|
||||||
|
+#else
|
||||||
|
+#define DEBUG_INIT()
|
||||||
|
+#define DEBUG_SET_HIGH()
|
||||||
|
+#define DEBUG_SET_LOW()
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+static const GpioPin led_pin = {.port = GPIOA, .pin = LL_GPIO_PIN_8};
|
||||||
|
+static uint8_t led_buffer[SK6805_LED_COUNT][3];
|
||||||
|
+
|
||||||
|
+void SK6805_init(void) {
|
||||||
|
+ DEBUG_INIT();
|
||||||
|
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||||
|
+ furi_hal_gpio_init(SK6805_LED_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+uint8_t SK6805_get_led_count(void) {
|
||||||
|
+ return (const uint8_t)SK6805_LED_COUNT;
|
||||||
|
+}
|
||||||
|
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b) {
|
||||||
|
+ furi_check(led_index < SK6805_LED_COUNT);
|
||||||
|
+
|
||||||
|
+ led_buffer[led_index][0] = g;
|
||||||
|
+ led_buffer[led_index][1] = r;
|
||||||
|
+ led_buffer[led_index][2] = b;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void SK6805_update(void) {
|
||||||
|
+ SK6805_init();
|
||||||
|
+ furi_kernel_lock();
|
||||||
|
+ uint32_t end;
|
||||||
|
+ /* Последовательная отправка цветов светодиодов */
|
||||||
|
+ for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
||||||
|
+ //Последовательная отправка цветов светодиода
|
||||||
|
+ for(uint8_t color = 0; color < 3; color++) {
|
||||||
|
+ //Последовательная отправка битов цвета
|
||||||
|
+ uint8_t i = 0b10000000;
|
||||||
|
+ while(i != 0) {
|
||||||
|
+ if(led_buffer[lednumber][color] & (i)) {
|
||||||
|
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||||
|
+ DEBUG_SET_HIGH();
|
||||||
|
+ end = DWT->CYCCNT + 30;
|
||||||
|
+ //T1H 600 us (615 us)
|
||||||
|
+ while(DWT->CYCCNT < end) {
|
||||||
|
+ }
|
||||||
|
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||||
|
+ DEBUG_SET_LOW();
|
||||||
|
+ end = DWT->CYCCNT + 26;
|
||||||
|
+ //T1L 600 us (587 us)
|
||||||
|
+ while(DWT->CYCCNT < end) {
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||||
|
+ DEBUG_SET_HIGH();
|
||||||
|
+ end = DWT->CYCCNT + 11;
|
||||||
|
+ //T0H 300 ns (312 ns)
|
||||||
|
+ while(DWT->CYCCNT < end) {
|
||||||
|
+ }
|
||||||
|
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||||
|
+ DEBUG_SET_LOW();
|
||||||
|
+ end = DWT->CYCCNT + 43;
|
||||||
|
+ //T0L 900 ns (890 ns)
|
||||||
|
+ while(DWT->CYCCNT < end) {
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ i >>= 1;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ furi_kernel_unlock();
|
||||||
|
+}
|
||||||
|
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..7c58956
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/drivers/SK6805.h
|
||||||
|
@@ -0,0 +1,51 @@
|
||||||
|
+/*
|
||||||
|
+ SK6805 FlipperZero driver
|
||||||
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
|
+
|
||||||
|
+ This program is free software: you can redistribute it and/or modify
|
||||||
|
+ it under the terms of the GNU General Public License as published by
|
||||||
|
+ the Free Software Foundation, either version 3 of the License, or
|
||||||
|
+ (at your option) any later version.
|
||||||
|
+
|
||||||
|
+ This program is distributed in the hope that it will be useful,
|
||||||
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
+ GNU General Public License for more details.
|
||||||
|
+
|
||||||
|
+ You should have received a copy of the GNU General Public License
|
||||||
|
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
+*/
|
||||||
|
+
|
||||||
|
+#ifndef SK6805_H_
|
||||||
|
+#define SK6805_H_
|
||||||
|
+
|
||||||
|
+#include <furi.h>
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Инициализация линии управления подсветкой
|
||||||
|
+ */
|
||||||
|
+void SK6805_init(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Получить количество светодиодов в подсветке
|
||||||
|
+ *
|
||||||
|
+ * @return Количество светодиодов
|
||||||
|
+ */
|
||||||
|
+uint8_t SK6805_get_led_count(void);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Установить цвет свечения светодиода
|
||||||
|
+ *
|
||||||
|
+ * @param led_index номер светодиода (от 0 до SK6805_get_led_count())
|
||||||
|
+ * @param r значение красного (0-255)
|
||||||
|
+ * @param g значение зелёного (0-255)
|
||||||
|
+ * @param b значение синего (0-255)
|
||||||
|
+ */
|
||||||
|
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
|
+ * @brief Обновление состояния подсветки дисплея
|
||||||
|
+ */
|
||||||
|
+void SK6805_update(void);
|
||||||
|
+
|
||||||
|
+#endif /* SK6805_H_ */
|
||||||
|
\ No newline at end of file
|
||||||
286
.drone.yml
286
.drone.yml
@@ -11,27 +11,48 @@ steps:
|
|||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git submodule sync
|
- git submodule sync
|
||||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||||
- git submodule foreach git config --local gc.auto 0
|
- git submodule foreach git config --local gc.auto 0
|
||||||
- git log -1 --format='%H'
|
- git log -1 --format='%H'
|
||||||
|
|
||||||
- name: "Build firmware"
|
- name: "Build clean"
|
||||||
|
image: hfdj/fztools
|
||||||
|
pull: never
|
||||||
|
commands:
|
||||||
|
- export DIST_SUFFIX=${DRONE_TAG}c
|
||||||
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- rm -rf assets/resources/apps/
|
||||||
|
- rm -rf build/
|
||||||
|
- rm -rf dist/
|
||||||
|
- rm -rf .sconsign.dblite
|
||||||
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
|
- mkdir artifacts-clean
|
||||||
|
- mv dist/f7-C/* artifacts-clean/
|
||||||
|
- ls -laS artifacts-clean
|
||||||
|
- ls -laS artifacts-clean/f7-update-${DRONE_TAG}c
|
||||||
|
environment:
|
||||||
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
|
from_secret: fbt_link
|
||||||
|
|
||||||
|
- name: "Build default"
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}
|
- export DIST_SUFFIX=${DRONE_TAG}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
|
- tar zxvf all-the-apps-base.tgz
|
||||||
|
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
||||||
|
- rm -rf base_pack_build
|
||||||
|
- rm -rf all-the-apps-base.tgz
|
||||||
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-default
|
- mkdir artifacts-default
|
||||||
- mv dist/f7-C/* artifacts-default/
|
- mv dist/f7-C/* artifacts-default/
|
||||||
- ls -laS artifacts-default
|
- ls -laS artifacts-default
|
||||||
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
|
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
|
||||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
|
||||||
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
|
||||||
- echo '' >> CHANGELOG.md
|
|
||||||
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
|
||||||
- echo '' >> CHANGELOG.md
|
|
||||||
- echo '### [Version with extra apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' >> CHANGELOG.md
|
|
||||||
environment:
|
environment:
|
||||||
FBT_TOOLS_CUSTOM_LINK:
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
from_secret: fbt_link
|
from_secret: fbt_link
|
||||||
@@ -40,9 +61,10 @@ steps:
|
|||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
- tar zxvf all-the-apps-extra.tgz
|
||||||
- rm -rf unleashed-extra-pack
|
- cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/
|
||||||
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
@@ -56,10 +78,30 @@ steps:
|
|||||||
FBT_TOOLS_CUSTOM_LINK:
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
from_secret: fbt_link
|
from_secret: fbt_link
|
||||||
|
|
||||||
|
- name: "Build with RGB patch"
|
||||||
|
image: hfdj/fztools
|
||||||
|
pull: never
|
||||||
|
commands:
|
||||||
|
- git apply .ci_files/rgb.patch
|
||||||
|
- export DIST_SUFFIX=${DRONE_TAG}r
|
||||||
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
|
- mkdir artifacts-rgb-patch
|
||||||
|
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||||
|
- ls -laS artifacts-rgb-patch
|
||||||
|
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||||
|
environment:
|
||||||
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
|
from_secret: fbt_link
|
||||||
|
|
||||||
- name: "Build with ofw anims"
|
- name: "Build with ofw anims"
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
|
- git clean -df
|
||||||
|
- git checkout -- .
|
||||||
- rm -f assets/dolphin/external/manifest.txt
|
- rm -f assets/dolphin/external/manifest.txt
|
||||||
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
||||||
- rm -rf assets/resources/apps/
|
- rm -rf assets/resources/apps/
|
||||||
@@ -68,10 +110,27 @@ steps:
|
|||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
|
- tar zxvf all-the-apps-base.tgz
|
||||||
|
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
||||||
|
- rm -rf base_pack_build
|
||||||
|
- rm -rf all-the-apps-base.tgz
|
||||||
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-ofw-anims
|
- mkdir artifacts-ofw-anims
|
||||||
- mv dist/f7-C/* artifacts-ofw-anims/
|
- mv dist/f7-C/* artifacts-ofw-anims/
|
||||||
- ls -laS artifacts-ofw-anims
|
- ls -laS artifacts-ofw-anims
|
||||||
- ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
- ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||||
|
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||||
|
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||||
|
- echo '' >> CHANGELOG.md
|
||||||
|
- echo '### [Version with only main apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)' >> CHANGELOG.md
|
||||||
|
- echo '' >> CHANGELOG.md
|
||||||
|
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
||||||
|
- echo '' >> CHANGELOG.md
|
||||||
|
- echo '### [Version with RGB patch - only for hardware mod! - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)' >> CHANGELOG.md
|
||||||
|
- echo '' >> CHANGELOG.md
|
||||||
|
- echo '## [Version with Extra apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' >> CHANGELOG.md
|
||||||
environment:
|
environment:
|
||||||
FBT_TOOLS_CUSTOM_LINK:
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
from_secret: fbt_link
|
from_secret: fbt_link
|
||||||
@@ -80,16 +139,24 @@ steps:
|
|||||||
image: kramos/alpine-zip
|
image: kramos/alpine-zip
|
||||||
commands:
|
commands:
|
||||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz .
|
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz .
|
||||||
|
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.tgz .
|
||||||
|
- cp artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.tgz .
|
||||||
- cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
- cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
||||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
|
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
|
||||||
- zip -r artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.zip artifacts-extra-apps/f7-update-${DRONE_TAG}e
|
- zip -r artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.zip artifacts-extra-apps/f7-update-${DRONE_TAG}e
|
||||||
|
- zip -r artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.zip artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||||
|
- zip -r artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.zip artifacts-clean/f7-update-${DRONE_TAG}c
|
||||||
- zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
- zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||||
- zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
|
- zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
|
||||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts debug
|
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts
|
||||||
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
||||||
|
- rm -rf artifacts-rgb-patch/f7-update-${DRONE_TAG}
|
||||||
|
- rm -rf artifacts-clean/f7-update-${DRONE_TAG}
|
||||||
- rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
|
- rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
|
||||||
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
||||||
- ls -laS artifacts-extra-apps
|
- ls -laS artifacts-extra-apps
|
||||||
|
- ls -laS artifacts-rgb-patch
|
||||||
|
- ls -laS artifacts-clean
|
||||||
- ls -laS artifacts-ofw-anims
|
- ls -laS artifacts-ofw-anims
|
||||||
- ls -laS artifacts-default
|
- ls -laS artifacts-default
|
||||||
- mv artifacts-default/ ${DRONE_TAG}
|
- mv artifacts-default/ ${DRONE_TAG}
|
||||||
@@ -146,6 +213,36 @@ steps:
|
|||||||
from_secret: dep_target_extra
|
from_secret: dep_target_extra
|
||||||
source: flipper-z-f7-update-${DRONE_TAG}e.tgz
|
source: flipper-z-f7-update-${DRONE_TAG}e.tgz
|
||||||
|
|
||||||
|
- name: "Upload rgb patch version to updates srv"
|
||||||
|
image: appleboy/drone-scp:linux-amd64
|
||||||
|
settings:
|
||||||
|
host:
|
||||||
|
from_secret: dep_host
|
||||||
|
username:
|
||||||
|
from_secret: dep_user
|
||||||
|
password:
|
||||||
|
from_secret: dep_passwd
|
||||||
|
port:
|
||||||
|
from_secret: dep_port
|
||||||
|
target:
|
||||||
|
from_secret: dep_target_extra
|
||||||
|
source: flipper-z-f7-update-${DRONE_TAG}r.tgz
|
||||||
|
|
||||||
|
- name: "Upload clean version to updates srv"
|
||||||
|
image: appleboy/drone-scp:linux-amd64
|
||||||
|
settings:
|
||||||
|
host:
|
||||||
|
from_secret: dep_host
|
||||||
|
username:
|
||||||
|
from_secret: dep_user
|
||||||
|
password:
|
||||||
|
from_secret: dep_passwd
|
||||||
|
port:
|
||||||
|
from_secret: dep_port
|
||||||
|
target:
|
||||||
|
from_secret: dep_target_extra
|
||||||
|
source: flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||||
|
|
||||||
- name: "Do Github release"
|
- name: "Do Github release"
|
||||||
image: ddplugins/github-release
|
image: ddplugins/github-release
|
||||||
pull: never
|
pull: never
|
||||||
@@ -160,6 +257,8 @@ steps:
|
|||||||
- ${DRONE_TAG}/*.zip
|
- ${DRONE_TAG}/*.zip
|
||||||
- artifacts-ofw-anims/*.tgz
|
- artifacts-ofw-anims/*.tgz
|
||||||
- artifacts-extra-apps/*.tgz
|
- artifacts-extra-apps/*.tgz
|
||||||
|
- artifacts-rgb-patch/*.tgz
|
||||||
|
- artifacts-clean/*.tgz
|
||||||
title: ${DRONE_TAG}
|
title: ${DRONE_TAG}
|
||||||
note: CHANGELOG.md
|
note: CHANGELOG.md
|
||||||
checksum:
|
checksum:
|
||||||
@@ -192,22 +291,34 @@ steps:
|
|||||||
Version: {{build.tag}}
|
Version: {{build.tag}}
|
||||||
|
|
||||||
|
|
||||||
|
[-> Sponsor our project](https://boosty.to/mmxdev)
|
||||||
|
|
||||||
|
|
||||||
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
||||||
|
|
||||||
|
|
||||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||||
|
|
||||||
|
|
||||||
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||||
|
|
||||||
|
|
||||||
[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})
|
[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}c.tgz&channel=release-cfw&version=${DRONE_TAG}c)
|
||||||
|
|
||||||
|
|
||||||
[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
||||||
|
|
||||||
|
|
||||||
[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}e.tgz&channel=release-cfw&version=${DRONE_TAG}e)"
|
[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}r.tgz&channel=release-cfw&version=${DRONE_TAG}r)
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}r.tgz)
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}e.tgz&channel=release-cfw&version=${DRONE_TAG}e)"
|
||||||
document:
|
document:
|
||||||
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||||
|
|
||||||
@@ -220,7 +331,19 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
|
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://github.com/xMasterX/all-the-plugins/releases/latest)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version with only main apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c)\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with RGB patch - only for hardware mod! - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz)\n\n[-Version with Extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
|
||||||
|
|
||||||
|
- name: "Send clean build to telegram"
|
||||||
|
image: appleboy/drone-telegram
|
||||||
|
settings:
|
||||||
|
token:
|
||||||
|
from_secret: tgtoken
|
||||||
|
to:
|
||||||
|
from_secret: tgid
|
||||||
|
format: markdown
|
||||||
|
message: "Build with only main apps:"
|
||||||
|
document:
|
||||||
|
- flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||||
|
|
||||||
- name: "Send extra pack build to telegram"
|
- name: "Send extra pack build to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
@@ -255,16 +378,44 @@ steps:
|
|||||||
image: alpine/git
|
image: alpine/git
|
||||||
commands:
|
commands:
|
||||||
- git submodule sync
|
- git submodule sync
|
||||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||||
- git submodule foreach git config --local gc.auto 0
|
- git submodule foreach git config --local gc.auto 0
|
||||||
- git log -1 --format='%H'
|
- git log -1 --format='%H'
|
||||||
|
|
||||||
- name: "Build dev FW"
|
- name: "Build dev clean"
|
||||||
|
image: hfdj/fztools
|
||||||
|
pull: never
|
||||||
|
commands:
|
||||||
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c
|
||||||
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- rm -rf assets/resources/apps/
|
||||||
|
- rm -rf build/
|
||||||
|
- rm -rf dist/
|
||||||
|
- rm -rf .sconsign.dblite
|
||||||
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
|
- mkdir artifacts-clean
|
||||||
|
- mv dist/f7-C/* artifacts-clean/
|
||||||
|
- ls -laS artifacts-clean
|
||||||
|
- ls -laS artifacts-clean/f7-update-${DRONE_BUILD_NUMBER}c
|
||||||
|
environment:
|
||||||
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
|
from_secret: fbt_link
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Build dev default"
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
|
- tar zxvf all-the-apps-base.tgz
|
||||||
|
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
||||||
|
- rm -rf base_pack_build
|
||||||
|
- rm -rf all-the-apps-base.tgz
|
||||||
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-default
|
- mkdir artifacts-default
|
||||||
- mv dist/f7-C/* artifacts-default/
|
- mv dist/f7-C/* artifacts-default/
|
||||||
@@ -278,9 +429,10 @@ steps:
|
|||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
- tar zxvf all-the-apps-extra.tgz
|
||||||
- rm -rf unleashed-extra-pack
|
- cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/
|
||||||
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
@@ -294,10 +446,30 @@ steps:
|
|||||||
FBT_TOOLS_CUSTOM_LINK:
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
from_secret: fbt_link
|
from_secret: fbt_link
|
||||||
|
|
||||||
|
- name: "Build dev with rgb patch"
|
||||||
|
image: hfdj/fztools
|
||||||
|
pull: never
|
||||||
|
commands:
|
||||||
|
- git apply .ci_files/rgb.patch
|
||||||
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
||||||
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
||||||
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
|
- mkdir artifacts-rgb-patch
|
||||||
|
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||||
|
- ls -laS artifacts-rgb-patch
|
||||||
|
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_BUILD_NUMBER}r
|
||||||
|
environment:
|
||||||
|
FBT_TOOLS_CUSTOM_LINK:
|
||||||
|
from_secret: fbt_link
|
||||||
|
|
||||||
- name: "Bundle self-update packages"
|
- name: "Bundle self-update packages"
|
||||||
image: kramos/alpine-zip
|
image: kramos/alpine-zip
|
||||||
commands:
|
commands:
|
||||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz .
|
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz .
|
||||||
|
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz .
|
||||||
|
- cp artifacts-clean/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz .
|
||||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
||||||
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||||
- ls -laS artifacts-default
|
- ls -laS artifacts-default
|
||||||
@@ -355,6 +527,36 @@ steps:
|
|||||||
from_secret: dep_target_extra
|
from_secret: dep_target_extra
|
||||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
||||||
|
|
||||||
|
- name: "Upload rgb patch version to updates srv"
|
||||||
|
image: appleboy/drone-scp:linux-amd64
|
||||||
|
settings:
|
||||||
|
host:
|
||||||
|
from_secret: dep_host
|
||||||
|
username:
|
||||||
|
from_secret: dep_user
|
||||||
|
password:
|
||||||
|
from_secret: dep_passwd
|
||||||
|
port:
|
||||||
|
from_secret: dep_port
|
||||||
|
target:
|
||||||
|
from_secret: dep_target_extra
|
||||||
|
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz
|
||||||
|
|
||||||
|
- name: "Upload clean version to updates srv"
|
||||||
|
image: appleboy/drone-scp:linux-amd64
|
||||||
|
settings:
|
||||||
|
host:
|
||||||
|
from_secret: dep_host
|
||||||
|
username:
|
||||||
|
from_secret: dep_user
|
||||||
|
password:
|
||||||
|
from_secret: dep_passwd
|
||||||
|
port:
|
||||||
|
from_secret: dep_port
|
||||||
|
target:
|
||||||
|
from_secret: dep_target_extra
|
||||||
|
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||||
|
|
||||||
- name: "Trigger update server reindex"
|
- name: "Trigger update server reindex"
|
||||||
image: hfdj/fztools
|
image: hfdj/fztools
|
||||||
pull: never
|
pull: never
|
||||||
@@ -366,7 +568,7 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||||
|
|
||||||
- name: "Send files to telegram"
|
- name: "Send message to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
settings:
|
settings:
|
||||||
token:
|
token:
|
||||||
@@ -379,19 +581,51 @@ steps:
|
|||||||
|
|
||||||
Build: {{build.number}}
|
Build: {{build.number}}
|
||||||
|
|
||||||
SHA: {{commit.sha}}
|
Commit: https://github.com/DarkFlippers/unleashed-firmware/commit/{{commit.sha}}
|
||||||
|
|
||||||
|
|
||||||
Commit: {{commit.message}}
|
|
||||||
|
[-> Sponsor our project](https://boosty.to/mmxdev)
|
||||||
|
|
||||||
|
|
||||||
[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}e)
|
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})
|
||||||
|
|
||||||
|
|
||||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})"
|
[-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}c)
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}r)
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz)
|
||||||
|
|
||||||
|
|
||||||
|
[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}e)"
|
||||||
|
|
||||||
|
- name: "Send build to telegram"
|
||||||
|
image: appleboy/drone-telegram
|
||||||
|
settings:
|
||||||
|
token:
|
||||||
|
from_secret: tgtoken
|
||||||
|
to:
|
||||||
|
from_secret: tgid_dev
|
||||||
|
format: markdown
|
||||||
|
message: "Regular Build:"
|
||||||
document:
|
document:
|
||||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
||||||
|
|
||||||
|
- name: "Send clean build to telegram"
|
||||||
|
image: appleboy/drone-telegram
|
||||||
|
settings:
|
||||||
|
token:
|
||||||
|
from_secret: tgtoken
|
||||||
|
to:
|
||||||
|
from_secret: tgid_dev
|
||||||
|
format: markdown
|
||||||
|
message: "Clean (Main apps only) Build:"
|
||||||
|
document:
|
||||||
|
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||||
|
|
||||||
- name: "Send extra pack build to telegram"
|
- name: "Send extra pack build to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
settings:
|
settings:
|
||||||
@@ -413,7 +647,7 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nSHA - '${DRONE_COMMIT_SHA}'\n\n[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
|
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nCommit - https://github.com/DarkFlippers/unleashed-firmware/commit/'${DRONE_COMMIT_SHA}'\n\n[-> Sponsor our project](https://boosty.to/mmxdev)\n\n[-Version with Extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Version with only main apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'c.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'c)\n\n[-Version with RGB patch - only for hardware mod! - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'r)\n\n[-Version with RGB patch - only for hardware mod! - Direct download-](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'r.tgz)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
|
|||||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -2,4 +2,4 @@
|
|||||||
* @xMasterX
|
* @xMasterX
|
||||||
|
|
||||||
# Assets
|
# Assets
|
||||||
/assets/resources/infrared/ @xMasterX @amec0e
|
/assets/resources/infrared/assets/ @amec0e @Leptopt1los @xMasterX
|
||||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
ko_fi: masterx
|
patreon: mmxdev
|
||||||
custom:
|
custom:
|
||||||
[
|
[
|
||||||
"https://boosty.to/mmxdev",
|
"https://boosty.to/mmxdev",
|
||||||
|
|||||||
30
.gitignore
vendored
30
.gitignore
vendored
@@ -1,6 +1,8 @@
|
|||||||
|
*~
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
*.gdb_history
|
*.gdb_history
|
||||||
|
*.old
|
||||||
|
|
||||||
|
|
||||||
# LSP
|
# LSP
|
||||||
@@ -28,28 +30,31 @@ bindings/
|
|||||||
.mxproject
|
.mxproject
|
||||||
Brewfile.lock.json
|
Brewfile.lock.json
|
||||||
|
|
||||||
# Visual Studio Code
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# Kate
|
# Kate
|
||||||
.kateproject
|
.kateproject
|
||||||
.kateconfig
|
.kateconfig
|
||||||
|
|
||||||
# legendary cmake's
|
|
||||||
build
|
|
||||||
CMakeLists.txt
|
|
||||||
|
|
||||||
# bundle output
|
|
||||||
dist
|
|
||||||
|
|
||||||
# kde
|
# kde
|
||||||
.directory
|
.directory
|
||||||
null.d
|
null.d
|
||||||
|
|
||||||
# SCons
|
# SCons
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
|
|
||||||
|
|
||||||
|
# Visual Studio Code
|
||||||
|
/.vscode
|
||||||
|
|
||||||
|
# bundle output
|
||||||
|
/dist
|
||||||
|
/artifacts-default
|
||||||
|
/artifacts-ofw-anims
|
||||||
|
/artifacts-rgb-patch
|
||||||
|
/artifacts-extra-apps
|
||||||
|
/artifacts-clean
|
||||||
|
|
||||||
# SCons build dir
|
# SCons build dir
|
||||||
build/
|
/build
|
||||||
|
|
||||||
# Toolchain
|
# Toolchain
|
||||||
/toolchain
|
/toolchain
|
||||||
@@ -60,5 +65,8 @@ openocd.log
|
|||||||
# PVS Studio temporary files
|
# PVS Studio temporary files
|
||||||
.PVS-Studio/
|
.PVS-Studio/
|
||||||
PVS-Studio.log
|
PVS-Studio.log
|
||||||
|
*.PVS-Studio.*
|
||||||
|
|
||||||
.gdbinit
|
.gdbinit
|
||||||
|
|
||||||
|
/fbt_options_local.py
|
||||||
26
.gitmodules
vendored
26
.gitmodules
vendored
@@ -1,9 +1,6 @@
|
|||||||
[submodule "lib/mlib"]
|
[submodule "lib/mlib"]
|
||||||
path = lib/mlib
|
path = lib/mlib
|
||||||
url = https://github.com/P-p-H-d/mlib.git
|
url = https://github.com/P-p-H-d/mlib.git
|
||||||
[submodule "lib/STM32CubeWB"]
|
|
||||||
path = lib/STM32CubeWB
|
|
||||||
url = https://github.com/Flipper-Zero/STM32CubeWB.git
|
|
||||||
[submodule "lib/littlefs"]
|
[submodule "lib/littlefs"]
|
||||||
path = lib/littlefs
|
path = lib/littlefs
|
||||||
url = https://github.com/littlefs-project/littlefs.git
|
url = https://github.com/littlefs-project/littlefs.git
|
||||||
@@ -13,6 +10,7 @@
|
|||||||
[submodule "assets/protobuf"]
|
[submodule "assets/protobuf"]
|
||||||
path = assets/protobuf
|
path = assets/protobuf
|
||||||
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
||||||
|
shallow = false
|
||||||
[submodule "lib/libusb_stm32"]
|
[submodule "lib/libusb_stm32"]
|
||||||
path = lib/libusb_stm32
|
path = lib/libusb_stm32
|
||||||
url = https://github.com/flipperdevices/libusb_stm32.git
|
url = https://github.com/flipperdevices/libusb_stm32.git
|
||||||
@@ -28,9 +26,19 @@
|
|||||||
[submodule "lib/cxxheaderparser"]
|
[submodule "lib/cxxheaderparser"]
|
||||||
path = lib/cxxheaderparser
|
path = lib/cxxheaderparser
|
||||||
url = https://github.com/robotpy/cxxheaderparser.git
|
url = https://github.com/robotpy/cxxheaderparser.git
|
||||||
[submodule "applications/plugins/subbrute"]
|
[submodule "lib/heatshrink"]
|
||||||
path = applications/plugins/subbrute
|
path = lib/heatshrink
|
||||||
url = https://github.com/derskythe/flipperzero-subbrute.git
|
url = https://github.com/flipperdevices/heatshrink.git
|
||||||
[submodule "applications/plugins/dap_link/lib/free-dap"]
|
[submodule "lib/st_cmsis_device_wb"]
|
||||||
path = applications/plugins/dap_link/lib/free-dap
|
path = lib/stm32wb_cmsis
|
||||||
url = https://github.com/ataradov/free-dap.git
|
url = https://github.com/STMicroelectronics/cmsis_device_wb
|
||||||
|
[submodule "lib/stm32wbxx_hal_driver"]
|
||||||
|
path = lib/stm32wb_hal
|
||||||
|
url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver
|
||||||
|
[submodule "lib/stm32wb_copro"]
|
||||||
|
path = lib/stm32wb_copro
|
||||||
|
url = https://github.com/flipperdevices/stm32wb_copro.git
|
||||||
|
[submodule "subghz_remote"]
|
||||||
|
path = applications/main/subghz_remote
|
||||||
|
url = https://github.com/DarkFlippers/SubGHz_Remote.git
|
||||||
|
branch = ufw_main_app
|
||||||
|
|||||||
@@ -44,3 +44,6 @@
|
|||||||
|
|
||||||
# Functions that always return the same error code
|
# Functions that always return the same error code
|
||||||
//-V:picopass_device_decrypt:1048
|
//-V:picopass_device_decrypt:1048
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
//V_EXCLUDE_PATH applications/examples/
|
||||||
@@ -1 +1 @@
|
|||||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
|
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
||||||
|
|||||||
9
.vscode/.gitignore
vendored
9
.vscode/.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
./c_cpp_properties.json
|
/c_cpp_properties.json
|
||||||
./launch.json
|
/extensions.json
|
||||||
./settings.json
|
/launch.json
|
||||||
./tasks.json
|
/settings.json
|
||||||
|
/tasks.json
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// List of extensions which should be recommended for users of this workspace.
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"ms-python.black-formatter",
|
"ms-python.black-formatter",
|
||||||
"ms-vscode.cpptools",
|
"llvm-vs-code-extensions.vscode-clangd",
|
||||||
"amiralizadeh9480.cpp-helper",
|
"amiralizadeh9480.cpp-helper",
|
||||||
"marus25.cortex-debug",
|
"marus25.cortex-debug",
|
||||||
"zxh404.vscode-proto3",
|
"zxh404.vscode-proto3",
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
"unwantedRecommendations": [
|
"unwantedRecommendations": [
|
||||||
"twxs.cmake",
|
"twxs.cmake",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
"ms-vscode.cmake-tools"
|
"ms-vscode.cmake-tools"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
20
.vscode/example/cpptools/extensions.json
vendored
Normal file
20
.vscode/example/cpptools/extensions.json
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||||
|
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||||
|
// List of extensions which should be recommended for users of this workspace.
|
||||||
|
"recommendations": [
|
||||||
|
"ms-python.black-formatter",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"amiralizadeh9480.cpp-helper",
|
||||||
|
"marus25.cortex-debug",
|
||||||
|
"zxh404.vscode-proto3",
|
||||||
|
"augustocdias.tasks-shell-input",
|
||||||
|
"rioj7.command-variable"
|
||||||
|
],
|
||||||
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
|
"unwantedRecommendations": [
|
||||||
|
"llvm-vs-code-extensions.vscode-clangd",
|
||||||
|
"twxs.cmake",
|
||||||
|
"ms-vscode.cmake-tools"
|
||||||
|
]
|
||||||
|
}
|
||||||
46
.vscode/example/launch.json
vendored
46
.vscode/example/launch.json
vendored
@@ -11,10 +11,10 @@
|
|||||||
"args": {
|
"args": {
|
||||||
"useSingleResult": true,
|
"useSingleResult": true,
|
||||||
"env": {
|
"env": {
|
||||||
"PATH": "${workspaceFolder};${env:PATH}"
|
"PATH": "${workspaceFolder}${command:extension.commandvariable.envListSep}${env:PATH}"
|
||||||
},
|
},
|
||||||
"command": "./fbt get_blackmagic",
|
"command": "fbt -s get_blackmagic",
|
||||||
"description": "Get Blackmagic device",
|
"description": "Get Blackmagic device"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -27,20 +27,21 @@
|
|||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"servertype": "openocd",
|
"servertype": "openocd",
|
||||||
"device": "stlink",
|
"device": "stlink",
|
||||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||||
// If you're debugging early in the boot process, before OS scheduler is running,
|
// If you're debugging early in the boot process, before OS scheduler is running,
|
||||||
// you have to comment out the following line.
|
// you have to comment out the following line.
|
||||||
"rtos": "FreeRTOS",
|
"rtos": "FreeRTOS",
|
||||||
"configFiles": [
|
"configFiles": [
|
||||||
"interface/stlink.cfg",
|
"interface/stlink.cfg",
|
||||||
"./debug/stm32wbx.cfg",
|
"./scripts/debug/stm32wbx.cfg",
|
||||||
],
|
],
|
||||||
"postAttachCommands": [
|
"postAttachCommands": [
|
||||||
|
"source scripts/debug/flipperversion.py",
|
||||||
|
"fw-version",
|
||||||
// "compare-sections",
|
// "compare-sections",
|
||||||
"source debug/flipperapps.py",
|
"source scripts/debug/flipperapps.py",
|
||||||
"fap-set-debug-elf-root build/latest/.extapps",
|
"fap-set-debug-elf-root build/latest/.extapps",
|
||||||
// "source debug/FreeRTOS/FreeRTOS.py",
|
// "source scripts/debug/FreeRTOS/FreeRTOS.py",
|
||||||
// "svd_load debug/STM32WB55_CM4.svd"
|
|
||||||
]
|
]
|
||||||
// "showDevDebugOutput": "raw",
|
// "showDevDebugOutput": "raw",
|
||||||
},
|
},
|
||||||
@@ -52,14 +53,16 @@
|
|||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"servertype": "external",
|
"servertype": "external",
|
||||||
"gdbTarget": "${input:BLACKMAGIC}",
|
"gdbTarget": "${input:BLACKMAGIC}",
|
||||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||||
"rtos": "FreeRTOS",
|
"rtos": "FreeRTOS",
|
||||||
"postAttachCommands": [
|
"postAttachCommands": [
|
||||||
"monitor swdp_scan",
|
"monitor swdp_scan",
|
||||||
"attach 1",
|
"attach 1",
|
||||||
"set confirm off",
|
"set confirm off",
|
||||||
"set mem inaccessible-by-default off",
|
"set mem inaccessible-by-default off",
|
||||||
"source debug/flipperapps.py",
|
"source scripts/debug/flipperversion.py",
|
||||||
|
"fw-version",
|
||||||
|
"source scripts/debug/flipperapps.py",
|
||||||
"fap-set-debug-elf-root build/latest/.extapps",
|
"fap-set-debug-elf-root build/latest/.extapps",
|
||||||
// "compare-sections",
|
// "compare-sections",
|
||||||
]
|
]
|
||||||
@@ -74,10 +77,12 @@
|
|||||||
"servertype": "jlink",
|
"servertype": "jlink",
|
||||||
"interface": "swd",
|
"interface": "swd",
|
||||||
"device": "STM32WB55RG",
|
"device": "STM32WB55RG",
|
||||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||||
"rtos": "FreeRTOS",
|
"rtos": "FreeRTOS",
|
||||||
"postAttachCommands": [
|
"postAttachCommands": [
|
||||||
"source debug/flipperapps.py",
|
"source scripts/debug/flipperversion.py",
|
||||||
|
"fw-version",
|
||||||
|
"source scripts/debug/flipperapps.py",
|
||||||
"fap-set-debug-elf-root build/latest/.extapps",
|
"fap-set-debug-elf-root build/latest/.extapps",
|
||||||
]
|
]
|
||||||
// "showDevDebugOutput": "raw",
|
// "showDevDebugOutput": "raw",
|
||||||
@@ -90,27 +95,20 @@
|
|||||||
"type": "cortex-debug",
|
"type": "cortex-debug",
|
||||||
"servertype": "openocd",
|
"servertype": "openocd",
|
||||||
"device": "cmsis-dap",
|
"device": "cmsis-dap",
|
||||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||||
"rtos": "FreeRTOS",
|
"rtos": "FreeRTOS",
|
||||||
"configFiles": [
|
"configFiles": [
|
||||||
"interface/cmsis-dap.cfg",
|
"interface/cmsis-dap.cfg",
|
||||||
"./debug/stm32wbx.cfg",
|
"./scripts/debug/stm32wbx.cfg",
|
||||||
],
|
],
|
||||||
"postAttachCommands": [
|
"postAttachCommands": [
|
||||||
"source debug/flipperapps.py",
|
"source scripts/debug/flipperversion.py",
|
||||||
|
"fw-version",
|
||||||
|
"source scripts/debug/flipperapps.py",
|
||||||
"fap-set-debug-elf-root build/latest/.extapps",
|
"fap-set-debug-elf-root build/latest/.extapps",
|
||||||
],
|
],
|
||||||
// "showDevDebugOutput": "raw",
|
// "showDevDebugOutput": "raw",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "fbt debug",
|
|
||||||
"type": "python",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "./lib/scons/scripts/scons.py",
|
|
||||||
"args": [
|
|
||||||
"plugin_dist"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "python debug",
|
"name": "python debug",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
|
|||||||
7
.vscode/example/settings.json
vendored
7
.vscode/example/settings.json
vendored
@@ -21,5 +21,10 @@
|
|||||||
"SConscript": "python",
|
"SConscript": "python",
|
||||||
"SConstruct": "python",
|
"SConstruct": "python",
|
||||||
"*.fam": "python",
|
"*.fam": "python",
|
||||||
}
|
},
|
||||||
|
"clangd.arguments": [
|
||||||
|
// We might be able to tighten this a bit more to only include the correct toolchain.
|
||||||
|
"--query-driver=**",
|
||||||
|
"--compile-commands-dir=${workspaceFolder}/build/latest"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
48
.vscode/example/tasks.json
vendored
48
.vscode/example/tasks.json
vendored
@@ -4,41 +4,41 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "[Release] Build",
|
"label": "[Release] Build Firmware",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0"
|
"command": "./fbt COMPACT=1 DEBUG=0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Debug] Build",
|
"label": "[Debug] Build Firmware",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt"
|
"command": "./fbt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Release] Flash (ST-Link)",
|
"label": "[FBT] Format",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./fbt format"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "[FBT] Clear",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./fbt -c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "[Release] Flash (SWD)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Debug] Flash (ST-Link)",
|
"label": "[Debug] Flash (SWD)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt FORCE=1 flash"
|
"command": "./fbt FORCE=1 flash"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"label": "[Release] Flash (blackmagic)",
|
|
||||||
"group": "build",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "[Debug] Flash (blackmagic)",
|
|
||||||
"group": "build",
|
|
||||||
"type": "shell",
|
|
||||||
"command": "./fbt FORCE=1 flash_blackmagic"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"label": "[Release] Flash (JLink)",
|
"label": "[Release] Flash (JLink)",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
@@ -123,17 +123,29 @@
|
|||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "[Debug] Build App",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./fbt build APPSRC=${relativeFileDirname}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "[Release] Build App",
|
||||||
|
"group": "build",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "[Debug] Launch App on Flipper",
|
"label": "[Debug] Launch App on Flipper",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt launch_app APPSRC=${relativeFileDirname}"
|
"command": "./fbt launch APPSRC=${relativeFileDirname}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Release] Launch App on Flipper",
|
"label": "[Release] Launch App on Flipper",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}"
|
"command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "[Debug] Launch App on Flipper with Serial Console",
|
"label": "[Debug] Launch App on Flipper with Serial Console",
|
||||||
|
|||||||
102
CHANGELOG.md
102
CHANGELOG.md
@@ -1,44 +1,90 @@
|
|||||||
### New changes
|
## New changes
|
||||||
* SubGHz: **Nice ON2E (Nice One)** support (by @assasinfil | PR #335)
|
* **Apple BLE Spam app** (by @Willy-JL | Plus research from ECTO-1A, xMasterX and techryptic) -> (app can be found in builds ` `, `e`, `n`, `r`)
|
||||||
* SubGHz: Remove 467.75 From freq analyzer since it has too much noise (Frequency is still can be used, just excluded from FA to avoid false detections)
|
* SubGHz: **FAAC SLH - Programming mode** (by @xMasterX & @Eng1n33r (full research and PoC by @Skorpionm)| PR #585) -> [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
* Archive and FileBrowser: **Fixed more navigation issues** (by @Willy-JL | PR #334)
|
* SubGHz: FAAC SLH -> Add manually new options
|
||||||
* Plugins -> SubGHz Bruteforcer: Fix Linear Delta 3 repeats (now its more stable and we will be sure signal is received correctly)
|
* SubGHz: Fix 0xFFFF counter value being skipped
|
||||||
* Plugins: Updated TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
* SubGHz: Fix path reset on save name scene exit
|
||||||
* OFW: **Fix Cyfral & Metakom emulation (My temp fix removed and proper fix from OFW applied)**
|
* SubGHz: Various fixes
|
||||||
* OFW: BadUSB: disable CDC mode, USB mode switch fix
|
* SubGHz Remote: Fix Sub-GHz Remote folder name (by @OperKH | PR #583)
|
||||||
* OFW: Updater visual fixes
|
* SubGHz Remote: submodule (by @gid9798 | PR #592)
|
||||||
|
* Infrared: Updated universal assets (by @amec0e | PR #594)
|
||||||
|
* Infrared: Remake custom universal remotes to use new design (New icons by @Svaarich)
|
||||||
|
* UI: Keyboard ok to toggle select all in cursor mode (by @Willy-JL)
|
||||||
|
* CI/CD: Fixed regular builds having `c` in version name in the device info while not being actual `c` build
|
||||||
|
* Docs: New FAAC SLH instructions
|
||||||
|
* Docs: Readme & Changelog fixes (by @gid9798 | PR #586)
|
||||||
|
* OFW: iButton: Return to the file selection if file is corrupted
|
||||||
|
* OFW: Account for the "-" in line carry-over
|
||||||
|
* OFW: github: workflow improvements
|
||||||
|
* OFW: Storage: force mount
|
||||||
|
* OFW: Add File Naming setting for more detailed naming -> **Breaking API change, API 35.x -> API 36.x** - **Update your apps!**
|
||||||
|
* OFW: Disconnect from BLE on protobuf error
|
||||||
|
* OFW: Add support for Mifare Classic 4k SAK 0x38 ATQA 0x02, 0x04, 0x08
|
||||||
|
* OFW: Undo some TODO
|
||||||
|
* OFW: Check the filetype of the update manifest
|
||||||
|
* OFW: StorageListRequest: size filter
|
||||||
|
* OFW: SubGhz: heap overflow text error
|
||||||
|
* OFW: nfc: add rfal wrong state error handling
|
||||||
|
* OFW: Rfid: fix crash on broken key launch from archive (fix was already done in UL in similar way)
|
||||||
|
* OFW: AC OFF button
|
||||||
|
* OFW: New IR universal remote graphics
|
||||||
|
* OFW: Intelligent probing with warnings for fwflash.py
|
||||||
|
* OFW: FuriHal: explicitly pull display pins at early init stage, move PUPD config to early stage
|
||||||
|
* OFW: Fix display last symbol in multiline text
|
||||||
|
* OFW: Properly reset the NFC device data
|
||||||
|
* OFW: fbt: various improvements and bug fixes
|
||||||
|
* OFW: Littlefs updated to v2.7.0
|
||||||
|
* OFW: loader: restored support for debug apps
|
||||||
|
* OFW: Removed explicit dependency on scons for external scripting
|
||||||
|
|
||||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
----
|
||||||
|
|
||||||
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||||
|
|
||||||
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
||||||
|
|
||||||
## Please support development of the project
|
## Please support development of the project
|
||||||
* Boosty: https://boosty.to/mmxdev
|
|Service|Remark|Link/Wallet|
|
||||||
* Ko-Fi: https://ko-fi.com/masterx
|
|-|-|-|
|
||||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
|**Patreon**||https://patreon.com/mmxdev|
|
||||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
||||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
||||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||||
|
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||||
|
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
||||||
|
|
||||||
### Thanks to our sponsors:
|
#### Thanks to our sponsors:
|
||||||
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||||
and all other great people who supported our project and me (xMasterX), thanks to you all!
|
and all other great people who supported our project and me (xMasterX), thanks to you all!
|
||||||
|
|
||||||
**Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed**
|
|
||||||
|
|
||||||
**Recommended option - Web Updater**
|
## **Recommended update option - Web Updater**
|
||||||
|
|
||||||
What means `n` or `e` in - `flipper-z-f7-update-(version)(n / e).tgz` ? - `n` means this build comes without our custom animations, only official flipper animations,
|
### What `n`, `r`, `e`, ` `, `c` means? What I need to download if I don't want to use Web updater?
|
||||||
`e` means build has extra apps pack preinstalled
|
What build I should download and what this name means - `flipper-z-f7-update-(version)(n / r / e / c).tgz` ? <br>
|
||||||
|
`flipper-z` = for Flipper Zero device<br>
|
||||||
|
`f7` = Hardware version - same for all flipper zero devices<br>
|
||||||
|
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself<br>
|
||||||
|
`(version)` = Firmware version<br>
|
||||||
|
| Designation | 3 Custom Animation | [Base Apps](https://github.com/xMasterX/all-the-plugins#default-pack) | [Extra Apps](https://github.com/xMasterX/all-the-plugins#extra-pack) | ⚠️RGB mode* |
|
||||||
|
|-----|:---:|:---:|:---:|:---:|
|
||||||
|
| ` ` | ✅ | ✅ | | |
|
||||||
|
| `c` | ✅ | | | |
|
||||||
|
| `n` | | ✅ | | |
|
||||||
|
| `e` | ✅ | ✅ | ✅ | |
|
||||||
|
| `r` | ✅ | ✅ | ✅ | ✅ |
|
||||||
|
|
||||||
|
⚠️This is [hardware mod](https://github.com/quen0n/flipperzero-firmware-rgb#readme), works only on modded flippers! do not install on non modded device!
|
||||||
|
|
||||||
|
Firmware Self-update package (update from microSD) - `flipper-z-f7-update-(version).tgz` for mobile app / qFlipper / web<br>
|
||||||
|
Archive of `scripts` folder (contains scripts for FW/plugins development) - `flipper-z-any-scripts-(version).tgz`<br>
|
||||||
|
SDK files for plugins development and uFBT - `flipper-z-f7-sdk-(version).zip`
|
||||||
|
|
||||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for mobile app / qFlipper
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Almost everything in flipper firmware is built around this concept.
|
|||||||
# C coding style
|
# C coding style
|
||||||
|
|
||||||
- Tab is 4 spaces
|
- Tab is 4 spaces
|
||||||
- Use `fbt format` to reformat source code and check style guide before commit
|
- Use `./fbt format` to reformat source code and check style guide before commit
|
||||||
|
|
||||||
## Naming
|
## Naming
|
||||||
|
|
||||||
|
|||||||
301
ReadMe.md
301
ReadMe.md
@@ -3,64 +3,105 @@
|
|||||||
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
||||||
</a>
|
</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
<div align="center" id="badges">
|
||||||
|
<a href="https://discord.unleashedflip.com">
|
||||||
|
<img src="https://img.shields.io/discord/937479784148115456?style=flat-square&logo=discord&label=Discord&color=%237289DA&link=https%3A%2F%2Fdiscord.unleashedflip.com%2F" alt="Discord server"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://t.me/flipperzero_unofficial">
|
||||||
|
<img src="https://img.shields.io/endpoint?label=EN%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial" alt="EN TG channel"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://t.me/flipperzero_unofficial_ru">
|
||||||
|
<img src="https://img.shields.io/endpoint?label=RU%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ru" alt="RU TG channel"/>
|
||||||
|
</a>
|
||||||
|
<a href="https://t.me/flipperzero_unofficial_ua">
|
||||||
|
<img src="https://img.shields.io/endpoint?label=UA%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ua" alt="UA TG channel"/>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
### Welcome to the Flipper Zero Unleashed Firmware repo!
|
### Welcome to the Flipper Zero Unleashed Firmware repo!
|
||||||
|
|
||||||
**This firmware is a fork from** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
#### **This firmware is a fork from** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
Our goal is to make all features possible on this device without any limitations!
|
### Most stable custom firmware focused on new features and improvements of original firmware components, with almost no UI changes
|
||||||
|
|
||||||
Please help us implement emulation for all Sub-GHz dynamic (rolling code) protocols!
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official devs.
|
##### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official devs.
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
Our Discord Community:
|
|
||||||
<br>
|
|
||||||
<a href="https://discord.unleashedflip.com"><img src="https://discordapp.com/api/guilds/937479784148115456/widget.png?style=banner4" alt="Unofficial Discord Community" target="_blank"></a>
|
|
||||||
|
|
||||||
<br>
|
## Dev builds (unstable)
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## Dev builds
|
|
||||||
- https://dev.unleashedflip.com/
|
- https://dev.unleashedflip.com/
|
||||||
- https://t.me/kotnehleb
|
- https://t.me/kotnehleb
|
||||||
## Releases in Telegram
|
## Releases in Telegram
|
||||||
- https://t.me/unleashed_fw
|
- https://t.me/unleashed_fw
|
||||||
|
|
||||||
# What's changed
|
# What's changed
|
||||||
* Sub-GHz regional TX restrictions removed
|
- **Sub-GHz** *lib & hal*
|
||||||
* Sub-GHz frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
- Regional TX restrictions removed
|
||||||
* Many rolling code protocols now have the ability to save & send captured signals
|
- Extra Sub-GHz frequencies
|
||||||
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
|
- Frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||||
* Sub-GHz static code brute-force plugin
|
- Many rolling code [protocols](https://github.com/DarkFlippers/unleashed-firmware#current-modified-and-new-sub-ghz-protocols-list) now have the ability to save & send captured signals
|
||||||
* LFRFID Fuzzer plugin
|
- FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation
|
||||||
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
- External CC1101 module support [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||||
* Extra Sub-GHz frequencies + extra Mifare Classic keys
|
- **Sub-GHz** *Main App*
|
||||||
* Picopass/iClass plugin included in releases
|
- Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||||
* Recompiled IR TV Universal Remote for ALL buttons
|
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||||
* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
|
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||||
* BadUSB keyboard layouts
|
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||||
* Customizable Flipper name
|
- New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
|
||||||
* Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes
|
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
||||||
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu
|
- External CC1101 module support (Hardware SPI used)
|
||||||
* Sub-GHz -> External CC1101 module support
|
- **Hold right in received signal list to delete selected signal**
|
||||||
* Other small fixes and changes throughout
|
- **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0 / CAME Atomo** - now you can use arrow buttons to send signal with different button code
|
||||||
* See other changes in changelog and in readme below
|
- `Add manually` menu extended with new protocols
|
||||||
|
- FAAC SLH, BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis)
|
||||||
|
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
||||||
|
- Debug PIN output settings for protocol development
|
||||||
|
|
||||||
Also check the changelog in releases for latest updates!
|
- **Sub-GHz apps** *by unleashed team*
|
||||||
|
- Sub-GHz Bruteforce - static code brute-force plugin |
|
||||||
|
- Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol
|
||||||
|
- Load your own file and select bytes you want to bruteforce or use preconfigured options in protocols list
|
||||||
|
- Sub-GHz Remote - remote control for 5 sub-ghz files | bind one file for each button
|
||||||
|
- use the built-in constructor or make config file by following this [instruction](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||||
|
- **Infrared**
|
||||||
|
- Recompiled IR TV Universal Remote for ALL buttons
|
||||||
|
- Universal remotes for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -> Also always updated and verified by our team
|
||||||
|
- Infrared -> `RCA` Protocol
|
||||||
|
- Infrared -> Debug TX PIN output settings
|
||||||
|
- **NFC/RFID/iButton**
|
||||||
|
* LFRFID/iButton Fuzzer plugins
|
||||||
|
* Extra Mifare Classic keys
|
||||||
|
* `Add manually` -> Mifare Classic with custom UID
|
||||||
|
* Picopass/iClass plugin (now with emulation support!) included in releases
|
||||||
|
- **Quality of life & other features**
|
||||||
|
- Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL)
|
||||||
|
- Text Input UI element -> Cursor feature (by @Willy-JL)
|
||||||
|
- Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears
|
||||||
|
- Clock on Desktop -> `Settings -> Desktop -> Show Clock`
|
||||||
|
- Battery percentage display with different styles `Settings -> Desktop -> Battery View`
|
||||||
|
- More games in Dummy Mode -> click or hold any of arrow buttons
|
||||||
|
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
||||||
|
- **BadBT** plugin (BT version of BadKB) [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/ClaraCrazy/Flipper-Xtreme/tree/dev/applications/main/bad_kb) - (See in Applications->Tools) - (aka BadUSB via Bluetooth)
|
||||||
|
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||||
|
- Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||||
|
- Other small fixes and changes throughout
|
||||||
|
- See other changes in readme below
|
||||||
|
|
||||||
|
Also check the [changelog in releases](https://github.com/DarkFlippers/unleashed-firmware/releases) for latest updates!
|
||||||
|
|
||||||
### Current modified and new Sub-GHz protocols list:
|
### Current modified and new Sub-GHz protocols list:
|
||||||
Thanks to Official team (to thier SubGHz Developer, Skorp) for implementing decoders for these protocols.
|
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW.
|
||||||
|
|
||||||
Encoders/sending made by Eng1n33r & @xMasterX:
|
Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||||
|
|
||||||
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
Encoders or sending made by @xMasterX:
|
||||||
|
- Nero Radio 57bit (+ 56bit encoder improvements)
|
||||||
|
- CAME 12bit/24bit encoder fixes (Fixes now merged in OFW)
|
||||||
- Keeloq: HCS101
|
- Keeloq: HCS101
|
||||||
- Keeloq: AN-Motors
|
- Keeloq: AN-Motors
|
||||||
- Keeloq: JCM Tech
|
- Keeloq: JCM Tech
|
||||||
@@ -70,159 +111,134 @@ Encoders/sending made by Eng1n33r & @xMasterX:
|
|||||||
- Keeloq: FAAC RC,XT
|
- Keeloq: FAAC RC,XT
|
||||||
- Keeloq: Mutancode
|
- Keeloq: Mutancode
|
||||||
- Keeloq: Normstahl
|
- Keeloq: Normstahl
|
||||||
- CAME Atomo
|
- Keeloq: Beninca + Allmatic
|
||||||
- Nice Flor S
|
- Keeloq: Stilmatic
|
||||||
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
- Keeloq: CAME Space
|
||||||
- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
- Keeloq: Aprimatic (model TR and similar)
|
||||||
- Security+ v1 & v2
|
- Keeloq: Centurion Nova (thanks Carlos !)
|
||||||
|
|
||||||
|
Encoders or sending made by @Eng1n33r(first implementation in Q2 2022) & @xMasterX (current version):
|
||||||
|
- CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
|
- Nice Flor S -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
|
- FAAC SLH (Spa) -> Update!!! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
|
- Keeloq: BFT Mitto -> Update! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
- Star Line
|
- Star Line
|
||||||
|
- Security+ v1 & v2 (encoders was made in OFW)
|
||||||
|
|
||||||
Encoders made by @assasinfil & @xMasterX:
|
Encoders made by @assasinfil & @xMasterX:
|
||||||
- Somfy Telis
|
- Somfy Telis -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
- Somfy Keytis
|
- Somfy Keytis
|
||||||
- KingGates Stylo 4k
|
- KingGates Stylo 4k
|
||||||
- Alutech AT-4N
|
- Alutech AT-4N -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
- Nice ON2E (Nice One)
|
- Nice ON2E (Nice One) -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
|
|
||||||
## Please support development of the project
|
## Please support development of the project
|
||||||
The majority of this project is developed and maintained by me, @xMasterX.
|
The majority of this project is developed and maintained by me, @xMasterX.
|
||||||
I'm unemployed because of the war, and the only income I receive is from your donations.
|
I'm unemployed, and the only income I receive is from your donations.
|
||||||
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
|
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
|
||||||
- @assasinfil - SubGHz
|
- @gid9798 - SubGHz, Plugins, many other things
|
||||||
|
- @assasinfil - SubGHz protocols
|
||||||
- @Svaarich - UI design and animations
|
- @Svaarich - UI design and animations
|
||||||
- @Amec0e - Infrared assets
|
- @amec0e & @Leptopt1los - Infrared assets
|
||||||
- Community moderators in Telegram, Discord, and Reddit
|
- Community moderators in Telegram, Discord, and Reddit
|
||||||
- And of course our GitHub community. Your PRs are a very important part of this firmware and open-source development.
|
- And of course our GitHub community. Your PRs are a very important part of this firmware and open-source development.
|
||||||
|
|
||||||
The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time.
|
The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time.
|
||||||
Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen.
|
Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen.
|
||||||
You can support us by using links or addresses below:
|
You can support us by using links or addresses below:
|
||||||
* Boosty: https://boosty.to/mmxdev
|
|Service|Remark|Link/Wallet|
|
||||||
* Ko-Fi: https://ko-fi.com/masterx
|
|-|-|-|
|
||||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
|**Patreon**||https://patreon.com/mmxdev|
|
||||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
|**Boosty**|patreon alternative|https://boosty.to/mmxdev|
|
||||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
|cloudtips|only RU payments accepted|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
|YooMoney|only RU payments accepted|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
|USDT|(TRC20)|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
|BCH||`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
|ETH|(BSC/ERC20-Tokens)|`darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)|
|
||||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
|BTC||`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
|DOGE||`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
|LTC||`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||||
|
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||||
|
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
||||||
|
|
||||||
### Community apps included:
|
## Community apps included
|
||||||
|
|
||||||
- **RFID Fuzzer** [(by Ganapati & @xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/54) & New protocols by @mvanzanten
|
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||||
- **Sub-GHz bruteforcer** [(by @derskythe & xMasterX)](https://github.com/derskythe/flipperzero-subbrute) [(original by Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57)
|
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Deafult)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
||||||
- **Sub-GHz playlist** [(by darmiel)](https://github.com/DarkFlippers/unleashed-firmware/pull/62)
|
|
||||||
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
|
|
||||||
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
|
|
||||||
- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
|
|
||||||
- USB Keyboard plugin [(by huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard)
|
|
||||||
- WAV Player [(OFW: DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) - Fixed and improved by [LTVA1](https://github.com/LTVA1/wav_player)
|
|
||||||
- Barcode generator plugin [(original by McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) - [EAN-8 and refactoring](https://github.com/DarkFlippers/unleashed-firmware/pull/154) by @msvsergey
|
|
||||||
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
|
|
||||||
- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
|
|
||||||
- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
|
|
||||||
- Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
|
|
||||||
- **Sub-GHz Remote** (UniversalRF Remix) [(by @darmiel & @xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols) (original by @ESurge)
|
|
||||||
- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
|
|
||||||
- Metronome [(by panki27)](https://github.com/panki27/Metronome)
|
|
||||||
- DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin)
|
|
||||||
- **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
|
||||||
- GPS [(by ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper)
|
|
||||||
- i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only!
|
|
||||||
- HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo)
|
|
||||||
- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP)
|
|
||||||
- **Unitemp - Temperature sensors reader** (DHT11/22, DS18B20, BMP280, HTU21x and more) [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero)
|
|
||||||
- BH1750 - Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
|
||||||
- **iButton Fuzzer** [(by xMasterX)](https://github.com/xMasterX/ibutton-fuzzer)
|
|
||||||
- HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer)
|
|
||||||
- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager)
|
|
||||||
- Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)
|
|
||||||
- **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main)
|
|
||||||
- **ProtoView** [(by antirez)](https://github.com/antirez/protoview)
|
|
||||||
|
|
||||||
Games:
|
See full list and sources here: [xMasterX/all-the-plugin](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
||||||
- DOOM (fixed) [(by p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
|
|
||||||
- Zombiez [(Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez)
|
|
||||||
- Flappy Bird [(by DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird)
|
|
||||||
- Arkanoid (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
|
||||||
- Tic Tac Toe (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
|
||||||
- Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
|
|
||||||
- Minesweeper [(by panki27)](https://github.com/panki27/minesweeper)
|
|
||||||
- Heap Defence (aka Stack Attack) - Ported to latest firmware by @xMasterX - [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki)
|
|
||||||
- Game15 [(by x27)](https://github.com/x27/flipperzero-game15)
|
|
||||||
- Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games)
|
|
||||||
- BlackJack [(by teeebor)](https://github.com/teeebor/flipper_games)
|
|
||||||
- 2048 game [(by eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game)
|
|
||||||
|
|
||||||
### Other changes
|
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
||||||
|
|
||||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
|
||||||
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
|
||||||
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
|
||||||
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
|
||||||
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
|
||||||
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
|
||||||
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
## [- How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
## First lock official docs [docs.flipper.net](https://docs.flipper.net/)
|
||||||
|
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#what-n-r-e--c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater): `n`,` `,`e`...
|
||||||
|
## Firmware & Development
|
||||||
|
|
||||||
## [- How to build firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md)
|
### - **[How to build](/documentation/HowToBuild.md#how-to-build-by-yourself) | [Project-structure](#project-structure)**
|
||||||
|
|
||||||
## [- How to connect external CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
### - **CLion IDE** - How to setup workspace for flipper firmware development [by Savely Krasovsky](https://krasovs.ky/2022/11/01/flipper-zero-clion.html)
|
||||||
|
|
||||||
## [- BadUSB: how to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
### - **"Hello world!"** - plugin tutorial [English<sub> by DroomOne</sub> ](https://github.com/DroomOne/Flipper-Plugin-Tutorial) | [Russian<sub> by Pavel Yakovlev</sub>](https://yakovlev.me/hello-flipper-zero/)
|
||||||
|
|
||||||
## [- How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
### - [How to write your own app](https://flipper.atmanos.com/docs/overview/intro). Docs by atmanos **⚠️outdated API**
|
||||||
|
|
||||||
### **Plugins**
|
## Firmware & main Apps feature
|
||||||
|
|
||||||
## [- 🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/unleashed-extra-pack)
|
### - System: [How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||||
|
|
||||||
## [- Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
### - BadUSB: [How to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||||
|
|
||||||
## [- TOTP (Authenticator) config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
### - Infrared: [How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
||||||
|
|
||||||
## [- Barcode Generator](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
## **Sub-GHz**
|
||||||
|
|
||||||
## [- Multi Converter](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||||
|
|
||||||
## [- WAV Player sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||||
|
|
||||||
## [- Sub-GHz playlist generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||||
|
|
||||||
### **Plugins that works with external hardware**
|
### - [How to use Flipper as new remote (Nice FlorS, BFT Mitto, Somfy Telis, Aprimatic, AN-Motors, etc..)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
|
|
||||||
## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme)
|
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recomeded, please use embedded configurator
|
||||||
|
|
||||||
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/gps_nmea_uart/README.md)
|
## **Plugins**
|
||||||
|
|
||||||
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/flipper_i2ctools/README.md)
|
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||||
|
|
||||||
## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
### - Mifare Nested plugin: [How to recover keys](https://github.com/AloneLiberty/FlipperNested#how-to-use-it)
|
||||||
|
|
||||||
## [- How to use: [WiFi] Scanner](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme)
|
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||||
|
|
||||||
## [- How to use: [ESP8266] Deauther](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme)
|
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||||
|
|
||||||
## [- How to use: [ESP32] WiFi Marauder](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)
|
### - WAV Player: [sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||||
|
|
||||||
## [- [WiFi] Scanner - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
### - Sub-GHz playlist: [generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||||
|
|
||||||
## [- [ESP8266] Deauther - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
## **Plugins that works with external hardware** [GPIO]
|
||||||
|
|
||||||
## [- Windows: How to Upload .bin to ESP32/ESP8266](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32)
|
### - Unitemp - Temperature sensors reader: [How to use & supported sensors](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||||
|
|
||||||
## [- How to use: [GPIO] SentrySafe plugin](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
### - [NMEA] GPS: [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/gps_nmea_uart/README.md)
|
||||||
|
|
||||||
### **Sub-GHz**
|
### - i2c Tools [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/flipper_i2ctools/README.md)
|
||||||
|
|
||||||
## [- Transmission is blocked? - How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
### - [NRF24] plugins: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||||
|
|
||||||
## [- How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
|
||||||
|
### - [WiFi] Scanner: [How to use](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
||||||
|
|
||||||
|
### - [ESP8266] Deauther: [How to use](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
||||||
|
|
||||||
|
### - [ESP32] WiFi Marauder: [How to use](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)<sub> docs by UberGuidoZ</sub> | [Marauder repo](https://github.com/justcallmekoko/ESP32Marauder)
|
||||||
|
|
||||||
|
### - [ESP32-CAM] Camera Suite: [How to use](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
||||||
|
|
||||||
|
### - How to Upload `.bin` to ESP32/ESP8266: [Windows](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32) | [FAP "ESP flasher"](https://github.com/0xchocolate/flipperzero-esp-flasher)
|
||||||
|
|
||||||
|
### - [GPIO] SentrySafe plugin: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
@@ -230,18 +246,13 @@ Games:
|
|||||||
# Where I can find IR, Sub-GHz, ... files, DBs, and other stuff?
|
# Where I can find IR, Sub-GHz, ... files, DBs, and other stuff?
|
||||||
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
||||||
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
||||||
## [CAME-12bit, NICE-12bit, Linear-10bit, PT-2240 - Sub-GHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
|
|
||||||
## [SMC5326, UNILARM - Sub-GHz fixed code bruteforce](https://github.com/Hong5489/flipperzero-gate-bruteforce)
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
# Links
|
# Links
|
||||||
|
|
||||||
* Unofficial Discord: [discord.unleashedflip.com](https://discord.unleashedflip.com)
|
* Official Docs: [docs.flipper.net](https://docs.flipper.net/)
|
||||||
* Docs by atmanos / How to write your own app (outdated API): [https://flipper.atmanos.com/docs/overview/intro](https://flipper.atmanos.com/docs/overview/intro)
|
|
||||||
|
|
||||||
* Official Docs: [http://docs.flipperzero.one](http://docs.flipperzero.one)
|
|
||||||
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
||||||
|
|
||||||
# Project structure
|
# Project structure
|
||||||
|
|||||||
88
SConstruct
88
SConstruct
@@ -45,6 +45,7 @@ distenv = coreenv.Clone(
|
|||||||
],
|
],
|
||||||
ENV=os.environ,
|
ENV=os.environ,
|
||||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||||
|
VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"),
|
||||||
)
|
)
|
||||||
|
|
||||||
firmware_env = distenv.AddFwProject(
|
firmware_env = distenv.AddFwProject(
|
||||||
@@ -139,40 +140,39 @@ if GetOption("fullenv") or any(
|
|||||||
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
||||||
distenv.Default(basic_dist)
|
distenv.Default(basic_dist)
|
||||||
|
|
||||||
dist_dir = distenv.GetProjetDirName()
|
dist_dir_name = distenv.GetProjectDirName()
|
||||||
|
dist_dir = distenv.Dir(f"#/dist/{dist_dir_name}")
|
||||||
|
external_apps_artifacts = firmware_env["FW_EXTAPPS"]
|
||||||
|
external_app_list = external_apps_artifacts.application_map.values()
|
||||||
|
|
||||||
fap_dist = [
|
fap_dist = [
|
||||||
distenv.Install(
|
distenv.Install(
|
||||||
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
|
dist_dir.Dir("debug_elf"),
|
||||||
list(
|
list(app_artifact.debug for app_artifact in external_app_list),
|
||||||
app_artifact.debug
|
|
||||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
*(
|
*(
|
||||||
distenv.Install(
|
distenv.Install(
|
||||||
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
|
dist_dir.File(dist_entry[1]).dir,
|
||||||
app_artifact.compact[0],
|
app_artifact.compact,
|
||||||
)
|
)
|
||||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
for app_artifact in external_app_list
|
||||||
|
for dist_entry in app_artifact.dist_entries
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
Depends(
|
Depends(
|
||||||
fap_dist,
|
fap_dist,
|
||||||
list(
|
list(app_artifact.validator for app_artifact in external_app_list),
|
||||||
app_artifact.validator
|
|
||||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
Alias("fap_dist", fap_dist)
|
Alias("fap_dist", fap_dist)
|
||||||
# distenv.Default(fap_dist)
|
# distenv.Default(fap_dist)
|
||||||
|
|
||||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
distenv.Depends(firmware_env["FW_RESOURCES"], external_apps_artifacts.resources_dist)
|
||||||
|
|
||||||
# Copy all faps to device
|
# Copy all faps to device
|
||||||
|
|
||||||
fap_deploy = distenv.PhonyTarget(
|
fap_deploy = distenv.PhonyTarget(
|
||||||
"fap_deploy",
|
"fap_deploy",
|
||||||
"${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
|
"${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py -p ${FLIP_PORT} send ${SOURCE} /ext/apps",
|
||||||
source=Dir("#/assets/resources/apps"),
|
source=Dir("#/assets/resources/apps"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -185,27 +185,15 @@ copro_dist = distenv.CoproBuilder(
|
|||||||
distenv.AlwaysBuild(copro_dist)
|
distenv.AlwaysBuild(copro_dist)
|
||||||
distenv.Alias("copro_dist", copro_dist)
|
distenv.Alias("copro_dist", copro_dist)
|
||||||
|
|
||||||
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
|
||||||
|
firmware_flash = distenv.AddFwFlashTarget(firmware_env)
|
||||||
distenv.Alias("flash", firmware_flash)
|
distenv.Alias("flash", firmware_flash)
|
||||||
|
|
||||||
|
# To be implemented in fwflash.py
|
||||||
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
||||||
distenv.Alias("jflash", firmware_jflash)
|
distenv.Alias("jflash", firmware_jflash)
|
||||||
|
|
||||||
firmware_bm_flash = distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"flash_blackmagic",
|
|
||||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
|
||||||
source=firmware_env["FW_ELF"],
|
|
||||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
|
||||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
|
||||||
GDBFLASH=[
|
|
||||||
"-ex",
|
|
||||||
"load",
|
|
||||||
"-ex",
|
|
||||||
"quit",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
gdb_backtrace_all_threads = distenv.PhonyTarget(
|
|
||||||
"gdb_trace_all",
|
"gdb_trace_all",
|
||||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||||
source=firmware_env["FW_ELF"],
|
source=firmware_env["FW_ELF"],
|
||||||
@@ -240,19 +228,31 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Debug alien elf
|
# Debug alien elf
|
||||||
|
debug_other_opts = [
|
||||||
|
"-ex",
|
||||||
|
"source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py",
|
||||||
|
# "-ex",
|
||||||
|
# "source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py",
|
||||||
|
"-ex",
|
||||||
|
"source ${FBT_DEBUG_DIR}/flipperversion.py",
|
||||||
|
"-ex",
|
||||||
|
"fw-version",
|
||||||
|
]
|
||||||
|
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"debug_other",
|
"debug_other",
|
||||||
"${GDBPYCOM}",
|
"${GDBPYCOM}",
|
||||||
GDBOPTS="${GDBOPTS_BASE}",
|
GDBOPTS="${GDBOPTS_BASE}",
|
||||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||||
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
|
GDBPYOPTS=debug_other_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"debug_other_blackmagic",
|
"debug_other_blackmagic",
|
||||||
"${GDBPYCOM}",
|
"${GDBPYCOM}",
|
||||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||||
GDBREMOTE="$${BLACKMAGIC_ADDR}",
|
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||||
|
GDBPYOPTS=debug_other_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -312,7 +312,12 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Start Flipper CLI via PySerial's miniterm
|
# Start Flipper CLI via PySerial's miniterm
|
||||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
distenv.PhonyTarget(
|
||||||
|
"cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update WiFi devboard firmware
|
||||||
|
distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py")
|
||||||
|
|
||||||
|
|
||||||
# Find blackmagic probe
|
# Find blackmagic probe
|
||||||
@@ -332,7 +337,20 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Prepare vscode environment
|
# Prepare vscode environment
|
||||||
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"]
|
||||||
|
vscode_dist = distenv.Install(
|
||||||
|
"#.vscode",
|
||||||
|
[
|
||||||
|
distenv.Glob("#.vscode/example/*.json"),
|
||||||
|
distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"),
|
||||||
|
],
|
||||||
|
)
|
||||||
distenv.Precious(vscode_dist)
|
distenv.Precious(vscode_dist)
|
||||||
distenv.NoClean(vscode_dist)
|
distenv.NoClean(vscode_dist)
|
||||||
distenv.Alias("vscode_dist", vscode_dist)
|
distenv.Alias("vscode_dist", vscode_dist)
|
||||||
|
|
||||||
|
# Configure shell with build tools
|
||||||
|
distenv.PhonyTarget(
|
||||||
|
"env",
|
||||||
|
"@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)",
|
||||||
|
)
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ Applications for main Flipper menu.
|
|||||||
|
|
||||||
- `archive` - Archive and file manager
|
- `archive` - Archive and file manager
|
||||||
- `bad_usb` - Bad USB application
|
- `bad_usb` - Bad USB application
|
||||||
- `fap_loader` - External applications loader
|
|
||||||
- `gpio` - GPIO application: includes USART bridge and GPIO control
|
- `gpio` - GPIO application: includes USART bridge and GPIO control
|
||||||
- `ibutton` - iButton application, onewire keys and more
|
- `ibutton` - iButton application, onewire keys and more
|
||||||
- `infrared` - Infrared application, controls your IR devices
|
- `infrared` - Infrared application, controls your IR devices
|
||||||
@@ -36,16 +35,6 @@ Applications for main Flipper menu.
|
|||||||
- `u2f` - U2F Application
|
- `u2f` - U2F Application
|
||||||
|
|
||||||
|
|
||||||
## plugins
|
|
||||||
|
|
||||||
Extra apps for Plugins & App Loader menus.
|
|
||||||
|
|
||||||
- `bt_hid_app` - BT Remote controller
|
|
||||||
- `music_player` - Music player app (demo)
|
|
||||||
- `picopass` - Picopass tool
|
|
||||||
- `snake_game` - Snake game application
|
|
||||||
|
|
||||||
|
|
||||||
## services
|
## services
|
||||||
|
|
||||||
Background services providing system APIs to applications.
|
Background services providing system APIs to applications.
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ void AccessorApp::run(void) {
|
|||||||
AccessorApp::AccessorApp()
|
AccessorApp::AccessorApp()
|
||||||
: text_store{0} {
|
: text_store{0} {
|
||||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||||
onewire_host = onewire_host_alloc(&ibutton_gpio);
|
onewire_host = onewire_host_alloc(&gpio_ibutton);
|
||||||
furi_hal_power_enable_otg();
|
furi_hal_power_enable_otg();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle validation failure case!
|
// TODO FL-3490: Handle validation failure case!
|
||||||
} else if(4 == _bitCount) {
|
} else if(4 == _bitCount) {
|
||||||
// 4-bit Wiegand codes have no data integrity check so we just
|
// 4-bit Wiegand codes have no data integrity check so we just
|
||||||
// read the LOW nibble.
|
// read the LOW nibble.
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ App(
|
|||||||
"vibro_test",
|
"vibro_test",
|
||||||
"keypad_test",
|
"keypad_test",
|
||||||
"usb_test",
|
"usb_test",
|
||||||
"USB_Mouse",
|
"usb_mouse",
|
||||||
"UART_Echo",
|
"uart_echo",
|
||||||
"display_test",
|
"display_test",
|
||||||
"text_box_test",
|
"text_box_test",
|
||||||
"file_browser_test",
|
"file_browser_test",
|
||||||
|
"speaker_debug",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
10
applications/debug/crash_test/application.fam
Normal file
10
applications/debug/crash_test/application.fam
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
App(
|
||||||
|
appid="crash_test",
|
||||||
|
name="Crash Test",
|
||||||
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
entry_point="crash_test_app",
|
||||||
|
cdefines=["APP_CRASH_TEST"],
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_category="Debug",
|
||||||
|
)
|
||||||
128
applications/debug/crash_test/crash_test.c
Normal file
128
applications/debug/crash_test/crash_test.c
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#include <furi_hal.h>
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
|
||||||
|
#define TAG "CrashTest"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
Submenu* submenu;
|
||||||
|
} CrashTest;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CrashTestViewSubmenu,
|
||||||
|
} CrashTestView;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CrashTestSubmenuCheck,
|
||||||
|
CrashTestSubmenuCheckMessage,
|
||||||
|
CrashTestSubmenuAssert,
|
||||||
|
CrashTestSubmenuAssertMessage,
|
||||||
|
CrashTestSubmenuCrash,
|
||||||
|
CrashTestSubmenuHalt,
|
||||||
|
} CrashTestSubmenu;
|
||||||
|
|
||||||
|
static void crash_test_submenu_callback(void* context, uint32_t index) {
|
||||||
|
CrashTest* instance = (CrashTest*)context;
|
||||||
|
UNUSED(instance);
|
||||||
|
|
||||||
|
switch(index) {
|
||||||
|
case CrashTestSubmenuCheck:
|
||||||
|
furi_check(false);
|
||||||
|
break;
|
||||||
|
case CrashTestSubmenuCheckMessage:
|
||||||
|
furi_check(false, "Crash test: furi_check with message");
|
||||||
|
break;
|
||||||
|
case CrashTestSubmenuAssert:
|
||||||
|
furi_assert(false);
|
||||||
|
break;
|
||||||
|
case CrashTestSubmenuAssertMessage:
|
||||||
|
furi_assert(false, "Crash test: furi_assert with message");
|
||||||
|
break;
|
||||||
|
case CrashTestSubmenuCrash:
|
||||||
|
furi_crash("Crash test: furi_crash");
|
||||||
|
break;
|
||||||
|
case CrashTestSubmenuHalt:
|
||||||
|
furi_halt("Crash test: furi_halt");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
furi_crash("Programming error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t crash_test_exit_callback(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
return VIEW_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CrashTest* crash_test_alloc() {
|
||||||
|
CrashTest* instance = malloc(sizeof(CrashTest));
|
||||||
|
|
||||||
|
View* view = NULL;
|
||||||
|
|
||||||
|
instance->gui = furi_record_open(RECORD_GUI);
|
||||||
|
instance->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
view_dispatcher_enable_queue(instance->view_dispatcher);
|
||||||
|
view_dispatcher_attach_to_gui(
|
||||||
|
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
instance->submenu = submenu_alloc();
|
||||||
|
view = submenu_get_view(instance->submenu);
|
||||||
|
view_set_previous_callback(view, crash_test_exit_callback);
|
||||||
|
view_dispatcher_add_view(instance->view_dispatcher, CrashTestViewSubmenu, view);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu, "Check", CrashTestSubmenuCheck, crash_test_submenu_callback, instance);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu,
|
||||||
|
"Check with message",
|
||||||
|
CrashTestSubmenuCheckMessage,
|
||||||
|
crash_test_submenu_callback,
|
||||||
|
instance);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu, "Assert", CrashTestSubmenuAssert, crash_test_submenu_callback, instance);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu,
|
||||||
|
"Assert with message",
|
||||||
|
CrashTestSubmenuAssertMessage,
|
||||||
|
crash_test_submenu_callback,
|
||||||
|
instance);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
|
||||||
|
submenu_add_item(
|
||||||
|
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void crash_test_free(CrashTest* instance) {
|
||||||
|
view_dispatcher_remove_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||||
|
submenu_free(instance->submenu);
|
||||||
|
|
||||||
|
view_dispatcher_free(instance->view_dispatcher);
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t crash_test_run(CrashTest* instance) {
|
||||||
|
view_dispatcher_switch_to_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||||
|
view_dispatcher_run(instance->view_dispatcher);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t crash_test_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
CrashTest* instance = crash_test_alloc();
|
||||||
|
|
||||||
|
int32_t ret = crash_test_run(instance);
|
||||||
|
|
||||||
|
crash_test_free(instance);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ typedef struct {
|
|||||||
uint16_t left;
|
uint16_t left;
|
||||||
uint16_t right;
|
uint16_t right;
|
||||||
uint16_t ok;
|
uint16_t ok;
|
||||||
|
FuriMutex* mutex;
|
||||||
} KeypadTestState;
|
} KeypadTestState;
|
||||||
|
|
||||||
static void keypad_test_reset_state(KeypadTestState* state) {
|
static void keypad_test_reset_state(KeypadTestState* state) {
|
||||||
@@ -22,7 +23,8 @@ static void keypad_test_reset_state(KeypadTestState* state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex((ValueMutex*)ctx, 25);
|
KeypadTestState* state = ctx;
|
||||||
|
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||||
canvas_clear(canvas);
|
canvas_clear(canvas);
|
||||||
char strings[5][20];
|
char strings[5][20];
|
||||||
|
|
||||||
@@ -51,7 +53,7 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
|||||||
|
|
||||||
canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit");
|
canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit");
|
||||||
|
|
||||||
release_mutex((ValueMutex*)ctx, state);
|
furi_mutex_release(state->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
|
static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||||
@@ -64,17 +66,17 @@ int32_t keypad_test_app(void* p) {
|
|||||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||||
furi_check(event_queue);
|
furi_check(event_queue);
|
||||||
|
|
||||||
KeypadTestState _state = {{false, false, false, false, false}, 0, 0, 0, 0, 0};
|
KeypadTestState state = {{false, false, false, false, false}, 0, 0, 0, 0, 0, NULL};
|
||||||
|
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
|
|
||||||
ValueMutex state_mutex;
|
if(!state.mutex) {
|
||||||
if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) {
|
|
||||||
FURI_LOG_E(TAG, "cannot create mutex");
|
FURI_LOG_E(TAG, "cannot create mutex");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
|
|
||||||
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state_mutex);
|
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state);
|
||||||
view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue);
|
view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// Open GUI and register view_port
|
||||||
@@ -83,7 +85,7 @@ int32_t keypad_test_app(void* p) {
|
|||||||
|
|
||||||
InputEvent event;
|
InputEvent event;
|
||||||
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex_block(&state_mutex);
|
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
"key: %s type: %s",
|
"key: %s type: %s",
|
||||||
@@ -92,54 +94,54 @@ int32_t keypad_test_app(void* p) {
|
|||||||
|
|
||||||
if(event.key == InputKeyRight) {
|
if(event.key == InputKeyRight) {
|
||||||
if(event.type == InputTypePress) {
|
if(event.type == InputTypePress) {
|
||||||
state->press[0] = true;
|
state.press[0] = true;
|
||||||
} else if(event.type == InputTypeRelease) {
|
} else if(event.type == InputTypeRelease) {
|
||||||
state->press[0] = false;
|
state.press[0] = false;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
++state->right;
|
++state.right;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyLeft) {
|
} else if(event.key == InputKeyLeft) {
|
||||||
if(event.type == InputTypePress) {
|
if(event.type == InputTypePress) {
|
||||||
state->press[1] = true;
|
state.press[1] = true;
|
||||||
} else if(event.type == InputTypeRelease) {
|
} else if(event.type == InputTypeRelease) {
|
||||||
state->press[1] = false;
|
state.press[1] = false;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
++state->left;
|
++state.left;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyUp) {
|
} else if(event.key == InputKeyUp) {
|
||||||
if(event.type == InputTypePress) {
|
if(event.type == InputTypePress) {
|
||||||
state->press[2] = true;
|
state.press[2] = true;
|
||||||
} else if(event.type == InputTypeRelease) {
|
} else if(event.type == InputTypeRelease) {
|
||||||
state->press[2] = false;
|
state.press[2] = false;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
++state->up;
|
++state.up;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyDown) {
|
} else if(event.key == InputKeyDown) {
|
||||||
if(event.type == InputTypePress) {
|
if(event.type == InputTypePress) {
|
||||||
state->press[3] = true;
|
state.press[3] = true;
|
||||||
} else if(event.type == InputTypeRelease) {
|
} else if(event.type == InputTypeRelease) {
|
||||||
state->press[3] = false;
|
state.press[3] = false;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
++state->down;
|
++state.down;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyOk) {
|
} else if(event.key == InputKeyOk) {
|
||||||
if(event.type == InputTypePress) {
|
if(event.type == InputTypePress) {
|
||||||
state->press[4] = true;
|
state.press[4] = true;
|
||||||
} else if(event.type == InputTypeRelease) {
|
} else if(event.type == InputTypeRelease) {
|
||||||
state->press[4] = false;
|
state.press[4] = false;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
++state->ok;
|
++state.ok;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyBack) {
|
} else if(event.key == InputKeyBack) {
|
||||||
if(event.type == InputTypeLong) {
|
if(event.type == InputTypeLong) {
|
||||||
release_mutex(&state_mutex, state);
|
furi_mutex_release(state.mutex);
|
||||||
break;
|
break;
|
||||||
} else if(event.type == InputTypeShort) {
|
} else if(event.type == InputTypeShort) {
|
||||||
keypad_test_reset_state(state);
|
keypad_test_reset_state(&state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release_mutex(&state_mutex, state);
|
furi_mutex_release(state.mutex);
|
||||||
view_port_update(view_port);
|
view_port_update(view_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +149,7 @@ int32_t keypad_test_app(void* p) {
|
|||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
furi_mutex_free(state.mutex);
|
||||||
|
|
||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ static void comparator_trigger_callback(bool level, void* comp_ctx) {
|
|||||||
furi_hal_gpio_write(&gpio_ext_pa7, !level);
|
furi_hal_gpio_write(&gpio_ext_pa7, !level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lfrfid_debug_view_tune_callback(void* context) {
|
||||||
|
LfRfidDebug* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, 0xBA);
|
||||||
|
}
|
||||||
|
|
||||||
void lfrfid_debug_scene_tune_on_enter(void* context) {
|
void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||||
LfRfidDebug* app = context;
|
LfRfidDebug* app = context;
|
||||||
|
|
||||||
@@ -14,9 +19,9 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
|
|||||||
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
|
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
|
||||||
furi_hal_rfid_comp_start();
|
furi_hal_rfid_comp_start();
|
||||||
|
|
||||||
furi_hal_rfid_pins_read();
|
furi_hal_rfid_tim_read_start(125000, 0.5);
|
||||||
furi_hal_rfid_tim_read(125000, 0.5);
|
|
||||||
furi_hal_rfid_tim_read_start();
|
lfrfid_debug_view_tune_set_callback(app->tune_view, lfrfid_debug_view_tune_callback, app);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
|
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
|
||||||
}
|
}
|
||||||
@@ -43,6 +48,5 @@ void lfrfid_debug_scene_tune_on_exit(void* context) {
|
|||||||
|
|
||||||
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
||||||
furi_hal_rfid_tim_read_stop();
|
furi_hal_rfid_tim_read_stop();
|
||||||
furi_hal_rfid_tim_reset();
|
|
||||||
furi_hal_rfid_pins_reset();
|
furi_hal_rfid_pins_reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ typedef struct {
|
|||||||
uint32_t ARR;
|
uint32_t ARR;
|
||||||
uint32_t CCR;
|
uint32_t CCR;
|
||||||
int pos;
|
int pos;
|
||||||
|
void (*update_callback)(void* context);
|
||||||
|
void* update_context;
|
||||||
} LfRfidTuneViewModel;
|
} LfRfidTuneViewModel;
|
||||||
|
|
||||||
static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
||||||
@@ -151,6 +153,18 @@ static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* conte
|
|||||||
consumed = false;
|
consumed = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(event->key == InputKeyLeft || event->key == InputKeyRight) {
|
||||||
|
with_view_model(
|
||||||
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
|
if(model->update_callback) {
|
||||||
|
model->update_callback(model->update_context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
@@ -161,19 +175,7 @@ LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
|
|||||||
tune_view->view = view_alloc();
|
tune_view->view = view_alloc();
|
||||||
view_set_context(tune_view->view, tune_view);
|
view_set_context(tune_view->view, tune_view);
|
||||||
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
||||||
|
lfrfid_debug_view_tune_clean(tune_view);
|
||||||
with_view_model(
|
|
||||||
tune_view->view,
|
|
||||||
LfRfidTuneViewModel * model,
|
|
||||||
{
|
|
||||||
model->dirty = true;
|
|
||||||
model->fine = false;
|
|
||||||
model->ARR = 511;
|
|
||||||
model->CCR = 255;
|
|
||||||
model->pos = 0;
|
|
||||||
},
|
|
||||||
true);
|
|
||||||
|
|
||||||
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
||||||
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
||||||
|
|
||||||
@@ -199,6 +201,8 @@ void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
|
|||||||
model->ARR = 511;
|
model->ARR = 511;
|
||||||
model->CCR = 255;
|
model->CCR = 255;
|
||||||
model->pos = 0;
|
model->pos = 0;
|
||||||
|
model->update_callback = NULL;
|
||||||
|
model->update_context = NULL;
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
@@ -232,3 +236,17 @@ uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void lfrfid_debug_view_tune_set_callback(
|
||||||
|
LfRfidTuneView* tune_view,
|
||||||
|
void (*callback)(void* context),
|
||||||
|
void* context) {
|
||||||
|
with_view_model(
|
||||||
|
tune_view->view,
|
||||||
|
LfRfidTuneViewModel * model,
|
||||||
|
{
|
||||||
|
model->update_callback = callback;
|
||||||
|
model->update_context = context;
|
||||||
|
},
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,3 +16,8 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view);
|
|||||||
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view);
|
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view);
|
||||||
|
|
||||||
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view);
|
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view);
|
||||||
|
|
||||||
|
void lfrfid_debug_view_tune_set_callback(
|
||||||
|
LfRfidTuneView* tune_view,
|
||||||
|
void (*callback)(void* context),
|
||||||
|
void* context);
|
||||||
|
|||||||
11
applications/debug/speaker_debug/application.fam
Normal file
11
applications/debug/speaker_debug/application.fam
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
App(
|
||||||
|
appid="speaker_debug",
|
||||||
|
name="Speaker Debug",
|
||||||
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
entry_point="speaker_debug_app",
|
||||||
|
requires=["gui", "notification"],
|
||||||
|
stack_size=2 * 1024,
|
||||||
|
order=10,
|
||||||
|
fap_category="Debug",
|
||||||
|
fap_libs=["music_worker"],
|
||||||
|
)
|
||||||
120
applications/debug/speaker_debug/speaker_debug.c
Normal file
120
applications/debug/speaker_debug/speaker_debug.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <music_worker/music_worker.h>
|
||||||
|
#include <cli/cli.h>
|
||||||
|
#include <toolbox/args.h>
|
||||||
|
|
||||||
|
#define TAG "SpeakerDebug"
|
||||||
|
#define CLI_COMMAND "speaker_debug"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SpeakerDebugAppMessageTypeStop,
|
||||||
|
} SpeakerDebugAppMessageType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpeakerDebugAppMessageType type;
|
||||||
|
} SpeakerDebugAppMessage;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
MusicWorker* music_worker;
|
||||||
|
FuriMessageQueue* message_queue;
|
||||||
|
Cli* cli;
|
||||||
|
} SpeakerDebugApp;
|
||||||
|
|
||||||
|
static SpeakerDebugApp* speaker_app_alloc() {
|
||||||
|
SpeakerDebugApp* app = (SpeakerDebugApp*)malloc(sizeof(SpeakerDebugApp));
|
||||||
|
app->music_worker = music_worker_alloc();
|
||||||
|
app->message_queue = furi_message_queue_alloc(8, sizeof(SpeakerDebugAppMessage));
|
||||||
|
app->cli = furi_record_open(RECORD_CLI);
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void speaker_app_free(SpeakerDebugApp* app) {
|
||||||
|
music_worker_free(app->music_worker);
|
||||||
|
furi_message_queue_free(app->message_queue);
|
||||||
|
furi_record_close(RECORD_CLI);
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void speaker_app_cli(Cli* cli, FuriString* args, void* context) {
|
||||||
|
UNUSED(cli);
|
||||||
|
|
||||||
|
SpeakerDebugApp* app = (SpeakerDebugApp*)context;
|
||||||
|
SpeakerDebugAppMessage message;
|
||||||
|
FuriString* cmd = furi_string_alloc();
|
||||||
|
|
||||||
|
if(!args_read_string_and_trim(args, cmd)) {
|
||||||
|
furi_string_free(cmd);
|
||||||
|
printf("Usage:\r\n");
|
||||||
|
printf("\t" CLI_COMMAND " stop\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(furi_string_cmp(cmd, "stop") == 0) {
|
||||||
|
message.type = SpeakerDebugAppMessageTypeStop;
|
||||||
|
FuriStatus status = furi_message_queue_put(app->message_queue, &message, 100);
|
||||||
|
if(status != FuriStatusOk) {
|
||||||
|
printf("Failed to send message\r\n");
|
||||||
|
} else {
|
||||||
|
printf("Stopping\r\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("Usage:\r\n");
|
||||||
|
printf("\t" CLI_COMMAND " stop\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_free(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool speaker_app_music_play(SpeakerDebugApp* app, const char* rtttl) {
|
||||||
|
if(music_worker_is_playing(app->music_worker)) {
|
||||||
|
music_worker_stop(app->music_worker);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!music_worker_load_rtttl_from_string(app->music_worker, rtttl)) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to load RTTTL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
music_worker_set_volume(app->music_worker, 1.0f);
|
||||||
|
music_worker_start(app->music_worker);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void speaker_app_music_stop(SpeakerDebugApp* app) {
|
||||||
|
if(music_worker_is_playing(app->music_worker)) {
|
||||||
|
music_worker_stop(app->music_worker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void speaker_app_run(SpeakerDebugApp* app, const char* arg) {
|
||||||
|
if(!arg || !speaker_app_music_play(app, arg)) {
|
||||||
|
FURI_LOG_E(TAG, "Provided RTTTL is invalid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cli_add_command(app->cli, CLI_COMMAND, CliCommandFlagParallelSafe, speaker_app_cli, app);
|
||||||
|
|
||||||
|
SpeakerDebugAppMessage message;
|
||||||
|
FuriStatus status;
|
||||||
|
while(true) {
|
||||||
|
status = furi_message_queue_get(app->message_queue, &message, FuriWaitForever);
|
||||||
|
|
||||||
|
if(status == FuriStatusOk) {
|
||||||
|
if(message.type == SpeakerDebugAppMessageTypeStop) {
|
||||||
|
speaker_app_music_stop(app);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cli_delete_command(app->cli, CLI_COMMAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t speaker_debug_app(void* arg) {
|
||||||
|
SpeakerDebugApp* app = speaker_app_alloc();
|
||||||
|
speaker_app_run(app, arg);
|
||||||
|
speaker_app_free(app);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
applications/debug/subghz_test/application.fam
Normal file
14
applications/debug/subghz_test/application.fam
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
App(
|
||||||
|
appid="subghz_test",
|
||||||
|
name="Sub-Ghz test",
|
||||||
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
targets=["f7"],
|
||||||
|
entry_point="subghz_test_app",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=4 * 1024,
|
||||||
|
order=50,
|
||||||
|
fap_icon="subghz_test_10px.png",
|
||||||
|
fap_category="Debug",
|
||||||
|
fap_icon_assets="images",
|
||||||
|
fap_version="0.1",
|
||||||
|
)
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
//SubGhzTestCustomEvent
|
||||||
|
SubGhzTestCustomEventStartId = 100,
|
||||||
|
SubGhzTestCustomEventSceneShowOnlyRX,
|
||||||
|
} SubGhzTestCustomEvent;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "subghz_testing.h"
|
#include "subghz_test_frequency.h"
|
||||||
|
|
||||||
const uint32_t subghz_frequencies_testing[] = {
|
const uint32_t subghz_frequencies_testing[] = {
|
||||||
/* 300 - 348 */
|
/* 300 - 348 */
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
extern const uint32_t subghz_frequencies_testing[];
|
extern const uint32_t subghz_frequencies_testing[];
|
||||||
extern const uint32_t subghz_frequencies_count_testing;
|
extern const uint32_t subghz_frequencies_count_testing;
|
||||||
18
applications/debug/subghz_test/helpers/subghz_test_types.h
Normal file
18
applications/debug/subghz_test/helpers/subghz_test_types.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#define SUBGHZ_TEST_VERSION_APP "0.1"
|
||||||
|
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
||||||
|
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubGhzTestViewVariableItemList,
|
||||||
|
SubGhzTestViewSubmenu,
|
||||||
|
SubGhzTestViewStatic,
|
||||||
|
SubGhzTestViewCarrier,
|
||||||
|
SubGhzTestViewPacket,
|
||||||
|
SubGhzTestViewWidget,
|
||||||
|
SubGhzTestViewPopup,
|
||||||
|
} SubGhzTestView;
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
244
applications/debug/subghz_test/protocol/math.c
Normal file
244
applications/debug/subghz_test/protocol/math.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
#include "math.h"
|
||||||
|
|
||||||
|
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count) {
|
||||||
|
uint64_t reverse_key = 0;
|
||||||
|
for(uint8_t i = 0; i < bit_count; i++) {
|
||||||
|
reverse_key = reverse_key << 1 | bit_read(key, i);
|
||||||
|
}
|
||||||
|
return reverse_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count) {
|
||||||
|
uint8_t parity = 0;
|
||||||
|
for(uint8_t i = 0; i < bit_count; i++) {
|
||||||
|
parity += bit_read(key, i);
|
||||||
|
}
|
||||||
|
return parity & 0x01;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_crc4(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init) {
|
||||||
|
uint8_t remainder = init << 4; // LSBs are unused
|
||||||
|
uint8_t poly = polynomial << 4;
|
||||||
|
uint8_t bit;
|
||||||
|
|
||||||
|
while(size--) {
|
||||||
|
remainder ^= *message++;
|
||||||
|
for(bit = 0; bit < 8; bit++) {
|
||||||
|
if(remainder & 0x80) {
|
||||||
|
remainder = (remainder << 1) ^ poly;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder >> 4 & 0x0f; // discard the LSBs
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_crc7(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init) {
|
||||||
|
uint8_t remainder = init << 1; // LSB is unused
|
||||||
|
uint8_t poly = polynomial << 1;
|
||||||
|
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
remainder ^= message[byte];
|
||||||
|
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 0x80) {
|
||||||
|
remainder = (remainder << 1) ^ poly;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder >> 1 & 0x7f; // discard the LSB
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_crc8(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init) {
|
||||||
|
uint8_t remainder = init;
|
||||||
|
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
remainder ^= message[byte];
|
||||||
|
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 0x80) {
|
||||||
|
remainder = (remainder << 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_crc8le(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init) {
|
||||||
|
uint8_t remainder = subghz_protocol_blocks_reverse_key(init, 8);
|
||||||
|
polynomial = subghz_protocol_blocks_reverse_key(polynomial, 8);
|
||||||
|
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
remainder ^= message[byte];
|
||||||
|
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 1) {
|
||||||
|
remainder = (remainder >> 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init) {
|
||||||
|
uint16_t remainder = init;
|
||||||
|
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
remainder ^= message[byte];
|
||||||
|
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 1) {
|
||||||
|
remainder = (remainder >> 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_crc16(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init) {
|
||||||
|
uint16_t remainder = init;
|
||||||
|
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
remainder ^= message[byte] << 8;
|
||||||
|
for(uint8_t bit = 0; bit < 8; ++bit) {
|
||||||
|
if(remainder & 0x8000) {
|
||||||
|
remainder = (remainder << 1) ^ polynomial;
|
||||||
|
} else {
|
||||||
|
remainder = (remainder << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key) {
|
||||||
|
uint8_t sum = 0;
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
uint8_t data = message[byte];
|
||||||
|
for(int i = 7; i >= 0; --i) {
|
||||||
|
// XOR key into sum if data bit is set
|
||||||
|
if((data >> i) & 1) sum ^= key;
|
||||||
|
|
||||||
|
// roll the key right (actually the LSB is dropped here)
|
||||||
|
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||||
|
if(key & 1)
|
||||||
|
key = (key >> 1) ^ gen;
|
||||||
|
else
|
||||||
|
key = (key >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key) {
|
||||||
|
uint8_t sum = 0;
|
||||||
|
// Process message from last byte to first byte (reflected)
|
||||||
|
for(int byte = size - 1; byte >= 0; --byte) {
|
||||||
|
uint8_t data = message[byte];
|
||||||
|
// Process individual bits of each byte (reflected)
|
||||||
|
for(uint8_t i = 0; i < 8; ++i) {
|
||||||
|
// XOR key into sum if data bit is set
|
||||||
|
if((data >> i) & 1) {
|
||||||
|
sum ^= key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// roll the key left (actually the LSB is dropped here)
|
||||||
|
// and apply the gen (needs to include the dropped lsb as MSB)
|
||||||
|
if(key & 0x80)
|
||||||
|
key = (key << 1) ^ gen;
|
||||||
|
else
|
||||||
|
key = (key << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t gen,
|
||||||
|
uint16_t key) {
|
||||||
|
uint16_t sum = 0;
|
||||||
|
for(size_t byte = 0; byte < size; ++byte) {
|
||||||
|
uint8_t data = message[byte];
|
||||||
|
for(int8_t i = 7; i >= 0; --i) {
|
||||||
|
// if data bit is set then xor with key
|
||||||
|
if((data >> i) & 1) sum ^= key;
|
||||||
|
|
||||||
|
// roll the key right (actually the LSB is dropped here)
|
||||||
|
// and apply the gen (needs to include the dropped LSB as MSB)
|
||||||
|
if(key & 1)
|
||||||
|
key = (key >> 1) ^ gen;
|
||||||
|
else
|
||||||
|
key = (key >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size) {
|
||||||
|
uint32_t result = 0;
|
||||||
|
for(size_t i = 0; i < size; ++i) {
|
||||||
|
result += message[i];
|
||||||
|
}
|
||||||
|
return (uint8_t)result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_parity8(uint8_t byte) {
|
||||||
|
byte ^= byte >> 4;
|
||||||
|
byte &= 0xf;
|
||||||
|
return (0x6996 >> byte) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size) {
|
||||||
|
uint8_t result = 0;
|
||||||
|
for(size_t i = 0; i < size; ++i) {
|
||||||
|
result ^= subghz_protocol_blocks_parity8(message[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size) {
|
||||||
|
uint8_t result = 0;
|
||||||
|
for(size_t i = 0; i < size; ++i) {
|
||||||
|
result ^= message[i];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
222
applications/debug/subghz_test/protocol/math.h
Normal file
222
applications/debug/subghz_test/protocol/math.h
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
|
||||||
|
#define bit_set(value, bit) \
|
||||||
|
({ \
|
||||||
|
__typeof__(value) _one = (1); \
|
||||||
|
(value) |= (_one << (bit)); \
|
||||||
|
})
|
||||||
|
#define bit_clear(value, bit) \
|
||||||
|
({ \
|
||||||
|
__typeof__(value) _one = (1); \
|
||||||
|
(value) &= ~(_one << (bit)); \
|
||||||
|
})
|
||||||
|
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||||
|
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Flip the data bitwise
|
||||||
|
*
|
||||||
|
* @param key In data
|
||||||
|
* @param bit_count number of data bits
|
||||||
|
*
|
||||||
|
* @return Reverse data
|
||||||
|
*/
|
||||||
|
uint64_t subghz_protocol_blocks_reverse_key(uint64_t key, uint8_t bit_count);
|
||||||
|
|
||||||
|
/** Get parity the data bitwise
|
||||||
|
*
|
||||||
|
* @param key In data
|
||||||
|
* @param bit_count number of data bits
|
||||||
|
*
|
||||||
|
* @return parity
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_get_parity(uint64_t key, uint8_t bit_count);
|
||||||
|
|
||||||
|
/** CRC-4
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_crc4(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init);
|
||||||
|
|
||||||
|
/** CRC-7
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_crc7(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init);
|
||||||
|
|
||||||
|
/** Generic Cyclic Redundancy Check CRC-8. Example polynomial: 0x31 = x8 + x5 +
|
||||||
|
* x4 + 1 (x8 is implicit) Example polynomial: 0x80 = x8 + x7 (a normal
|
||||||
|
* bit-by-bit parity XOR)
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_crc8(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init);
|
||||||
|
|
||||||
|
/** "Little-endian" Cyclic Redundancy Check CRC-8 LE Input and output are
|
||||||
|
* reflected, i.e. least significant bit is shifted in first
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_crc8le(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t polynomial,
|
||||||
|
uint8_t init);
|
||||||
|
|
||||||
|
/** CRC-16 LSB. Input and output are reflected, i.e. least significant bit is
|
||||||
|
* shifted in first. Note that poly and init already need to be reflected
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint16_t subghz_protocol_blocks_crc16lsb(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init);
|
||||||
|
|
||||||
|
/** CRC-16
|
||||||
|
*
|
||||||
|
* @param message array of bytes to check
|
||||||
|
* @param size number of bytes in message
|
||||||
|
* @param polynomial CRC polynomial
|
||||||
|
* @param init starting crc value
|
||||||
|
*
|
||||||
|
* @return CRC value
|
||||||
|
*/
|
||||||
|
uint16_t subghz_protocol_blocks_crc16(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t polynomial,
|
||||||
|
uint16_t init);
|
||||||
|
|
||||||
|
/** Digest-8 by "LFSR-based Toeplitz hash"
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the
|
||||||
|
* LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
*
|
||||||
|
* @return digest value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key);
|
||||||
|
|
||||||
|
/** Digest-8 by "LFSR-based Toeplitz hash", byte reflect, bit reflect
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the
|
||||||
|
* LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
*
|
||||||
|
* @return digest value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_lfsr_digest8_reflect(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint8_t gen,
|
||||||
|
uint8_t key);
|
||||||
|
|
||||||
|
/** Digest-16 by "LFSR-based Toeplitz hash"
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to digest
|
||||||
|
* @param gen key stream generator, needs to includes the MSB if the
|
||||||
|
* LFSR is rolling
|
||||||
|
* @param key initial key
|
||||||
|
*
|
||||||
|
* @return digest value
|
||||||
|
*/
|
||||||
|
uint16_t subghz_protocol_blocks_lfsr_digest16(
|
||||||
|
uint8_t const message[],
|
||||||
|
size_t size,
|
||||||
|
uint16_t gen,
|
||||||
|
uint16_t key);
|
||||||
|
|
||||||
|
/** Compute Addition of a number of bytes
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to sum
|
||||||
|
*
|
||||||
|
* @return summation value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_add_bytes(uint8_t const message[], size_t size);
|
||||||
|
|
||||||
|
/** Compute bit parity of a single byte (8 bits)
|
||||||
|
*
|
||||||
|
* @param byte single byte to check
|
||||||
|
*
|
||||||
|
* @return 1 odd parity, 0 even parity
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_parity8(uint8_t byte);
|
||||||
|
|
||||||
|
/** Compute bit parity of a number of bytes
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to sum
|
||||||
|
*
|
||||||
|
* @return 1 odd parity, 0 even parity
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_parity_bytes(uint8_t const message[], size_t size);
|
||||||
|
|
||||||
|
/** Compute XOR (byte-wide parity) of a number of bytes
|
||||||
|
*
|
||||||
|
* @param message bytes of message data
|
||||||
|
* @param size number of bytes to sum
|
||||||
|
*
|
||||||
|
* @return summation value, per bit-position 1 odd parity, 0 even parity
|
||||||
|
*/
|
||||||
|
uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "princeton_for_testing.h"
|
#include "princeton_for_testing.h"
|
||||||
|
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include "../blocks/math.h"
|
#include "math.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Help
|
* Help
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "base.h"
|
//#include "base.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include <lib/toolbox/level_duration.h>
|
||||||
|
|
||||||
/** SubGhzDecoderPrinceton anonymous type */
|
/** SubGhzDecoderPrinceton anonymous type */
|
||||||
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
typedef struct SubGhzDecoderPrinceton SubGhzDecoderPrinceton;
|
||||||
30
applications/debug/subghz_test/scenes/subghz_test_scene.c
Normal file
30
applications/debug/subghz_test/scenes/subghz_test_scene.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||||
|
void (*const subghz_test_scene_on_enter_handlers[])(void*) = {
|
||||||
|
#include "subghz_test_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||||
|
bool (*const subghz_test_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||||
|
#include "subghz_test_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||||
|
void (*const subghz_test_scene_on_exit_handlers[])(void* context) = {
|
||||||
|
#include "subghz_test_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Initialize scene handlers configuration structure
|
||||||
|
const SceneManagerHandlers subghz_test_scene_handlers = {
|
||||||
|
.on_enter_handlers = subghz_test_scene_on_enter_handlers,
|
||||||
|
.on_event_handlers = subghz_test_scene_on_event_handlers,
|
||||||
|
.on_exit_handlers = subghz_test_scene_on_exit_handlers,
|
||||||
|
.scene_num = SubGhzTestSceneNum,
|
||||||
|
};
|
||||||
@@ -3,27 +3,27 @@
|
|||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
// Generate scene id and total number
|
// Generate scene id and total number
|
||||||
#define ADD_SCENE(prefix, name, id) NfcMagicScene##id,
|
#define ADD_SCENE(prefix, name, id) SubGhzTestScene##id,
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#include "nfc_magic_scene_config.h"
|
#include "subghz_test_scene_config.h"
|
||||||
NfcMagicSceneNum,
|
SubGhzTestSceneNum,
|
||||||
} NfcMagicScene;
|
} SubGhzTestScene;
|
||||||
#undef ADD_SCENE
|
#undef ADD_SCENE
|
||||||
|
|
||||||
extern const SceneManagerHandlers nfc_magic_scene_handlers;
|
extern const SceneManagerHandlers subghz_test_scene_handlers;
|
||||||
|
|
||||||
// Generate scene on_enter handlers declaration
|
// Generate scene on_enter handlers declaration
|
||||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||||
#include "nfc_magic_scene_config.h"
|
#include "subghz_test_scene_config.h"
|
||||||
#undef ADD_SCENE
|
#undef ADD_SCENE
|
||||||
|
|
||||||
// Generate scene on_event handlers declaration
|
// Generate scene on_event handlers declaration
|
||||||
#define ADD_SCENE(prefix, name, id) \
|
#define ADD_SCENE(prefix, name, id) \
|
||||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||||
#include "nfc_magic_scene_config.h"
|
#include "subghz_test_scene_config.h"
|
||||||
#undef ADD_SCENE
|
#undef ADD_SCENE
|
||||||
|
|
||||||
// Generate scene on_exit handlers declaration
|
// Generate scene on_exit handlers declaration
|
||||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||||
#include "nfc_magic_scene_config.h"
|
#include "subghz_test_scene_config.h"
|
||||||
#undef ADD_SCENE
|
#undef ADD_SCENE
|
||||||
@@ -1,31 +1,27 @@
|
|||||||
#include "../../lightmeter.h"
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
void lightmeter_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
|
void subghz_test_scene_about_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
LightMeterApp* app = context;
|
SubGhzTestApp* app = context;
|
||||||
|
|
||||||
UNUSED(app);
|
|
||||||
UNUSED(result);
|
|
||||||
UNUSED(type);
|
|
||||||
if(type == InputTypeShort) {
|
if(type == InputTypeShort) {
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void lightmeter_scene_about_on_enter(void* context) {
|
void subghz_test_scene_about_on_enter(void* context) {
|
||||||
LightMeterApp* app = context;
|
SubGhzTestApp* app = context;
|
||||||
|
|
||||||
FuriString* temp_str;
|
FuriString* temp_str;
|
||||||
temp_str = furi_string_alloc();
|
temp_str = furi_string_alloc();
|
||||||
furi_string_printf(temp_str, "\e#%s\n", "Information");
|
furi_string_printf(temp_str, "\e#%s\n", "Information");
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "Version: %s\n", LM_VERSION_APP);
|
furi_string_cat_printf(temp_str, "Version: %s\n", SUBGHZ_TEST_VERSION_APP);
|
||||||
furi_string_cat_printf(temp_str, "Developed by: %s\n", LM_DEVELOPED);
|
furi_string_cat_printf(temp_str, "Developed by: %s\n", SUBGHZ_TEST_DEVELOPED);
|
||||||
furi_string_cat_printf(temp_str, "Github: %s\n\n", LM_GITHUB);
|
furi_string_cat_printf(temp_str, "Github: %s\n\n", SUBGHZ_TEST_GITHUB);
|
||||||
|
|
||||||
furi_string_cat_printf(temp_str, "\e#%s\n", "Description");
|
furi_string_cat_printf(temp_str, "\e#%s\n", "Description");
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str,
|
temp_str,
|
||||||
"Showing suggested camera\nsettings based on ambient\nlight or flash.\n\nInspired by a lightmeter\nproject by vpominchuk\n");
|
"This application is designed\nto test the functionality of the\nbuilt-in CC1101 module.\n\n");
|
||||||
|
|
||||||
widget_add_text_box_element(
|
widget_add_text_box_element(
|
||||||
app->widget,
|
app->widget,
|
||||||
@@ -45,17 +41,16 @@ void lightmeter_scene_about_on_enter(void* context) {
|
|||||||
14,
|
14,
|
||||||
AlignCenter,
|
AlignCenter,
|
||||||
AlignBottom,
|
AlignBottom,
|
||||||
"\e#\e! Lightmeter \e!\n",
|
"\e#\e! Sub-Ghz Test \e!\n",
|
||||||
false);
|
false);
|
||||||
widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
|
widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str));
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, LightMeterAppViewAbout);
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lightmeter_scene_about_on_event(void* context, SceneManagerEvent event) {
|
bool subghz_test_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||||
LightMeterApp* app = context;
|
SubGhzTestApp* app = context;
|
||||||
|
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
UNUSED(app);
|
UNUSED(app);
|
||||||
UNUSED(event);
|
UNUSED(event);
|
||||||
@@ -63,8 +58,8 @@ bool lightmeter_scene_about_on_event(void* context, SceneManagerEvent event) {
|
|||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lightmeter_scene_about_on_exit(void* context) {
|
void subghz_test_scene_about_on_exit(void* context) {
|
||||||
LightMeterApp* app = context;
|
SubGhzTestApp* app = context;
|
||||||
|
|
||||||
// Clear views
|
// Clear views
|
||||||
widget_reset(app->widget);
|
widget_reset(app->widget);
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
|
void subghz_test_scene_carrier_callback(SubGhzTestCarrierEvent event, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_carrier_on_enter(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
subghz_test_carrier_set_callback(
|
||||||
|
app->subghz_test_carrier, subghz_test_scene_carrier_callback, app);
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewCarrier);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_test_scene_carrier_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubGhzTestCarrierEventOnlyRx) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_carrier_on_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
ADD_SCENE(subghz_test, start, Start)
|
||||||
|
ADD_SCENE(subghz_test, about, About)
|
||||||
|
ADD_SCENE(subghz_test, carrier, Carrier)
|
||||||
|
ADD_SCENE(subghz_test, packet, Packet)
|
||||||
|
ADD_SCENE(subghz_test, static, Static)
|
||||||
|
ADD_SCENE(subghz_test, show_only_rx, ShowOnlyRx)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
|
void subghz_test_scene_packet_callback(SubGhzTestPacketEvent event, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_packet_on_enter(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
subghz_test_packet_set_callback(
|
||||||
|
app->subghz_test_packet, subghz_test_scene_packet_callback, app);
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_test_scene_packet_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubGhzTestPacketEventOnlyRx) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_packet_on_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
#include <subghz_test_icons.h>
|
||||||
|
|
||||||
|
void subghz_test_scene_show_only_rx_popup_callback(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, SubGhzTestCustomEventSceneShowOnlyRX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_show_only_rx_on_enter(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
|
||||||
|
// Setup view
|
||||||
|
Popup* popup = app->popup;
|
||||||
|
|
||||||
|
const char* header_text = "Transmission is blocked";
|
||||||
|
const char* message_text = "Transmission on\nthis frequency is\nrestricted in\nyour region";
|
||||||
|
if(!furi_hal_region_is_provisioned()) {
|
||||||
|
header_text = "Firmware update needed";
|
||||||
|
message_text = "Please update\nfirmware before\nusing this feature\nflipp.dev/upd";
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_set_header(popup, header_text, 63, 3, AlignCenter, AlignTop);
|
||||||
|
popup_set_text(popup, message_text, 0, 17, AlignLeft, AlignTop);
|
||||||
|
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||||
|
|
||||||
|
popup_set_timeout(popup, 1500);
|
||||||
|
popup_set_context(popup, app);
|
||||||
|
popup_set_callback(popup, subghz_test_scene_show_only_rx_popup_callback);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_test_scene_show_only_rx_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubGhzTestCustomEventSceneShowOnlyRX) {
|
||||||
|
scene_manager_previous_scene(app->scene_manager);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_show_only_rx_on_exit(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
Popup* popup = app->popup;
|
||||||
|
|
||||||
|
popup_reset(popup);
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubmenuIndexSubGhzTestCarrier,
|
||||||
|
SubmenuIndexSubGhzTestPacket,
|
||||||
|
SubmenuIndexSubGhzTestStatic,
|
||||||
|
SubmenuIndexSubGhzTestAbout,
|
||||||
|
} SubmenuIndex;
|
||||||
|
|
||||||
|
void subghz_test_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_start_on_enter(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
Submenu* submenu = app->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Carrier",
|
||||||
|
SubmenuIndexSubGhzTestCarrier,
|
||||||
|
subghz_test_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Packet",
|
||||||
|
SubmenuIndexSubGhzTestPacket,
|
||||||
|
subghz_test_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Static",
|
||||||
|
SubmenuIndexSubGhzTestStatic,
|
||||||
|
subghz_test_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"About",
|
||||||
|
SubmenuIndexSubGhzTestAbout,
|
||||||
|
subghz_test_scene_start_submenu_callback,
|
||||||
|
app);
|
||||||
|
|
||||||
|
submenu_set_selected_item(
|
||||||
|
submenu, scene_manager_get_scene_state(app->scene_manager, SubGhzTestSceneStart));
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_test_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubmenuIndexSubGhzTestAbout) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneAbout);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexSubGhzTestCarrier) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneCarrier);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexSubGhzTestPacket) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestScenePacket);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexSubGhzTestStatic) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStatic);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
scene_manager_set_scene_state(app->scene_manager, SubGhzTestSceneStart, event.event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_start_on_exit(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
submenu_reset(app->submenu);
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include "../subghz_test_app_i.h"
|
||||||
|
|
||||||
|
void subghz_test_scene_static_callback(SubGhzTestStaticEvent event, void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_static_on_enter(void* context) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
subghz_test_static_set_callback(
|
||||||
|
app->subghz_test_static, subghz_test_scene_static_callback, app);
|
||||||
|
view_dispatcher_switch_to_view(app->view_dispatcher, SubGhzTestViewStatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_test_scene_static_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubGhzTestStaticEventOnlyRx) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneShowOnlyRx);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_scene_static_on_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
BIN
applications/debug/subghz_test/subghz_test_10px.png
Normal file
BIN
applications/debug/subghz_test/subghz_test_10px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 181 B |
139
applications/debug/subghz_test/subghz_test_app.c
Normal file
139
applications/debug/subghz_test/subghz_test_app.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
#include "subghz_test_app_i.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
static bool subghz_test_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool subghz_test_app_back_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
return scene_manager_handle_back_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_test_app_tick_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubGhzTestApp* app = context;
|
||||||
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubGhzTestApp* subghz_test_app_alloc() {
|
||||||
|
SubGhzTestApp* app = malloc(sizeof(SubGhzTestApp));
|
||||||
|
|
||||||
|
// GUI
|
||||||
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
|
|
||||||
|
// View Dispatcher
|
||||||
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
app->scene_manager = scene_manager_alloc(&subghz_test_scene_handlers, app);
|
||||||
|
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||||
|
|
||||||
|
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||||
|
view_dispatcher_set_custom_event_callback(
|
||||||
|
app->view_dispatcher, subghz_test_app_custom_event_callback);
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
app->view_dispatcher, subghz_test_app_back_event_callback);
|
||||||
|
view_dispatcher_set_tick_event_callback(
|
||||||
|
app->view_dispatcher, subghz_test_app_tick_event_callback, 100);
|
||||||
|
|
||||||
|
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
// Open Notification record
|
||||||
|
app->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
// SubMenu
|
||||||
|
app->submenu = submenu_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, SubGhzTestViewSubmenu, submenu_get_view(app->submenu));
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
app->widget = widget_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, SubGhzTestViewWidget, widget_get_view(app->widget));
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
app->popup = popup_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, SubGhzTestViewPopup, popup_get_view(app->popup));
|
||||||
|
|
||||||
|
// Carrier Test Module
|
||||||
|
app->subghz_test_carrier = subghz_test_carrier_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
SubGhzTestViewCarrier,
|
||||||
|
subghz_test_carrier_get_view(app->subghz_test_carrier));
|
||||||
|
|
||||||
|
// Packet Test
|
||||||
|
app->subghz_test_packet = subghz_test_packet_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
SubGhzTestViewPacket,
|
||||||
|
subghz_test_packet_get_view(app->subghz_test_packet));
|
||||||
|
|
||||||
|
// Static send
|
||||||
|
app->subghz_test_static = subghz_test_static_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher,
|
||||||
|
SubGhzTestViewStatic,
|
||||||
|
subghz_test_static_get_view(app->subghz_test_static));
|
||||||
|
|
||||||
|
scene_manager_next_scene(app->scene_manager, SubGhzTestSceneStart);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_test_app_free(SubGhzTestApp* app) {
|
||||||
|
furi_assert(app);
|
||||||
|
|
||||||
|
// Submenu
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewSubmenu);
|
||||||
|
submenu_free(app->submenu);
|
||||||
|
|
||||||
|
// Widget
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewWidget);
|
||||||
|
widget_free(app->widget);
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPopup);
|
||||||
|
popup_free(app->popup);
|
||||||
|
|
||||||
|
// Carrier Test
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewCarrier);
|
||||||
|
subghz_test_carrier_free(app->subghz_test_carrier);
|
||||||
|
|
||||||
|
// Packet Test
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewPacket);
|
||||||
|
subghz_test_packet_free(app->subghz_test_packet);
|
||||||
|
|
||||||
|
// Static
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, SubGhzTestViewStatic);
|
||||||
|
subghz_test_static_free(app->subghz_test_static);
|
||||||
|
|
||||||
|
// View dispatcher
|
||||||
|
view_dispatcher_free(app->view_dispatcher);
|
||||||
|
scene_manager_free(app->scene_manager);
|
||||||
|
|
||||||
|
// Notifications
|
||||||
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
app->notifications = NULL;
|
||||||
|
|
||||||
|
// Close records
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t subghz_test_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
SubGhzTestApp* subghz_test_app = subghz_test_app_alloc();
|
||||||
|
|
||||||
|
view_dispatcher_run(subghz_test_app->view_dispatcher);
|
||||||
|
|
||||||
|
subghz_test_app_free(subghz_test_app);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
5
applications/debug/subghz_test/subghz_test_app_i.c
Normal file
5
applications/debug/subghz_test/subghz_test_app_i.c
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "subghz_test_app_i.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define TAG "SubGhzTest"
|
||||||
32
applications/debug/subghz_test/subghz_test_app_i.h
Normal file
32
applications/debug/subghz_test/subghz_test_app_i.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "helpers/subghz_test_types.h"
|
||||||
|
#include "helpers/subghz_test_event.h"
|
||||||
|
|
||||||
|
#include "scenes/subghz_test_scene.h"
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/modules/widget.h>
|
||||||
|
#include <gui/modules/popup.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
|
#include "views/subghz_test_static.h"
|
||||||
|
#include "views/subghz_test_carrier.h"
|
||||||
|
#include "views/subghz_test_packet.h"
|
||||||
|
|
||||||
|
typedef struct SubGhzTestApp SubGhzTestApp;
|
||||||
|
|
||||||
|
struct SubGhzTestApp {
|
||||||
|
Gui* gui;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
SceneManager* scene_manager;
|
||||||
|
NotificationApp* notifications;
|
||||||
|
Submenu* submenu;
|
||||||
|
Widget* widget;
|
||||||
|
Popup* popup;
|
||||||
|
SubGhzTestStatic* subghz_test_static;
|
||||||
|
SubGhzTestCarrier* subghz_test_carrier;
|
||||||
|
SubGhzTestPacket* subghz_test_packet;
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "subghz_test_carrier.h"
|
#include "subghz_test_carrier.h"
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_test_app_i.h"
|
||||||
#include "../helpers/subghz_testing.h"
|
#include "../helpers/subghz_test_frequency.h"
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
@@ -11,6 +12,7 @@ struct SubGhzTestCarrier {
|
|||||||
View* view;
|
View* view;
|
||||||
FuriTimer* timer;
|
FuriTimer* timer;
|
||||||
SubGhzTestCarrierCallback callback;
|
SubGhzTestCarrierCallback callback;
|
||||||
|
// const SubGhzDevice* radio_device;
|
||||||
void* context;
|
void* context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -83,6 +85,7 @@ void subghz_test_carrier_draw(Canvas* canvas, SubGhzTestCarrierModel* model) {
|
|||||||
bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||||
|
// const SubGhzDevice* radio_device = subghz_test_carrier->radio_device;
|
||||||
|
|
||||||
if(event->key == InputKeyBack || event->type != InputTypeShort) {
|
if(event->key == InputKeyBack || event->type != InputTypeShort) {
|
||||||
return false;
|
return false;
|
||||||
@@ -93,6 +96,7 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
|||||||
SubGhzTestCarrierModel * model,
|
SubGhzTestCarrierModel * model,
|
||||||
{
|
{
|
||||||
furi_hal_subghz_idle();
|
furi_hal_subghz_idle();
|
||||||
|
// subghz_devices_idle(radio_device);
|
||||||
|
|
||||||
if(event->key == InputKeyLeft) {
|
if(event->key == InputKeyLeft) {
|
||||||
if(model->frequency > 0) model->frequency--;
|
if(model->frequency > 0) model->frequency--;
|
||||||
@@ -113,24 +117,36 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
|||||||
model->real_frequency =
|
model->real_frequency =
|
||||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||||
furi_hal_subghz_set_path(model->path);
|
furi_hal_subghz_set_path(model->path);
|
||||||
|
// model->real_frequency = subghz_devices_set_frequency(
|
||||||
|
// radio_device, subghz_frequencies_testing[model->frequency]);
|
||||||
|
|
||||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||||
furi_hal_gpio_init(
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
|
||||||
furi_hal_subghz_rx();
|
furi_hal_subghz_rx();
|
||||||
|
// furi_hal_gpio_init(
|
||||||
|
// subghz_devices_get_data_gpio(radio_device),
|
||||||
|
// GpioModeInput,
|
||||||
|
// GpioPullNo,
|
||||||
|
// GpioSpeedLow);
|
||||||
|
// subghz_devices_set_rx(radio_device);
|
||||||
} else {
|
} else {
|
||||||
furi_hal_gpio_init(
|
furi_hal_gpio_init(
|
||||||
furi_hal_subghz.cc1101_g0_pin,
|
&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
GpioModeOutputPushPull,
|
furi_hal_gpio_write(&gpio_cc1101_g0, true);
|
||||||
GpioPullNo,
|
|
||||||
GpioSpeedLow);
|
|
||||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, true);
|
|
||||||
if(!furi_hal_subghz_tx()) {
|
if(!furi_hal_subghz_tx()) {
|
||||||
furi_hal_gpio_init(
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
|
||||||
subghz_test_carrier->callback(
|
subghz_test_carrier->callback(
|
||||||
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
||||||
}
|
}
|
||||||
|
// if(!subghz_devices_set_tx(radio_device)) {
|
||||||
|
// furi_hal_gpio_init(
|
||||||
|
// subghz_devices_get_data_gpio(radio_device),
|
||||||
|
// GpioModeInput,
|
||||||
|
// GpioPullNo,
|
||||||
|
// GpioSpeedLow);
|
||||||
|
// subghz_test_carrier->callback(
|
||||||
|
// SubGhzTestCarrierEventOnlyRx, subghz_test_carrier->context);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
true);
|
true);
|
||||||
@@ -141,11 +157,19 @@ bool subghz_test_carrier_input(InputEvent* event, void* context) {
|
|||||||
void subghz_test_carrier_enter(void* context) {
|
void subghz_test_carrier_enter(void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzTestCarrier* subghz_test_carrier = context;
|
SubGhzTestCarrier* subghz_test_carrier = context;
|
||||||
|
// furi_assert(subghz_test_carrier->radio_device);
|
||||||
|
// const SubGhzDevice* radio_device = subghz_test_carrier->radio_device;
|
||||||
|
|
||||||
furi_hal_subghz_reset();
|
furi_hal_subghz_reset();
|
||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||||
|
|
||||||
furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
|
// subghz_devices_reset(radio_device);
|
||||||
|
// subghz_devices_load_preset(radio_device, FuriHalSubGhzPresetOok650Async, NULL);
|
||||||
|
|
||||||
|
// furi_hal_gpio_init(
|
||||||
|
// subghz_devices_get_data_gpio(radio_device), GpioModeInput, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
subghz_test_carrier->view,
|
subghz_test_carrier->view,
|
||||||
@@ -154,6 +178,8 @@ void subghz_test_carrier_enter(void* context) {
|
|||||||
model->frequency = subghz_frequencies_433_92_testing; // 433
|
model->frequency = subghz_frequencies_433_92_testing; // 433
|
||||||
model->real_frequency =
|
model->real_frequency =
|
||||||
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
furi_hal_subghz_set_frequency(subghz_frequencies_testing[model->frequency]);
|
||||||
|
// model->real_frequency = subghz_devices_set_frequency(
|
||||||
|
// radio_device, subghz_frequencies_testing[model->frequency]);
|
||||||
model->path = FuriHalSubGhzPathIsolate; // isolate
|
model->path = FuriHalSubGhzPathIsolate; // isolate
|
||||||
model->rssi = 0.0f;
|
model->rssi = 0.0f;
|
||||||
model->status = SubGhzTestCarrierModelStatusRx;
|
model->status = SubGhzTestCarrierModelStatusRx;
|
||||||
@@ -161,6 +187,7 @@ void subghz_test_carrier_enter(void* context) {
|
|||||||
true);
|
true);
|
||||||
|
|
||||||
furi_hal_subghz_rx();
|
furi_hal_subghz_rx();
|
||||||
|
// subghz_devices_set_rx(radio_device);
|
||||||
|
|
||||||
furi_timer_start(subghz_test_carrier->timer, furi_kernel_get_tick_frequency() / 4);
|
furi_timer_start(subghz_test_carrier->timer, furi_kernel_get_tick_frequency() / 4);
|
||||||
}
|
}
|
||||||
@@ -173,6 +200,7 @@ void subghz_test_carrier_exit(void* context) {
|
|||||||
|
|
||||||
// Reinitialize IC to default state
|
// Reinitialize IC to default state
|
||||||
furi_hal_subghz_sleep();
|
furi_hal_subghz_sleep();
|
||||||
|
// subghz_devices_sleep(subghz_test_carrier->radio_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_test_carrier_rssi_timer_callback(void* context) {
|
void subghz_test_carrier_rssi_timer_callback(void* context) {
|
||||||
@@ -185,6 +213,7 @@ void subghz_test_carrier_rssi_timer_callback(void* context) {
|
|||||||
{
|
{
|
||||||
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
if(model->status == SubGhzTestCarrierModelStatusRx) {
|
||||||
model->rssi = furi_hal_subghz_get_rssi();
|
model->rssi = furi_hal_subghz_get_rssi();
|
||||||
|
// model->rssi = subghz_devices_get_rssi(subghz_test_carrier->radio_device);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false);
|
false);
|
||||||
@@ -220,3 +249,10 @@ View* subghz_test_carrier_get_view(SubGhzTestCarrier* subghz_test_carrier) {
|
|||||||
furi_assert(subghz_test_carrier);
|
furi_assert(subghz_test_carrier);
|
||||||
return subghz_test_carrier->view;
|
return subghz_test_carrier->view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void subghz_test_carrier_set_radio(
|
||||||
|
// SubGhzTestCarrier* subghz_test_carrier,
|
||||||
|
// const SubGhzDevice* radio_device) {
|
||||||
|
// furi_assert(subghz_test_carrier);
|
||||||
|
// subghz_test_carrier->radio_device = radio_device;
|
||||||
|
// }
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
|
// #include <lib/subghz/devices/devices.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubGhzTestCarrierEventOnlyRx,
|
SubGhzTestCarrierEventOnlyRx,
|
||||||
@@ -20,3 +21,7 @@ SubGhzTestCarrier* subghz_test_carrier_alloc();
|
|||||||
void subghz_test_carrier_free(SubGhzTestCarrier* subghz_test_carrier);
|
void subghz_test_carrier_free(SubGhzTestCarrier* subghz_test_carrier);
|
||||||
|
|
||||||
View* subghz_test_carrier_get_view(SubGhzTestCarrier* subghz_test_carrier);
|
View* subghz_test_carrier_get_view(SubGhzTestCarrier* subghz_test_carrier);
|
||||||
|
|
||||||
|
// void subghz_test_carrier_set_radio(
|
||||||
|
// SubGhzTestCarrier* subghz_test_carrier,
|
||||||
|
// const SubGhzDevice* radio_device);
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#include "subghz_test_packet.h"
|
#include "subghz_test_packet.h"
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_test_app_i.h"
|
||||||
#include "../helpers/subghz_testing.h"
|
#include "../helpers/subghz_test_frequency.h"
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <toolbox/level_duration.h>
|
#include <toolbox/level_duration.h>
|
||||||
#include <lib/subghz/protocols/princeton_for_testing.h>
|
#include "../protocol/princeton_for_testing.h"
|
||||||
|
|
||||||
#define SUBGHZ_TEST_PACKET_COUNT 500
|
#define SUBGHZ_TEST_PACKET_COUNT 500
|
||||||
|
|
||||||
@@ -55,7 +56,6 @@ static void subghz_test_packet_rx_callback(bool level, uint32_t duration, void*
|
|||||||
subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration);
|
subghz_decoder_princeton_for_testing_parse(instance->decoder, level, duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo
|
|
||||||
static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) {
|
static void subghz_test_packet_rx_pt_callback(SubGhzDecoderPrinceton* parser, void* context) {
|
||||||
UNUSED(parser);
|
UNUSED(parser);
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
@@ -194,7 +194,7 @@ void subghz_test_packet_enter(void* context) {
|
|||||||
SubGhzTestPacket* instance = context;
|
SubGhzTestPacket* instance = context;
|
||||||
|
|
||||||
furi_hal_subghz_reset();
|
furi_hal_subghz_reset();
|
||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
instance->view,
|
instance->view,
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
#include "subghz_test_static.h"
|
#include "subghz_test_static.h"
|
||||||
#include "../subghz_i.h"
|
#include "../subghz_test_app_i.h"
|
||||||
#include "../helpers/subghz_testing.h"
|
#include "../helpers/subghz_test_frequency.h"
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <lib/subghz/protocols/princeton_for_testing.h>
|
#include "../protocol/princeton_for_testing.h"
|
||||||
|
|
||||||
#define TAG "SubGhzTestStatic"
|
#define TAG "SubGhzTestStatic"
|
||||||
|
|
||||||
@@ -141,11 +142,10 @@ void subghz_test_static_enter(void* context) {
|
|||||||
SubGhzTestStatic* instance = context;
|
SubGhzTestStatic* instance = context;
|
||||||
|
|
||||||
furi_hal_subghz_reset();
|
furi_hal_subghz_reset();
|
||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||||
|
|
||||||
furi_hal_gpio_init(
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
||||||
furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
|
furi_hal_gpio_write(&gpio_cc1101_g0, false);
|
||||||
furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false);
|
|
||||||
instance->status_tx = SubGhzTestStaticStatusIDLE;
|
instance->status_tx = SubGhzTestStaticStatusIDLE;
|
||||||
|
|
||||||
with_view_model(
|
with_view_model(
|
||||||
@@ -53,15 +53,17 @@ static void (*text_box_test_render[])(Canvas* canvas) = {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
FuriMutex* mutex;
|
||||||
} TextBoxTestState;
|
} TextBoxTestState;
|
||||||
|
|
||||||
static void text_box_test_render_callback(Canvas* canvas, void* ctx) {
|
static void text_box_test_render_callback(Canvas* canvas, void* ctx) {
|
||||||
TextBoxTestState* state = acquire_mutex((ValueMutex*)ctx, 25);
|
TextBoxTestState* state = ctx;
|
||||||
|
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||||
canvas_clear(canvas);
|
canvas_clear(canvas);
|
||||||
|
|
||||||
text_box_test_render[state->idx](canvas);
|
text_box_test_render[state->idx](canvas);
|
||||||
|
|
||||||
release_mutex((ValueMutex*)ctx, state);
|
furi_mutex_release(state->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void text_box_test_input_callback(InputEvent* input_event, void* ctx) {
|
static void text_box_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||||
@@ -74,17 +76,17 @@ int32_t text_box_test_app(void* p) {
|
|||||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||||
furi_check(event_queue);
|
furi_check(event_queue);
|
||||||
|
|
||||||
TextBoxTestState _state = {.idx = 0};
|
TextBoxTestState state = {.idx = 0, .mutex = NULL};
|
||||||
|
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
|
|
||||||
ValueMutex state_mutex;
|
if(!state.mutex) {
|
||||||
if(!init_mutex(&state_mutex, &_state, sizeof(TextBoxTestState))) {
|
|
||||||
FURI_LOG_E(TAG, "Cannot create mutex");
|
FURI_LOG_E(TAG, "Cannot create mutex");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
|
|
||||||
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state_mutex);
|
view_port_draw_callback_set(view_port, text_box_test_render_callback, &state);
|
||||||
view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue);
|
view_port_input_callback_set(view_port, text_box_test_input_callback, event_queue);
|
||||||
|
|
||||||
// Open GUI and register view_port
|
// Open GUI and register view_port
|
||||||
@@ -94,24 +96,24 @@ int32_t text_box_test_app(void* p) {
|
|||||||
uint32_t test_renders_num = COUNT_OF(text_box_test_render);
|
uint32_t test_renders_num = COUNT_OF(text_box_test_render);
|
||||||
InputEvent event;
|
InputEvent event;
|
||||||
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||||
TextBoxTestState* state = acquire_mutex_block(&state_mutex);
|
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||||
|
|
||||||
if(event.type == InputTypeShort) {
|
if(event.type == InputTypeShort) {
|
||||||
if(event.key == InputKeyRight) {
|
if(event.key == InputKeyRight) {
|
||||||
if(state->idx < test_renders_num - 1) {
|
if(state.idx < test_renders_num - 1) {
|
||||||
state->idx++;
|
state.idx++;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyLeft) {
|
} else if(event.key == InputKeyLeft) {
|
||||||
if(state->idx > 0) {
|
if(state.idx > 0) {
|
||||||
state->idx--;
|
state.idx--;
|
||||||
}
|
}
|
||||||
} else if(event.key == InputKeyBack) {
|
} else if(event.key == InputKeyBack) {
|
||||||
release_mutex(&state_mutex, state);
|
furi_mutex_release(state.mutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
release_mutex(&state_mutex, state);
|
furi_mutex_release(state.mutex);
|
||||||
view_port_update(view_port);
|
view_port_update(view_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +121,7 @@ int32_t text_box_test_app(void* p) {
|
|||||||
gui_remove_view_port(gui, view_port);
|
gui_remove_view_port(gui, view_port);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
furi_message_queue_free(event_queue);
|
furi_message_queue_free(event_queue);
|
||||||
delete_mutex(&state_mutex);
|
furi_mutex_free(state.mutex);
|
||||||
|
|
||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
App(
|
App(
|
||||||
appid="UART_Echo",
|
appid="uart_echo",
|
||||||
name="UART Echo",
|
name="UART Echo",
|
||||||
apptype=FlipperAppType.PLUGIN,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="uart_echo_app",
|
entry_point="uart_echo_app",
|
||||||
cdefines=["APP_UART_ECHO"],
|
cdefines=["APP_UART_ECHO"],
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
order=70,
|
order=70,
|
||||||
fap_icon="uart_10px.png",
|
fap_icon="uart_10px.png",
|
||||||
fap_category="GPIO",
|
fap_category="Debug",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
#define LINES_ON_SCREEN 6
|
#define LINES_ON_SCREEN 6
|
||||||
#define COLUMNS_ON_SCREEN 21
|
#define COLUMNS_ON_SCREEN 21
|
||||||
|
#define TAG "UartEcho"
|
||||||
|
#define DEFAULT_BAUD_RATE 230400
|
||||||
|
|
||||||
typedef struct UartDumpModel UartDumpModel;
|
typedef struct UartDumpModel UartDumpModel;
|
||||||
|
|
||||||
@@ -179,7 +181,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UartEchoApp* uart_echo_app_alloc() {
|
static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
||||||
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
||||||
|
|
||||||
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
||||||
@@ -220,7 +222,7 @@ static UartEchoApp* uart_echo_app_alloc() {
|
|||||||
|
|
||||||
// Enable uart listener
|
// Enable uart listener
|
||||||
furi_hal_console_disable();
|
furi_hal_console_disable();
|
||||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
|
furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
|
||||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
@@ -263,8 +265,18 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32_t uart_echo_app(void* p) {
|
int32_t uart_echo_app(void* p) {
|
||||||
UNUSED(p);
|
uint32_t baudrate = DEFAULT_BAUD_RATE;
|
||||||
UartEchoApp* app = uart_echo_app_alloc();
|
if(p) {
|
||||||
|
const char* baudrate_str = p;
|
||||||
|
if(sscanf(baudrate_str, "%lu", &baudrate) != 1) {
|
||||||
|
FURI_LOG_E(TAG, "Invalid baudrate: %s", baudrate_str);
|
||||||
|
baudrate = DEFAULT_BAUD_RATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Using baudrate: %lu", baudrate);
|
||||||
|
|
||||||
|
UartEchoApp* app = uart_echo_app_alloc(baudrate);
|
||||||
view_dispatcher_run(app->view_dispatcher);
|
view_dispatcher_run(app->view_dispatcher);
|
||||||
uart_echo_app_free(app);
|
uart_echo_app_free(app);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ App(
|
|||||||
apptype=FlipperAppType.STARTUP,
|
apptype=FlipperAppType.STARTUP,
|
||||||
entry_point="unit_tests_on_system_start",
|
entry_point="unit_tests_on_system_start",
|
||||||
cdefines=["APP_UNIT_TESTS"],
|
cdefines=["APP_UNIT_TESTS"],
|
||||||
|
requires=["system_settings"],
|
||||||
provides=["delay_test"],
|
provides=["delay_test"],
|
||||||
order=100,
|
order=100,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#include <dialogs/dialogs.h>
|
||||||
|
|
||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
MU_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields) {
|
||||||
|
mu_assert(
|
||||||
|
sizeof(DialogsFileBrowserOptions) == 28,
|
||||||
|
"Changes to `DialogsFileBrowserOptions` should also be reflected in `dialog_file_browser_set_basic_options`");
|
||||||
|
|
||||||
|
DialogsFileBrowserOptions options;
|
||||||
|
dialog_file_browser_set_basic_options(&options, ".fap", NULL);
|
||||||
|
// note: this assertions can safely be changed, their primary purpose is to remind the maintainer
|
||||||
|
// to update `dialog_file_browser_set_basic_options` by including all structure fields in it
|
||||||
|
mu_assert_string_eq(".fap", options.extension);
|
||||||
|
mu_assert_null(options.base_path);
|
||||||
|
mu_assert(options.skip_assets, "`skip_assets` should default to `true");
|
||||||
|
mu_assert(options.hide_dot_files, "`hide_dot_files` should default to `true");
|
||||||
|
mu_assert_null(options.icon);
|
||||||
|
mu_assert(options.hide_ext, "`hide_ext` should default to `true");
|
||||||
|
mu_assert_null(options.item_loader_callback);
|
||||||
|
mu_assert_null(options.item_loader_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(dialogs_file_browser_options) {
|
||||||
|
MU_RUN_TEST(test_dialog_file_browser_set_basic_options_should_init_all_fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_minunit_test_dialogs_file_browser_options() {
|
||||||
|
MU_RUN_SUITE(dialogs_file_browser_options);
|
||||||
|
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
@@ -26,7 +26,6 @@ void test_furi_memmgr() {
|
|||||||
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
|
mu_assert_int_eq(66, ((uint8_t*)ptr)[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix realloc to copy only old size, and write testcase that leftover of reallocated memory is zero-initialized
|
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
|
||||||
// allocate and zero-initialize array (calloc)
|
// allocate and zero-initialize array (calloc)
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ MU_TEST(mu_test_furi_string_mem) {
|
|||||||
mu_check(string != NULL);
|
mu_check(string != NULL);
|
||||||
mu_check(!furi_string_empty(string));
|
mu_check(!furi_string_empty(string));
|
||||||
|
|
||||||
// TODO: how to test furi_string_reserve?
|
// TODO FL-3493: how to test furi_string_reserve?
|
||||||
|
|
||||||
// test furi_string_reset
|
// test furi_string_reset
|
||||||
furi_string_reset(string);
|
furi_string_reset(string);
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
// v2 tests
|
// v2 tests
|
||||||
void test_furi_create_open();
|
void test_furi_create_open();
|
||||||
void test_furi_valuemutex();
|
|
||||||
void test_furi_concurrent_access();
|
void test_furi_concurrent_access();
|
||||||
void test_furi_pubsub();
|
void test_furi_pubsub();
|
||||||
|
|
||||||
@@ -30,10 +29,6 @@ MU_TEST(mu_test_furi_create_open) {
|
|||||||
test_furi_create_open();
|
test_furi_create_open();
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(mu_test_furi_valuemutex) {
|
|
||||||
test_furi_valuemutex();
|
|
||||||
}
|
|
||||||
|
|
||||||
MU_TEST(mu_test_furi_pubsub) {
|
MU_TEST(mu_test_furi_pubsub) {
|
||||||
test_furi_pubsub();
|
test_furi_pubsub();
|
||||||
}
|
}
|
||||||
@@ -51,7 +46,6 @@ MU_TEST_SUITE(test_suite) {
|
|||||||
|
|
||||||
// v2 tests
|
// v2 tests
|
||||||
MU_RUN_TEST(mu_test_furi_create_open);
|
MU_RUN_TEST(mu_test_furi_create_open);
|
||||||
MU_RUN_TEST(mu_test_furi_valuemutex);
|
|
||||||
MU_RUN_TEST(mu_test_furi_pubsub);
|
MU_RUN_TEST(mu_test_furi_pubsub);
|
||||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
MU_RUN_TEST(mu_test_furi_memmgr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <furi.h>
|
|
||||||
|
|
||||||
#include "../minunit.h"
|
|
||||||
|
|
||||||
void test_furi_valuemutex() {
|
|
||||||
const int init_value = 0xdeadbeef;
|
|
||||||
const int changed_value = 0x12345678;
|
|
||||||
|
|
||||||
int value = init_value;
|
|
||||||
bool result;
|
|
||||||
ValueMutex valuemutex;
|
|
||||||
|
|
||||||
// init mutex case
|
|
||||||
result = init_mutex(&valuemutex, &value, sizeof(value));
|
|
||||||
mu_assert(result, "init mutex failed");
|
|
||||||
|
|
||||||
// acquire mutex case
|
|
||||||
int* value_pointer = acquire_mutex(&valuemutex, 100);
|
|
||||||
mu_assert_pointers_eq(value_pointer, &value);
|
|
||||||
|
|
||||||
// second acquire mutex case
|
|
||||||
int* value_pointer_second = acquire_mutex(&valuemutex, 100);
|
|
||||||
mu_assert_pointers_eq(value_pointer_second, NULL);
|
|
||||||
|
|
||||||
// change value case
|
|
||||||
*value_pointer = changed_value;
|
|
||||||
mu_assert_int_eq(value, changed_value);
|
|
||||||
|
|
||||||
// release mutex case
|
|
||||||
result = release_mutex(&valuemutex, &value);
|
|
||||||
mu_assert(result, "release mutex failed");
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
//acquire mutex blocking case
|
|
||||||
//write mutex blocking case
|
|
||||||
//read mutex blocking case
|
|
||||||
|
|
||||||
mu_check(delete_mutex(&valuemutex));
|
|
||||||
}
|
|
||||||
602
applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c
Normal file
602
applications/debug/unit_tests/furi_hal/furi_hal_crypto_tests.c
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
static const uint8_t key_ctr_1[32] = {
|
||||||
|
0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C,
|
||||||
|
0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_ctr_1[16] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x60,
|
||||||
|
0xDB,
|
||||||
|
0x56,
|
||||||
|
0x72,
|
||||||
|
0xC9,
|
||||||
|
0x7A,
|
||||||
|
0xA8,
|
||||||
|
0xF0,
|
||||||
|
0xB2,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_ctr_1[16] = {
|
||||||
|
0x53,
|
||||||
|
0x69,
|
||||||
|
0x6E,
|
||||||
|
0x67,
|
||||||
|
0x6C,
|
||||||
|
0x65,
|
||||||
|
0x20,
|
||||||
|
0x62,
|
||||||
|
0x6C,
|
||||||
|
0x6F,
|
||||||
|
0x63,
|
||||||
|
0x6B,
|
||||||
|
0x20,
|
||||||
|
0x6D,
|
||||||
|
0x73,
|
||||||
|
0x67,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_ctr_ct_1[16] = {
|
||||||
|
0x14,
|
||||||
|
0x5A,
|
||||||
|
0xD0,
|
||||||
|
0x1D,
|
||||||
|
0xBF,
|
||||||
|
0x82,
|
||||||
|
0x4E,
|
||||||
|
0xC7,
|
||||||
|
0x56,
|
||||||
|
0x08,
|
||||||
|
0x63,
|
||||||
|
0xDC,
|
||||||
|
0x71,
|
||||||
|
0xE3,
|
||||||
|
0xE0,
|
||||||
|
0xC0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_ctr_2[32] = {
|
||||||
|
0x77, 0x6B, 0xEF, 0xF2, 0x85, 0x1D, 0xB0, 0x6F, 0x4C, 0x8A, 0x05, 0x42, 0xC8, 0x69, 0x6F, 0x6C,
|
||||||
|
0x6A, 0x81, 0xAF, 0x1E, 0xEC, 0x96, 0xB4, 0xD3, 0x7F, 0xC1, 0xD6, 0x89, 0xE6, 0xC1, 0xC1, 0x04,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_ctr_2[16] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x60,
|
||||||
|
0xDB,
|
||||||
|
0x56,
|
||||||
|
0x72,
|
||||||
|
0xC9,
|
||||||
|
0x7A,
|
||||||
|
0xA8,
|
||||||
|
0xF0,
|
||||||
|
0xB2,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_ctr_2[0] = {};
|
||||||
|
//static const uint8_t tv_ctr_ct_2[0] = {};
|
||||||
|
|
||||||
|
static const uint8_t key_ctr_3[32] = {
|
||||||
|
0xF6, 0xD6, 0x6D, 0x6B, 0xD5, 0x2D, 0x59, 0xBB, 0x07, 0x96, 0x36, 0x58, 0x79, 0xEF, 0xF8, 0x86,
|
||||||
|
0xC6, 0x6D, 0xD5, 0x1A, 0x5B, 0x6A, 0x99, 0x74, 0x4B, 0x50, 0x59, 0x0C, 0x87, 0xA2, 0x38, 0x84,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_ctr_3[16] = {
|
||||||
|
0x00,
|
||||||
|
0xFA,
|
||||||
|
0xAC,
|
||||||
|
0x24,
|
||||||
|
0xC1,
|
||||||
|
0x58,
|
||||||
|
0x5E,
|
||||||
|
0xF1,
|
||||||
|
0x5A,
|
||||||
|
0x43,
|
||||||
|
0xD8,
|
||||||
|
0x75,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_ctr_3[32] = {
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
|
||||||
|
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_ctr_ct_3[32] = {
|
||||||
|
0xF0, 0x5E, 0x23, 0x1B, 0x38, 0x94, 0x61, 0x2C, 0x49, 0xEE, 0x00, 0x0B, 0x80, 0x4E, 0xB2, 0xA9,
|
||||||
|
0xB8, 0x30, 0x6B, 0x50, 0x8F, 0x83, 0x9D, 0x6A, 0x55, 0x30, 0x83, 0x1D, 0x93, 0x44, 0xAF, 0x1C,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_ctr_4[32] = {
|
||||||
|
0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2,
|
||||||
|
0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_ctr_4[16] = {
|
||||||
|
0x00,
|
||||||
|
0x1C,
|
||||||
|
0xC5,
|
||||||
|
0xB7,
|
||||||
|
0x51,
|
||||||
|
0xA5,
|
||||||
|
0x1D,
|
||||||
|
0x70,
|
||||||
|
0xA1,
|
||||||
|
0xC1,
|
||||||
|
0x11,
|
||||||
|
0x48,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_ctr_4[36] = {
|
||||||
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
|
||||||
|
0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||||
|
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_ctr_ct_4[36] = {
|
||||||
|
0xEB, 0x6C, 0x52, 0x82, 0x1D, 0x0B, 0xBB, 0xF7, 0xCE, 0x75, 0x94, 0x46,
|
||||||
|
0x2A, 0xCA, 0x4F, 0xAA, 0xB4, 0x07, 0xDF, 0x86, 0x65, 0x69, 0xFD, 0x07,
|
||||||
|
0xF4, 0x8C, 0xC0, 0xB5, 0x83, 0xD6, 0x07, 0x1F, 0x1E, 0xC0, 0xE6, 0xB8,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_ctr_5[32] = {
|
||||||
|
0xFF, 0x7A, 0x61, 0x7C, 0xE6, 0x91, 0x48, 0xE4, 0xF1, 0x72, 0x6E, 0x2F, 0x43, 0x58, 0x1D, 0xE2,
|
||||||
|
0xAA, 0x62, 0xD9, 0xF8, 0x05, 0x53, 0x2E, 0xDF, 0xF1, 0xEE, 0xD6, 0x87, 0xFB, 0x54, 0x15, 0x3D,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_ctr_5[16] = {
|
||||||
|
0x00,
|
||||||
|
0x1C,
|
||||||
|
0xC5,
|
||||||
|
0xB7,
|
||||||
|
0x51,
|
||||||
|
0xA5,
|
||||||
|
0x1D,
|
||||||
|
0x70,
|
||||||
|
0xA1,
|
||||||
|
0xC1,
|
||||||
|
0x11,
|
||||||
|
0x48,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x01,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_ctr_5[0] = {};
|
||||||
|
//static const uint8_t tv_ctr_ct_5[0] = {};
|
||||||
|
|
||||||
|
static const uint8_t key_gcm_1[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_gcm_1[16] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_gcm_1[0] = {};
|
||||||
|
//static const uint8_t tv_gcm_ct_1[0] = {};
|
||||||
|
static const uint8_t aad_gcm_1[0] = {};
|
||||||
|
static const uint8_t tv_gcm_tag_1[16] = {
|
||||||
|
0x53,
|
||||||
|
0x0F,
|
||||||
|
0x8A,
|
||||||
|
0xFB,
|
||||||
|
0xC7,
|
||||||
|
0x45,
|
||||||
|
0x36,
|
||||||
|
0xB9,
|
||||||
|
0xA9,
|
||||||
|
0x63,
|
||||||
|
0xB4,
|
||||||
|
0xF1,
|
||||||
|
0xC4,
|
||||||
|
0xCB,
|
||||||
|
0x73,
|
||||||
|
0x8B,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_gcm_2[32] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_gcm_2[16] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_gcm_2[16] = {
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_gcm_ct_2[16] = {
|
||||||
|
0xCE,
|
||||||
|
0xA7,
|
||||||
|
0x40,
|
||||||
|
0x3D,
|
||||||
|
0x4D,
|
||||||
|
0x60,
|
||||||
|
0x6B,
|
||||||
|
0x6E,
|
||||||
|
0x07,
|
||||||
|
0x4E,
|
||||||
|
0xC5,
|
||||||
|
0xD3,
|
||||||
|
0xBA,
|
||||||
|
0xF3,
|
||||||
|
0x9D,
|
||||||
|
0x18,
|
||||||
|
};
|
||||||
|
static const uint8_t aad_gcm_2[0] = {};
|
||||||
|
static const uint8_t tv_gcm_tag_2[16] = {
|
||||||
|
0xD0,
|
||||||
|
0xD1,
|
||||||
|
0xC8,
|
||||||
|
0xA7,
|
||||||
|
0x99,
|
||||||
|
0x99,
|
||||||
|
0x6B,
|
||||||
|
0xF0,
|
||||||
|
0x26,
|
||||||
|
0x5B,
|
||||||
|
0x98,
|
||||||
|
0xB5,
|
||||||
|
0xD4,
|
||||||
|
0x8A,
|
||||||
|
0xB9,
|
||||||
|
0x19,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_gcm_3[32] = {
|
||||||
|
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||||
|
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_gcm_3[16] = {
|
||||||
|
0xCA,
|
||||||
|
0xFE,
|
||||||
|
0xBA,
|
||||||
|
0xBE,
|
||||||
|
0xFA,
|
||||||
|
0xCE,
|
||||||
|
0xDB,
|
||||||
|
0xAD,
|
||||||
|
0xDE,
|
||||||
|
0xCA,
|
||||||
|
0xF8,
|
||||||
|
0x88,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_gcm_3[64] = {
|
||||||
|
0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26, 0x9A,
|
||||||
|
0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31, 0x8A, 0x72,
|
||||||
|
0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49, 0xA6, 0xB5, 0x25,
|
||||||
|
0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39, 0x1A, 0xAF, 0xD2, 0x55,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_gcm_ct_3[64] = {
|
||||||
|
0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42, 0x7D,
|
||||||
|
0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55, 0xD1, 0xAA,
|
||||||
|
0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56, 0x82, 0x88, 0x38,
|
||||||
|
0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62, 0x89, 0x80, 0x15, 0xAD,
|
||||||
|
};
|
||||||
|
static const uint8_t aad_gcm_3[0] = {};
|
||||||
|
static const uint8_t tv_gcm_tag_3[16] = {
|
||||||
|
0xB0,
|
||||||
|
0x94,
|
||||||
|
0xDA,
|
||||||
|
0xC5,
|
||||||
|
0xD9,
|
||||||
|
0x34,
|
||||||
|
0x71,
|
||||||
|
0xBD,
|
||||||
|
0xEC,
|
||||||
|
0x1A,
|
||||||
|
0x50,
|
||||||
|
0x22,
|
||||||
|
0x70,
|
||||||
|
0xE3,
|
||||||
|
0xCC,
|
||||||
|
0x6C,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint8_t key_gcm_4[32] = {
|
||||||
|
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||||
|
0xFE, 0xFF, 0xE9, 0x92, 0x86, 0x65, 0x73, 0x1C, 0x6D, 0x6A, 0x8F, 0x94, 0x67, 0x30, 0x83, 0x08,
|
||||||
|
};
|
||||||
|
static const uint8_t iv_gcm_4[16] = {
|
||||||
|
0xCA,
|
||||||
|
0xFE,
|
||||||
|
0xBA,
|
||||||
|
0xBE,
|
||||||
|
0xFA,
|
||||||
|
0xCE,
|
||||||
|
0xDB,
|
||||||
|
0xAD,
|
||||||
|
0xDE,
|
||||||
|
0xCA,
|
||||||
|
0xF8,
|
||||||
|
0x88,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
};
|
||||||
|
static const uint8_t pt_gcm_4[60] = {
|
||||||
|
0xD9, 0x31, 0x32, 0x25, 0xF8, 0x84, 0x06, 0xE5, 0xA5, 0x59, 0x09, 0xC5, 0xAF, 0xF5, 0x26,
|
||||||
|
0x9A, 0x86, 0xA7, 0xA9, 0x53, 0x15, 0x34, 0xF7, 0xDA, 0x2E, 0x4C, 0x30, 0x3D, 0x8A, 0x31,
|
||||||
|
0x8A, 0x72, 0x1C, 0x3C, 0x0C, 0x95, 0x95, 0x68, 0x09, 0x53, 0x2F, 0xCF, 0x0E, 0x24, 0x49,
|
||||||
|
0xA6, 0xB5, 0x25, 0xB1, 0x6A, 0xED, 0xF5, 0xAA, 0x0D, 0xE6, 0x57, 0xBA, 0x63, 0x7B, 0x39,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_gcm_ct_4[60] = {
|
||||||
|
0x52, 0x2D, 0xC1, 0xF0, 0x99, 0x56, 0x7D, 0x07, 0xF4, 0x7F, 0x37, 0xA3, 0x2A, 0x84, 0x42,
|
||||||
|
0x7D, 0x64, 0x3A, 0x8C, 0xDC, 0xBF, 0xE5, 0xC0, 0xC9, 0x75, 0x98, 0xA2, 0xBD, 0x25, 0x55,
|
||||||
|
0xD1, 0xAA, 0x8C, 0xB0, 0x8E, 0x48, 0x59, 0x0D, 0xBB, 0x3D, 0xA7, 0xB0, 0x8B, 0x10, 0x56,
|
||||||
|
0x82, 0x88, 0x38, 0xC5, 0xF6, 0x1E, 0x63, 0x93, 0xBA, 0x7A, 0x0A, 0xBC, 0xC9, 0xF6, 0x62,
|
||||||
|
};
|
||||||
|
static const uint8_t aad_gcm_4[20] = {
|
||||||
|
0xFE, 0xED, 0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED,
|
||||||
|
0xFA, 0xCE, 0xDE, 0xAD, 0xBE, 0xEF, 0xAB, 0xAD, 0xDA, 0xD2,
|
||||||
|
};
|
||||||
|
static const uint8_t tv_gcm_tag_4[16] = {
|
||||||
|
0x76,
|
||||||
|
0xFC,
|
||||||
|
0x6E,
|
||||||
|
0xCE,
|
||||||
|
0x0F,
|
||||||
|
0x4E,
|
||||||
|
0x17,
|
||||||
|
0x68,
|
||||||
|
0xCD,
|
||||||
|
0xDF,
|
||||||
|
0x88,
|
||||||
|
0x53,
|
||||||
|
0xBB,
|
||||||
|
0x2D,
|
||||||
|
0x55,
|
||||||
|
0x1B,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void furi_hal_crypto_ctr_setup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void furi_hal_crypto_ctr_teardown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void furi_hal_crypto_gcm_setup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static void furi_hal_crypto_gcm_teardown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_ctr_1) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t ct[sizeof(pt_ctr_1)];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_ctr(key_ctr_1, iv_ctr_1, pt_ctr_1, ct, sizeof(pt_ctr_1));
|
||||||
|
mu_assert(ret, "CTR 1 failed");
|
||||||
|
mu_assert_mem_eq(tv_ctr_ct_1, ct, sizeof(pt_ctr_1));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_ctr_2) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t ct[sizeof(pt_ctr_2)];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_ctr(key_ctr_2, iv_ctr_2, pt_ctr_2, ct, sizeof(pt_ctr_2));
|
||||||
|
mu_assert(ret, "CTR 2 failed");
|
||||||
|
//mu_assert_mem_eq(tv_ctr_ct_2, ct, sizeof(pt_ctr_2));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_ctr_3) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t ct[sizeof(pt_ctr_3)];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_ctr(key_ctr_3, iv_ctr_3, pt_ctr_3, ct, sizeof(pt_ctr_3));
|
||||||
|
mu_assert(ret, "CTR 3 failed");
|
||||||
|
mu_assert_mem_eq(tv_ctr_ct_3, ct, sizeof(pt_ctr_3));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_ctr_4) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t ct[sizeof(pt_ctr_4)];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_ctr(key_ctr_4, iv_ctr_4, pt_ctr_4, ct, sizeof(pt_ctr_4));
|
||||||
|
mu_assert(ret, "CTR 4 failed");
|
||||||
|
mu_assert_mem_eq(tv_ctr_ct_4, ct, sizeof(pt_ctr_4));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_ctr_5) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t ct[sizeof(pt_ctr_5)];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_ctr(key_ctr_5, iv_ctr_5, pt_ctr_5, ct, sizeof(pt_ctr_5));
|
||||||
|
mu_assert(ret, "CTR 5 failed");
|
||||||
|
//mu_assert_mem_eq(tv_ctr_ct_5, ct, sizeof(pt_ctr_5));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_gcm_1) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t pt[sizeof(pt_gcm_1)];
|
||||||
|
uint8_t ct[sizeof(pt_gcm_1)];
|
||||||
|
uint8_t tag_enc[16];
|
||||||
|
uint8_t tag_dec[16];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_1,
|
||||||
|
iv_gcm_1,
|
||||||
|
aad_gcm_1,
|
||||||
|
sizeof(aad_gcm_1),
|
||||||
|
pt_gcm_1,
|
||||||
|
ct,
|
||||||
|
sizeof(pt_gcm_1),
|
||||||
|
tag_enc,
|
||||||
|
false);
|
||||||
|
mu_assert(ret, "GCM 1 encryption failed");
|
||||||
|
//mu_assert_mem_eq(tv_gcm_ct_1, ct, sizeof(pt_gcm_1));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_1, tag_enc, 16);
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_1, iv_gcm_1, aad_gcm_1, sizeof(aad_gcm_1), ct, pt, sizeof(pt_gcm_1), tag_dec, true);
|
||||||
|
mu_assert(ret, "GCM 1 decryption failed");
|
||||||
|
//mu_assert_mem_eq(pt_gcm_1, pt, sizeof(pt_gcm_1));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_1, tag_dec, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_gcm_2) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t pt[sizeof(pt_gcm_2)];
|
||||||
|
uint8_t ct[sizeof(pt_gcm_2)];
|
||||||
|
uint8_t tag_enc[16];
|
||||||
|
uint8_t tag_dec[16];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_2,
|
||||||
|
iv_gcm_2,
|
||||||
|
aad_gcm_2,
|
||||||
|
sizeof(aad_gcm_2),
|
||||||
|
pt_gcm_2,
|
||||||
|
ct,
|
||||||
|
sizeof(pt_gcm_2),
|
||||||
|
tag_enc,
|
||||||
|
false);
|
||||||
|
mu_assert(ret, "GCM 2 encryption failed");
|
||||||
|
mu_assert_mem_eq(tv_gcm_ct_2, ct, sizeof(pt_gcm_2));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_2, tag_enc, 16);
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_2, iv_gcm_2, aad_gcm_2, sizeof(aad_gcm_2), ct, pt, sizeof(pt_gcm_2), tag_dec, true);
|
||||||
|
mu_assert(ret, "GCM 2 decryption failed");
|
||||||
|
mu_assert_mem_eq(pt_gcm_2, pt, sizeof(pt_gcm_2));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_2, tag_dec, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_gcm_3) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t pt[sizeof(pt_gcm_3)];
|
||||||
|
uint8_t ct[sizeof(pt_gcm_3)];
|
||||||
|
uint8_t tag_enc[16];
|
||||||
|
uint8_t tag_dec[16];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_3,
|
||||||
|
iv_gcm_3,
|
||||||
|
aad_gcm_3,
|
||||||
|
sizeof(aad_gcm_3),
|
||||||
|
pt_gcm_3,
|
||||||
|
ct,
|
||||||
|
sizeof(pt_gcm_3),
|
||||||
|
tag_enc,
|
||||||
|
false);
|
||||||
|
mu_assert(ret, "GCM 3 encryption failed");
|
||||||
|
mu_assert_mem_eq(tv_gcm_ct_3, ct, sizeof(pt_gcm_3));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_3, tag_enc, 16);
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_3, iv_gcm_3, aad_gcm_3, sizeof(aad_gcm_3), ct, pt, sizeof(pt_gcm_3), tag_dec, true);
|
||||||
|
mu_assert(ret, "GCM 3 decryption failed");
|
||||||
|
mu_assert_mem_eq(pt_gcm_3, pt, sizeof(pt_gcm_3));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_3, tag_dec, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_crypto_gcm_4) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t pt[sizeof(pt_gcm_4)];
|
||||||
|
uint8_t ct[sizeof(pt_gcm_4)];
|
||||||
|
uint8_t tag_enc[16];
|
||||||
|
uint8_t tag_dec[16];
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_4,
|
||||||
|
iv_gcm_4,
|
||||||
|
aad_gcm_4,
|
||||||
|
sizeof(aad_gcm_4),
|
||||||
|
pt_gcm_4,
|
||||||
|
ct,
|
||||||
|
sizeof(pt_gcm_4),
|
||||||
|
tag_enc,
|
||||||
|
false);
|
||||||
|
mu_assert(ret, "GCM 4 encryption failed");
|
||||||
|
mu_assert_mem_eq(tv_gcm_ct_4, ct, sizeof(pt_gcm_4));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_4, tag_enc, 16);
|
||||||
|
|
||||||
|
ret = furi_hal_crypto_gcm(
|
||||||
|
key_gcm_4, iv_gcm_4, aad_gcm_4, sizeof(aad_gcm_4), ct, pt, sizeof(pt_gcm_4), tag_dec, true);
|
||||||
|
mu_assert(ret, "GCM 4 decryption failed");
|
||||||
|
mu_assert_mem_eq(pt_gcm_4, pt, sizeof(pt_gcm_4));
|
||||||
|
mu_assert_mem_eq(tv_gcm_tag_4, tag_dec, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(furi_hal_crypto_ctr_test) {
|
||||||
|
MU_SUITE_CONFIGURE(&furi_hal_crypto_ctr_setup, &furi_hal_crypto_ctr_teardown);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_ctr_1);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_ctr_2);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_ctr_3);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_ctr_4);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_ctr_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(furi_hal_crypto_gcm_test) {
|
||||||
|
MU_SUITE_CONFIGURE(&furi_hal_crypto_gcm_setup, &furi_hal_crypto_gcm_teardown);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_gcm_1);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_gcm_2);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_gcm_3);
|
||||||
|
MU_RUN_TEST(furi_hal_crypto_gcm_4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_minunit_test_furi_hal_crypto() {
|
||||||
|
MU_RUN_SUITE(furi_hal_crypto_ctr_test);
|
||||||
|
MU_RUN_SUITE(furi_hal_crypto_gcm_test);
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
@@ -425,6 +425,7 @@ MU_TEST(infrared_test_decoder_mixed) {
|
|||||||
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
infrared_test_run_decoder(InfraredProtocolSamsung32, 1);
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_nec) {
|
MU_TEST(infrared_test_decoder_nec) {
|
||||||
@@ -499,6 +500,15 @@ MU_TEST(infrared_test_decoder_kaseikyo) {
|
|||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(infrared_test_decoder_rca) {
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 1);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 2);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 3);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 4);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 5);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolRCA, 6);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||||
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
|
infrared_test_run_encoder_decoder(InfraredProtocolNEC, 1);
|
||||||
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
|
infrared_test_run_encoder_decoder(InfraredProtocolNECext, 1);
|
||||||
@@ -509,6 +519,7 @@ MU_TEST(infrared_test_encoder_decoder_all) {
|
|||||||
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
infrared_test_run_encoder_decoder(InfraredProtocolRC5, 1);
|
||||||
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
infrared_test_run_encoder_decoder(InfraredProtocolSIRC, 1);
|
||||||
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
|
infrared_test_run_encoder_decoder(InfraredProtocolKaseikyo, 1);
|
||||||
|
infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(infrared_test) {
|
MU_TEST_SUITE(infrared_test) {
|
||||||
@@ -527,6 +538,7 @@ MU_TEST_SUITE(infrared_test) {
|
|||||||
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
MU_RUN_TEST(infrared_test_decoder_samsung32);
|
||||||
MU_RUN_TEST(infrared_test_decoder_necext1);
|
MU_RUN_TEST(infrared_test_decoder_necext1);
|
||||||
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
|
MU_RUN_TEST(infrared_test_decoder_kaseikyo);
|
||||||
|
MU_RUN_TEST(infrared_test_decoder_rca);
|
||||||
MU_RUN_TEST(infrared_test_decoder_mixed);
|
MU_RUN_TEST(infrared_test_decoder_mixed);
|
||||||
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
MU_RUN_TEST(infrared_test_encoder_decoder_all);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -311,7 +311,7 @@ MU_TEST(test_bit_lib_test_parity) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
MU_TEST(test_bit_lib_remove_bit_every_nth) {
|
||||||
// TODO: more tests
|
// TODO FL-3494: more tests
|
||||||
uint8_t data_i[1] = {0b00001111};
|
uint8_t data_i[1] = {0b00001111};
|
||||||
uint8_t data_o[1] = {0b00011111};
|
uint8_t data_o[1] = {0b00011111};
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|||||||
@@ -27,6 +27,12 @@ static const uint32_t nfc_test_file_version = 1;
|
|||||||
#define NFC_TEST_DATA_MAX_LEN 18
|
#define NFC_TEST_DATA_MAX_LEN 18
|
||||||
#define NFC_TETS_TIMINGS_MAX_LEN 1350
|
#define NFC_TETS_TIMINGS_MAX_LEN 1350
|
||||||
|
|
||||||
|
// Maximum allowed time for buffer preparation to fit 500us nt message timeout
|
||||||
|
#define NFC_TEST_4_BYTE_BUILD_BUFFER_TIM_MAX (150)
|
||||||
|
#define NFC_TEST_16_BYTE_BUILD_BUFFER_TIM_MAX (640)
|
||||||
|
#define NFC_TEST_4_BYTE_BUILD_SIGNAL_TIM_MAX (110)
|
||||||
|
#define NFC_TEST_16_BYTE_BUILD_SIGNAL_TIM_MAX (440)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Storage* storage;
|
Storage* storage;
|
||||||
NfcaSignal* signal;
|
NfcaSignal* signal;
|
||||||
@@ -89,13 +95,13 @@ static bool nfc_test_read_signal_from_file(const char* file_name) {
|
|||||||
|
|
||||||
static bool nfc_test_digital_signal_test_encode(
|
static bool nfc_test_digital_signal_test_encode(
|
||||||
const char* file_name,
|
const char* file_name,
|
||||||
uint32_t encode_max_time,
|
uint32_t build_signal_max_time_us,
|
||||||
|
uint32_t build_buffer_max_time_us,
|
||||||
uint32_t timing_tolerance,
|
uint32_t timing_tolerance,
|
||||||
uint32_t timings_sum_tolerance) {
|
uint32_t timings_sum_tolerance) {
|
||||||
furi_assert(nfc_test);
|
furi_assert(nfc_test);
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
uint32_t time = 0;
|
|
||||||
uint32_t dut_timings_sum = 0;
|
uint32_t dut_timings_sum = 0;
|
||||||
uint32_t ref_timings_sum = 0;
|
uint32_t ref_timings_sum = 0;
|
||||||
uint8_t parity[10] = {};
|
uint8_t parity[10] = {};
|
||||||
@@ -109,17 +115,37 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
|
|
||||||
// Encode signal
|
// Encode signal
|
||||||
FURI_CRITICAL_ENTER();
|
FURI_CRITICAL_ENTER();
|
||||||
time = DWT->CYCCNT;
|
uint32_t time_start = DWT->CYCCNT;
|
||||||
|
|
||||||
nfca_signal_encode(
|
nfca_signal_encode(
|
||||||
nfc_test->signal, nfc_test->test_data, nfc_test->test_data_len * 8, parity);
|
nfc_test->signal, nfc_test->test_data, nfc_test->test_data_len * 8, parity);
|
||||||
|
|
||||||
|
uint32_t time_signal =
|
||||||
|
(DWT->CYCCNT - time_start) / furi_hal_cortex_instructions_per_microsecond();
|
||||||
|
|
||||||
|
time_start = DWT->CYCCNT;
|
||||||
|
|
||||||
digital_signal_prepare_arr(nfc_test->signal->tx_signal);
|
digital_signal_prepare_arr(nfc_test->signal->tx_signal);
|
||||||
time = (DWT->CYCCNT - time) / furi_hal_cortex_instructions_per_microsecond();
|
|
||||||
|
uint32_t time_buffer =
|
||||||
|
(DWT->CYCCNT - time_start) / furi_hal_cortex_instructions_per_microsecond();
|
||||||
FURI_CRITICAL_EXIT();
|
FURI_CRITICAL_EXIT();
|
||||||
|
|
||||||
// Check timings
|
// Check timings
|
||||||
if(time > encode_max_time) {
|
if(time_signal > build_signal_max_time_us) {
|
||||||
FURI_LOG_E(
|
FURI_LOG_E(
|
||||||
TAG, "Encoding time: %ld us while accepted value: %ld us", time, encode_max_time);
|
TAG,
|
||||||
|
"Build signal time: %ld us while accepted value: %ld us",
|
||||||
|
time_signal,
|
||||||
|
build_signal_max_time_us);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(time_buffer > build_buffer_max_time_us) {
|
||||||
|
FURI_LOG_E(
|
||||||
|
TAG,
|
||||||
|
"Build buffer time: %ld us while accepted value: %ld us",
|
||||||
|
time_buffer,
|
||||||
|
build_buffer_max_time_us);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +182,16 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
FURI_LOG_I(TAG, "Encoding time: %ld us. Acceptable time: %ld us", time, encode_max_time);
|
FURI_LOG_I(
|
||||||
|
TAG,
|
||||||
|
"Build signal time: %ld us. Acceptable time: %ld us",
|
||||||
|
time_signal,
|
||||||
|
build_signal_max_time_us);
|
||||||
|
FURI_LOG_I(
|
||||||
|
TAG,
|
||||||
|
"Build buffer time: %ld us. Acceptable time: %ld us",
|
||||||
|
time_buffer,
|
||||||
|
build_buffer_max_time_us);
|
||||||
FURI_LOG_I(
|
FURI_LOG_I(
|
||||||
TAG,
|
TAG,
|
||||||
"Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]",
|
"Timings sum difference: %ld [1/64MHZ]. Acceptable difference: %ld [1/64MHz]",
|
||||||
@@ -171,11 +206,19 @@ static bool nfc_test_digital_signal_test_encode(
|
|||||||
MU_TEST(nfc_digital_signal_test) {
|
MU_TEST(nfc_digital_signal_test) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
nfc_test_digital_signal_test_encode(
|
nfc_test_digital_signal_test_encode(
|
||||||
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_SHORT_FILE, 500, 1, 37),
|
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_SHORT_FILE,
|
||||||
|
NFC_TEST_4_BYTE_BUILD_SIGNAL_TIM_MAX,
|
||||||
|
NFC_TEST_4_BYTE_BUILD_BUFFER_TIM_MAX,
|
||||||
|
1,
|
||||||
|
37),
|
||||||
"NFC short digital signal test failed\r\n");
|
"NFC short digital signal test failed\r\n");
|
||||||
mu_assert(
|
mu_assert(
|
||||||
nfc_test_digital_signal_test_encode(
|
nfc_test_digital_signal_test_encode(
|
||||||
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_LONG_FILE, 2000, 1, 37),
|
NFC_TEST_RESOURCES_DIR NFC_TEST_SIGNAL_LONG_FILE,
|
||||||
|
NFC_TEST_16_BYTE_BUILD_SIGNAL_TIM_MAX,
|
||||||
|
NFC_TEST_16_BYTE_BUILD_BUFFER_TIM_MAX,
|
||||||
|
1,
|
||||||
|
37),
|
||||||
"NFC long digital signal test failed\r\n");
|
"NFC long digital signal test failed\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,56 +3,63 @@
|
|||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
|
|
||||||
static void power_test_deinit(void) {
|
static void power_test_deinit(void) {
|
||||||
// Try to reset to default charging voltage
|
// Try to reset to default charge voltage limit
|
||||||
furi_hal_power_set_battery_charging_voltage(4.208f);
|
furi_hal_power_set_battery_charge_voltage_limit(4.208f);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_power_charge_voltage_exact) {
|
MU_TEST(test_power_charge_voltage_limit_exact) {
|
||||||
// Power of 16mV charge voltages get applied exactly
|
// Power of 16mV charge voltage limits get applied exactly
|
||||||
// (bq25896 charge controller works in 16mV increments)
|
// (bq25896 charge controller works in 16mV increments)
|
||||||
//
|
//
|
||||||
// This test may need adapted if other charge controllers are used in the future.
|
// This test may need adapted if other charge controllers are used in the future.
|
||||||
for(uint16_t charge_mv = 3840; charge_mv <= 4208; charge_mv += 16) {
|
for(uint16_t charge_mv = 3840; charge_mv <= 4208; charge_mv += 16) {
|
||||||
float charge_volt = (float)charge_mv / 1000.0f;
|
float charge_volt = (float)charge_mv / 1000.0f;
|
||||||
furi_hal_power_set_battery_charging_voltage(charge_volt);
|
furi_hal_power_set_battery_charge_voltage_limit(charge_volt);
|
||||||
mu_assert_double_eq(charge_volt, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(charge_volt, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_power_charge_voltage_floating_imprecision) {
|
MU_TEST(test_power_charge_voltage_limit_floating_imprecision) {
|
||||||
// 4.016f should act as 4.016 V, even with floating point imprecision
|
// 4.016f should act as 4.016 V, even with floating point imprecision
|
||||||
furi_hal_power_set_battery_charging_voltage(4.016f);
|
furi_hal_power_set_battery_charge_voltage_limit(4.016f);
|
||||||
mu_assert_double_eq(4.016f, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(4.016f, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_power_charge_voltage_inexact) {
|
MU_TEST(test_power_charge_voltage_limit_inexact) {
|
||||||
// Charge voltages that are not power of 16mV get truncated down
|
// Charge voltage limits that are not power of 16mV get truncated down
|
||||||
furi_hal_power_set_battery_charging_voltage(3.841f);
|
furi_hal_power_set_battery_charge_voltage_limit(3.841f);
|
||||||
mu_assert_double_eq(3.840, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(3.840, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
|
|
||||||
furi_hal_power_set_battery_charging_voltage(3.900f);
|
furi_hal_power_set_battery_charge_voltage_limit(3.900f);
|
||||||
mu_assert_double_eq(3.888, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(3.888, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
|
|
||||||
furi_hal_power_set_battery_charging_voltage(4.200f);
|
furi_hal_power_set_battery_charge_voltage_limit(4.200f);
|
||||||
mu_assert_double_eq(4.192, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(4.192, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_power_charge_voltage_invalid_clamped) {
|
MU_TEST(test_power_charge_voltage_limit_invalid_clamped) {
|
||||||
// Out-of-range charge voltages get clamped to 3.840 V and 4.208 V
|
// Out-of-range charge voltage limits get clamped to 3.840 V and 4.208 V
|
||||||
furi_hal_power_set_battery_charging_voltage(3.808f);
|
furi_hal_power_set_battery_charge_voltage_limit(3.808f);
|
||||||
mu_assert_double_eq(3.840, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(3.840, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
|
furi_hal_power_set_battery_charge_voltage_limit(1.0f);
|
||||||
|
mu_assert_double_eq(3.840, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
|
|
||||||
// NOTE: Intentionally picking a small increment above 4.208 V to reduce the risk of an
|
// NOTE: Intentionally picking a small increment above 4.208 V to reduce the risk of an
|
||||||
// unhappy battery if this fails.
|
// unhappy battery if this fails.
|
||||||
furi_hal_power_set_battery_charging_voltage(4.240f);
|
furi_hal_power_set_battery_charge_voltage_limit(4.240f);
|
||||||
mu_assert_double_eq(4.208, furi_hal_power_get_battery_charging_voltage());
|
mu_assert_double_eq(4.208, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
|
// Likewise, picking a number that the uint8_t wraparound in the driver would result in a
|
||||||
|
// VREG value under 23 if this test fails.
|
||||||
|
// E.g. (uint8_t)((8105-3840)/16) -> 10
|
||||||
|
furi_hal_power_set_battery_charge_voltage_limit(8.105f);
|
||||||
|
mu_assert_double_eq(4.208, furi_hal_power_get_battery_charge_voltage_limit());
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(test_power_suite) {
|
MU_TEST_SUITE(test_power_suite) {
|
||||||
MU_RUN_TEST(test_power_charge_voltage_exact);
|
MU_RUN_TEST(test_power_charge_voltage_limit_exact);
|
||||||
MU_RUN_TEST(test_power_charge_voltage_floating_imprecision);
|
MU_RUN_TEST(test_power_charge_voltage_limit_floating_imprecision);
|
||||||
MU_RUN_TEST(test_power_charge_voltage_inexact);
|
MU_RUN_TEST(test_power_charge_voltage_limit_inexact);
|
||||||
MU_RUN_TEST(test_power_charge_voltage_invalid_clamped);
|
MU_RUN_TEST(test_power_charge_voltage_limit_invalid_clamped);
|
||||||
power_test_deinit();
|
power_test_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <pb.h>
|
#include <pb.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
#include <lib/toolbox/md5.h>
|
#include <lib/toolbox/md5_calc.h>
|
||||||
#include <lib/toolbox/path.h>
|
#include <lib/toolbox/path.h>
|
||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
@@ -67,7 +67,6 @@ static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size);
|
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size);
|
||||||
static void clean_directory(Storage* fs_api, const char* clean_dir);
|
|
||||||
static void
|
static void
|
||||||
test_rpc_add_empty_to_list(MsgList_t msg_list, PB_CommandStatus status, uint32_t command_id);
|
test_rpc_add_empty_to_list(MsgList_t msg_list, PB_CommandStatus status, uint32_t command_id);
|
||||||
static void test_rpc_encode_and_feed(MsgList_t msg_list, uint8_t session);
|
static void test_rpc_encode_and_feed(MsgList_t msg_list, uint8_t session);
|
||||||
@@ -84,7 +83,7 @@ static void test_rpc_setup(void) {
|
|||||||
|
|
||||||
rpc = furi_record_open(RECORD_RPC);
|
rpc = furi_record_open(RECORD_RPC);
|
||||||
for(int i = 0; !(rpc_session[0].session) && (i < 10000); ++i) {
|
for(int i = 0; !(rpc_session[0].session) && (i < 10000); ++i) {
|
||||||
rpc_session[0].session = rpc_session_open(rpc);
|
rpc_session[0].session = rpc_session_open(rpc, RpcOwnerUnknown);
|
||||||
furi_delay_tick(1);
|
furi_delay_tick(1);
|
||||||
}
|
}
|
||||||
furi_check(rpc_session[0].session);
|
furi_check(rpc_session[0].session);
|
||||||
@@ -104,7 +103,7 @@ static void test_rpc_setup_second_session(void) {
|
|||||||
furi_check(!(rpc_session[1].session));
|
furi_check(!(rpc_session[1].session));
|
||||||
|
|
||||||
for(int i = 0; !(rpc_session[1].session) && (i < 10000); ++i) {
|
for(int i = 0; !(rpc_session[1].session) && (i < 10000); ++i) {
|
||||||
rpc_session[1].session = rpc_session_open(rpc);
|
rpc_session[1].session = rpc_session_open(rpc, RpcOwnerUnknown);
|
||||||
furi_delay_tick(1);
|
furi_delay_tick(1);
|
||||||
}
|
}
|
||||||
furi_check(rpc_session[1].session);
|
furi_check(rpc_session[1].session);
|
||||||
@@ -149,11 +148,41 @@ static void test_rpc_teardown_second_session(void) {
|
|||||||
rpc_session[1].session = NULL;
|
rpc_session[1].session = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_rpc_storage_clean_directory(Storage* fs_api, const char* clean_dir) {
|
||||||
|
furi_check(fs_api);
|
||||||
|
furi_check(clean_dir);
|
||||||
|
storage_simply_remove_recursive(fs_api, clean_dir);
|
||||||
|
FS_Error error = storage_common_mkdir(fs_api, clean_dir);
|
||||||
|
furi_check(error == FSE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_rpc_storage_create_file(Storage* fs_api, const char* path, size_t size) {
|
||||||
|
File* file = storage_file_alloc(fs_api);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
do {
|
||||||
|
if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break;
|
||||||
|
if(!storage_file_seek(file, size, true)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
storage_file_close(file);
|
||||||
|
storage_file_free(file);
|
||||||
|
|
||||||
|
furi_check(success);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_rpc_storage_setup(void) {
|
static void test_rpc_storage_setup(void) {
|
||||||
test_rpc_setup();
|
test_rpc_setup();
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
clean_directory(fs_api, TEST_DIR_NAME);
|
test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file100", 100);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file250", 250);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file500", 200);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file1000", 1000);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file2500", 2500);
|
||||||
|
test_rpc_storage_create_file(fs_api, TEST_DIR_NAME "/file5000", 5000);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +190,7 @@ static void test_rpc_storage_teardown(void) {
|
|||||||
test_rpc_teardown();
|
test_rpc_teardown();
|
||||||
|
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
clean_directory(fs_api, TEST_DIR_NAME);
|
test_rpc_storage_clean_directory(fs_api, TEST_DIR_NAME);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,36 +208,6 @@ static void test_rpc_session_terminated_callback(void* context) {
|
|||||||
xSemaphoreGive(callbacks_context->terminate_semaphore);
|
xSemaphoreGive(callbacks_context->terminate_semaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clean_directory(Storage* fs_api, const char* clean_dir) {
|
|
||||||
furi_check(fs_api);
|
|
||||||
furi_check(clean_dir);
|
|
||||||
|
|
||||||
File* dir = storage_file_alloc(fs_api);
|
|
||||||
if(storage_dir_open(dir, clean_dir)) {
|
|
||||||
FileInfo fileinfo;
|
|
||||||
char* name = malloc(MAX_NAME_LENGTH + 1);
|
|
||||||
while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) {
|
|
||||||
size_t size = strlen(clean_dir) + strlen(name) + 1 + 1;
|
|
||||||
char* fullname = malloc(size);
|
|
||||||
snprintf(fullname, size, "%s/%s", clean_dir, name);
|
|
||||||
if(fileinfo.flags & FSF_DIRECTORY) {
|
|
||||||
clean_directory(fs_api, fullname);
|
|
||||||
}
|
|
||||||
FS_Error error = storage_common_remove(fs_api, fullname);
|
|
||||||
furi_check(error == FSE_OK);
|
|
||||||
free(fullname);
|
|
||||||
}
|
|
||||||
free(name);
|
|
||||||
} else {
|
|
||||||
FS_Error error = storage_common_mkdir(fs_api, clean_dir);
|
|
||||||
(void)error;
|
|
||||||
furi_check(error == FSE_OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
storage_dir_close(dir);
|
|
||||||
storage_file_free(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_rpc_print_message_list(MsgList_t msg_list) {
|
static void test_rpc_print_message_list(MsgList_t msg_list) {
|
||||||
#if DEBUG_PRINT
|
#if DEBUG_PRINT
|
||||||
MsgList_reverse(msg_list);
|
MsgList_reverse(msg_list);
|
||||||
@@ -282,6 +281,27 @@ static void test_rpc_add_ping_to_list(MsgList_t msg_list, bool request, uint32_t
|
|||||||
response->which_content = (request == PING_REQUEST) ? PB_Main_system_ping_request_tag :
|
response->which_content = (request == PING_REQUEST) ? PB_Main_system_ping_request_tag :
|
||||||
PB_Main_system_ping_response_tag;
|
PB_Main_system_ping_response_tag;
|
||||||
}
|
}
|
||||||
|
static void test_rpc_fill_basic_message(PB_Main* message, uint16_t tag, uint32_t command_id) {
|
||||||
|
message->command_id = command_id;
|
||||||
|
message->command_status = PB_CommandStatus_OK;
|
||||||
|
message->cb_content.funcs.encode = NULL;
|
||||||
|
message->which_content = tag;
|
||||||
|
message->has_next = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_rpc_create_storage_list_request(
|
||||||
|
PB_Main* message,
|
||||||
|
const char* path,
|
||||||
|
bool include_md5,
|
||||||
|
uint32_t command_id,
|
||||||
|
uint32_t filter_max_size) {
|
||||||
|
furi_check(message);
|
||||||
|
furi_check(path);
|
||||||
|
test_rpc_fill_basic_message(message, PB_Main_storage_list_request_tag, command_id);
|
||||||
|
message->content.storage_list_request.path = strdup(path);
|
||||||
|
message->content.storage_list_request.include_md5 = include_md5;
|
||||||
|
message->content.storage_list_request.filter_max_size = filter_max_size;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_rpc_create_simple_message(
|
static void test_rpc_create_simple_message(
|
||||||
PB_Main* message,
|
PB_Main* message,
|
||||||
@@ -294,11 +314,7 @@ static void test_rpc_create_simple_message(
|
|||||||
if(str) {
|
if(str) {
|
||||||
str_copy = strdup(str);
|
str_copy = strdup(str);
|
||||||
}
|
}
|
||||||
message->command_id = command_id;
|
test_rpc_fill_basic_message(message, tag, command_id);
|
||||||
message->command_status = PB_CommandStatus_OK;
|
|
||||||
message->cb_content.funcs.encode = NULL;
|
|
||||||
message->which_content = tag;
|
|
||||||
message->has_next = false;
|
|
||||||
switch(tag) {
|
switch(tag) {
|
||||||
case PB_Main_storage_info_request_tag:
|
case PB_Main_storage_info_request_tag:
|
||||||
message->content.storage_info_request.path = str_copy;
|
message->content.storage_info_request.path = str_copy;
|
||||||
@@ -306,9 +322,6 @@ static void test_rpc_create_simple_message(
|
|||||||
case PB_Main_storage_stat_request_tag:
|
case PB_Main_storage_stat_request_tag:
|
||||||
message->content.storage_stat_request.path = str_copy;
|
message->content.storage_stat_request.path = str_copy;
|
||||||
break;
|
break;
|
||||||
case PB_Main_storage_list_request_tag:
|
|
||||||
message->content.storage_list_request.path = str_copy;
|
|
||||||
break;
|
|
||||||
case PB_Main_storage_mkdir_request_tag:
|
case PB_Main_storage_mkdir_request_tag:
|
||||||
message->content.storage_mkdir_request.path = str_copy;
|
message->content.storage_mkdir_request.path = str_copy;
|
||||||
break;
|
break;
|
||||||
@@ -419,6 +432,7 @@ static void
|
|||||||
}
|
}
|
||||||
mu_check(result_msg_file->size == expected_msg_file->size);
|
mu_check(result_msg_file->size == expected_msg_file->size);
|
||||||
mu_check(result_msg_file->type == expected_msg_file->type);
|
mu_check(result_msg_file->type == expected_msg_file->type);
|
||||||
|
mu_assert_string_eq(expected_msg_file->md5sum, result_msg_file->md5sum);
|
||||||
|
|
||||||
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
|
if(result_msg_file->data && result_msg_file->type != PB_Storage_File_FileType_DIR) {
|
||||||
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
|
mu_check(!result_msg_file->data == !expected_msg_file->data); // Zlo: WTF???
|
||||||
@@ -430,10 +444,10 @@ static void
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
static void test_rpc_compare_messages(PB_Main* result, PB_Main* expected) {
|
||||||
mu_check(result->command_id == expected->command_id);
|
mu_assert_int_eq(expected->command_id, result->command_id);
|
||||||
mu_check(result->command_status == expected->command_status);
|
mu_assert_int_eq(expected->command_status, result->command_status);
|
||||||
mu_check(result->has_next == expected->has_next);
|
mu_assert_int_eq(expected->has_next, result->has_next);
|
||||||
mu_check(result->which_content == expected->which_content);
|
mu_assert_int_eq(expected->which_content, result->which_content);
|
||||||
if(result->command_status != PB_CommandStatus_OK) {
|
if(result->command_status != PB_CommandStatus_OK) {
|
||||||
mu_check(result->which_content == PB_Main_empty_tag);
|
mu_check(result->which_content == PB_Main_empty_tag);
|
||||||
}
|
}
|
||||||
@@ -570,13 +584,36 @@ static void
|
|||||||
message->content.storage_list_response.file[2].name = str;
|
message->content.storage_list_response.file[2].name = str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool test_rpc_system_storage_list_filter(
|
||||||
|
const FileInfo* fileinfo,
|
||||||
|
const char* name,
|
||||||
|
size_t filter_max_size) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!path_contains_only_ascii(name)) break;
|
||||||
|
if(filter_max_size) {
|
||||||
|
if(fileinfo->size > filter_max_size) break;
|
||||||
|
}
|
||||||
|
result = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void test_rpc_storage_list_create_expected_list(
|
static void test_rpc_storage_list_create_expected_list(
|
||||||
MsgList_t msg_list,
|
MsgList_t msg_list,
|
||||||
const char* path,
|
const char* path,
|
||||||
uint32_t command_id) {
|
uint32_t command_id,
|
||||||
|
bool append_md5,
|
||||||
|
size_t filter_max_size) {
|
||||||
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
Storage* fs_api = furi_record_open(RECORD_STORAGE);
|
||||||
File* dir = storage_file_alloc(fs_api);
|
File* dir = storage_file_alloc(fs_api);
|
||||||
|
|
||||||
|
FuriString* md5 = furi_string_alloc();
|
||||||
|
FuriString* md5_path = furi_string_alloc();
|
||||||
|
File* file = storage_file_alloc(fs_api);
|
||||||
|
|
||||||
PB_Main response = {
|
PB_Main response = {
|
||||||
.command_id = command_id,
|
.command_id = command_id,
|
||||||
.has_next = false,
|
.has_next = false,
|
||||||
@@ -607,14 +644,24 @@ static void test_rpc_storage_list_create_expected_list(
|
|||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(path_contains_only_ascii(name)) {
|
if(test_rpc_system_storage_list_filter(&fileinfo, name, filter_max_size)) {
|
||||||
list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ?
|
list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR :
|
||||||
PB_Storage_File_FileType_DIR :
|
PB_Storage_File_FileType_FILE;
|
||||||
PB_Storage_File_FileType_FILE;
|
|
||||||
list->file[i].size = fileinfo.size;
|
list->file[i].size = fileinfo.size;
|
||||||
list->file[i].data = NULL;
|
list->file[i].data = NULL;
|
||||||
/* memory free inside rpc_encode_and_send() -> pb_release() */
|
/* memory free inside rpc_encode_and_send() -> pb_release() */
|
||||||
list->file[i].name = name;
|
list->file[i].name = name;
|
||||||
|
|
||||||
|
if(append_md5 && !file_info_is_dir(&fileinfo)) {
|
||||||
|
furi_string_printf(md5_path, "%s/%s", path, name);
|
||||||
|
|
||||||
|
if(md5_string_calc_file(file, furi_string_get_cstr(md5_path), md5, NULL)) {
|
||||||
|
char* md5sum = list->file[i].md5sum;
|
||||||
|
size_t md5sum_size = sizeof(list->file[i].md5sum);
|
||||||
|
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -627,6 +674,10 @@ static void test_rpc_storage_list_create_expected_list(
|
|||||||
response.has_next = false;
|
response.has_next = false;
|
||||||
MsgList_push_back(msg_list, response);
|
MsgList_push_back(msg_list, response);
|
||||||
|
|
||||||
|
furi_string_free(md5);
|
||||||
|
furi_string_free(md5_path);
|
||||||
|
storage_file_free(file);
|
||||||
|
|
||||||
storage_dir_close(dir);
|
storage_dir_close(dir);
|
||||||
storage_file_free(dir);
|
storage_file_free(dir);
|
||||||
|
|
||||||
@@ -676,16 +727,21 @@ static void test_rpc_free_msg_list(MsgList_t msg_list) {
|
|||||||
MsgList_clear(msg_list);
|
MsgList_clear(msg_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_rpc_storage_list_run(const char* path, uint32_t command_id) {
|
static void test_rpc_storage_list_run(
|
||||||
|
const char* path,
|
||||||
|
uint32_t command_id,
|
||||||
|
bool md5,
|
||||||
|
size_t filter_max_size) {
|
||||||
PB_Main request;
|
PB_Main request;
|
||||||
MsgList_t expected_msg_list;
|
MsgList_t expected_msg_list;
|
||||||
MsgList_init(expected_msg_list);
|
MsgList_init(expected_msg_list);
|
||||||
|
|
||||||
test_rpc_create_simple_message(&request, PB_Main_storage_list_request_tag, path, command_id);
|
test_rpc_create_storage_list_request(&request, path, md5, command_id, filter_max_size);
|
||||||
if(!strcmp(path, "/")) {
|
if(!strcmp(path, "/")) {
|
||||||
test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id);
|
test_rpc_storage_list_create_expected_list_root(expected_msg_list, command_id);
|
||||||
} else {
|
} else {
|
||||||
test_rpc_storage_list_create_expected_list(expected_msg_list, path, command_id);
|
test_rpc_storage_list_create_expected_list(
|
||||||
|
expected_msg_list, path, command_id, md5, filter_max_size);
|
||||||
}
|
}
|
||||||
test_rpc_encode_and_feed_one(&request, 0);
|
test_rpc_encode_and_feed_one(&request, 0);
|
||||||
test_rpc_decode_and_compare(expected_msg_list, 0);
|
test_rpc_decode_and_compare(expected_msg_list, 0);
|
||||||
@@ -695,15 +751,32 @@ static void test_rpc_storage_list_run(const char* path, uint32_t command_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(test_storage_list) {
|
MU_TEST(test_storage_list) {
|
||||||
test_rpc_storage_list_run("/", ++command_id);
|
test_rpc_storage_list_run("/", ++command_id, false, 0);
|
||||||
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id);
|
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run("error_path", ++command_id, false, 0);
|
||||||
|
}
|
||||||
|
|
||||||
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id);
|
MU_TEST(test_storage_list_md5) {
|
||||||
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id);
|
test_rpc_storage_list_run("/", ++command_id, true, 0);
|
||||||
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id);
|
test_rpc_storage_list_run(EXT_PATH("nfc"), ++command_id, true, 0);
|
||||||
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id);
|
test_rpc_storage_list_run(STORAGE_INT_PATH_PREFIX, ++command_id, true, 0);
|
||||||
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id);
|
test_rpc_storage_list_run(STORAGE_EXT_PATH_PREFIX, ++command_id, true, 0);
|
||||||
test_rpc_storage_list_run("error_path", ++command_id);
|
test_rpc_storage_list_run(EXT_PATH("infrared"), ++command_id, true, 0);
|
||||||
|
test_rpc_storage_list_run(EXT_PATH("ibutton"), ++command_id, true, 0);
|
||||||
|
test_rpc_storage_list_run(EXT_PATH("lfrfid"), ++command_id, true, 0);
|
||||||
|
test_rpc_storage_list_run("error_path", ++command_id, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_storage_list_size) {
|
||||||
|
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 0);
|
||||||
|
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1);
|
||||||
|
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 1000);
|
||||||
|
test_rpc_storage_list_run(TEST_DIR_NAME, ++command_id, false, 2500);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -873,7 +946,7 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) {
|
|||||||
if(error == FSE_OK) {
|
if(error == FSE_OK) {
|
||||||
response->which_content = PB_Main_storage_stat_response_tag;
|
response->which_content = PB_Main_storage_stat_response_tag;
|
||||||
response->content.storage_stat_response.has_file = true;
|
response->content.storage_stat_response.has_file = true;
|
||||||
response->content.storage_stat_response.file.type = (fileinfo.flags & FSF_DIRECTORY) ?
|
response->content.storage_stat_response.file.type = file_info_is_dir(&fileinfo) ?
|
||||||
PB_Storage_File_FileType_DIR :
|
PB_Storage_File_FileType_DIR :
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
response->content.storage_stat_response.file.size = fileinfo.size;
|
response->content.storage_stat_response.file.size = fileinfo.size;
|
||||||
@@ -1230,33 +1303,15 @@ MU_TEST(test_storage_mkdir) {
|
|||||||
static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) {
|
static void test_storage_calculate_md5sum(const char* path, char* md5sum, size_t md5sum_size) {
|
||||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||||
File* file = storage_file_alloc(api);
|
File* file = storage_file_alloc(api);
|
||||||
|
FuriString* md5 = furi_string_alloc();
|
||||||
|
|
||||||
if(storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
if(md5_string_calc_file(file, path, md5, NULL)) {
|
||||||
const uint16_t once_read_size = 512;
|
snprintf(md5sum, md5sum_size, "%s", furi_string_get_cstr(md5));
|
||||||
const uint8_t hash_size = MD5SUM_SIZE;
|
|
||||||
uint8_t* data = malloc(once_read_size);
|
|
||||||
uint8_t* hash = malloc(sizeof(uint8_t) * hash_size);
|
|
||||||
md5_context* md5_ctx = malloc(sizeof(md5_context));
|
|
||||||
|
|
||||||
md5_starts(md5_ctx);
|
|
||||||
while(true) {
|
|
||||||
uint16_t read_size = storage_file_read(file, data, once_read_size);
|
|
||||||
if(read_size == 0) break;
|
|
||||||
md5_update(md5_ctx, data, read_size);
|
|
||||||
}
|
|
||||||
md5_finish(md5_ctx, hash);
|
|
||||||
free(md5_ctx);
|
|
||||||
|
|
||||||
for(uint8_t i = 0; i < hash_size; i++) {
|
|
||||||
md5sum += snprintf(md5sum, md5sum_size, "%02x", hash[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(hash);
|
|
||||||
free(data);
|
|
||||||
} else {
|
} else {
|
||||||
furi_check(0);
|
furi_check(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
furi_string_free(md5);
|
||||||
storage_file_close(file);
|
storage_file_close(file);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|
||||||
@@ -1434,6 +1489,8 @@ MU_TEST_SUITE(test_rpc_storage) {
|
|||||||
MU_RUN_TEST(test_storage_info);
|
MU_RUN_TEST(test_storage_info);
|
||||||
MU_RUN_TEST(test_storage_stat);
|
MU_RUN_TEST(test_storage_stat);
|
||||||
MU_RUN_TEST(test_storage_list);
|
MU_RUN_TEST(test_storage_list);
|
||||||
|
MU_RUN_TEST(test_storage_list_md5);
|
||||||
|
MU_RUN_TEST(test_storage_list_size);
|
||||||
MU_RUN_TEST(test_storage_read);
|
MU_RUN_TEST(test_storage_read);
|
||||||
MU_RUN_TEST(test_storage_write_read);
|
MU_RUN_TEST(test_storage_write_read);
|
||||||
MU_RUN_TEST(test_storage_write);
|
MU_RUN_TEST(test_storage_write);
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ MU_TEST_1(test_dirwalk_full, Storage* storage) {
|
|||||||
|
|
||||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_walk_free(dir_walk);
|
dir_walk_free(dir_walk);
|
||||||
@@ -204,7 +204,7 @@ MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) {
|
|||||||
|
|
||||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_walk_free(dir_walk);
|
dir_walk_free(dir_walk);
|
||||||
@@ -219,7 +219,7 @@ static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* filein
|
|||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
|
|
||||||
// only files
|
// only files
|
||||||
if(!(fileinfo->flags & FSF_DIRECTORY)) {
|
if(!file_info_is_dir(fileinfo)) {
|
||||||
// with ".test" in name
|
// with ".test" in name
|
||||||
if(strstr(name, ".test") != NULL) {
|
if(strstr(name, ".test") != NULL) {
|
||||||
return true;
|
return true;
|
||||||
@@ -243,7 +243,7 @@ MU_TEST_1(test_dirwalk_filter, Storage* storage) {
|
|||||||
|
|
||||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
||||||
mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY)));
|
mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo)));
|
||||||
}
|
}
|
||||||
|
|
||||||
dir_walk_free(dir_walk);
|
dir_walk_free(dir_walk);
|
||||||
|
|||||||
@@ -2,9 +2,40 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
// DO NOT USE THIS IN PRODUCTION CODE
|
||||||
|
// This is a hack to access internal storage functions and definitions
|
||||||
|
#include <storage/storage_i.h>
|
||||||
|
|
||||||
|
#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path)
|
||||||
|
|
||||||
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
||||||
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
||||||
|
|
||||||
|
#define STORAGE_TEST_DIR UNIT_TESTS_PATH("test_dir")
|
||||||
|
|
||||||
|
static bool storage_file_create(Storage* storage, const char* path, const char* data) {
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
bool result = false;
|
||||||
|
do {
|
||||||
|
if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_NEW)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(storage_file_write(file, data, strlen(data)) != strlen(data)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!storage_file_close(file)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
storage_file_free(file);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void storage_file_open_lock_setup() {
|
static void storage_file_open_lock_setup() {
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
File* file = storage_file_alloc(storage);
|
File* file = storage_file_alloc(storage);
|
||||||
@@ -115,7 +146,7 @@ static int32_t storage_dir_locker(void* ctx) {
|
|||||||
File* file = storage_file_alloc(storage);
|
File* file = storage_file_alloc(storage);
|
||||||
furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
||||||
furi_semaphore_release(semaphore);
|
furi_semaphore_release(semaphore);
|
||||||
furi_delay_ms(1000);
|
furi_delay_ms(100);
|
||||||
|
|
||||||
furi_check(storage_dir_close(file));
|
furi_check(storage_dir_close(file));
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
@@ -152,9 +183,21 @@ MU_TEST(storage_dir_open_lock) {
|
|||||||
mu_assert(result, "cannot open locked dir");
|
mu_assert(result, "cannot open locked dir");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(storage_dir_exists_test) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
mu_check(!storage_dir_exists(storage, STORAGE_TEST_DIR));
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, STORAGE_TEST_DIR));
|
||||||
|
mu_check(storage_dir_exists(storage, STORAGE_TEST_DIR));
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_remove(storage, STORAGE_TEST_DIR));
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(storage_dir) {
|
MU_TEST_SUITE(storage_dir) {
|
||||||
MU_RUN_TEST(storage_dir_open_close);
|
MU_RUN_TEST(storage_dir_open_close);
|
||||||
MU_RUN_TEST(storage_dir_open_lock);
|
MU_RUN_TEST(storage_dir_open_lock);
|
||||||
|
MU_RUN_TEST(storage_dir_exists_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const storage_copy_test_paths[] = {
|
static const char* const storage_copy_test_paths[] = {
|
||||||
@@ -303,9 +346,304 @@ MU_TEST_SUITE(storage_rename) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define APPSDATA_APP_PATH(path) APPS_DATA_PATH "/" path
|
||||||
|
|
||||||
|
static const char* storage_test_apps[] = {
|
||||||
|
"-_twilight_-",
|
||||||
|
"-_rainbow_-",
|
||||||
|
"-_pinkie_-",
|
||||||
|
"-_apple_-",
|
||||||
|
"-_flutter_-",
|
||||||
|
"-_rare_-",
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t storage_test_apps_count = COUNT_OF(storage_test_apps);
|
||||||
|
|
||||||
|
static int32_t storage_test_app(void* arg) {
|
||||||
|
UNUSED(arg);
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
storage_common_remove(storage, "/data/test");
|
||||||
|
int32_t ret = storage_file_create(storage, "/data/test", "test");
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_storage_data_path_apps) {
|
||||||
|
for(size_t i = 0; i < storage_test_apps_count; i++) {
|
||||||
|
FuriThread* thread =
|
||||||
|
furi_thread_alloc_ex(storage_test_apps[i], 1024, storage_test_app, NULL);
|
||||||
|
furi_thread_set_appid(thread, storage_test_apps[i]);
|
||||||
|
furi_thread_start(thread);
|
||||||
|
furi_thread_join(thread);
|
||||||
|
|
||||||
|
mu_assert_int_eq(true, furi_thread_get_return_code(thread));
|
||||||
|
|
||||||
|
// Check if app data dir and file exists
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
FuriString* expected = furi_string_alloc();
|
||||||
|
furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]);
|
||||||
|
|
||||||
|
mu_check(storage_dir_exists(storage, furi_string_get_cstr(expected)));
|
||||||
|
furi_string_cat(expected, "/test");
|
||||||
|
mu_check(storage_file_exists(storage, furi_string_get_cstr(expected)));
|
||||||
|
|
||||||
|
furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]);
|
||||||
|
storage_simply_remove_recursive(storage, furi_string_get_cstr(expected));
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
furi_string_free(expected);
|
||||||
|
furi_thread_free(thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_storage_data_path) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
mu_check(storage_dir_open(file, "/data"));
|
||||||
|
mu_check(storage_dir_close(file));
|
||||||
|
storage_file_free(file);
|
||||||
|
|
||||||
|
// check that appsdata folder exists
|
||||||
|
mu_check(storage_dir_exists(storage, APPS_DATA_PATH));
|
||||||
|
|
||||||
|
// check that cli folder exists
|
||||||
|
mu_check(storage_dir_exists(storage, APPSDATA_APP_PATH("cli")));
|
||||||
|
|
||||||
|
storage_simply_remove(storage, APPSDATA_APP_PATH("cli"));
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_storage_common_migrate) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
// Setup test folders
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
|
||||||
|
// Test migration from non existing
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
// Test migration from existing folder to non existing
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file1"), "test1"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file2.ext"), "test2"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file3.ext.ext"), "test3"));
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file1")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file2.ext")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext.ext")));
|
||||||
|
mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
|
||||||
|
// Test migration from existing folder to existing folder
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file1"), "test1"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file2.ext"), "test2"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file3.ext.ext"), "test3"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file1")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file2.ext")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext.ext")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file11")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file21.ext")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext1.ext")));
|
||||||
|
mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
|
||||||
|
// Test migration from empty folder to existing file
|
||||||
|
// Expected result: FSE_OK, folder removed, file untouched
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new"), "test1"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
|
||||||
|
// Test migration from empty folder to existing folder
|
||||||
|
// Expected result: FSE_OK, old folder removed, new folder untouched
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
|
||||||
|
// Test migration from existing file to non existing, no extension
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
|
||||||
|
// Test migration from existing file to non existing, with extension
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old.file"), "test1"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old.file"), UNIT_TESTS_PATH("migrate_new.file")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new.file")));
|
||||||
|
mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old.file")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old.file"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new.file"));
|
||||||
|
|
||||||
|
// Test migration from existing file to existing file, no extension
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new"), "test2"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1"));
|
||||||
|
|
||||||
|
// Test migration from existing file to existing file, with extension
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old.file"), "test1"));
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new.file"), "test2"));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old.file"), UNIT_TESTS_PATH("migrate_new.file")));
|
||||||
|
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new.file")));
|
||||||
|
mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old.file")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1.file")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old.file"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new.file"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1.file"));
|
||||||
|
|
||||||
|
// Test migration from existing file to existing folder
|
||||||
|
mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1"));
|
||||||
|
mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
FSE_OK,
|
||||||
|
storage_common_migrate(
|
||||||
|
storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
|
||||||
|
mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new")));
|
||||||
|
mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old")));
|
||||||
|
mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1")));
|
||||||
|
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new"));
|
||||||
|
storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1"));
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MD5_HASH_SIZE (16)
|
||||||
|
#include <lib/toolbox/md5_calc.h>
|
||||||
|
|
||||||
|
MU_TEST(test_md5_calc) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
|
||||||
|
const char* path = UNIT_TESTS_PATH("storage/md5.txt");
|
||||||
|
const char* md5_cstr = "2a456fa43e75088fdde41c93159d62a2";
|
||||||
|
const uint8_t md5[MD5_HASH_SIZE] = {
|
||||||
|
0x2a,
|
||||||
|
0x45,
|
||||||
|
0x6f,
|
||||||
|
0xa4,
|
||||||
|
0x3e,
|
||||||
|
0x75,
|
||||||
|
0x08,
|
||||||
|
0x8f,
|
||||||
|
0xdd,
|
||||||
|
0xe4,
|
||||||
|
0x1c,
|
||||||
|
0x93,
|
||||||
|
0x15,
|
||||||
|
0x9d,
|
||||||
|
0x62,
|
||||||
|
0xa2,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t md5_output[MD5_HASH_SIZE];
|
||||||
|
FuriString* md5_output_str = furi_string_alloc();
|
||||||
|
memset(md5_output, 0, MD5_HASH_SIZE);
|
||||||
|
|
||||||
|
mu_check(md5_calc_file(file, path, md5_output, NULL));
|
||||||
|
mu_check(md5_string_calc_file(file, path, md5_output_str, NULL));
|
||||||
|
|
||||||
|
mu_assert_mem_eq(md5, md5_output, MD5_HASH_SIZE);
|
||||||
|
mu_assert_string_eq(md5_cstr, furi_string_get_cstr(md5_output_str));
|
||||||
|
|
||||||
|
storage_file_free(file);
|
||||||
|
furi_string_free(md5_output_str);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_data_path) {
|
||||||
|
MU_RUN_TEST(test_storage_data_path);
|
||||||
|
MU_RUN_TEST(test_storage_data_path_apps);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_storage_common) {
|
||||||
|
MU_RUN_TEST(test_storage_common_migrate);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_md5_calc_suite) {
|
||||||
|
MU_RUN_TEST(test_md5_calc);
|
||||||
|
}
|
||||||
|
|
||||||
int run_minunit_test_storage() {
|
int run_minunit_test_storage() {
|
||||||
MU_RUN_SUITE(storage_file);
|
MU_RUN_SUITE(storage_file);
|
||||||
MU_RUN_SUITE(storage_dir);
|
MU_RUN_SUITE(storage_dir);
|
||||||
MU_RUN_SUITE(storage_rename);
|
MU_RUN_SUITE(storage_rename);
|
||||||
|
MU_RUN_SUITE(test_data_path);
|
||||||
|
MU_RUN_SUITE(test_storage_common);
|
||||||
|
MU_RUN_SUITE(test_md5_calc_suite);
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||||
#include <lib/subghz/protocols/protocol_items.h>
|
#include <lib/subghz/protocols/protocol_items.h>
|
||||||
#include <flipper_format/flipper_format_i.h>
|
#include <flipper_format/flipper_format_i.h>
|
||||||
|
#include <lib/subghz/devices/devices.h>
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#define TAG "SubGhz TEST"
|
#define TAG "SubGhzTest"
|
||||||
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||||
@@ -40,8 +42,6 @@ static void subghz_test_rx_callback(
|
|||||||
|
|
||||||
static void subghz_test_init(void) {
|
static void subghz_test_init(void) {
|
||||||
environment_handler = subghz_environment_alloc();
|
environment_handler = subghz_environment_alloc();
|
||||||
subghz_environment_set_came_atomo_rainbow_table_file_name(
|
|
||||||
environment_handler, CAME_ATOMO_DIR_NAME);
|
|
||||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||||
environment_handler, NICE_FLOR_S_DIR_NAME);
|
environment_handler, NICE_FLOR_S_DIR_NAME);
|
||||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||||
@@ -49,12 +49,15 @@ static void subghz_test_init(void) {
|
|||||||
subghz_environment_set_protocol_registry(
|
subghz_environment_set_protocol_registry(
|
||||||
environment_handler, (void*)&subghz_protocol_registry);
|
environment_handler, (void*)&subghz_protocol_registry);
|
||||||
|
|
||||||
|
subghz_devices_init();
|
||||||
|
|
||||||
receiver_handler = subghz_receiver_alloc_init(environment_handler);
|
receiver_handler = subghz_receiver_alloc_init(environment_handler);
|
||||||
subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable);
|
subghz_receiver_set_filter(receiver_handler, SubGhzProtocolFlag_Decodable);
|
||||||
subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL);
|
subghz_receiver_set_rx_callback(receiver_handler, subghz_test_rx_callback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_test_deinit(void) {
|
static void subghz_test_deinit(void) {
|
||||||
|
subghz_devices_deinit();
|
||||||
subghz_receiver_free(receiver_handler);
|
subghz_receiver_free(receiver_handler);
|
||||||
subghz_environment_free(environment_handler);
|
subghz_environment_free(environment_handler);
|
||||||
}
|
}
|
||||||
@@ -68,7 +71,7 @@ static bool subghz_decoder_test(const char* path, const char* name_decoder) {
|
|||||||
|
|
||||||
if(decoder) {
|
if(decoder) {
|
||||||
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
||||||
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
|
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path, NULL)) {
|
||||||
// the worker needs a file in order to open and read part of the file
|
// the worker needs a file in order to open and read part of the file
|
||||||
furi_delay_ms(100);
|
furi_delay_ms(100);
|
||||||
|
|
||||||
@@ -108,7 +111,7 @@ static bool subghz_decode_random_test(const char* path) {
|
|||||||
uint32_t test_start = furi_get_tick();
|
uint32_t test_start = furi_get_tick();
|
||||||
|
|
||||||
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
file_worker_encoder_handler = subghz_file_encoder_worker_alloc();
|
||||||
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path)) {
|
if(subghz_file_encoder_worker_start(file_worker_encoder_handler, path, NULL)) {
|
||||||
// the worker needs a file in order to open and read part of the file
|
// the worker needs a file in order to open and read part of the file
|
||||||
furi_delay_ms(100);
|
furi_delay_ms(100);
|
||||||
|
|
||||||
@@ -318,14 +321,19 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) {
|
|||||||
SubGhzHalAsyncTxTest test = {0};
|
SubGhzHalAsyncTxTest test = {0};
|
||||||
test.type = type;
|
test.type = type;
|
||||||
furi_hal_subghz_reset();
|
furi_hal_subghz_reset();
|
||||||
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
|
furi_hal_subghz_load_custom_preset(subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||||
furi_hal_subghz_set_frequency_and_path(433920000);
|
furi_hal_subghz_set_frequency_and_path(433920000);
|
||||||
|
|
||||||
if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) {
|
if(!furi_hal_subghz_start_async_tx(subghz_hal_async_tx_test_yield, &test)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(30000000);
|
||||||
|
|
||||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||||
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
furi_delay_ms(10);
|
furi_delay_ms(10);
|
||||||
}
|
}
|
||||||
furi_hal_subghz_stop_async_tx();
|
furi_hal_subghz_stop_async_tx();
|
||||||
@@ -407,7 +415,7 @@ MU_TEST(subghz_decoder_ido_test) {
|
|||||||
"Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n");
|
"Test decoder " SUBGHZ_PROTOCOL_IDO_NAME " error\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(subghz_decoder_keelog_test) {
|
MU_TEST(subghz_decoder_keeloq_test) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
subghz_decoder_test(
|
subghz_decoder_test(
|
||||||
EXT_PATH("unit_tests/subghz/doorhan_raw.sub"), SUBGHZ_PROTOCOL_KEELOQ_NAME),
|
EXT_PATH("unit_tests/subghz/doorhan_raw.sub"), SUBGHZ_PROTOCOL_KEELOQ_NAME),
|
||||||
@@ -676,7 +684,7 @@ MU_TEST(subghz_encoder_nice_flo_test) {
|
|||||||
"Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
|
"Test encoder " SUBGHZ_PROTOCOL_NICE_FLO_NAME " error\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(subghz_encoder_keelog_test) {
|
MU_TEST(subghz_encoder_keeloq_test) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
subghz_encoder_test(EXT_PATH("unit_tests/subghz/doorhan.sub")),
|
subghz_encoder_test(EXT_PATH("unit_tests/subghz/doorhan.sub")),
|
||||||
"Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
|
"Test encoder " SUBGHZ_PROTOCOL_KEELOQ_NAME " error\r\n");
|
||||||
@@ -813,7 +821,7 @@ MU_TEST_SUITE(subghz) {
|
|||||||
MU_RUN_TEST(subghz_decoder_gate_tx_test);
|
MU_RUN_TEST(subghz_decoder_gate_tx_test);
|
||||||
MU_RUN_TEST(subghz_decoder_hormann_hsm_test);
|
MU_RUN_TEST(subghz_decoder_hormann_hsm_test);
|
||||||
MU_RUN_TEST(subghz_decoder_ido_test);
|
MU_RUN_TEST(subghz_decoder_ido_test);
|
||||||
MU_RUN_TEST(subghz_decoder_keelog_test);
|
MU_RUN_TEST(subghz_decoder_keeloq_test);
|
||||||
MU_RUN_TEST(subghz_decoder_kia_seed_test);
|
MU_RUN_TEST(subghz_decoder_kia_seed_test);
|
||||||
MU_RUN_TEST(subghz_decoder_nero_radio_test);
|
MU_RUN_TEST(subghz_decoder_nero_radio_test);
|
||||||
MU_RUN_TEST(subghz_decoder_nero_sketch_test);
|
MU_RUN_TEST(subghz_decoder_nero_sketch_test);
|
||||||
@@ -852,7 +860,7 @@ MU_TEST_SUITE(subghz) {
|
|||||||
MU_RUN_TEST(subghz_encoder_came_twee_test);
|
MU_RUN_TEST(subghz_encoder_came_twee_test);
|
||||||
MU_RUN_TEST(subghz_encoder_gate_tx_test);
|
MU_RUN_TEST(subghz_encoder_gate_tx_test);
|
||||||
MU_RUN_TEST(subghz_encoder_nice_flo_test);
|
MU_RUN_TEST(subghz_encoder_nice_flo_test);
|
||||||
MU_RUN_TEST(subghz_encoder_keelog_test);
|
MU_RUN_TEST(subghz_encoder_keeloq_test);
|
||||||
MU_RUN_TEST(subghz_encoder_linear_test);
|
MU_RUN_TEST(subghz_encoder_linear_test);
|
||||||
MU_RUN_TEST(subghz_encoder_linear_delta3_test);
|
MU_RUN_TEST(subghz_encoder_linear_delta3_test);
|
||||||
MU_RUN_TEST(subghz_encoder_megacode_test);
|
MU_RUN_TEST(subghz_encoder_megacode_test);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
int run_minunit_test_furi();
|
int run_minunit_test_furi();
|
||||||
int run_minunit_test_furi_hal();
|
int run_minunit_test_furi_hal();
|
||||||
|
int run_minunit_test_furi_hal_crypto();
|
||||||
int run_minunit_test_furi_string();
|
int run_minunit_test_furi_string();
|
||||||
int run_minunit_test_infrared();
|
int run_minunit_test_infrared();
|
||||||
int run_minunit_test_rpc();
|
int run_minunit_test_rpc();
|
||||||
@@ -27,6 +28,7 @@ int run_minunit_test_nfc();
|
|||||||
int run_minunit_test_bit_lib();
|
int run_minunit_test_bit_lib();
|
||||||
int run_minunit_test_float_tools();
|
int run_minunit_test_float_tools();
|
||||||
int run_minunit_test_bt();
|
int run_minunit_test_bt();
|
||||||
|
int run_minunit_test_dialogs_file_browser_options();
|
||||||
|
|
||||||
typedef int (*UnitTestEntry)();
|
typedef int (*UnitTestEntry)();
|
||||||
|
|
||||||
@@ -38,6 +40,7 @@ typedef struct {
|
|||||||
const UnitTest unit_tests[] = {
|
const UnitTest unit_tests[] = {
|
||||||
{.name = "furi", .entry = run_minunit_test_furi},
|
{.name = "furi", .entry = run_minunit_test_furi},
|
||||||
{.name = "furi_hal", .entry = run_minunit_test_furi_hal},
|
{.name = "furi_hal", .entry = run_minunit_test_furi_hal},
|
||||||
|
{.name = "furi_hal_crypto", .entry = run_minunit_test_furi_hal_crypto},
|
||||||
{.name = "furi_string", .entry = run_minunit_test_furi_string},
|
{.name = "furi_string", .entry = run_minunit_test_furi_string},
|
||||||
{.name = "storage", .entry = run_minunit_test_storage},
|
{.name = "storage", .entry = run_minunit_test_storage},
|
||||||
{.name = "stream", .entry = run_minunit_test_stream},
|
{.name = "stream", .entry = run_minunit_test_stream},
|
||||||
@@ -55,6 +58,8 @@ const UnitTest unit_tests[] = {
|
|||||||
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
||||||
{.name = "float_tools", .entry = run_minunit_test_float_tools},
|
{.name = "float_tools", .entry = run_minunit_test_float_tools},
|
||||||
{.name = "bt", .entry = run_minunit_test_bt},
|
{.name = "bt", .entry = run_minunit_test_bt},
|
||||||
|
{.name = "dialogs_file_browser_options",
|
||||||
|
.entry = run_minunit_test_dialogs_file_browser_options},
|
||||||
};
|
};
|
||||||
|
|
||||||
void minunit_print_progress() {
|
void minunit_print_progress() {
|
||||||
@@ -85,7 +90,7 @@ void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
Loader* loader = furi_record_open(RECORD_LOADER);
|
Loader* loader = furi_record_open(RECORD_LOADER);
|
||||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
// TODO: lock device while test running
|
// TODO FL-3491: lock device while test running
|
||||||
if(loader_is_locked(loader)) {
|
if(loader_is_locked(loader)) {
|
||||||
printf("RPC: stop all applications to run tests\r\n");
|
printf("RPC: stop all applications to run tests\r\n");
|
||||||
notification_message(notification, &sequence_blink_magenta_100);
|
notification_message(notification, &sequence_blink_magenta_100);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
App(
|
App(
|
||||||
appid="USB_Mouse",
|
appid="usb_mouse",
|
||||||
name="USB Mouse",
|
name="USB Mouse",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="usb_mouse_app",
|
entry_point="usb_mouse_app",
|
||||||
@@ -7,6 +7,5 @@ App(
|
|||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=60,
|
order=60,
|
||||||
fap_icon="../../plugins/mousejacker/mouse_10px.png",
|
|
||||||
fap_category="Debug",
|
fap_category="Debug",
|
||||||
)
|
)
|
||||||
|
|||||||
6
applications/drivers/application.fam
Normal file
6
applications/drivers/application.fam
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Placeholder
|
||||||
|
App(
|
||||||
|
appid="drivers",
|
||||||
|
name="Drivers device",
|
||||||
|
apptype=FlipperAppType.METAPACKAGE,
|
||||||
|
)
|
||||||
9
applications/drivers/subghz/application.fam
Normal file
9
applications/drivers/subghz/application.fam
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
App(
|
||||||
|
appid="radio_device_cc1101_ext",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
targets=["f7"],
|
||||||
|
entry_point="subghz_device_cc1101_ext_ep",
|
||||||
|
requires=["subghz"],
|
||||||
|
sdk_headers=["cc1101_ext/cc1101_ext_interconnect.h"],
|
||||||
|
fap_libs=["hwdrivers"],
|
||||||
|
)
|
||||||
850
applications/drivers/subghz/cc1101_ext/cc1101_ext.c
Normal file
850
applications/drivers/subghz/cc1101_ext/cc1101_ext.c
Normal file
@@ -0,0 +1,850 @@
|
|||||||
|
#include "cc1101_ext.h"
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
|
#include <furi_hal_version.h>
|
||||||
|
#include <furi_hal_rtc.h>
|
||||||
|
#include <furi_hal_spi.h>
|
||||||
|
#include <furi_hal_interrupt.h>
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
#include <furi_hal_bus.h>
|
||||||
|
|
||||||
|
#include <stm32wbxx_ll_dma.h>
|
||||||
|
#include <furi_hal_cortex.h>
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <cc1101.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define TAG "SubGhzDeviceCc1101Ext"
|
||||||
|
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO &gpio_ext_pb2
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO &gpio_ext_pc3
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
||||||
|
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
||||||
|
|
||||||
|
/* DMA Channels definition */
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA DMA2
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL LL_DMA_CHANNEL_3
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL LL_DMA_CHANNEL_4
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL LL_DMA_CHANNEL_5
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ FuriHalInterruptIdDma2Ch3
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF \
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL
|
||||||
|
|
||||||
|
/** Low level buffer dimensions and guard times */
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL (256)
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF \
|
||||||
|
(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL / 2)
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME 999 << 1
|
||||||
|
|
||||||
|
/** SubGhz state */
|
||||||
|
typedef enum {
|
||||||
|
SubGhzDeviceCC1101ExtStateInit, /**< Init pending */
|
||||||
|
SubGhzDeviceCC1101ExtStateIdle, /**< Idle, energy save mode */
|
||||||
|
SubGhzDeviceCC1101ExtStateAsyncRx, /**< Async RX started */
|
||||||
|
SubGhzDeviceCC1101ExtStateAsyncTx, /**< Async TX started, DMA and timer is on */
|
||||||
|
SubGhzDeviceCC1101ExtStateAsyncTxEnd, /**< Async TX complete, cleanup needed */
|
||||||
|
} SubGhzDeviceCC1101ExtState;
|
||||||
|
|
||||||
|
/** SubGhz regulation, receive transmission on the current frequency for the
|
||||||
|
* region */
|
||||||
|
typedef enum {
|
||||||
|
SubGhzDeviceCC1101ExtRegulationOnlyRx, /**only Rx*/
|
||||||
|
SubGhzDeviceCC1101ExtRegulationTxRx, /**TxRx*/
|
||||||
|
} SubGhzDeviceCC1101ExtRegulation;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t* buffer;
|
||||||
|
LevelDuration carry_ld;
|
||||||
|
SubGhzDeviceCC1101ExtCallback callback;
|
||||||
|
void* callback_context;
|
||||||
|
uint32_t gpio_tx_buff[2];
|
||||||
|
uint32_t debug_gpio_buff[2];
|
||||||
|
} SubGhzDeviceCC1101ExtAsyncTx;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t capture_delta_duration;
|
||||||
|
SubGhzDeviceCC1101ExtCaptureCallback capture_callback;
|
||||||
|
void* capture_callback_context;
|
||||||
|
} SubGhzDeviceCC1101ExtAsyncRx;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
volatile SubGhzDeviceCC1101ExtState state;
|
||||||
|
volatile SubGhzDeviceCC1101ExtRegulation regulation;
|
||||||
|
const GpioPin* async_mirror_pin;
|
||||||
|
FuriHalSpiBusHandle* spi_bus_handle;
|
||||||
|
const GpioPin* g0_pin;
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTx async_tx;
|
||||||
|
SubGhzDeviceCC1101ExtAsyncRx async_rx;
|
||||||
|
bool power_amp;
|
||||||
|
bool extended_range;
|
||||||
|
} SubGhzDeviceCC1101Ext;
|
||||||
|
|
||||||
|
static SubGhzDeviceCC1101Ext* subghz_device_cc1101_ext = NULL;
|
||||||
|
|
||||||
|
static bool subghz_device_cc1101_ext_check_init() {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateInit);
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle;
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
CC1101Status cc1101_status = {0};
|
||||||
|
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(100 * 1000);
|
||||||
|
do {
|
||||||
|
// Reset
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle->miso,
|
||||||
|
GpioModeInput,
|
||||||
|
GpioPullUp,
|
||||||
|
GpioSpeedLow);
|
||||||
|
|
||||||
|
cc1101_status = cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cc1101_status = cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Prepare GD0 for power on self test
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeInput, GpioPullUp, GpioSpeedLow);
|
||||||
|
|
||||||
|
// GD0 low
|
||||||
|
cc1101_status = cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHW);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while(furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin) != false) {
|
||||||
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
//timeout
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
//timeout
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GD0 high
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeInput, GpioPullDown, GpioSpeedLow);
|
||||||
|
cc1101_status = cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle,
|
||||||
|
CC1101_IOCFG0,
|
||||||
|
CC1101IocfgHW | CC1101_IOCFG_INV);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
while(furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin) != true) {
|
||||||
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
//timeout
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
//timeout
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset GD0 to floating state
|
||||||
|
cc1101_status = cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
|
// Go to sleep
|
||||||
|
cc1101_status = cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(cc1101_status.CHIP_RDYn != 0) {
|
||||||
|
//timeout or error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
if(ret) {
|
||||||
|
FURI_LOG_I(TAG, "Init OK");
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Init failed");
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf) {
|
||||||
|
furi_assert(subghz_device_cc1101_ext == NULL);
|
||||||
|
subghz_device_cc1101_ext = malloc(sizeof(SubGhzDeviceCC1101Ext));
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateInit;
|
||||||
|
subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx;
|
||||||
|
subghz_device_cc1101_ext->async_mirror_pin = NULL;
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle = &furi_hal_spi_bus_handle_external;
|
||||||
|
subghz_device_cc1101_ext->g0_pin = SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO;
|
||||||
|
subghz_device_cc1101_ext->power_amp = false;
|
||||||
|
subghz_device_cc1101_ext->extended_range = false;
|
||||||
|
if(conf) {
|
||||||
|
if(conf->ver == SUBGHZ_DEVICE_CC1101_CONFIG_VER) {
|
||||||
|
subghz_device_cc1101_ext->power_amp = conf->power_amp;
|
||||||
|
subghz_device_cc1101_ext->extended_range = conf->extended_range;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Config version mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0;
|
||||||
|
|
||||||
|
furi_hal_spi_bus_handle_init(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
|
furi_hal_gpio_init_simple(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, GpioModeOutputPushPull);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subghz_device_cc1101_ext_check_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_free() {
|
||||||
|
furi_assert(subghz_device_cc1101_ext != NULL);
|
||||||
|
|
||||||
|
furi_hal_spi_bus_handle_deinit(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
|
furi_hal_gpio_init_simple(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, GpioModeAnalog);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(subghz_device_cc1101_ext);
|
||||||
|
subghz_device_cc1101_ext = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_set_async_mirror_pin(const GpioPin* pin) {
|
||||||
|
subghz_device_cc1101_ext->async_mirror_pin = pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GpioPin* subghz_device_cc1101_ext_get_data_gpio() {
|
||||||
|
return subghz_device_cc1101_ext->g0_pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_is_connect() {
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if(subghz_device_cc1101_ext == NULL) { // not initialized
|
||||||
|
ret = subghz_device_cc1101_ext_alloc(NULL);
|
||||||
|
subghz_device_cc1101_ext_free();
|
||||||
|
} else { // initialized
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint8_t partnumber = cc1101_get_partnumber(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
ret = (partnumber != 0) && (partnumber != 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_sleep() {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle);
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
|
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
|
cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_dump_state() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
printf(
|
||||||
|
"[subghz_device_cc1101_ext] cc1101 chip %d, version %d\r\n",
|
||||||
|
cc1101_get_partnumber(subghz_device_cc1101_ext->spi_bus_handle),
|
||||||
|
cc1101_get_version(subghz_device_cc1101_ext->spi_bus_handle));
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data) {
|
||||||
|
//load config
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint32_t i = 0;
|
||||||
|
uint8_t pa[8] = {0};
|
||||||
|
while(preset_data[i]) {
|
||||||
|
cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, preset_data[i], preset_data[i + 1]);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
//load pa table
|
||||||
|
memcpy(&pa[0], &preset_data[i + 2], 8);
|
||||||
|
subghz_device_cc1101_ext_load_patable(pa);
|
||||||
|
|
||||||
|
//show debug
|
||||||
|
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||||
|
i = 0;
|
||||||
|
FURI_LOG_D(TAG, "Loading custom preset");
|
||||||
|
while(preset_data[i]) {
|
||||||
|
FURI_LOG_D(TAG, "Reg[%lu]: %02X=%02X", i, preset_data[i], preset_data[i + 1]);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
for(uint8_t y = i; y < i + 10; y++) {
|
||||||
|
FURI_LOG_D(TAG, "PA[%u]: %02X", y, preset_data[y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_load_registers(const uint8_t* data) {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint32_t i = 0;
|
||||||
|
while(data[i]) {
|
||||||
|
cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, data[i], data[i + 1]);
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_load_patable(const uint8_t data[8]) {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_set_pa_table(subghz_device_cc1101_ext->spi_bus_handle, data);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_write_packet(const uint8_t* data, uint8_t size) {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_flush_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, CC1101_FIFO, size);
|
||||||
|
cc1101_write_fifo(subghz_device_cc1101_ext->spi_bus_handle, data, size);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_flush_rx() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_flush_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_flush_tx() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_flush_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_rx_pipe_not_empty() {
|
||||||
|
CC1101RxBytes status[1];
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_read_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle,
|
||||||
|
(CC1101_STATUS_RXBYTES) | CC1101_BURST,
|
||||||
|
(uint8_t*)status);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
// TODO: Find reason why RXFIFO_OVERFLOW doesnt work correctly
|
||||||
|
if(status->NUM_RXBYTES > 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_is_rx_data_crc_valid() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint8_t data[1];
|
||||||
|
cc1101_read_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(((data[0] >> 7) & 0x01)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_read_packet(uint8_t* data, uint8_t* size) {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_read_fifo(subghz_device_cc1101_ext->spi_bus_handle, data, size);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_shutdown() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
// Reset and shutdown
|
||||||
|
cc1101_shutdown(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_reset() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_write_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_idle() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_rx() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_tx() {
|
||||||
|
if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false;
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float subghz_device_cc1101_ext_get_rssi() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
int32_t rssi_dec = cc1101_get_rssi(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
float rssi = rssi_dec;
|
||||||
|
if(rssi_dec >= 128) {
|
||||||
|
rssi = ((rssi - 256.0f) / 2.0f) - 74.0f;
|
||||||
|
} else {
|
||||||
|
rssi = (rssi / 2.0f) - 74.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rssi;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t subghz_device_cc1101_ext_get_lqi() {
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint8_t data[1];
|
||||||
|
cc1101_read_reg(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data);
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
return data[0] & 0x7F;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_is_frequency_valid(uint32_t value) {
|
||||||
|
if(!(value >= 281000000 && value <= 361000000) &&
|
||||||
|
!(value >= 378000000 && value <= 481000000) &&
|
||||||
|
!(value >= 749000000 && value <= 962000000)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_is_tx_allowed(uint32_t value) {
|
||||||
|
if(!(SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE ||
|
||||||
|
subghz_device_cc1101_ext->extended_range) &&
|
||||||
|
!(value >= 299999755 && value <= 350000335) && // was increased from 348 to 350
|
||||||
|
!(value >= 386999938 && value <= 467750000) && // was increased from 464 to 467.75
|
||||||
|
!(value >= 778999847 && value <= 928000000)) {
|
||||||
|
FURI_LOG_I(TAG, "Frequency blocked - outside default range");
|
||||||
|
return false;
|
||||||
|
} else if(
|
||||||
|
(SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE ||
|
||||||
|
subghz_device_cc1101_ext->extended_range) &&
|
||||||
|
!subghz_device_cc1101_ext_is_frequency_valid(value)) {
|
||||||
|
FURI_LOG_I(TAG, "Frequency blocked - outside dangerous range");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t subghz_device_cc1101_ext_set_frequency(uint32_t value) {
|
||||||
|
if(subghz_device_cc1101_ext_is_tx_allowed(value)) {
|
||||||
|
subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx;
|
||||||
|
} else {
|
||||||
|
subghz_device_cc1101_ext->regulation = SubGhzDeviceCC1101ExtRegulationTxRx;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
uint32_t real_frequency =
|
||||||
|
cc1101_set_frequency(subghz_device_cc1101_ext->spi_bus_handle, value);
|
||||||
|
cc1101_calibrate(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
CC1101Status status = cc1101_get_status(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
if(status.STATE == CC1101StateIDLE) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
return real_frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool subghz_device_cc1101_ext_start_debug() {
|
||||||
|
bool ret = false;
|
||||||
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL) {
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->async_mirror_pin,
|
||||||
|
GpioModeOutputPushPull,
|
||||||
|
GpioPullNo,
|
||||||
|
GpioSpeedVeryHigh);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool subghz_device_cc1101_ext_stop_debug() {
|
||||||
|
bool ret = false;
|
||||||
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL) {
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->async_mirror_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_capture_ISR() {
|
||||||
|
if(!furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin)) {
|
||||||
|
if(subghz_device_cc1101_ext->async_rx.capture_callback) {
|
||||||
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL)
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, false);
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_callback(
|
||||||
|
true,
|
||||||
|
LL_TIM_GetCounter(TIM17) << 1,
|
||||||
|
(void*)subghz_device_cc1101_ext->async_rx.capture_callback_context);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(subghz_device_cc1101_ext->async_rx.capture_callback) {
|
||||||
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL)
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, true);
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_callback(
|
||||||
|
false,
|
||||||
|
LL_TIM_GetCounter(TIM17) << 1,
|
||||||
|
(void*)subghz_device_cc1101_ext->async_rx.capture_callback_context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LL_TIM_SetCounter(TIM17, 4); //8>>1
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_start_async_rx(
|
||||||
|
SubGhzDeviceCC1101ExtCaptureCallback callback,
|
||||||
|
void* context) {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle);
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncRx;
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_callback = callback;
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_callback_context = context;
|
||||||
|
|
||||||
|
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||||
|
|
||||||
|
// Configure TIM
|
||||||
|
//Set the timer resolution to 2 us
|
||||||
|
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||||
|
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||||
|
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||||
|
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||||
|
|
||||||
|
// Timer: advanced
|
||||||
|
LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||||
|
LL_TIM_DisableARRPreload(TIM17);
|
||||||
|
LL_TIM_DisableDMAReq_TRIG(TIM17);
|
||||||
|
LL_TIM_DisableIT_TRIG(TIM17);
|
||||||
|
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedVeryHigh);
|
||||||
|
furi_hal_gpio_remove_int_callback(subghz_device_cc1101_ext->g0_pin);
|
||||||
|
furi_hal_gpio_add_int_callback(
|
||||||
|
subghz_device_cc1101_ext->g0_pin,
|
||||||
|
subghz_device_cc1101_ext_capture_ISR,
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_callback);
|
||||||
|
|
||||||
|
// Start timer
|
||||||
|
LL_TIM_SetCounter(TIM17, 0);
|
||||||
|
LL_TIM_EnableCounter(TIM17);
|
||||||
|
|
||||||
|
// Start debug
|
||||||
|
subghz_device_cc1101_ext_start_debug();
|
||||||
|
|
||||||
|
// Switch to RX
|
||||||
|
subghz_device_cc1101_ext_rx();
|
||||||
|
|
||||||
|
//Clear the variable after the end of the session
|
||||||
|
subghz_device_cc1101_ext->async_rx.capture_delta_duration = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_stop_async_rx() {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncRx);
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle;
|
||||||
|
|
||||||
|
// Shutdown radio
|
||||||
|
subghz_device_cc1101_ext_idle();
|
||||||
|
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
furi_hal_bus_disable(FuriHalBusTIM17);
|
||||||
|
|
||||||
|
// Stop debug
|
||||||
|
subghz_device_cc1101_ext_stop_debug();
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
furi_hal_gpio_remove_int_callback(subghz_device_cc1101_ext->g0_pin);
|
||||||
|
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_async_tx_refill(uint32_t* buffer, size_t samples) {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
||||||
|
while(samples > 0) {
|
||||||
|
bool is_odd = samples % 2;
|
||||||
|
LevelDuration ld;
|
||||||
|
if(level_duration_is_reset(subghz_device_cc1101_ext->async_tx.carry_ld)) {
|
||||||
|
ld = subghz_device_cc1101_ext->async_tx.callback(
|
||||||
|
subghz_device_cc1101_ext->async_tx.callback_context);
|
||||||
|
} else {
|
||||||
|
ld = subghz_device_cc1101_ext->async_tx.carry_ld;
|
||||||
|
subghz_device_cc1101_ext->async_tx.carry_ld = level_duration_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(level_duration_is_wait(ld)) {
|
||||||
|
*buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
||||||
|
buffer++;
|
||||||
|
samples--;
|
||||||
|
} else if(level_duration_is_reset(ld)) {
|
||||||
|
*buffer = 0;
|
||||||
|
buffer++;
|
||||||
|
samples--;
|
||||||
|
LL_DMA_DisableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
LL_DMA_DisableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
LL_TIM_EnableIT_UPDATE(TIM17);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
bool level = level_duration_get_level(ld);
|
||||||
|
|
||||||
|
// Inject guard time if level is incorrect
|
||||||
|
if(is_odd != level) {
|
||||||
|
*buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
||||||
|
buffer++;
|
||||||
|
samples--;
|
||||||
|
|
||||||
|
// Special case: prevent buffer overflow if sample is last
|
||||||
|
if(samples == 0) {
|
||||||
|
subghz_device_cc1101_ext->async_tx.carry_ld = ld;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t duration = level_duration_get_duration(ld);
|
||||||
|
furi_assert(duration > 0);
|
||||||
|
*buffer = duration >> 1;
|
||||||
|
buffer++;
|
||||||
|
samples--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_async_tx_dma_isr() {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
||||||
|
|
||||||
|
#if SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL == LL_DMA_CHANNEL_3
|
||||||
|
if(LL_DMA_IsActiveFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) {
|
||||||
|
LL_DMA_ClearFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA);
|
||||||
|
subghz_device_cc1101_ext_async_tx_refill(
|
||||||
|
subghz_device_cc1101_ext->async_tx.buffer,
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF);
|
||||||
|
}
|
||||||
|
if(LL_DMA_IsActiveFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) {
|
||||||
|
LL_DMA_ClearFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA);
|
||||||
|
subghz_device_cc1101_ext_async_tx_refill(
|
||||||
|
subghz_device_cc1101_ext->async_tx.buffer +
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF,
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error Update this code. Would you kindly?
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_async_tx_timer_isr() {
|
||||||
|
if(LL_TIM_IsActiveFlag_UPDATE(TIM17)) {
|
||||||
|
if(LL_TIM_GetAutoReload(TIM17) == 0) {
|
||||||
|
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false);
|
||||||
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL)
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->async_mirror_pin, false);
|
||||||
|
LL_TIM_DisableCounter(TIM17);
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncTxEnd;
|
||||||
|
}
|
||||||
|
LL_TIM_ClearFlag_UPDATE(TIM17);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callback, void* context) {
|
||||||
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle);
|
||||||
|
furi_assert(callback);
|
||||||
|
|
||||||
|
//If transmission is prohibited by regional settings
|
||||||
|
if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false;
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_tx.callback = callback;
|
||||||
|
subghz_device_cc1101_ext->async_tx.callback_context = context;
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateAsyncTx;
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_tx.buffer =
|
||||||
|
malloc(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL * sizeof(uint32_t));
|
||||||
|
|
||||||
|
//Signal generation with mem-to-mem DMA
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false);
|
||||||
|
furi_hal_gpio_init(
|
||||||
|
subghz_device_cc1101_ext->g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||||
|
|
||||||
|
// Configure DMA update timer
|
||||||
|
LL_DMA_SetMemoryAddress(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, (uint32_t)subghz_device_cc1101_ext->async_tx.buffer);
|
||||||
|
LL_DMA_SetPeriphAddress(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, (uint32_t) & (TIM17->ARR));
|
||||||
|
LL_DMA_ConfigTransfer(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF,
|
||||||
|
LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||||
|
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD |
|
||||||
|
LL_DMA_MODE_NORMAL);
|
||||||
|
LL_DMA_SetDataLength(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL);
|
||||||
|
LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, LL_DMAMUX_REQ_TIM17_UP);
|
||||||
|
|
||||||
|
LL_DMA_EnableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
LL_DMA_EnableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
|
||||||
|
furi_hal_interrupt_set_isr(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ, subghz_device_cc1101_ext_async_tx_dma_isr, NULL);
|
||||||
|
|
||||||
|
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||||
|
|
||||||
|
// Configure TIM
|
||||||
|
// Set the timer resolution to 2 us
|
||||||
|
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||||
|
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||||
|
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||||
|
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||||
|
LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||||
|
LL_TIM_DisableARRPreload(TIM17);
|
||||||
|
|
||||||
|
furi_hal_interrupt_set_isr(
|
||||||
|
FuriHalInterruptIdTim1TrgComTim17, subghz_device_cc1101_ext_async_tx_timer_isr, NULL);
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext_async_tx_refill(
|
||||||
|
subghz_device_cc1101_ext->async_tx.buffer, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL);
|
||||||
|
|
||||||
|
// Configure tx gpio dma
|
||||||
|
const GpioPin* gpio = subghz_device_cc1101_ext->g0_pin;
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->async_tx.gpio_tx_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
|
||||||
|
subghz_device_cc1101_ext->async_tx.gpio_tx_buff[1] = gpio->pin;
|
||||||
|
|
||||||
|
LL_DMA_SetMemoryAddress(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF,
|
||||||
|
(uint32_t)subghz_device_cc1101_ext->async_tx.gpio_tx_buff);
|
||||||
|
LL_DMA_SetPeriphAddress(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, (uint32_t) & (gpio->port->BSRR));
|
||||||
|
LL_DMA_ConfigTransfer(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF,
|
||||||
|
LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||||
|
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD |
|
||||||
|
LL_DMA_PRIORITY_HIGH);
|
||||||
|
LL_DMA_SetDataLength(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, 2);
|
||||||
|
LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF, LL_DMAMUX_REQ_TIM17_UP);
|
||||||
|
LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF);
|
||||||
|
|
||||||
|
// Start debug
|
||||||
|
if(subghz_device_cc1101_ext_start_debug()) {
|
||||||
|
gpio = subghz_device_cc1101_ext->async_mirror_pin;
|
||||||
|
subghz_device_cc1101_ext->async_tx.debug_gpio_buff[0] = (uint32_t)gpio->pin << GPIO_NUMBER;
|
||||||
|
subghz_device_cc1101_ext->async_tx.debug_gpio_buff[1] = gpio->pin;
|
||||||
|
|
||||||
|
LL_DMA_SetMemoryAddress(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF,
|
||||||
|
(uint32_t)subghz_device_cc1101_ext->async_tx.debug_gpio_buff);
|
||||||
|
LL_DMA_SetPeriphAddress(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, (uint32_t) & (gpio->port->BSRR));
|
||||||
|
LL_DMA_ConfigTransfer(
|
||||||
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF,
|
||||||
|
LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||||
|
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD |
|
||||||
|
LL_DMA_PRIORITY_LOW);
|
||||||
|
LL_DMA_SetDataLength(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, 2);
|
||||||
|
LL_DMA_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF, LL_DMAMUX_REQ_TIM17_UP);
|
||||||
|
LL_DMA_EnableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start counter
|
||||||
|
LL_TIM_EnableDMAReq_UPDATE(TIM17);
|
||||||
|
LL_TIM_GenerateEvent_UPDATE(TIM17);
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext_tx();
|
||||||
|
|
||||||
|
LL_TIM_SetCounter(TIM17, 0);
|
||||||
|
LL_TIM_EnableCounter(TIM17);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subghz_device_cc1101_ext_is_async_tx_complete() {
|
||||||
|
return subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subghz_device_cc1101_ext_stop_async_tx() {
|
||||||
|
furi_assert(
|
||||||
|
subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx ||
|
||||||
|
subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd);
|
||||||
|
|
||||||
|
// Shutdown radio
|
||||||
|
subghz_device_cc1101_ext_idle();
|
||||||
|
|
||||||
|
// Deinitialize Timer
|
||||||
|
FURI_CRITICAL_ENTER();
|
||||||
|
furi_hal_bus_disable(FuriHalBusTIM17);
|
||||||
|
furi_hal_interrupt_set_isr(FuriHalInterruptIdTim1TrgComTim17, NULL, NULL);
|
||||||
|
|
||||||
|
// Deinitialize DMA
|
||||||
|
LL_DMA_DeInit(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
|
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF);
|
||||||
|
furi_hal_interrupt_set_isr(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ, NULL, NULL);
|
||||||
|
|
||||||
|
// Deinitialize GPIO
|
||||||
|
furi_hal_gpio_write(subghz_device_cc1101_ext->g0_pin, false);
|
||||||
|
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||||
|
|
||||||
|
// Stop debug
|
||||||
|
if(subghz_device_cc1101_ext_stop_debug()) {
|
||||||
|
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF);
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_CRITICAL_EXIT();
|
||||||
|
|
||||||
|
free(subghz_device_cc1101_ext->async_tx.buffer);
|
||||||
|
|
||||||
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle;
|
||||||
|
}
|
||||||
207
applications/drivers/subghz/cc1101_ext/cc1101_ext.h
Normal file
207
applications/drivers/subghz/cc1101_ext/cc1101_ext.h
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/**
|
||||||
|
* @file furi_hal_subghz.h
|
||||||
|
* SubGhz HAL API
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <lib/subghz/devices/preset.h>
|
||||||
|
#include <lib/subghz/devices/types.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <toolbox/level_duration.h>
|
||||||
|
#include <furi_hal_gpio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Mirror RX/TX async modulation signal to specified pin
|
||||||
|
*
|
||||||
|
* @warning Configures pin to output mode. Make sure it is not connected
|
||||||
|
* directly to power or ground.
|
||||||
|
*
|
||||||
|
* @param[in] pin pointer to the gpio pin structure or NULL to disable
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_set_async_mirror_pin(const GpioPin* pin);
|
||||||
|
|
||||||
|
/** Get data GPIO
|
||||||
|
*
|
||||||
|
* @return pointer to the gpio pin structure
|
||||||
|
*/
|
||||||
|
const GpioPin* subghz_device_cc1101_ext_get_data_gpio();
|
||||||
|
|
||||||
|
/** Initialize device
|
||||||
|
*
|
||||||
|
* @return true if success
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_alloc(SubGhzDeviceConf* conf);
|
||||||
|
|
||||||
|
/** Deinitialize device
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_free();
|
||||||
|
|
||||||
|
/** Check and switch to power save mode Used by internal API-HAL
|
||||||
|
* initialization routine Can be used to reinitialize device to safe state and
|
||||||
|
* send it to sleep
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_is_connect();
|
||||||
|
|
||||||
|
/** Send device to sleep mode
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_sleep();
|
||||||
|
|
||||||
|
/** Dump info to stdout
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_dump_state();
|
||||||
|
|
||||||
|
/** Load custom registers from preset
|
||||||
|
*
|
||||||
|
* @param preset_data registers to load
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data);
|
||||||
|
|
||||||
|
/** Load registers
|
||||||
|
*
|
||||||
|
* @param data Registers data
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_load_registers(const uint8_t* data);
|
||||||
|
|
||||||
|
/** Load PATABLE
|
||||||
|
*
|
||||||
|
* @param data 8 uint8_t values
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_load_patable(const uint8_t data[8]);
|
||||||
|
|
||||||
|
/** Write packet to FIFO
|
||||||
|
*
|
||||||
|
* @param data bytes array
|
||||||
|
* @param size size
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_write_packet(const uint8_t* data, uint8_t size);
|
||||||
|
|
||||||
|
/** Check if receive pipe is not empty
|
||||||
|
*
|
||||||
|
* @return true if not empty
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_rx_pipe_not_empty();
|
||||||
|
|
||||||
|
/** Check if received data crc is valid
|
||||||
|
*
|
||||||
|
* @return true if valid
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_is_rx_data_crc_valid();
|
||||||
|
|
||||||
|
/** Read packet from FIFO
|
||||||
|
*
|
||||||
|
* @param data pointer
|
||||||
|
* @param size size
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_read_packet(uint8_t* data, uint8_t* size);
|
||||||
|
|
||||||
|
/** Flush rx FIFO buffer
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_flush_rx();
|
||||||
|
|
||||||
|
/** Flush tx FIFO buffer
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_flush_tx();
|
||||||
|
|
||||||
|
/** Shutdown Issue SPWD command
|
||||||
|
* @warning registers content will be lost
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_shutdown();
|
||||||
|
|
||||||
|
/** Reset Issue reset command
|
||||||
|
* @warning registers content will be lost
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_reset();
|
||||||
|
|
||||||
|
/** Switch to Idle
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_idle();
|
||||||
|
|
||||||
|
/** Switch to Receive
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_rx();
|
||||||
|
|
||||||
|
/** Switch to Transmit
|
||||||
|
*
|
||||||
|
* @return true if the transfer is allowed by belonging to the region
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_tx();
|
||||||
|
|
||||||
|
/** Get RSSI value in dBm
|
||||||
|
*
|
||||||
|
* @return RSSI value
|
||||||
|
*/
|
||||||
|
float subghz_device_cc1101_ext_get_rssi();
|
||||||
|
|
||||||
|
/** Get LQI
|
||||||
|
*
|
||||||
|
* @return LQI value
|
||||||
|
*/
|
||||||
|
uint8_t subghz_device_cc1101_ext_get_lqi();
|
||||||
|
|
||||||
|
/** Check if frequency is in valid range
|
||||||
|
*
|
||||||
|
* @param value frequency in Hz
|
||||||
|
*
|
||||||
|
* @return true if frequency is valid, otherwise false
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_is_frequency_valid(uint32_t value);
|
||||||
|
|
||||||
|
/** Set frequency
|
||||||
|
*
|
||||||
|
* @param value frequency in Hz
|
||||||
|
*
|
||||||
|
* @return real frequency in Hz
|
||||||
|
*/
|
||||||
|
uint32_t subghz_device_cc1101_ext_set_frequency(uint32_t value);
|
||||||
|
|
||||||
|
/* High Level API */
|
||||||
|
|
||||||
|
/** Signal Timings Capture callback */
|
||||||
|
typedef void (*SubGhzDeviceCC1101ExtCaptureCallback)(bool level, uint32_t duration, void* context);
|
||||||
|
|
||||||
|
/** Enable signal timings capture Initializes GPIO and TIM2 for timings capture
|
||||||
|
*
|
||||||
|
* @param callback SubGhzDeviceCC1101ExtCaptureCallback
|
||||||
|
* @param context callback context
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_start_async_rx(
|
||||||
|
SubGhzDeviceCC1101ExtCaptureCallback callback,
|
||||||
|
void* context);
|
||||||
|
|
||||||
|
/** Disable signal timings capture Resets GPIO and TIM2
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_stop_async_rx();
|
||||||
|
|
||||||
|
/** Async TX callback type
|
||||||
|
* @param context callback context
|
||||||
|
* @return LevelDuration
|
||||||
|
*/
|
||||||
|
typedef LevelDuration (*SubGhzDeviceCC1101ExtCallback)(void* context);
|
||||||
|
|
||||||
|
/** Start async TX Initializes GPIO, TIM2 and DMA1 for signal output
|
||||||
|
*
|
||||||
|
* @param callback SubGhzDeviceCC1101ExtCallback
|
||||||
|
* @param context callback context
|
||||||
|
*
|
||||||
|
* @return true if the transfer is allowed by belonging to the region
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callback, void* context);
|
||||||
|
|
||||||
|
/** Wait for async transmission to complete
|
||||||
|
*
|
||||||
|
* @return true if TX complete
|
||||||
|
*/
|
||||||
|
bool subghz_device_cc1101_ext_is_async_tx_complete();
|
||||||
|
|
||||||
|
/** Stop async transmission and cleanup resources Resets GPIO, TIM2, and DMA1
|
||||||
|
*/
|
||||||
|
void subghz_device_cc1101_ext_stop_async_tx();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
110
applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c
Normal file
110
applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
#include "cc1101_ext_interconnect.h"
|
||||||
|
#include "cc1101_ext.h"
|
||||||
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
|
#define TAG "SubGhzDeviceCc1101Ext"
|
||||||
|
|
||||||
|
static bool subghz_device_cc1101_ext_interconnect_is_frequency_valid(uint32_t frequency) {
|
||||||
|
bool ret = subghz_device_cc1101_ext_is_frequency_valid(frequency);
|
||||||
|
if(!ret) {
|
||||||
|
furi_crash("SubGhz: Incorrect frequency.");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t subghz_device_cc1101_ext_interconnect_set_frequency(uint32_t frequency) {
|
||||||
|
subghz_device_cc1101_ext_interconnect_is_frequency_valid(frequency);
|
||||||
|
return subghz_device_cc1101_ext_set_frequency(frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool subghz_device_cc1101_ext_interconnect_start_async_tx(void* callback, void* context) {
|
||||||
|
return subghz_device_cc1101_ext_start_async_tx(
|
||||||
|
(SubGhzDeviceCC1101ExtCallback)callback, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_interconnect_start_async_rx(void* callback, void* context) {
|
||||||
|
subghz_device_cc1101_ext_start_async_rx(
|
||||||
|
(SubGhzDeviceCC1101ExtCaptureCallback)callback, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void subghz_device_cc1101_ext_interconnect_load_preset(
|
||||||
|
FuriHalSubGhzPreset preset,
|
||||||
|
uint8_t* preset_data) {
|
||||||
|
switch(preset) {
|
||||||
|
case FuriHalSubGhzPresetOok650Async:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_ook_650khz_async_regs);
|
||||||
|
break;
|
||||||
|
case FuriHalSubGhzPresetOok270Async:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_ook_270khz_async_regs);
|
||||||
|
break;
|
||||||
|
case FuriHalSubGhzPreset2FSKDev238Async:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_2fsk_dev2_38khz_async_regs);
|
||||||
|
break;
|
||||||
|
case FuriHalSubGhzPreset2FSKDev476Async:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_2fsk_dev47_6khz_async_regs);
|
||||||
|
break;
|
||||||
|
case FuriHalSubGhzPresetMSK99_97KbAsync:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_msk_99_97kb_async_regs);
|
||||||
|
break;
|
||||||
|
case FuriHalSubGhzPresetGFSK9_99KbAsync:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(
|
||||||
|
subghz_device_cc1101_preset_gfsk_9_99kb_async_regs);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
subghz_device_cc1101_ext_load_custom_preset(preset_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SubGhzDeviceInterconnect subghz_device_cc1101_ext_interconnect = {
|
||||||
|
.begin = subghz_device_cc1101_ext_alloc,
|
||||||
|
.end = subghz_device_cc1101_ext_free,
|
||||||
|
.is_connect = subghz_device_cc1101_ext_is_connect,
|
||||||
|
.reset = subghz_device_cc1101_ext_reset,
|
||||||
|
.sleep = subghz_device_cc1101_ext_sleep,
|
||||||
|
.idle = subghz_device_cc1101_ext_idle,
|
||||||
|
.load_preset = subghz_device_cc1101_ext_interconnect_load_preset,
|
||||||
|
.set_frequency = subghz_device_cc1101_ext_interconnect_set_frequency,
|
||||||
|
.is_frequency_valid = subghz_device_cc1101_ext_is_frequency_valid,
|
||||||
|
.set_async_mirror_pin = subghz_device_cc1101_ext_set_async_mirror_pin,
|
||||||
|
.get_data_gpio = subghz_device_cc1101_ext_get_data_gpio,
|
||||||
|
|
||||||
|
.set_tx = subghz_device_cc1101_ext_tx,
|
||||||
|
.flush_tx = subghz_device_cc1101_ext_flush_tx,
|
||||||
|
.start_async_tx = subghz_device_cc1101_ext_interconnect_start_async_tx,
|
||||||
|
.is_async_complete_tx = subghz_device_cc1101_ext_is_async_tx_complete,
|
||||||
|
.stop_async_tx = subghz_device_cc1101_ext_stop_async_tx,
|
||||||
|
|
||||||
|
.set_rx = subghz_device_cc1101_ext_rx,
|
||||||
|
.flush_rx = subghz_device_cc1101_ext_flush_rx,
|
||||||
|
.start_async_rx = subghz_device_cc1101_ext_interconnect_start_async_rx,
|
||||||
|
.stop_async_rx = subghz_device_cc1101_ext_stop_async_rx,
|
||||||
|
|
||||||
|
.get_rssi = subghz_device_cc1101_ext_get_rssi,
|
||||||
|
.get_lqi = subghz_device_cc1101_ext_get_lqi,
|
||||||
|
|
||||||
|
.rx_pipe_not_empty = subghz_device_cc1101_ext_rx_pipe_not_empty,
|
||||||
|
.is_rx_data_crc_valid = subghz_device_cc1101_ext_is_rx_data_crc_valid,
|
||||||
|
.read_packet = subghz_device_cc1101_ext_read_packet,
|
||||||
|
.write_packet = subghz_device_cc1101_ext_write_packet,
|
||||||
|
};
|
||||||
|
|
||||||
|
const SubGhzDevice subghz_device_cc1101_ext = {
|
||||||
|
.name = SUBGHZ_DEVICE_CC1101_EXT_NAME,
|
||||||
|
.interconnect = &subghz_device_cc1101_ext_interconnect,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const FlipperAppPluginDescriptor subghz_device_cc1101_ext_descriptor = {
|
||||||
|
.appid = SUBGHZ_RADIO_DEVICE_PLUGIN_APP_ID,
|
||||||
|
.ep_api_version = SUBGHZ_RADIO_DEVICE_PLUGIN_API_VERSION,
|
||||||
|
.entry_point = &subghz_device_cc1101_ext,
|
||||||
|
};
|
||||||
|
|
||||||
|
const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep() {
|
||||||
|
return &subghz_device_cc1101_ext_descriptor;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <lib/subghz/devices/types.h>
|
||||||
|
|
||||||
|
#define SUBGHZ_DEVICE_CC1101_EXT_NAME "cc1101_ext"
|
||||||
|
|
||||||
|
typedef struct SubGhzDeviceCC1101Ext SubGhzDeviceCC1101Ext;
|
||||||
|
|
||||||
|
const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep();
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
# Placeholder
|
||||||
App(
|
App(
|
||||||
appid="example_apps",
|
appid="example_apps",
|
||||||
name="Example apps bundle",
|
name="Example apps bundle",
|
||||||
|
|||||||
58
applications/examples/example_apps_assets/README.md
Normal file
58
applications/examples/example_apps_assets/README.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
# Apps Assets folder Example
|
||||||
|
|
||||||
|
This example shows how to use the Apps Assets folder to store data that is not part of the application itself, but is required for its operation, and that data is provided with the application.
|
||||||
|
|
||||||
|
## What is the Apps Assets Folder?
|
||||||
|
|
||||||
|
The **Apps Assets** folder is a folder where external applications unpack their assets.
|
||||||
|
|
||||||
|
The path to the current application folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file.
|
||||||
|
The Apps Assets folder is located only on the external storage, the SD card.
|
||||||
|
|
||||||
|
For example, if the `appid` of the app is `snake_game`, the path to the Apps Assets folder will be `/ext/apps_assets/snake_game`. But using raw paths is not recommended, because the path to the Apps Assets folder can change in the future. Use the `/assets` alias instead.
|
||||||
|
|
||||||
|
## How to get the path to the Apps Assets folder?
|
||||||
|
|
||||||
|
You can use `/assets` alias to get the path to the current application data folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use the next path: `/data/database.txt`. But this way is not recommended, because even the `/assets` alias can change in the future.
|
||||||
|
|
||||||
|
We recommend to use the `APP_ASSETS_PATH` macro to get the path to the Apps Assets folder. For example, if you want to open a file `database.txt` in the Apps Assets folder, you can use the next path: `APP_ASSETS_PATH("database.txt")`.
|
||||||
|
|
||||||
|
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
||||||
|
|
||||||
|
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (contant data) in the Apps Assets folder.
|
||||||
|
|
||||||
|
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
||||||
|
|
||||||
|
## How to provide the data with the app?
|
||||||
|
|
||||||
|
To provide data with an application, you need to create a folder inside your application folder (eg "files") and place the data in it. After that, you need to add `fap_file_assets="files"` to your application.fam file.
|
||||||
|
|
||||||
|
For example, if you want to provide game levels with the application, you need to create a "levels" folder inside the "files" folder and put the game levels in it. After that, you need to add `fap_file_assets="files"` to your application.fam file. The final application folder structure will look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
snake_game
|
||||||
|
├── application.fam
|
||||||
|
├── snake_game.c
|
||||||
|
└── files
|
||||||
|
└── levels
|
||||||
|
├── level1.txt
|
||||||
|
├── level2.txt
|
||||||
|
└── level3.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
When app is launched, the `files` folder will be unpacked to the Apps Assets folder. The final structure of the Apps Assets folder will look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
/assets
|
||||||
|
├── .assets.signature
|
||||||
|
└── levels
|
||||||
|
├── level1.txt
|
||||||
|
├── level2.txt
|
||||||
|
└── level3.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
## When will the data be unpacked?
|
||||||
|
|
||||||
|
The data is unpacked when the application starts, if the application is launched for the first time, or if the data within the application is updated.
|
||||||
|
|
||||||
|
When an application is compiled, the contents of the "files" folder are hashed and stored within the application itself. When the application starts, this hash is compared to the hash stored in the `.assets.signature` file. If the hashes differ or the `.assets.signature` file does not exist, the application folder is deleted and the new data is unpacked.
|
||||||
10
applications/examples/example_apps_assets/application.fam
Normal file
10
applications/examples/example_apps_assets/application.fam
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
App(
|
||||||
|
appid="example_apps_assets",
|
||||||
|
name="Example: Apps Assets",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_apps_assets_main",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=4 * 1024,
|
||||||
|
fap_category="Examples",
|
||||||
|
fap_file_assets="files",
|
||||||
|
)
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <toolbox/stream/stream.h>
|
||||||
|
#include <toolbox/stream/file_stream.h>
|
||||||
|
|
||||||
|
// Define log tag
|
||||||
|
#define TAG "ExampleAppsAssets"
|
||||||
|
|
||||||
|
static void example_apps_data_print_file_content(Storage* storage, const char* path) {
|
||||||
|
Stream* stream = file_stream_alloc(storage);
|
||||||
|
FuriString* line = furi_string_alloc();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "----------------------------------------");
|
||||||
|
FURI_LOG_I(TAG, "File \"%s\" content:", path);
|
||||||
|
if(file_stream_open(stream, path, FSAM_READ, FSOM_OPEN_EXISTING)) {
|
||||||
|
while(stream_read_line(stream, line)) {
|
||||||
|
furi_string_replace_all(line, "\r", "");
|
||||||
|
furi_string_replace_all(line, "\n", "");
|
||||||
|
FURI_LOG_I(TAG, "%s", furi_string_get_cstr(line));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Failed to open file");
|
||||||
|
}
|
||||||
|
FURI_LOG_I(TAG, "----------------------------------------");
|
||||||
|
|
||||||
|
furi_string_free(line);
|
||||||
|
file_stream_close(stream);
|
||||||
|
stream_free(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Application entry point
|
||||||
|
int32_t example_apps_assets_main(void* p) {
|
||||||
|
// Mark argument as unused
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
// Open storage
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
example_apps_data_print_file_content(storage, APP_ASSETS_PATH("test_asset.txt"));
|
||||||
|
example_apps_data_print_file_content(storage, APP_ASSETS_PATH("poems/a jelly-fish.txt"));
|
||||||
|
example_apps_data_print_file_content(storage, APP_ASSETS_PATH("poems/theme in yellow.txt"));
|
||||||
|
example_apps_data_print_file_content(storage, APP_ASSETS_PATH("poems/my shadow.txt"));
|
||||||
|
|
||||||
|
// Close storage
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
A Jelly-Fish by Marianne Moore
|
||||||
|
|
||||||
|
Visible, invisible,
|
||||||
|
A fluctuating charm,
|
||||||
|
An amber-colored amethyst
|
||||||
|
Inhabits it; your arm
|
||||||
|
Approaches, and
|
||||||
|
It opens and
|
||||||
|
It closes;
|
||||||
|
You have meant
|
||||||
|
To catch it,
|
||||||
|
And it shrivels;
|
||||||
|
You abandon
|
||||||
|
Your intent—
|
||||||
|
It opens, and it
|
||||||
|
Closes and you
|
||||||
|
Reach for it—
|
||||||
|
The blue
|
||||||
|
Surrounding it
|
||||||
|
Grows cloudy, and
|
||||||
|
It floats away
|
||||||
|
From you.
|
||||||
|
|
||||||
|
source: "https://poets.org/anthology/poems-your-poetry-project-public-domain"
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
My Shadow by Robert Louis Stevenson
|
||||||
|
|
||||||
|
I have a little shadow that goes in and out with me,
|
||||||
|
And what can be the use of him is more than I can see.
|
||||||
|
He is very, very like me from the heels up to the head;
|
||||||
|
And I see him jump before me, when I jump into my bed.
|
||||||
|
|
||||||
|
The funniest thing about him is the way he likes to grow—
|
||||||
|
Not at all like proper children, which is always very slow;
|
||||||
|
For he sometimes shoots up taller like an India-rubber ball,
|
||||||
|
And he sometimes gets so little that there’s none of him at all.
|
||||||
|
|
||||||
|
He hasn’t got a notion of how children ought to play,
|
||||||
|
And can only make a fool of me in every sort of way.
|
||||||
|
He stays so close beside me, he’s a coward you can see;
|
||||||
|
I’d think shame to stick to nursie as that shadow sticks to me!
|
||||||
|
|
||||||
|
One morning, very early, before the sun was up,
|
||||||
|
I rose and found the shining dew on every buttercup;
|
||||||
|
But my lazy little shadow, like an arrant sleepy-head,
|
||||||
|
Had stayed at home behind me and was fast asleep in bed.
|
||||||
|
|
||||||
|
source: "https://poets.org/anthology/poems-your-poetry-project-public-domain"
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
Theme in Yellow by Carl Sandburg
|
||||||
|
|
||||||
|
I spot the hills
|
||||||
|
With yellow balls in autumn.
|
||||||
|
I light the prairie cornfields
|
||||||
|
Orange and tawny gold clusters
|
||||||
|
And I am called pumpkins.
|
||||||
|
On the last of October
|
||||||
|
When dusk is fallen
|
||||||
|
Children join hands
|
||||||
|
And circle round me
|
||||||
|
Singing ghost songs
|
||||||
|
And love to the harvest moon;
|
||||||
|
I am a jack-o'-lantern
|
||||||
|
With terrible teeth
|
||||||
|
And the children know
|
||||||
|
I am fooling.
|
||||||
|
|
||||||
|
source: "https://poets.org/anthology/poems-your-poetry-project-public-domain"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
## This is test file content
|
||||||
24
applications/examples/example_apps_data/README.md
Normal file
24
applications/examples/example_apps_data/README.md
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Apps Data folder Example
|
||||||
|
|
||||||
|
This example demonstrates how to utilize the Apps Data folder to store data that is not part of the app itself, such as user data, configuration files, and so forth.
|
||||||
|
|
||||||
|
## What is the Apps Data Folder?
|
||||||
|
|
||||||
|
The **Apps Data** folder is a folder used to store data for external apps that are not part of the main firmware.
|
||||||
|
|
||||||
|
The path to the current application folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file.
|
||||||
|
The Apps Data folder is located only on the external storage, the SD card.
|
||||||
|
|
||||||
|
For example, if the `appid` of the app is `snake_game`, the path to the Apps Data folder will be `/ext/apps_data/snake_game`. But using raw paths is not recommended, because the path to the Apps Data folder can change in the future. Use the `/data` alias instead.
|
||||||
|
|
||||||
|
## How to get the path to the Apps Data folder?
|
||||||
|
|
||||||
|
You can use `/data` alias to get the path to the current application data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `/data/config.txt`. But this way is not recommended, because even the `/data` alias can change in the future.
|
||||||
|
|
||||||
|
We recommend to use the `APP_DATA_PATH` macro to get the path to the Apps Data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `APP_DATA_PATH("config.txt")`.
|
||||||
|
|
||||||
|
## What is the difference between the Apps Assets folder and the Apps Data folder?
|
||||||
|
|
||||||
|
The Apps Assets folder is used to store the data <u>provided</u> with the application. For example, if you want to create a game, you can store game levels (contant data) in the Apps Assets folder.
|
||||||
|
|
||||||
|
The Apps Data folder is used to store data <u>generated</u> by the application. For example, if you want to create a game, you can save the progress of the game (user-generated data) in the Apps Data folder.
|
||||||
9
applications/examples/example_apps_data/application.fam
Normal file
9
applications/examples/example_apps_data/application.fam
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
App(
|
||||||
|
appid="example_apps_data",
|
||||||
|
name="Example: Apps Data",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_apps_data_main",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
||||||
40
applications/examples/example_apps_data/example_apps_data.c
Normal file
40
applications/examples/example_apps_data/example_apps_data.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
// Define log tag
|
||||||
|
#define TAG "ExampleAppsData"
|
||||||
|
|
||||||
|
// Application entry point
|
||||||
|
int32_t example_apps_data_main(void* p) {
|
||||||
|
// Mark argument as unused
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
// Open storage
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
// Allocate file
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
|
||||||
|
// Get the path to the current application data folder
|
||||||
|
// That is: /ext/apps_data/<app_name>
|
||||||
|
// And it will create folders in the path if they don't exist
|
||||||
|
// In this example it will create /ext/apps_data/example_apps_data
|
||||||
|
// And file will be /ext/apps_data/example_apps_data/test.txt
|
||||||
|
|
||||||
|
// Open file, write data and close it
|
||||||
|
if(!storage_file_open(file, APP_DATA_PATH("test.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to open file");
|
||||||
|
}
|
||||||
|
if(!storage_file_write(file, "Hello World!", strlen("Hello World!"))) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to write to file");
|
||||||
|
}
|
||||||
|
storage_file_close(file);
|
||||||
|
|
||||||
|
// Deallocate file
|
||||||
|
storage_file_free(file);
|
||||||
|
|
||||||
|
// Close storage
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
31
applications/examples/example_plugins/application.fam
Normal file
31
applications/examples/example_plugins/application.fam
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
App(
|
||||||
|
appid="example_plugins",
|
||||||
|
name="Example: App w/plugin",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_plugins_app",
|
||||||
|
stack_size=2 * 1024,
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
||||||
|
|
||||||
|
App(
|
||||||
|
appid="example_plugins_multi",
|
||||||
|
name="Example: App w/plugins",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="example_plugins_multi_app",
|
||||||
|
stack_size=2 * 1024,
|
||||||
|
fap_category="Examples",
|
||||||
|
)
|
||||||
|
|
||||||
|
App(
|
||||||
|
appid="example_plugin1",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
entry_point="example_plugin1_ep",
|
||||||
|
requires=["example_plugins", "example_plugins_multi"],
|
||||||
|
)
|
||||||
|
|
||||||
|
App(
|
||||||
|
appid="example_plugin2",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
entry_point="example_plugin2_ep",
|
||||||
|
requires=["example_plugins_multi"],
|
||||||
|
)
|
||||||
70
applications/examples/example_plugins/example_plugins.c
Normal file
70
applications/examples/example_plugins/example_plugins.c
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* An example of a plugin host application.
|
||||||
|
* Loads a single plugin and calls its methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "plugin_interface.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#include <flipper_application/flipper_application.h>
|
||||||
|
#include <loader/firmware_api/firmware_api.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
#define TAG "ExamplePlugins"
|
||||||
|
|
||||||
|
int32_t example_plugins_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Starting");
|
||||||
|
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
|
||||||
|
|
||||||
|
do {
|
||||||
|
FlipperApplicationPreloadStatus preload_res =
|
||||||
|
flipper_application_preload(app, APP_DATA_PATH("plugins/example_plugin1.fal"));
|
||||||
|
|
||||||
|
if(preload_res != FlipperApplicationPreloadStatusSuccess) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to preload plugin");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!flipper_application_is_plugin(app)) {
|
||||||
|
FURI_LOG_E(TAG, "Plugin file is not a library");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperApplicationLoadStatus load_status = flipper_application_map_to_memory(app);
|
||||||
|
if(load_status != FlipperApplicationLoadStatusSuccess) {
|
||||||
|
FURI_LOG_E(TAG, "Failed to load plugin file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FlipperAppPluginDescriptor* app_descriptor =
|
||||||
|
flipper_application_plugin_get_descriptor(app);
|
||||||
|
|
||||||
|
FURI_LOG_I(
|
||||||
|
TAG,
|
||||||
|
"Loaded plugin for appid '%s', API %lu",
|
||||||
|
app_descriptor->appid,
|
||||||
|
app_descriptor->ep_api_version);
|
||||||
|
|
||||||
|
furi_check(app_descriptor->ep_api_version == PLUGIN_API_VERSION);
|
||||||
|
furi_check(strcmp(app_descriptor->appid, PLUGIN_APP_ID) == 0);
|
||||||
|
|
||||||
|
const ExamplePlugin* plugin = app_descriptor->entry_point;
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Plugin name: %s", plugin->name);
|
||||||
|
FURI_LOG_I(TAG, "Plugin method1: %d", plugin->method1());
|
||||||
|
FURI_LOG_I(TAG, "Plugin method2(7,8): %d", plugin->method2(7, 8));
|
||||||
|
FURI_LOG_I(TAG, "Plugin method2(1337,228): %d", plugin->method2(1337, 228));
|
||||||
|
} while(false);
|
||||||
|
flipper_application_free(app);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
FURI_LOG_I(TAG, "Goodbye!");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user