mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 20:49:49 +04:00
Compare commits
798 Commits
nfcrefacto
...
unlshd-072
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b62b6cbd8 | ||
|
|
81a16e5a28 | ||
|
|
79ac603efa | ||
|
|
8d75af8457 | ||
|
|
aaa7c81f99 | ||
|
|
385c3c1c01 | ||
|
|
c323656037 | ||
|
|
46a90ec97f | ||
|
|
d1d3c43939 | ||
|
|
34fac96ef6 | ||
|
|
c1441b1331 | ||
|
|
6d73b266d5 | ||
|
|
09c46a3381 | ||
|
|
6d9a2cc699 | ||
|
|
760deb66c5 | ||
|
|
e0469ae1ed | ||
|
|
3bd64bead1 | ||
|
|
139cc3c93d | ||
|
|
3b83d8b825 | ||
|
|
8c0ba4de9f | ||
|
|
4a673397b3 | ||
|
|
a5bb1ead68 | ||
|
|
7c607abfe6 | ||
|
|
6f560ef210 | ||
|
|
71111b0d2f | ||
|
|
2276432745 | ||
|
|
c541227483 | ||
|
|
a09ec4d976 | ||
|
|
a0dc2b5cfc | ||
|
|
7e9ecdf394 | ||
|
|
ce67472dc4 | ||
|
|
f88da8b0c3 | ||
|
|
d573cc06da | ||
|
|
17dd089b5a | ||
|
|
eb013ab6ec | ||
|
|
d7711d729f | ||
|
|
375eb55d33 | ||
|
|
6e52c591e5 | ||
|
|
c5bf29cb8c | ||
|
|
2aa85347ee | ||
|
|
75432346de | ||
|
|
98c328f93f | ||
|
|
3f7a070397 | ||
|
|
b27066b508 | ||
|
|
5cfc773b7b | ||
|
|
2da05bfa6c | ||
|
|
9050a242e6 | ||
|
|
022fccf0d7 | ||
|
|
adbe4d44f4 | ||
|
|
79a286fe1a | ||
|
|
2f5be8f695 | ||
|
|
e8e596e4c9 | ||
|
|
7b09a22a5c | ||
|
|
c9434492b8 | ||
|
|
1bd56fb190 | ||
|
|
25d4c4f829 | ||
|
|
175f603678 | ||
|
|
df57ecd786 | ||
|
|
58cd56a439 | ||
|
|
b1a9904ea5 | ||
|
|
43d1659200 | ||
|
|
8f9fbc3a79 | ||
|
|
bf97209c9b | ||
|
|
2961ad5ee1 | ||
|
|
4f7eb77071 | ||
|
|
ecab4d53d2 | ||
|
|
4e7f25a539 | ||
|
|
5e47048369 | ||
|
|
a6c5a1ba69 | ||
|
|
7b26dc5ebf | ||
|
|
1070064f89 | ||
|
|
88b354b57e | ||
|
|
4b7ca736d6 | ||
|
|
18ea2371a4 | ||
|
|
22be2629e0 | ||
|
|
7fc4ba7c1c | ||
|
|
33fe146a57 | ||
|
|
a2739ab0c1 | ||
|
|
bc309cebe6 | ||
|
|
cc937a97ef | ||
|
|
02f8840ac7 | ||
|
|
1c56a30d35 | ||
|
|
b0a741233f | ||
|
|
b29a5896a4 | ||
|
|
dbb81055f2 | ||
|
|
465fcf93a7 | ||
|
|
65b0aa8e99 | ||
|
|
90a8009d43 | ||
|
|
b1ebb142c4 | ||
|
|
ee2c7bed92 | ||
|
|
d4433fabd4 | ||
|
|
10d2911af2 | ||
|
|
b8d5dfdd05 | ||
|
|
c778233223 | ||
|
|
614f9b8705 | ||
|
|
26cb315845 | ||
|
|
e1bc60b7eb | ||
|
|
a88adc2a27 | ||
|
|
aa54a477d8 | ||
|
|
c69ce4c921 | ||
|
|
b77e430df5 | ||
|
|
a64907d84b | ||
|
|
bc98c788fe | ||
|
|
59370e03db | ||
|
|
16d1e71d6e | ||
|
|
111438361d | ||
|
|
113afc0d0f | ||
|
|
21962da715 | ||
|
|
d731918197 | ||
|
|
e143833ee1 | ||
|
|
ee11aca464 | ||
|
|
71e763d9b3 | ||
|
|
02a827da38 | ||
|
|
2d32ea68fe | ||
|
|
66c60e65aa | ||
|
|
b15787053a | ||
|
|
b38d2e8d84 | ||
|
|
9fcf3795ee | ||
|
|
073902f83e | ||
|
|
c7952d57d8 | ||
|
|
e114c01ce2 | ||
|
|
1e473e59f4 | ||
|
|
3e3250ea5f | ||
|
|
a484e42d42 | ||
|
|
c2613c00f1 | ||
|
|
90e60560c7 | ||
|
|
9edf2a7624 | ||
|
|
fb956e2427 | ||
|
|
4e1089ec49 | ||
|
|
2c650b5bc7 | ||
|
|
fcf3b50f69 | ||
|
|
88a3b4593d | ||
|
|
b6a6528526 | ||
|
|
01d937ca0b | ||
|
|
60a9d7e6cf | ||
|
|
ae160efa16 | ||
|
|
33cf554f06 | ||
|
|
200a6138ef | ||
|
|
4adb492e29 | ||
|
|
698d0b4b49 | ||
|
|
f7742c692d | ||
|
|
b8b344c6e1 | ||
|
|
4d73794100 | ||
|
|
913659325b | ||
|
|
d19f8f51ea | ||
|
|
8e4c366f0b | ||
|
|
7b01a33b3f | ||
|
|
11a34e5bc3 | ||
|
|
2c5973be22 | ||
|
|
597d295743 | ||
|
|
62edabe9dd | ||
|
|
890bb9838c | ||
|
|
87804374c5 | ||
|
|
26ac455fb9 | ||
|
|
9298e567d0 | ||
|
|
c3c54f672c | ||
|
|
feb45f6645 | ||
|
|
887083b7f5 | ||
|
|
c061fb1681 | ||
|
|
8dd59a5d9e | ||
|
|
cc457fade2 | ||
|
|
d72c449b13 | ||
|
|
d70bcfdfff | ||
|
|
6d15c23231 | ||
|
|
0397dd0a40 | ||
|
|
dd988ba449 | ||
|
|
a46038acbf | ||
|
|
3f29295380 | ||
|
|
3c77dc7930 | ||
|
|
13493916e2 | ||
|
|
0acd3bfc66 | ||
|
|
3d9a6a41db | ||
|
|
7d7f15bdf1 | ||
|
|
5c88e680a6 | ||
|
|
fdde5856b8 | ||
|
|
949098bbc5 | ||
|
|
4042852825 | ||
|
|
71a93e8cc3 | ||
|
|
d75f2c62ca | ||
|
|
dd87afcbde | ||
|
|
f5cc40af0c | ||
|
|
25a280c818 | ||
|
|
19fe8e8954 | ||
|
|
9d5135daff | ||
|
|
3a847243bc | ||
|
|
a9fb8da642 | ||
|
|
7e7c2b746c | ||
|
|
42d3876d22 | ||
|
|
0f7411d03a | ||
|
|
d61931e69d | ||
|
|
75c7c7473a | ||
|
|
c8e62ba5e8 | ||
|
|
1faeca6e1b | ||
|
|
0fddc8ed60 | ||
|
|
9d1b14effa | ||
|
|
0154018363 | ||
|
|
b904555ebf | ||
|
|
14d3510d8e | ||
|
|
11cfbd1ec8 | ||
|
|
389affd904 | ||
|
|
6d09bebf14 | ||
|
|
b0df852944 | ||
|
|
6836a7b7c5 | ||
|
|
14dabf523a | ||
|
|
809e1b3aff | ||
|
|
a9de06d6f2 | ||
|
|
08f096df24 | ||
|
|
4a382bc1de | ||
|
|
6f71f1113a | ||
|
|
c24625fae8 | ||
|
|
a35159c220 | ||
|
|
2d2fac5045 | ||
|
|
c35f258ab8 | ||
|
|
702e4f39ab | ||
|
|
56875ed9a7 | ||
|
|
1e09034e23 | ||
|
|
8a86571068 | ||
|
|
37708b0e79 | ||
|
|
14ae52f88f | ||
|
|
8584702fd7 | ||
|
|
ed9cb357b5 | ||
|
|
34a1d9eba4 | ||
|
|
357df80642 | ||
|
|
1a02152d03 | ||
|
|
ab609bc294 | ||
|
|
e6935f2a9d | ||
|
|
5b97ddc842 | ||
|
|
7ab888bb98 | ||
|
|
b135c8e792 | ||
|
|
edda4e5508 | ||
|
|
ed055cbdf6 | ||
|
|
cf41c98d66 | ||
|
|
73deff8863 | ||
|
|
4c2e997997 | ||
|
|
ade84ccb9c | ||
|
|
bcdb9cb13c | ||
|
|
afad5e4407 | ||
|
|
962d809ad7 | ||
|
|
3c73123a81 | ||
|
|
f3f3e56c63 | ||
|
|
b2a7bb0696 | ||
|
|
c0db3d541e | ||
|
|
50e0521bf7 | ||
|
|
ebd09a1981 | ||
|
|
6bc63b7734 | ||
|
|
f6eb79e1e5 | ||
|
|
d195de502e | ||
|
|
ec356626fa | ||
|
|
b1674711a1 | ||
|
|
9ceae3a3b2 | ||
|
|
ded9b121ba | ||
|
|
534fe2fb26 | ||
|
|
3cbc68f07a | ||
|
|
26da5f564b | ||
|
|
1ad9bb8caf | ||
|
|
5a92adaefc | ||
|
|
c489c956e7 | ||
|
|
afd41aade1 | ||
|
|
fee6f12684 | ||
|
|
4265b9c28e | ||
|
|
95e653cf76 | ||
|
|
29fa68118d | ||
|
|
4625d6f17c | ||
|
|
dd4f873439 | ||
|
|
4984e9e414 | ||
|
|
3e53e69827 | ||
|
|
8c54c14742 | ||
|
|
e180266c1a | ||
|
|
751cf23410 | ||
|
|
cd8e76bbcd | ||
|
|
2d78e23d25 | ||
|
|
9d6f51484a | ||
|
|
9a77dbec56 | ||
|
|
a83e421d71 | ||
|
|
2c784d3fea | ||
|
|
c736c3f3f0 | ||
|
|
e0782966d4 | ||
|
|
ed34dfa1c6 | ||
|
|
962a7b1ba7 | ||
|
|
2e05489a82 | ||
|
|
ff28c23f64 | ||
|
|
3721a71eab | ||
|
|
6846e808cf | ||
|
|
2f0adf73c7 | ||
|
|
35674a306b | ||
|
|
fb2bff6c4d | ||
|
|
bddedd9efc | ||
|
|
12d70a3c32 | ||
|
|
5fce81cfa0 | ||
|
|
f9b6d22534 | ||
|
|
c63089a929 | ||
|
|
ebcc317816 | ||
|
|
be46c62105 | ||
|
|
603421bd8c | ||
|
|
6aa7f2e261 | ||
|
|
1bd42af688 | ||
|
|
398a468fd7 | ||
|
|
90b49926ea | ||
|
|
7caf2bd2ff | ||
|
|
3446b38a06 | ||
|
|
22be06174a | ||
|
|
6bfa591e92 | ||
|
|
4573046df8 | ||
|
|
fe05c678c4 | ||
|
|
f89a0c91e9 | ||
|
|
5d4dae5fa8 | ||
|
|
89e1620883 | ||
|
|
4fd0ce3eb5 | ||
|
|
28723949c4 | ||
|
|
cbab316607 | ||
|
|
19a5f02d66 | ||
|
|
754fffac6b | ||
|
|
289fbe56be | ||
|
|
c31052848a | ||
|
|
a8651a2861 | ||
|
|
76a5c444fa | ||
|
|
da44d70bf2 | ||
|
|
e702cdedc3 | ||
|
|
67eb679435 | ||
|
|
ed3cd21f5c | ||
|
|
d3dcc1d27d | ||
|
|
e6f078eeb7 | ||
|
|
097632fb7a | ||
|
|
834c2efb8b | ||
|
|
1cb8b0e369 | ||
|
|
100a46d7af | ||
|
|
b0371b3465 | ||
|
|
872987f002 | ||
|
|
51d8b18f3e | ||
|
|
92a25af3c3 | ||
|
|
ce80586822 | ||
|
|
fee4a5a8f7 | ||
|
|
a15312e052 | ||
|
|
d23bc9f58a | ||
|
|
35a93e6eef | ||
|
|
a5b77aa228 | ||
|
|
3612814a18 | ||
|
|
1165e25f00 | ||
|
|
64fe987fb5 | ||
|
|
c8ea167a06 | ||
|
|
653af9a5cd | ||
|
|
16d1c938bf | ||
|
|
1074af905c | ||
|
|
786f3568c0 | ||
|
|
830dbc7a71 | ||
|
|
686c05d20c | ||
|
|
4b786fb77e | ||
|
|
16b8fa4715 | ||
|
|
39055ff701 | ||
|
|
cbc0231461 | ||
|
|
1ceacc6555 | ||
|
|
ae04fc70eb | ||
|
|
acd6445d3b | ||
|
|
7a89789a28 | ||
|
|
63eeb86bc7 | ||
|
|
1e6fe92b44 | ||
|
|
c014491f55 | ||
|
|
5e384ccc43 | ||
|
|
3fce83eb79 | ||
|
|
3f6092d95c | ||
|
|
87f8f1d9c4 | ||
|
|
eb4d0bb737 | ||
|
|
b9498826fd | ||
|
|
2617eccb46 | ||
|
|
aef18f6b2f | ||
|
|
aad9f6be28 | ||
|
|
9fb14704c3 | ||
|
|
1ad17878e3 | ||
|
|
391c32654b | ||
|
|
74023e43ce | ||
|
|
c470748e3f | ||
|
|
84abb53712 | ||
|
|
46eec3f568 | ||
|
|
007e29425d | ||
|
|
41c316d612 | ||
|
|
39e9dd0ab0 | ||
|
|
a989c8adcc | ||
|
|
5f041a22e5 | ||
|
|
ecabcbc58a | ||
|
|
c002684233 | ||
|
|
a4ebbeabd2 | ||
|
|
7db8d5aa82 | ||
|
|
7981cb832e | ||
|
|
c27494ac39 | ||
|
|
f37d00a8ba | ||
|
|
11ecb54576 | ||
|
|
8d60c0ff21 | ||
|
|
a1e62c3e76 | ||
|
|
16a3f4c06a | ||
|
|
b5964b9795 | ||
|
|
eef4574a63 | ||
|
|
e3930a30c0 | ||
|
|
36114de5f7 | ||
|
|
1fd4839bb6 | ||
|
|
a7ab4b9c32 | ||
|
|
51f6dcffa4 | ||
|
|
ab236f3763 | ||
|
|
81e4e94adf | ||
|
|
5655be1b8f | ||
|
|
61067b0984 | ||
|
|
dc8b0b02d8 | ||
|
|
d9e4a60010 | ||
|
|
9e8e5d8ae9 | ||
|
|
bae0baa42f | ||
|
|
027ea9ea36 | ||
|
|
4f50ef9b54 | ||
|
|
a11fcfc72d | ||
|
|
cb0cf7b9e2 | ||
|
|
95737958ad | ||
|
|
f9f67e6d54 | ||
|
|
dd182ab179 | ||
|
|
fc043da9c6 | ||
|
|
f1a972607a | ||
|
|
4b7b0ad6b9 | ||
|
|
ba6b56445d | ||
|
|
be15c5ff4a | ||
|
|
957a89f2b3 | ||
|
|
08a5adf18e | ||
|
|
3a82b3aa3c | ||
|
|
d73d007797 | ||
|
|
3fd5f15e7f | ||
|
|
1f9fd4c42a | ||
|
|
c539cfa5ae | ||
|
|
48e4de1213 | ||
|
|
18ea59051a | ||
|
|
34517ec43e | ||
|
|
9aae348cae | ||
|
|
634e841ce8 | ||
|
|
924520a9a7 | ||
|
|
0d40e57cc8 | ||
|
|
321a56d934 | ||
|
|
22aba527b7 | ||
|
|
6103de1754 | ||
|
|
8799e1112b | ||
|
|
01d178a1f3 | ||
|
|
685ed6bfad | ||
|
|
d337222cbe | ||
|
|
81efe25a6e | ||
|
|
781794f699 | ||
|
|
bfffaf5b53 | ||
|
|
0789cbdefa | ||
|
|
d289545bf8 | ||
|
|
e8b468b492 | ||
|
|
e6db0842d4 | ||
|
|
4b3d6e7332 | ||
|
|
d3c994c403 | ||
|
|
4397e2cff5 | ||
|
|
8a3557bc97 | ||
|
|
b757544ede | ||
|
|
e9454b629b | ||
|
|
34539cda17 | ||
|
|
85f437ee22 | ||
|
|
14af1fe022 | ||
|
|
686fd208dc | ||
|
|
cfb974dc1f | ||
|
|
1ea99d119b | ||
|
|
843fa3eecc | ||
|
|
3959827fd4 | ||
|
|
d0c466ccc0 | ||
|
|
0b15fc3807 | ||
|
|
4d99a454fd | ||
|
|
3452fbc351 | ||
|
|
8c04947aa2 | ||
|
|
b71fb8c966 | ||
|
|
c85e1305c0 | ||
|
|
5dfa2fd24c | ||
|
|
71ed7f8e94 | ||
|
|
4636444464 | ||
|
|
e7bf9b4df2 | ||
|
|
f0e011e73a | ||
|
|
f224a8ec57 | ||
|
|
4a47644e64 | ||
|
|
7af56e8717 | ||
|
|
526f728f89 | ||
|
|
7de861bb4c | ||
|
|
4e068ba593 | ||
|
|
0d68fb409c | ||
|
|
b77f41949c | ||
|
|
1d35110a98 | ||
|
|
e5738ec703 | ||
|
|
942f024db9 | ||
|
|
a640dfecf8 | ||
|
|
4fa617b772 | ||
|
|
4b95efda49 | ||
|
|
f6a363e7d2 | ||
|
|
d2549b3b1a | ||
|
|
1bae3d19ee | ||
|
|
d1df26cc83 | ||
|
|
66756853a6 | ||
|
|
00d9c60515 | ||
|
|
e243ca47ba | ||
|
|
941652ec57 | ||
|
|
7eeb60e17e | ||
|
|
c8ce5e6ed4 | ||
|
|
1e89197349 | ||
|
|
b57f4ce848 | ||
|
|
48e80adccc | ||
|
|
d511d76a1b | ||
|
|
0049b19994 | ||
|
|
56ad7ece69 | ||
|
|
b48103196f | ||
|
|
4d5e096437 | ||
|
|
e5ceef3422 | ||
|
|
18fbe364f2 | ||
|
|
c9ffe4ab4d | ||
|
|
0a44c75b20 | ||
|
|
82ecc8e73f | ||
|
|
e2a7d5f3f4 | ||
|
|
5994c26de3 | ||
|
|
a7b60bf2a6 | ||
|
|
f4e738a9ef | ||
|
|
13fe87259f | ||
|
|
d55652deff | ||
|
|
4b363472dd | ||
|
|
bf78ace9e2 | ||
|
|
cf4b537c37 | ||
|
|
305d5bcc83 | ||
|
|
d65dfe1958 | ||
|
|
895694c624 | ||
|
|
3edbf8f538 | ||
|
|
2a0a54a224 | ||
|
|
35e74c07d1 | ||
|
|
f6a38352e8 | ||
|
|
76ed466eb4 | ||
|
|
f7e0338a75 | ||
|
|
ca62254ee7 | ||
|
|
a6bfc27530 | ||
|
|
40cc78489a | ||
|
|
bc2a2f5907 | ||
|
|
5ef6adb9ea | ||
|
|
eef8c0ffa7 | ||
|
|
528d29b82d | ||
|
|
5c00a403f6 | ||
|
|
c9e3f20314 | ||
|
|
0084443ed7 | ||
|
|
b84f14386c | ||
|
|
111750c420 | ||
|
|
2832160891 | ||
|
|
531ba24e9a | ||
|
|
4d56bb4e44 | ||
|
|
92bed4a081 | ||
|
|
bcadbc6353 | ||
|
|
1543170f4c | ||
|
|
18194b6bb5 | ||
|
|
cdede67f31 | ||
|
|
c5a76af1dd | ||
|
|
1acbd84b7c | ||
|
|
e9e44db964 | ||
|
|
271ec6cf97 | ||
|
|
9b156fbdca | ||
|
|
de9765fa25 | ||
|
|
abcb9b2f38 | ||
|
|
eaae5da519 | ||
|
|
77f458fb6e | ||
|
|
8fa21c49b2 | ||
|
|
49b2a4da8a | ||
|
|
09defbc4d4 | ||
|
|
2b3e12fcb6 | ||
|
|
bc1fdabce4 | ||
|
|
fc6e152fd1 | ||
|
|
3ec070313e | ||
|
|
33136b441c | ||
|
|
5bff5ca40d | ||
|
|
d5164c427f | ||
|
|
17b122990f | ||
|
|
78d1507f14 | ||
|
|
1e1d9fcb69 | ||
|
|
6f6074dc01 | ||
|
|
14c6abe4eb | ||
|
|
25d24f1e4c | ||
|
|
528d2a7ec3 | ||
|
|
4a77a236b4 | ||
|
|
cf6829f608 | ||
|
|
7642d67cae | ||
|
|
238187730c | ||
|
|
c53f5aa5b5 | ||
|
|
ebe1a8f55f | ||
|
|
510f217cd5 | ||
|
|
364b334654 | ||
|
|
afc2b14578 | ||
|
|
db57ff947b | ||
|
|
8c4716f170 | ||
|
|
11ac6240d2 | ||
|
|
d6680d1f75 | ||
|
|
09540929c3 | ||
|
|
36aecfbec9 | ||
|
|
0af74fb755 | ||
|
|
78b7310057 | ||
|
|
ccbb3a3498 | ||
|
|
69d1d5498e | ||
|
|
d7b54dfa66 | ||
|
|
04e28f3e39 | ||
|
|
1a56ce77e2 | ||
|
|
94e8e5d498 | ||
|
|
f3cbb0363d | ||
|
|
2d860b4a22 | ||
|
|
09a66e2285 | ||
|
|
fb17718a5d | ||
|
|
73145e0beb | ||
|
|
55b4f87cd7 | ||
|
|
3dde112676 | ||
|
|
155e4e9fa4 | ||
|
|
90cb1c4f2e | ||
|
|
e2e3663524 | ||
|
|
7b85e04462 | ||
|
|
96412202ba | ||
|
|
05b183f5e5 | ||
|
|
0b356c2d6d | ||
|
|
ee9092c8e5 | ||
|
|
2e7bb26eef | ||
|
|
5d28939c28 | ||
|
|
15a29e1483 | ||
|
|
c22b3b57bd | ||
|
|
1daa2fa377 | ||
|
|
59e94566fd | ||
|
|
1b45b8a17d | ||
|
|
e94beff204 | ||
|
|
82baf1e923 | ||
|
|
fa146d8770 | ||
|
|
064c60e52e | ||
|
|
18ea05edee | ||
|
|
c416041379 | ||
|
|
10444b943e | ||
|
|
2308a54ada | ||
|
|
0ed6738a5b | ||
|
|
12180ba707 | ||
|
|
278ae51d73 | ||
|
|
dc25bfb831 | ||
|
|
d113bbf4dd | ||
|
|
38b65fba3b | ||
|
|
7af6a46c8f | ||
|
|
ff724ce4b5 | ||
|
|
d6fcb04aa8 | ||
|
|
9bf8f1015d | ||
|
|
c477d1321a | ||
|
|
ec99b70b38 | ||
|
|
06a58ebd53 | ||
|
|
eb6fe0a4db | ||
|
|
c6a14e1a67 | ||
|
|
04cead1fc5 | ||
|
|
93732865ac | ||
|
|
6a5d63803a | ||
|
|
159aef022b | ||
|
|
f7c63c675b | ||
|
|
99d657fcfb | ||
|
|
00ceb2cd5d | ||
|
|
f151d3be01 | ||
|
|
fa04e36df2 | ||
|
|
7554e7bedb | ||
|
|
59e797b312 | ||
|
|
94cdaf20a2 | ||
|
|
b51a754fd9 | ||
|
|
c1e0d02afc | ||
|
|
890c9e87ce | ||
|
|
961dd297dd | ||
|
|
d675563271 | ||
|
|
e027d5c3e8 | ||
|
|
fdcfd5996b | ||
|
|
f7de65684a | ||
|
|
810dfa1b79 | ||
|
|
f0838dd5fc | ||
|
|
a849d49c92 | ||
|
|
ff129e524a | ||
|
|
05479103a6 | ||
|
|
ff41d262dc | ||
|
|
8628a2c6a2 | ||
|
|
30914678c9 | ||
|
|
c4bf1fe717 | ||
|
|
1946aaf5e1 | ||
|
|
a7b2427007 | ||
|
|
f9101d8084 | ||
|
|
1c3cbec661 | ||
|
|
cea423742b | ||
|
|
8c5f28d6a0 | ||
|
|
6c2e332638 | ||
|
|
5f18532a59 | ||
|
|
63f072a819 | ||
|
|
df1d6503c0 | ||
|
|
972054b377 | ||
|
|
e1c89834df | ||
|
|
c145cad653 | ||
|
|
4261063c99 | ||
|
|
f8546937c0 | ||
|
|
3daaea6ecf | ||
|
|
4a84fbc6e3 | ||
|
|
d8800e9fe3 | ||
|
|
7fd921227c | ||
|
|
b6ad07b47c | ||
|
|
1a21f0e3c9 | ||
|
|
c666368446 | ||
|
|
91d614dd25 | ||
|
|
baca59927b | ||
|
|
4eb40ce948 | ||
|
|
00b1018e9e | ||
|
|
9c92338ddf | ||
|
|
8188b63522 | ||
|
|
0e172b67eb | ||
|
|
156948ec58 | ||
|
|
bbdda5a3d7 | ||
|
|
51a2e638ed | ||
|
|
ffd9d3c218 | ||
|
|
9513ff5307 | ||
|
|
12e736b283 | ||
|
|
a64c9534e2 | ||
|
|
4b3e8aba29 | ||
|
|
98d5718ec9 | ||
|
|
457aa5331f | ||
|
|
a61b5d4b4c | ||
|
|
ba074068b0 | ||
|
|
615a147973 | ||
|
|
c00776ca22 | ||
|
|
d0b9a3a4ae | ||
|
|
dc246ddb09 | ||
|
|
591a2f2b02 | ||
|
|
7aaa847835 | ||
|
|
42101c6594 | ||
|
|
3e9ecd2f4f | ||
|
|
725811d7b3 | ||
|
|
a56a52b4bb | ||
|
|
da18305119 | ||
|
|
c71d04a660 | ||
|
|
f3f68fd5d3 | ||
|
|
d4ce47c941 | ||
|
|
7413a78013 | ||
|
|
83967d6e06 | ||
|
|
4d1c6a8d20 | ||
|
|
c95a0a0171 | ||
|
|
feba1dbc24 | ||
|
|
5b578cf69d | ||
|
|
dafea08581 | ||
|
|
5c50224571 | ||
|
|
b510df47f9 | ||
|
|
2aec3ec5fd | ||
|
|
4b8c017302 | ||
|
|
b579bca227 | ||
|
|
3a676f7afa | ||
|
|
ca479303a1 | ||
|
|
5e649d8c41 | ||
|
|
0bc626ba1d | ||
|
|
3821ee7709 | ||
|
|
cb17189b15 | ||
|
|
80e8167054 | ||
|
|
eede5ed29e | ||
|
|
360fef7777 | ||
|
|
b83da5d3cb | ||
|
|
ae5d28fbc5 | ||
|
|
f4cd7c0100 | ||
|
|
7b68fd30ec | ||
|
|
ac222f1b0c | ||
|
|
b0e8e68909 | ||
|
|
ef5f6e2f70 | ||
|
|
30f6da3fa3 | ||
|
|
3a47154cdb | ||
|
|
d953d35991 | ||
|
|
4b74d13e10 | ||
|
|
98bf353287 | ||
|
|
eb8c751b31 | ||
|
|
9abad8704f | ||
|
|
6716c0f792 | ||
|
|
35f7ec6c07 | ||
|
|
a524fd7674 | ||
|
|
ff27fd3094 | ||
|
|
977ac09fe6 | ||
|
|
1a88e01899 | ||
|
|
6e710c5164 | ||
|
|
fd56ac3400 | ||
|
|
1d801c38f9 | ||
|
|
8afdb5b7b4 | ||
|
|
83624b1dee | ||
|
|
56adcf1ad8 | ||
|
|
ad27f87a0c | ||
|
|
346cf299ee | ||
|
|
05489fda7d | ||
|
|
1b12526357 | ||
|
|
802035d92e | ||
|
|
a24d0f1958 | ||
|
|
da68f2e4ed | ||
|
|
8f16dbb8e7 | ||
|
|
49e458f1b5 | ||
|
|
5cf46d2aa9 | ||
|
|
beedf54e75 | ||
|
|
70ccb89c3d | ||
|
|
5ea43a2a4b | ||
|
|
41f60dbbf4 | ||
|
|
827341ec08 | ||
|
|
5c36043d03 | ||
|
|
cf5811f8d9 | ||
|
|
ec6a169bf8 | ||
|
|
f1dec87c1b | ||
|
|
ab29951a99 | ||
|
|
bbe9f88bbe | ||
|
|
9188bf0013 | ||
|
|
f33ed59567 | ||
|
|
3fd8c80861 | ||
|
|
7b8ac3a5a0 | ||
|
|
6fef957001 | ||
|
|
0de1c9df89 | ||
|
|
a0e8cfbe97 |
@@ -69,7 +69,7 @@ Min butthurt: 0
|
|||||||
Max butthurt: 9
|
Max butthurt: 9
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Painting_128x64
|
Name: L1_Painting_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
@@ -85,26 +85,33 @@ Min level: 1
|
|||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L1_Senpai_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 5
|
||||||
|
Min level: 1
|
||||||
|
Max level: 3
|
||||||
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Kaiju_128x64
|
Name: L1_Kaiju_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 10
|
Max butthurt: 10
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_My_dude_128x64
|
Name: L1_My_dude_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 8
|
Max butthurt: 8
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L2_Wake_up_128x64
|
Name: L2_Wake_up_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 12
|
Max butthurt: 12
|
||||||
Min level: 2
|
Min level: 2
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L2_Furippa2_128x64
|
Name: L2_Furippa2_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
@@ -132,7 +139,7 @@ Min butthurt: 0
|
|||||||
Max butthurt: 8
|
Max butthurt: 8
|
||||||
Min level: 2
|
Min level: 2
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L3_Furippa3_128x64
|
Name: L3_Furippa3_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
@@ -155,23 +162,30 @@ Min level: 3
|
|||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 3
|
Weight: 3
|
||||||
|
|
||||||
Name: L1_Senpai_128x64
|
|
||||||
Min butthurt: 0
|
|
||||||
Max butthurt: 5
|
|
||||||
Min level: 1
|
|
||||||
Max level: 3
|
|
||||||
Weight: 4
|
|
||||||
|
|
||||||
Name: L1_Sad_song_128x64
|
Name: L1_Sad_song_128x64
|
||||||
Min butthurt: 8
|
Min butthurt: 8
|
||||||
Max butthurt: 13
|
Max butthurt: 13
|
||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
Name: L2_Coding_in_the_shell_128x64
|
Name: L2_Coding_in_the_shell_128x64
|
||||||
Min butthurt: 0
|
Min butthurt: 0
|
||||||
Max butthurt: 12
|
Max butthurt: 12
|
||||||
Min level: 2
|
Min level: 2
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L2_Secret_door_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 12
|
||||||
|
Min level: 2
|
||||||
|
Max level: 3
|
||||||
|
Weight: 3
|
||||||
|
|
||||||
|
Name: L3_Freedom_2_dolphins_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 12
|
||||||
|
Min level: 3
|
||||||
|
Max level: 3
|
||||||
|
Weight: 5
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||||
index 5769ced..c5d3088 100644
|
index 9baa738..91ad7c1 100644
|
||||||
--- a/applications/services/notification/notification_app.c
|
--- a/applications/services/notification/notification_app.c
|
||||||
+++ b/applications/services/notification/notification_app.c
|
+++ b/applications/services/notification/notification_app.c
|
||||||
@@ -9,6 +9,7 @@
|
@@ -9,6 +9,7 @@
|
||||||
@@ -19,7 +19,7 @@ index 5769ced..c5d3088 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
index 1955012..19d953d 100644
|
index 2a1d988..dda86f3 100644
|
||||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -30,16 +30,16 @@ index 1955012..19d953d 100644
|
|||||||
|
|
||||||
#define MAX_NOTIFICATION_SETTINGS 4
|
#define MAX_NOTIFICATION_SETTINGS 4
|
||||||
|
|
||||||
@@ -20,6 +21,8 @@ static const NotificationSequence sequence_note_c = {
|
@@ -13,6 +14,8 @@ typedef struct {
|
||||||
NULL,
|
VariableItemList* variable_item_list;
|
||||||
};
|
} NotificationAppSettings;
|
||||||
|
|
||||||
+static VariableItem* temp_item;
|
+static VariableItem* temp_item;
|
||||||
+
|
+
|
||||||
#define CONTRAST_COUNT 11
|
static const NotificationSequence sequence_note_c = {
|
||||||
const char* const contrast_text[CONTRAST_COUNT] = {
|
&message_note_c5,
|
||||||
"-5",
|
&message_delay_100,
|
||||||
@@ -156,6 +159,59 @@ static void vibro_changed(VariableItem* item) {
|
@@ -168,6 +171,59 @@ static void vibro_changed(VariableItem* item) {
|
||||||
notification_message(app->notification, &sequence_single_vibro);
|
notification_message(app->notification, &sequence_single_vibro);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ index 1955012..19d953d 100644
|
|||||||
static uint32_t notification_app_settings_exit(void* context) {
|
static uint32_t notification_app_settings_exit(void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
return VIEW_NONE;
|
return VIEW_NONE;
|
||||||
@@ -180,8 +236,40 @@ static NotificationAppSettings* alloc_settings() {
|
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings() {
|
||||||
variable_item_set_current_value_index(item, value_index);
|
variable_item_set_current_value_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||||
|
|
||||||
@@ -462,54 +462,6 @@ index 0000000..68dacda
|
|||||||
+ */
|
+ */
|
||||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||||
\ No newline at end of file
|
\ 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..45798ca 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, false);
|
|
||||||
+ } 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
|
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..572e1df
|
index 0000000..572e1df
|
||||||
@@ -575,7 +527,7 @@ index 0000000..572e1df
|
|||||||
+
|
+
|
||||||
+void SK6805_update(void) {
|
+void SK6805_update(void) {
|
||||||
+ SK6805_init();
|
+ SK6805_init();
|
||||||
+ furi_kernel_lock();
|
+ FURI_CRITICAL_ENTER();
|
||||||
+ uint32_t end;
|
+ uint32_t end;
|
||||||
+ /* Последовательная отправка цветов светодиодов */
|
+ /* Последовательная отправка цветов светодиодов */
|
||||||
+ for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
+ for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
||||||
@@ -615,7 +567,7 @@ index 0000000..572e1df
|
|||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+ furi_kernel_unlock();
|
+ FURI_CRITICAL_EXIT();
|
||||||
+}
|
+}
|
||||||
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
@@ -675,3 +627,51 @@ index 0000000..7c58956
|
|||||||
+
|
+
|
||||||
+#endif /* SK6805_H_ */
|
+#endif /* SK6805_H_ */
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
|
diff --git a/targets/f7/furi_hal/furi_hal_light.c b/targets/f7/furi_hal/furi_hal_light.c
|
||||||
|
index 83e1603..45798ca 100644
|
||||||
|
--- a/targets/f7/furi_hal/furi_hal_light.c
|
||||||
|
+++ b/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, false);
|
||||||
|
+ } 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) {
|
||||||
|
|||||||
32
.drone.yml
32
.drone.yml
@@ -45,7 +45,9 @@ steps:
|
|||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxf all-the-apps-base.tgz
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
@@ -65,7 +67,8 @@ steps:
|
|||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- tar zxf all-the-apps-extra.tgz
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps
|
||||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||||
- rm -rf extra_pack_build
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||||
@@ -117,7 +120,9 @@ steps:
|
|||||||
- 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
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxf all-the-apps-base.tgz
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
@@ -336,9 +341,10 @@ steps:
|
|||||||
DISCORD_WEBHOOK:
|
DISCORD_WEBHOOK:
|
||||||
from_secret: dis_release_webhook
|
from_secret: dis_release_webhook
|
||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./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)'
|
- echo '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)' > messagedisc.txt
|
||||||
|
- ./discord.sh --text "$(jq -Rs . <messagedisc.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||||
|
|
||||||
- name: "Send clean build to telegram"
|
- name: "Send clean build to telegram"
|
||||||
image: appleboy/drone-telegram
|
image: appleboy/drone-telegram
|
||||||
@@ -369,7 +375,7 @@ trigger:
|
|||||||
- tag
|
- tag
|
||||||
|
|
||||||
node:
|
node:
|
||||||
typ: haupt
|
typ: dev1
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
@@ -420,7 +426,9 @@ steps:
|
|||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxf all-the-apps-base.tgz
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||||
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
@@ -440,7 +448,8 @@ steps:
|
|||||||
pull: never
|
pull: never
|
||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- tar zxf all-the-apps-extra.tgz
|
||||||
|
- mkdir -p applications/main/clock_app/resources/apps
|
||||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||||
- rm -rf extra_pack_build
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||||
@@ -657,9 +666,10 @@ steps:
|
|||||||
DISCORD_WEBHOOK:
|
DISCORD_WEBHOOK:
|
||||||
from_secret: dis_dev_webhook
|
from_secret: dis_dev_webhook
|
||||||
commands:
|
commands:
|
||||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||||
- chmod +x ./discord.sh
|
- chmod +x ./discord.sh
|
||||||
- ./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}')'
|
- echo '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}')' > messagedisc.txt
|
||||||
|
- ./discord.sh --text "$(jq -Rs . <messagedisc.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
@@ -668,4 +678,4 @@ trigger:
|
|||||||
- push
|
- push
|
||||||
|
|
||||||
node:
|
node:
|
||||||
typ: haupt
|
typ: dev1
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
--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/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
--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/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e lib/mjs -e */arm-none-eabi/*
|
||||||
|
|||||||
2
.vscode/ReadMe.md
vendored
2
.vscode/ReadMe.md
vendored
@@ -1,4 +1,4 @@
|
|||||||
# Visual Studio Code workspace for Flipper Zero
|
# Visual Studio Code workspace for Flipper Zero {#vscode}
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
|
|||||||
15
.vscode/example/cpptools/c_cpp_properties.json
vendored
15
.vscode/example/cpptools/c_cpp_properties.json
vendored
@@ -5,27 +5,24 @@
|
|||||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
||||||
"intelliSenseMode": "gcc-arm",
|
"intelliSenseMode": "gcc-arm",
|
||||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||||
"configurationProvider": "ms-vscode.cpptools",
|
"cStandard": "gnu23",
|
||||||
"cStandard": "gnu17",
|
"cppStandard": "c++20"
|
||||||
"cppStandard": "c++17"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
||||||
"intelliSenseMode": "gcc-arm",
|
"intelliSenseMode": "gcc-arm",
|
||||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||||
"configurationProvider": "ms-vscode.cpptools",
|
"cStandard": "gnu23",
|
||||||
"cStandard": "gnu17",
|
"cppStandard": "c++20"
|
||||||
"cppStandard": "c++17"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Mac",
|
"name": "Mac",
|
||||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
||||||
"intelliSenseMode": "gcc-arm",
|
"intelliSenseMode": "gcc-arm",
|
||||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||||
"configurationProvider": "ms-vscode.cpptools",
|
"cStandard": "gnu23",
|
||||||
"cStandard": "gnu17",
|
"cppStandard": "c++20"
|
||||||
"cppStandard": "c++17"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 4
|
"version": 4
|
||||||
|
|||||||
16
.vscode/example/settings.json
vendored
16
.vscode/example/settings.json
vendored
@@ -1,20 +1,14 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.default.cStandard": "gnu17",
|
"C_Cpp.default.cStandard": "gnu23",
|
||||||
"C_Cpp.default.cppStandard": "c++17",
|
"C_Cpp.default.cppStandard": "c++20",
|
||||||
"python.formatting.provider": "black",
|
"python.formatting.provider": "black",
|
||||||
"workbench.tree.indent": 12,
|
"workbench.tree.indent": 12,
|
||||||
"cortex-debug.enableTelemetry": false,
|
"cortex-debug.enableTelemetry": false,
|
||||||
"cortex-debug.variableUseNaturalFormat": true,
|
"cortex-debug.variableUseNaturalFormat": true,
|
||||||
"cortex-debug.showRTOS": true,
|
"cortex-debug.showRTOS": true,
|
||||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin",
|
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
||||||
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
|
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
||||||
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
|
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
||||||
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/openocd/bin/openocd.exe",
|
|
||||||
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
|
|
||||||
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
|
|
||||||
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
|
|
||||||
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
|
|
||||||
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
|
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"*.scons": "python",
|
"*.scons": "python",
|
||||||
|
|||||||
105
CHANGELOG.md
105
CHANGELOG.md
@@ -1,13 +1,94 @@
|
|||||||
## New changes
|
## New changes
|
||||||
* SubGHz: Add 4 more systems to Add Manually (untested!)
|
* NFC: **EMV Fixes and imporvements** (old saved files may be not compatible now) (by @wosk & @Leptopt1los | PR #702)
|
||||||
* SubGHz: Add Manually fixes
|
* NFC: **Parsers refactoring** (by @Leptopt1los)
|
||||||
* SubGHz: Added NiceFlor-S to ignore options, removed colons. (by @G2Dolphin | PR #620)
|
* NFC: **Kazan parser improved** - token parse option added (by @Leptopt1los)
|
||||||
* Misc code cleanup
|
* NFC: **Update ndef parser**, mf classic dict changes (by @Willy-JL)
|
||||||
* RGB: Fix white color on reboot, move settings, add custom color option
|
* RFID: Test swap of em4100 t5577 blocks (details in issue 3463 OFW)
|
||||||
* **BLE Spam app** updated to latest version (Android, Windows support) (by @Willy-JL) -> (app can be found in builds ` `, `e`, `n`, `r`)
|
* RFID: Fix RAW read crash (by @Willy-JL)
|
||||||
* OFW: Fix double arrows and add proper indication
|
* Infrared: Update universal remote assets (by @amec0e | PR #718 #719)
|
||||||
* OFW: SubGHz: add manually fix 12-bits is 0xFFF (or 0xFF0) CAME/NICE 12-bit
|
* SubGHz: Add 430.50 mhz (by @MizumasuShoichi | PR #721)
|
||||||
* OFW: Fix various crashes if debug libraries used
|
* SubGHz: **Magellan Event Code Update** (by @wooferguy | PR #713)
|
||||||
|
* SubGHz: Reduce subghz add manually scene flash size (by @Willy-JL)
|
||||||
|
* SubGHz: Fix led blink on decode raw > signal info (by @Willy-JL)
|
||||||
|
* HID App: apply fix for ms teams on macos (by @cpressland)
|
||||||
|
* HID App: merge official fw hid app keyboard changes
|
||||||
|
* Misc: Use non prefixed names for regular files with random name
|
||||||
|
* Misc: Revert usb cdc config changes to verify issue (storage timeout during firmware update) (OFW 3452)
|
||||||
|
* Misc: Fixes for text box and uart echo demo app, remove duplicated emv parser plugin (by @Willy-JL)
|
||||||
|
* Expansion `is_connected` API to check for VGM (by @HaxSam)
|
||||||
|
* New JavaScript Modules `UsbDisk`,`badusb.quit() + altstring`,`SubGHz`,`Submenu`,`BleBeacon`,`Keyboard`,`Math`,`GPIO`, `textbox` (by @Willy-JL, @Spooks4576, @Sil333033, @oldip)
|
||||||
|
* Apps: **BadBT renamed and moved from Apps-Bluetooth to Apps-Tools as BadKB**
|
||||||
|
* Apps: Added **FindMy Flipper** app
|
||||||
|
* Apps: NFC Magic - **Gen4 improvements**
|
||||||
|
* Apps: **Check out Apps updates by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||||
|
* OFW: BLE/GAP fixes
|
||||||
|
* OFW: Add support for Pioneer SR IR remotes
|
||||||
|
* OFW: fbt/ufbt: Ensure POSIX paths are passed to GDB on all platforms
|
||||||
|
* OFW: Add support for DEFAULT_STRING_DELAY in Bad USB App
|
||||||
|
* OFW: Adding F13-F24 function key support to BadUSB
|
||||||
|
* OFW PR 3532: NFC UI fixes (by gornekich)
|
||||||
|
* OFW PR 3504: NFC: **Slix privacy password reveal and Desfire detect fix** (by gornekich)
|
||||||
|
* OFW: **Infrared fixes and more**
|
||||||
|
* OFW: NFC Parsers cosmetic fixes
|
||||||
|
* OFW: NFC wording fixes
|
||||||
|
* OFW: **Fix iButton emulation regression**
|
||||||
|
* OFW: Add the Freedom_2_dolphins animation
|
||||||
|
* OFW: Infrared: Add Fujitsu ASYG24KMTB
|
||||||
|
* OFW: Asynchronous Infrared remote manipulation
|
||||||
|
* OFW: Fix troika 4K keys
|
||||||
|
* OFW: Archive: Fix item focus after aborting the Delete operation
|
||||||
|
* OFW: Troyka parser improvements (by UL Team)
|
||||||
|
* OFW: NFC: Fix washcity plugin verify function being to greedy
|
||||||
|
* OFW: Parser for Santiago, Chile BIP transit card
|
||||||
|
* OFW: WiFi board: fixed update script on Windows (unfortunately also Mac and Linux)
|
||||||
|
* OFW: Gui: reset canvas orientation and frame when entering direct draw mode
|
||||||
|
* OFW: FBT/uFBT: Enable C++20/GNU23 in VSCode IntelliSense
|
||||||
|
* OFW: Toolchain fixes
|
||||||
|
* OFW: Quote $FBT_TOOLCHAIN_PATH to avoid splitting
|
||||||
|
* OFW: **ble: profile rework**
|
||||||
|
* OFW: lfrfid/em4100: added support for different bit rates (16clk was added back into UL, still not reading properly)
|
||||||
|
* OFW: T5577 lib: write with mask function added
|
||||||
|
* OFW: Archive: fixed Apps tab ext filter
|
||||||
|
* OFW: FuriHalRtc refactor: new datetime lib (by UL Team)
|
||||||
|
* OFW: bit_lib and nfc_util refactor (by UL Team)
|
||||||
|
* OFW: Gui text box: fix formatted string memory reservation
|
||||||
|
* OFW: JS debug disabled, archive and file browser fixes
|
||||||
|
* OFW: VSCode integration fixes for new toolchain
|
||||||
|
* OFW: **FIX ISO15693 emulation**
|
||||||
|
* OFW: JS serial module renamed, uart channel selection
|
||||||
|
* OFW: mjs: minor fixes
|
||||||
|
* OFW: **JavaScript runner**
|
||||||
|
* OFW: Fixed MyKey check LockID
|
||||||
|
* OFW: Check universal remote files before loading
|
||||||
|
* OFW: NFC: fix retry scene navigation logic
|
||||||
|
* OFW: Expansion module service improvements
|
||||||
|
* OFW: New toolchain with gcc 12 (+ aarch64 support!)
|
||||||
|
* OFW: HID app: keyboard modifiers fix
|
||||||
|
* OFW: CLI: cat command crash workaround
|
||||||
|
* OFW: NFC: Custom UID entry when adding manually
|
||||||
|
* OFW: Added NFC plugin; Some parser
|
||||||
|
* OFW: **Slix disable privacy** (Unlock SLIX-L)
|
||||||
|
* OFW: NFC: **Add support for Gallagher access control** (MIFARE Classic only)
|
||||||
|
* OFW: furi/core/timer: resolve timer handle use-after-free post deletion
|
||||||
|
* OFW: FuriHal: various GPIO improvements
|
||||||
|
* OFW: GUI: canvas commit callback has been moved to canvas. Direct Draw apps can now be streamed via RPC.
|
||||||
|
* OFW: nfc app: fix incorrect protocol detection in save scene (by UL Team)
|
||||||
|
* OFW: NFC: **MFC Unlock with Dictionary**
|
||||||
|
* OFW: ITSO Parser (UK)
|
||||||
|
* OFW: NFC: fix application opening from browser
|
||||||
|
* OFW: Rework more info scene for Ultralight cards
|
||||||
|
* OFW: NFC UI refactor
|
||||||
|
* OFW: Add an NFC parser for the San Francisco Bay Area "Clipper" transit card.
|
||||||
|
* OFW: Fix nfc_protocol_support_scene_save_name_on_event crash
|
||||||
|
* OFW: NFC: Display unread Mifare Classic bytes as question marks
|
||||||
|
* OFW: Troika layout fixes
|
||||||
|
* OFW: NFC: MF Classic parsers read() fix (dictionary attack skip)
|
||||||
|
<br><br>
|
||||||
|
#### Known NFC post-refactor regressions list:
|
||||||
|
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||||
|
- NFC CLI was removed with refactoring (OFW) (will be back soon)
|
||||||
|
- Current list of affected apps: https://github.com/xMasterX/all-the-plugins/tree/dev/apps_broken_by_last_refactors
|
||||||
|
- Also in app **Enhanced Sub-GHz Chat** - NFC part was temporarily removed to make app usable, NFC part of the app requires remaking it with new nfc stack
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
@@ -31,8 +112,8 @@
|
|||||||
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
|XMR|(Monero)| `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||||
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
|TON||`EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`|
|
||||||
|
|
||||||
#### Thanks to our sponsors:
|
#### Thanks to our sponsors who supported project in the past and special thanks to sponsors who supports us on regular basis:
|
||||||
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
ClaraCrazy, Pathfinder [Count Zero cDc], 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!
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +131,7 @@ What build I should download and what this name means - `flipper-z-f7-update-(ve
|
|||||||
| `c` | ✅ | | | |
|
| `c` | ✅ | | | |
|
||||||
| `n` | | ✅ | | |
|
| `n` | | ✅ | | |
|
||||||
| `e` | ✅ | ✅ | ✅ | |
|
| `e` | ✅ | ✅ | ✅ | |
|
||||||
| `r` | ✅ | ✅ | ✅ | ✅ |
|
| `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!
|
⚠️This is [hardware mod](https://github.com/quen0n/flipperzero-firmware-rgb#readme), works only on modded flippers! do not install on non modded device!
|
||||||
|
|
||||||
|
|||||||
48
ReadMe.md
48
ReadMe.md
@@ -55,13 +55,13 @@
|
|||||||
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||||
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||||
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||||
- New option to use timestamps + protocol name when you saving file, instead of random name - Enable in `Radio Settings -> Time in names = ON`
|
- New option to use timestamps + protocol name when you saving file, instead of random name or timestamp only - Enable in `Radio Settings -> Protocol Names = ON`
|
||||||
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
||||||
- External CC1101 module support (Hardware SPI used)
|
- External CC1101 module support (Hardware SPI used)
|
||||||
- **Hold right in received signal list to delete selected signal**
|
- **Hold right in received signal list to delete selected signal**
|
||||||
- **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
|
- **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
|
||||||
- `Add manually` menu extended with new protocols
|
- `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)
|
- 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, (right arrow button for other protocols))
|
||||||
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
||||||
- Debug PIN output settings for protocol development
|
- Debug PIN output settings for protocol development
|
||||||
|
|
||||||
@@ -79,13 +79,15 @@
|
|||||||
- **NFC/RFID/iButton**
|
- **NFC/RFID/iButton**
|
||||||
* LFRFID/iButton Fuzzer plugins
|
* LFRFID/iButton Fuzzer plugins
|
||||||
* Extra Mifare Classic keys
|
* Extra Mifare Classic keys
|
||||||
* `Add manually` -> Mifare Classic with custom UID
|
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
||||||
* Picopass/iClass plugin (now with emulation support!) included in releases
|
* NFC/LFRFID - Stop emulation after 5 mins to avoid antenna damage (by @Leptopt1los)
|
||||||
|
* NFC `Add manually` -> Mifare Classic with custom UID
|
||||||
|
* NFC parsers: Umarsh, Zolotaya Korona, Kazan, Metromoney, Moscow Social Card, Troika (reworked) and [many others](https://github.com/DarkFlippers/unleashed-firmware/tree/dev/applications/main/nfc/plugins/supported_cards) (by @Leptopt1los and @assasinfil)
|
||||||
- **Quality of life & other features**
|
- **Quality of life & other features**
|
||||||
- Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL)
|
- 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)
|
- Text Input UI element -> Cursor feature (by @Willy-JL)
|
||||||
- Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears
|
- Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears (by @gid9798)
|
||||||
- Clock on Desktop -> `Settings -> Desktop -> Show Clock`
|
- Clock on Desktop -> `Settings -> Desktop -> Show Clock` (by @gid9798)
|
||||||
- Battery percentage display with different styles `Settings -> Desktop -> Battery View`
|
- Battery percentage display with different styles `Settings -> Desktop -> Battery View`
|
||||||
- More games in Dummy Mode -> click or hold any of arrow buttons
|
- 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)
|
- 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)
|
||||||
@@ -100,25 +102,12 @@ Also check the [changelog in releases](https://github.com/DarkFlippers/unleashed
|
|||||||
### Current modified and new Sub-GHz protocols list:
|
### Current modified and new Sub-GHz protocols list:
|
||||||
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW.
|
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing decoders for these protocols in OFW.
|
||||||
|
|
||||||
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!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m)
|
||||||
|
|
||||||
Encoders or sending made by @xMasterX:
|
Encoders or sending made by @xMasterX:
|
||||||
- Nero Radio 57bit (+ 56bit encoder improvements)
|
- Nero Radio 57bit (+ 56bit encoder improvements)
|
||||||
- CAME 12bit/24bit encoder fixes (Fixes now merged in OFW)
|
- CAME 12bit/24bit encoder fixes (Fixes now merged in OFW)
|
||||||
- Keeloq: HCS101
|
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !)
|
||||||
- Keeloq: AN-Motors
|
|
||||||
- Keeloq: JCM Tech
|
|
||||||
- Keeloq: MHouse
|
|
||||||
- Keeloq: Nice Smilo
|
|
||||||
- Keeloq: DTM Neo
|
|
||||||
- Keeloq: FAAC RC,XT
|
|
||||||
- Keeloq: Mutancode
|
|
||||||
- Keeloq: Normstahl
|
|
||||||
- Keeloq: Beninca + Allmatic
|
|
||||||
- Keeloq: Stilmatic
|
|
||||||
- Keeloq: CAME Space
|
|
||||||
- Keeloq: Aprimatic (model TR and similar)
|
|
||||||
- Keeloq: Centurion Nova (thanks Carlos !)
|
|
||||||
|
|
||||||
Encoders or sending made by @Eng1n33r(first implementation in Q2 2022) & @xMasterX (current version):
|
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)
|
- CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
@@ -139,10 +128,11 @@ Encoders made by @assasinfil & @xMasterX:
|
|||||||
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, 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.
|
||||||
|
- @Leptopt1los - NFC, RFID, IR Assets (only ACs), Plugins, and many other things
|
||||||
- @gid9798 - SubGHz, Plugins, many other things
|
- @gid9798 - SubGHz, Plugins, many other things
|
||||||
- @assasinfil - SubGHz protocols
|
- @assasinfil - SubGHz protocols, NFC parsers
|
||||||
- @Svaarich - UI design and animations
|
- @Svaarich - UI design and animations
|
||||||
- @amec0e & @Leptopt1los - Infrared assets
|
- @amec0e - 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.
|
||||||
|
|
||||||
@@ -167,14 +157,14 @@ You can support us by using links or addresses below:
|
|||||||
## Community apps included
|
## Community apps included
|
||||||
|
|
||||||
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||||
### [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)
|
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Default)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
||||||
|
|
||||||
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
||||||
|
|
||||||
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
## First lock official docs [docs.flipper.net](https://docs.flipper.net/)
|
## First look at official docs [docs.flipper.net](https://docs.flipper.net/)
|
||||||
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `n`,` `,`e`...
|
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `n`,` `,`e`...
|
||||||
## Firmware & Development
|
## Firmware & Development
|
||||||
|
|
||||||
@@ -196,22 +186,20 @@ See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xM
|
|||||||
|
|
||||||
## **Sub-GHz**
|
## **Sub-GHz**
|
||||||
|
|
||||||
|
### - [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)
|
||||||
|
|
||||||
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||||
|
|
||||||
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||||
|
|
||||||
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||||
|
|
||||||
### - [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)
|
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recommended, please use embedded configurator
|
||||||
|
|
||||||
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recomeded, please use embedded configurator
|
|
||||||
|
|
||||||
## **Plugins**
|
## **Plugins**
|
||||||
|
|
||||||
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||||
|
|
||||||
### - Mifare Nested plugin: [How to recover keys](https://github.com/AloneLiberty/FlipperNested#how-to-use-it)
|
|
||||||
|
|
||||||
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||||
|
|
||||||
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||||
|
|||||||
88
SConstruct
88
SConstruct
@@ -7,7 +7,7 @@
|
|||||||
# construction of certain targets behind command-line options.
|
# construction of certain targets behind command-line options.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from fbt.util import path_as_posix
|
from fbt.util import open_browser_action
|
||||||
|
|
||||||
DefaultEnvironment(tools=[])
|
DefaultEnvironment(tools=[])
|
||||||
|
|
||||||
@@ -66,6 +66,7 @@ if GetOption("fullenv") or any(
|
|||||||
|
|
||||||
# Target for self-update package
|
# Target for self-update package
|
||||||
dist_basic_arguments = [
|
dist_basic_arguments = [
|
||||||
|
"${ARGS}",
|
||||||
"--bundlever",
|
"--bundlever",
|
||||||
"${UPDATE_VERSION_STRING}",
|
"${UPDATE_VERSION_STRING}",
|
||||||
]
|
]
|
||||||
@@ -172,6 +173,7 @@ Alias("fap_dist", fap_dist)
|
|||||||
|
|
||||||
fap_deploy = distenv.PhonyTarget(
|
fap_deploy = distenv.PhonyTarget(
|
||||||
"fap_deploy",
|
"fap_deploy",
|
||||||
|
Action(
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
"${PYTHON3}",
|
"${PYTHON3}",
|
||||||
@@ -181,8 +183,10 @@ fap_deploy = distenv.PhonyTarget(
|
|||||||
"send",
|
"send",
|
||||||
"${SOURCE}",
|
"${SOURCE}",
|
||||||
"/ext/apps",
|
"/ext/apps",
|
||||||
|
"${ARGS}",
|
||||||
]
|
]
|
||||||
],
|
]
|
||||||
|
),
|
||||||
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
||||||
)
|
)
|
||||||
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
||||||
@@ -206,7 +210,7 @@ distenv.Alias("jflash", firmware_jflash)
|
|||||||
|
|
||||||
distenv.PhonyTarget(
|
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"],
|
||||||
GDBOPTS="${GDBOPTS_BASE}",
|
GDBOPTS="${GDBOPTS_BASE}",
|
||||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||||
@@ -225,7 +229,6 @@ firmware_debug = distenv.PhonyTarget(
|
|||||||
source=firmware_env["FW_ELF"],
|
source=firmware_env["FW_ELF"],
|
||||||
GDBOPTS="${GDBOPTS_BASE}",
|
GDBOPTS="${GDBOPTS_BASE}",
|
||||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
|
||||||
)
|
)
|
||||||
distenv.Depends(firmware_debug, firmware_flash)
|
distenv.Depends(firmware_debug, firmware_flash)
|
||||||
|
|
||||||
@@ -235,7 +238,6 @@ distenv.PhonyTarget(
|
|||||||
source=firmware_env["FW_ELF"],
|
source=firmware_env["FW_ELF"],
|
||||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Debug alien elf
|
# Debug alien elf
|
||||||
@@ -270,29 +272,49 @@ distenv.PhonyTarget(
|
|||||||
# Just start OpenOCD
|
# Just start OpenOCD
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"openocd",
|
"openocd",
|
||||||
"${OPENOCDCOM}",
|
[["${OPENOCDCOM}", "${ARGS}"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Linter
|
# Linter
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"lint",
|
"lint",
|
||||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
[
|
||||||
|
[
|
||||||
|
"${PYTHON3}",
|
||||||
|
"${FBT_SCRIPT_DIR}/lint.py",
|
||||||
|
"check",
|
||||||
|
"${LINT_SOURCES}",
|
||||||
|
"${ARGS}",
|
||||||
|
]
|
||||||
|
],
|
||||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"format",
|
"format",
|
||||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
[
|
||||||
|
[
|
||||||
|
"${PYTHON3}",
|
||||||
|
"${FBT_SCRIPT_DIR}/lint.py",
|
||||||
|
"format",
|
||||||
|
"${LINT_SOURCES}",
|
||||||
|
"${ARGS}",
|
||||||
|
]
|
||||||
|
],
|
||||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
# PY_LINT_SOURCES contains recursively-built modules' SConscript files
|
||||||
# Here we add additional Python files residing in repo root
|
# Here we add additional Python files residing in repo root
|
||||||
firmware_env.Append(
|
firmware_env.Append(
|
||||||
PY_LINT_SOURCES=[
|
PY_LINT_SOURCES=[
|
||||||
# Py code folders
|
# Py code folders
|
||||||
"site_scons",
|
"site_scons",
|
||||||
"scripts",
|
"scripts",
|
||||||
|
"applications",
|
||||||
|
"applications_user",
|
||||||
|
"assets",
|
||||||
|
"targets",
|
||||||
# Extra files
|
# Extra files
|
||||||
"SConstruct",
|
"SConstruct",
|
||||||
"firmware.scons",
|
"firmware.scons",
|
||||||
@@ -301,8 +323,20 @@ firmware_env.Append(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}"
|
black_commandline = [
|
||||||
black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"']
|
[
|
||||||
|
"@${PYTHON3}",
|
||||||
|
"-m",
|
||||||
|
"black",
|
||||||
|
"${PY_BLACK_ARGS}",
|
||||||
|
"${PY_LINT_SOURCES}",
|
||||||
|
"${ARGS}",
|
||||||
|
]
|
||||||
|
]
|
||||||
|
black_base_args = [
|
||||||
|
"--include",
|
||||||
|
'"(\\.scons|\\.py|SConscript|SConstruct|\\.fam)$"',
|
||||||
|
]
|
||||||
|
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"lint_py",
|
"lint_py",
|
||||||
@@ -323,10 +357,30 @@ 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 -p ${FLIP_PORT}")
|
distenv.PhonyTarget(
|
||||||
|
"cli",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"${PYTHON3}",
|
||||||
|
"${FBT_SCRIPT_DIR}/serial_cli.py",
|
||||||
|
"-p",
|
||||||
|
"${FLIP_PORT}",
|
||||||
|
"${ARGS}",
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
# Update WiFi devboard firmware
|
# Update WiFi devboard firmware with release channel
|
||||||
distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py")
|
distenv.PhonyTarget(
|
||||||
|
"devboard_flash",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"${PYTHON3}",
|
||||||
|
"${FBT_SCRIPT_DIR}/wifi_board.py",
|
||||||
|
"${ARGS}",
|
||||||
|
]
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Find blackmagic probe
|
# Find blackmagic probe
|
||||||
@@ -340,7 +394,7 @@ distenv.PhonyTarget(
|
|||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"get_stlink",
|
"get_stlink",
|
||||||
distenv.Action(
|
distenv.Action(
|
||||||
lambda **kw: distenv.GetDevices(),
|
lambda **_: distenv.GetDevices(),
|
||||||
None,
|
None,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@@ -356,10 +410,10 @@ vscode_dist = distenv.Install(
|
|||||||
)
|
)
|
||||||
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, firmware_env["FW_CDB"]))
|
||||||
|
|
||||||
# Configure shell with build tools
|
# Configure shell with build tools
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget(
|
||||||
"env",
|
"env",
|
||||||
"@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)",
|
"@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ Applications for main Flipper menu.
|
|||||||
Background services providing system APIs to applications.
|
Background services providing system APIs to applications.
|
||||||
|
|
||||||
- `applications.h` - Firmware application list header
|
- `applications.h` - Firmware application list header
|
||||||
|
|
||||||
- `bt` - BLE service and application
|
- `bt` - BLE service and application
|
||||||
- `cli` - Console service and API
|
- `cli` - Console service and API
|
||||||
- `crypto` - Crypto cli tools
|
- `crypto` - Crypto cli tools
|
||||||
@@ -72,7 +71,10 @@ Small applications providing configuration for basic firmware and its services.
|
|||||||
|
|
||||||
## system
|
## system
|
||||||
|
|
||||||
Utility apps not visible in other menus.
|
Utility apps not visible in other menus, plus few external apps pre-packaged with the firmware.
|
||||||
|
|
||||||
|
- `hid_app` - BLE & USB HID remote
|
||||||
|
- `js_app` - JS engine runner
|
||||||
|
- `snake_game` - Snake game
|
||||||
- `storage_move_to_sd` - Data migration tool for internal storage
|
- `storage_move_to_sd` - Data migration tool for internal storage
|
||||||
- `updater` - Update service & application
|
- `updater` - Update service & application
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "accessor_view_manager.h"
|
#include "accessor_view_manager.h"
|
||||||
#include "accessor_event.h"
|
#include "accessor_event.h"
|
||||||
#include <callback-connector.h>
|
#include "callback_connector.h"
|
||||||
|
|
||||||
AccessorAppViewManager::AccessorAppViewManager() {
|
AccessorAppViewManager::AccessorAppViewManager() {
|
||||||
event_queue = furi_message_queue_alloc(10, sizeof(AccessorEvent));
|
event_queue = furi_message_queue_alloc(10, sizeof(AccessorEvent));
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ App(
|
|||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
targets=["f7"],
|
targets=["f7"],
|
||||||
entry_point="accessor_app",
|
entry_point="accessor_app",
|
||||||
cdefines=["APP_ACCESSOR"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=4 * 1024,
|
stack_size=4 * 1024,
|
||||||
order=40,
|
order=40,
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#ifndef CALLBACKCONNECTOR_H
|
#ifndef CALLBACKCONNECTOR_H
|
||||||
#define CALLBACKCONNECTOR_H
|
#define CALLBACKCONNECTOR_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
#include <functional>
|
#include <functional>
|
||||||
namespace cbc {
|
namespace cbc {
|
||||||
namespace Details {
|
namespace Details {
|
||||||
|
|
||||||
template <std::size_t Tag, typename T, typename Ret, typename... Args> class FuncMemberWrapper {
|
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||||
|
class FuncMemberWrapper {
|
||||||
public:
|
public:
|
||||||
FuncMemberWrapper() = delete;
|
FuncMemberWrapper() = delete;
|
||||||
using member_fun_t = Ret (T::*)(Args...);
|
using member_fun_t = Ret (T::*)(Args...);
|
||||||
@@ -43,7 +46,8 @@ template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
|||||||
typename FuncMemberWrapper<Tag, T, Ret, Args...>::const_member_fun_t
|
typename FuncMemberWrapper<Tag, T, Ret, Args...>::const_member_fun_t
|
||||||
FuncMemberWrapper<Tag, T, Ret, Args...>::const_member{};
|
FuncMemberWrapper<Tag, T, Ret, Args...>::const_member{};
|
||||||
|
|
||||||
template <typename Functor, typename Ret, typename... Args> struct FunctorWrapper {
|
template <typename Functor, typename Ret, typename... Args>
|
||||||
|
struct FunctorWrapper {
|
||||||
public:
|
public:
|
||||||
static std::function<Ret(Args...)> functor;
|
static std::function<Ret(Args...)> functor;
|
||||||
static auto instatiate(Functor fn) {
|
static auto instatiate(Functor fn) {
|
||||||
@@ -75,7 +79,8 @@ auto const_instantiate(T* t, Ret (T::*ptr)(Args...) const) {
|
|||||||
return FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
return FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <std::size_t tag, typename T, typename Func> auto const_instantiate(T* t, Func ptr) {
|
template <std::size_t tag, typename T, typename Func>
|
||||||
|
auto const_instantiate(T* t, Func ptr) {
|
||||||
return const_instantiate(t, ptr);
|
return const_instantiate(t, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,9 +96,11 @@ auto obtain_connector(T* t, Ret (T::*ptr)(Args...) const) {
|
|||||||
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Functor> auto obtain_connector(Functor functor) {
|
template <typename Functor>
|
||||||
|
auto obtain_connector(Functor functor) {
|
||||||
return Details::deducer(std::move(functor), &Functor::operator());
|
return Details::deducer(std::move(functor), &Functor::operator());
|
||||||
}
|
}
|
||||||
} //end of cbc scope
|
} //end of cbc scope
|
||||||
|
|
||||||
|
#endif // __cplusplus
|
||||||
#endif // CALLBACKCONNECTOR_H
|
#endif // CALLBACKCONNECTOR_H
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
volatile unsigned long WIEGAND::_cardTempHigh = 0;
|
unsigned long WIEGAND::_cardTempHigh = 0;
|
||||||
volatile unsigned long WIEGAND::_cardTemp = 0;
|
unsigned long WIEGAND::_cardTemp = 0;
|
||||||
volatile unsigned long WIEGAND::_lastWiegand = 0;
|
unsigned long WIEGAND::_lastWiegand = 0;
|
||||||
unsigned long WIEGAND::_code = 0;
|
unsigned long WIEGAND::_code = 0;
|
||||||
unsigned long WIEGAND::_codeHigh = 0;
|
unsigned long WIEGAND::_codeHigh = 0;
|
||||||
volatile int WIEGAND::_bitCount = 0;
|
int WIEGAND::_bitCount = 0;
|
||||||
int WIEGAND::_wiegandType = 0;
|
int WIEGAND::_wiegandType = 0;
|
||||||
|
|
||||||
constexpr uint32_t clocks_in_ms = 64 * 1000;
|
constexpr uint32_t clocks_in_ms = 64 * 1000;
|
||||||
@@ -98,10 +98,7 @@ void WIEGAND::ReadD1() {
|
|||||||
_lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
|
_lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long WIEGAND::GetCardId(
|
unsigned long WIEGAND::GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength) {
|
||||||
volatile unsigned long* codehigh,
|
|
||||||
volatile unsigned long* codelow,
|
|
||||||
char bitlength) {
|
|
||||||
if(bitlength == 26) // EM tag
|
if(bitlength == 26) // EM tag
|
||||||
return (*codelow & 0x1FFFFFE) >> 1;
|
return (*codelow & 0x1FFFFFE) >> 1;
|
||||||
|
|
||||||
|
|||||||
@@ -15,15 +15,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static bool DoWiegandConversion();
|
static bool DoWiegandConversion();
|
||||||
static unsigned long GetCardId(
|
static unsigned long
|
||||||
volatile unsigned long* codehigh,
|
GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength);
|
||||||
volatile unsigned long* codelow,
|
|
||||||
char bitlength);
|
|
||||||
|
|
||||||
static volatile unsigned long _cardTempHigh;
|
static unsigned long _cardTempHigh;
|
||||||
static volatile unsigned long _cardTemp;
|
static unsigned long _cardTemp;
|
||||||
static volatile unsigned long _lastWiegand;
|
static unsigned long _lastWiegand;
|
||||||
static volatile int _bitCount;
|
static int _bitCount;
|
||||||
static int _wiegandType;
|
static int _wiegandType;
|
||||||
static unsigned long _code;
|
static unsigned long _code;
|
||||||
static unsigned long _codeHigh;
|
static unsigned long _codeHigh;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "../accessor_app.h"
|
#include "../accessor_app.h"
|
||||||
#include "../accessor_view_manager.h"
|
#include "../accessor_view_manager.h"
|
||||||
#include "../accessor_event.h"
|
#include "../accessor_event.h"
|
||||||
#include <callback-connector.h>
|
#include "callback_connector.h"
|
||||||
#include "accessor_scene_start.h"
|
#include "accessor_scene_start.h"
|
||||||
|
|
||||||
void AccessorSceneStart::on_enter(AccessorApp* app) {
|
void AccessorSceneStart::on_enter(AccessorApp* app) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Battery Test",
|
name="Battery Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="battery_test_app",
|
entry_point="battery_test_app",
|
||||||
cdefines=["APP_BATTERY_TEST"],
|
|
||||||
requires=[
|
requires=[
|
||||||
"gui",
|
"gui",
|
||||||
"power",
|
"power",
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ void battery_test_dialog_callback(DialogExResult result, void* context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t battery_test_exit_confirm_view() {
|
uint32_t battery_test_exit_confirm_view(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
return BatteryTestAppViewExitDialog;
|
return BatteryTestAppViewExitDialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Blink Test",
|
name="Blink Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="blink_test_app",
|
entry_point="blink_test_app",
|
||||||
cdefines=["APP_BLINK"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=10,
|
order=10,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="CCID Debug",
|
name="CCID Debug",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="ccid_test_app",
|
entry_point="ccid_test_app",
|
||||||
cdefines=["CCID_TEST"],
|
|
||||||
requires=[
|
requires=[
|
||||||
"gui",
|
"gui",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ struct ISO7816_Command_APDU {
|
|||||||
//body
|
//body
|
||||||
uint8_t Lc;
|
uint8_t Lc;
|
||||||
uint8_t Le;
|
uint8_t Le;
|
||||||
} __attribute__((packed));
|
} FURI_PACKED;
|
||||||
|
|
||||||
struct ISO7816_Response_APDU {
|
struct ISO7816_Response_APDU {
|
||||||
uint8_t SW1;
|
uint8_t SW1;
|
||||||
uint8_t SW2;
|
uint8_t SW2;
|
||||||
} __attribute__((packed));
|
} FURI_PACKED;
|
||||||
|
|
||||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||||
void iso7816_read_command_apdu(
|
void iso7816_read_command_apdu(
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Crash Test",
|
name="Crash Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="crash_test_app",
|
entry_point="crash_test_app",
|
||||||
cdefines=["APP_CRASH_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
fap_category="Debug",
|
fap_category="Debug",
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ App(
|
|||||||
name="Display Test",
|
name="Display Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="display_test_app",
|
entry_point="display_test_app",
|
||||||
cdefines=["APP_DISPLAY_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
fap_libs=["misc"],
|
fap_libs=["u8g2"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=120,
|
order=120,
|
||||||
fap_category="Debug",
|
fap_category="Debug",
|
||||||
|
|||||||
12
applications/debug/expansion_test/application.fam
Normal file
12
applications/debug/expansion_test/application.fam
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
App(
|
||||||
|
appid="expansion_test",
|
||||||
|
name="Expansion Module Test",
|
||||||
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
entry_point="expansion_test_app",
|
||||||
|
requires=["expansion_start"],
|
||||||
|
fap_libs=["assets"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
order=20,
|
||||||
|
fap_category="Debug",
|
||||||
|
fap_file_assets="assets",
|
||||||
|
)
|
||||||
9
applications/debug/expansion_test/assets/test.txt
Normal file
9
applications/debug/expansion_test/assets/test.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
"Did you ever hear the tragedy of Darth Plagueis the Wise?"
|
||||||
|
"No."
|
||||||
|
"I thought not. It's not a story the Jedi would tell you. It's a Sith legend. Darth Plagueis... was a Dark Lord of the Sith so powerful and so wise, he could use the Force to influence the midi-chlorians... to create... life. He had such a knowledge of the dark side, he could even keep the ones he cared about... from dying."
|
||||||
|
"He could actually... save people from death?"
|
||||||
|
"The dark side of the Force is a pathway to many abilities... some consider to be unnatural."
|
||||||
|
"Wh– What happened to him?"
|
||||||
|
"He became so powerful, the only thing he was afraid of was... losing his power. Which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew. Then his apprentice killed him in his sleep. It's ironic. He could save others from death, but not himself."
|
||||||
|
"Is it possible to learn this power?"
|
||||||
|
"Not from a Jedi."
|
||||||
457
applications/debug/expansion_test/expansion_test.c
Normal file
457
applications/debug/expansion_test/expansion_test.c
Normal file
@@ -0,0 +1,457 @@
|
|||||||
|
/**
|
||||||
|
* @file expansion_test.c
|
||||||
|
* @brief Expansion module support testing application.
|
||||||
|
*
|
||||||
|
* Before running, connect pins using the following scheme:
|
||||||
|
* 13 -> 16 (USART TX to LPUART RX)
|
||||||
|
* 14 -> 15 (USART RX to LPUART TX)
|
||||||
|
*
|
||||||
|
* What this application does:
|
||||||
|
*
|
||||||
|
* - Enables module support and emulates the module on a single device
|
||||||
|
* (hence the above connection),
|
||||||
|
* - Connects to the expansion module service, sets baud rate,
|
||||||
|
* - Starts the RPC session,
|
||||||
|
* - Creates a directory at `/ext/ExpansionTest` and writes a file
|
||||||
|
* named `test.txt` under it,
|
||||||
|
* - Plays an audiovisual alert (sound and blinking display),
|
||||||
|
* - Waits 10 cycles of idle loop,
|
||||||
|
* - Stops the RPC session,
|
||||||
|
* - Waits another 10 cycles of idle loop,
|
||||||
|
* - Exits (plays a sound if any of the above steps failed).
|
||||||
|
*/
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#include <furi_hal_resources.h>
|
||||||
|
|
||||||
|
#include <furi_hal_serial.h>
|
||||||
|
#include <furi_hal_serial_control.h>
|
||||||
|
|
||||||
|
#include <pb.h>
|
||||||
|
#include <pb_decode.h>
|
||||||
|
#include <pb_encode.h>
|
||||||
|
|
||||||
|
#include <flipper.pb.h>
|
||||||
|
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <expansion/expansion.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
#include <expansion/expansion_protocol.h>
|
||||||
|
|
||||||
|
#define TAG "ExpansionTest"
|
||||||
|
|
||||||
|
#define TEST_DIR_PATH EXT_PATH(TAG)
|
||||||
|
#define TEST_FILE_NAME "test.txt"
|
||||||
|
#define TEST_FILE_PATH EXT_PATH(TAG "/" TEST_FILE_NAME)
|
||||||
|
|
||||||
|
#define HOST_SERIAL_ID (FuriHalSerialIdLpuart)
|
||||||
|
#define MODULE_SERIAL_ID (FuriHalSerialIdUsart)
|
||||||
|
|
||||||
|
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ExpansionTestAppFlagData = 1U << 0,
|
||||||
|
ExpansionTestAppFlagExit = 1U << 1,
|
||||||
|
} ExpansionTestAppFlag;
|
||||||
|
|
||||||
|
#define EXPANSION_TEST_APP_ALL_FLAGS (ExpansionTestAppFlagData | ExpansionTestAppFlagExit)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FuriThreadId thread_id;
|
||||||
|
Expansion* expansion;
|
||||||
|
FuriHalSerialHandle* handle;
|
||||||
|
FuriStreamBuffer* buf;
|
||||||
|
ExpansionFrame frame;
|
||||||
|
PB_Main msg;
|
||||||
|
Storage* storage;
|
||||||
|
} ExpansionTestApp;
|
||||||
|
|
||||||
|
static void expansion_test_app_serial_rx_callback(
|
||||||
|
FuriHalSerialHandle* handle,
|
||||||
|
FuriHalSerialRxEvent event,
|
||||||
|
void* context) {
|
||||||
|
furi_assert(handle);
|
||||||
|
furi_assert(context);
|
||||||
|
ExpansionTestApp* app = context;
|
||||||
|
|
||||||
|
if(event == FuriHalSerialRxEventData) {
|
||||||
|
const uint8_t data = furi_hal_serial_async_rx(handle);
|
||||||
|
furi_stream_buffer_send(app->buf, &data, sizeof(data), 0);
|
||||||
|
furi_thread_flags_set(app->thread_id, ExpansionTestAppFlagData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ExpansionTestApp* expansion_test_app_alloc() {
|
||||||
|
ExpansionTestApp* instance = malloc(sizeof(ExpansionTestApp));
|
||||||
|
instance->buf = furi_stream_buffer_alloc(RECEIVE_BUFFER_SIZE, 1);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expansion_test_app_free(ExpansionTestApp* instance) {
|
||||||
|
furi_stream_buffer_free(instance->buf);
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expansion_test_app_start(ExpansionTestApp* instance) {
|
||||||
|
instance->thread_id = furi_thread_get_current_id();
|
||||||
|
instance->expansion = furi_record_open(RECORD_EXPANSION);
|
||||||
|
instance->handle = furi_hal_serial_control_acquire(MODULE_SERIAL_ID);
|
||||||
|
furi_check(instance->handle);
|
||||||
|
// Configure the serial port
|
||||||
|
furi_hal_serial_init(instance->handle, EXPANSION_PROTOCOL_DEFAULT_BAUD_RATE);
|
||||||
|
// Start waiting for the initial pulse
|
||||||
|
expansion_set_listen_serial(instance->expansion, HOST_SERIAL_ID);
|
||||||
|
|
||||||
|
furi_hal_serial_async_rx_start(
|
||||||
|
instance->handle, expansion_test_app_serial_rx_callback, instance, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void expansion_test_app_stop(ExpansionTestApp* instance) {
|
||||||
|
// Disable expansion module support
|
||||||
|
expansion_disable(instance->expansion);
|
||||||
|
// Give back the module handle
|
||||||
|
furi_hal_serial_control_release(instance->handle);
|
||||||
|
// Restore expansion user settings
|
||||||
|
expansion_enable(instance->expansion);
|
||||||
|
furi_record_close(RECORD_EXPANSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool expansion_test_app_is_success_response(const ExpansionFrame* response) {
|
||||||
|
return response->header.type == ExpansionFrameTypeStatus &&
|
||||||
|
response->content.status.error == ExpansionFrameErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool expansion_test_app_is_success_rpc_message(const PB_Main* message) {
|
||||||
|
return (message->command_status == PB_CommandStatus_OK ||
|
||||||
|
message->command_status == PB_CommandStatus_ERROR_STORAGE_EXIST) &&
|
||||||
|
(message->which_content == PB_Main_empty_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t expansion_test_app_receive_callback(uint8_t* data, size_t data_size, void* context) {
|
||||||
|
ExpansionTestApp* instance = context;
|
||||||
|
|
||||||
|
size_t received_size = 0;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
received_size += furi_stream_buffer_receive(
|
||||||
|
instance->buf, data + received_size, data_size - received_size, 0);
|
||||||
|
if(received_size == data_size) break;
|
||||||
|
|
||||||
|
const uint32_t flags = furi_thread_flags_wait(
|
||||||
|
EXPANSION_TEST_APP_ALL_FLAGS, FuriFlagWaitAny, EXPANSION_PROTOCOL_TIMEOUT_MS);
|
||||||
|
|
||||||
|
// Exit on any error
|
||||||
|
if(flags & FuriFlagError) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return received_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
expansion_test_app_send_callback(const uint8_t* data, size_t data_size, void* context) {
|
||||||
|
ExpansionTestApp* instance = context;
|
||||||
|
|
||||||
|
furi_hal_serial_tx(instance->handle, data, data_size);
|
||||||
|
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||||
|
|
||||||
|
return data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_receive_frame(ExpansionTestApp* instance, ExpansionFrame* frame) {
|
||||||
|
return expansion_protocol_decode(frame, expansion_test_app_receive_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
expansion_test_app_send_status_response(ExpansionTestApp* instance, ExpansionFrameError error) {
|
||||||
|
ExpansionFrame frame = {
|
||||||
|
.header.type = ExpansionFrameTypeStatus,
|
||||||
|
.content.status.error = error,
|
||||||
|
};
|
||||||
|
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_send_heartbeat(ExpansionTestApp* instance) {
|
||||||
|
ExpansionFrame frame = {
|
||||||
|
.header.type = ExpansionFrameTypeHeartbeat,
|
||||||
|
.content.heartbeat = {},
|
||||||
|
};
|
||||||
|
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
expansion_test_app_send_baud_rate_request(ExpansionTestApp* instance, uint32_t baud_rate) {
|
||||||
|
ExpansionFrame frame = {
|
||||||
|
.header.type = ExpansionFrameTypeBaudRate,
|
||||||
|
.content.baud_rate.baud = baud_rate,
|
||||||
|
};
|
||||||
|
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_send_control_request(
|
||||||
|
ExpansionTestApp* instance,
|
||||||
|
ExpansionFrameControlCommand command) {
|
||||||
|
ExpansionFrame frame = {
|
||||||
|
.header.type = ExpansionFrameTypeControl,
|
||||||
|
.content.control.command = command,
|
||||||
|
};
|
||||||
|
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_send_data_request(
|
||||||
|
ExpansionTestApp* instance,
|
||||||
|
const uint8_t* data,
|
||||||
|
size_t data_size) {
|
||||||
|
furi_assert(data_size <= EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||||
|
|
||||||
|
ExpansionFrame frame = {
|
||||||
|
.header.type = ExpansionFrameTypeData,
|
||||||
|
.content.data.size = data_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
memcpy(frame.content.data.bytes, data, data_size);
|
||||||
|
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||||
|
ExpansionProtocolStatusOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_rpc_encode_callback(
|
||||||
|
pb_ostream_t* stream,
|
||||||
|
const pb_byte_t* data,
|
||||||
|
size_t data_size) {
|
||||||
|
ExpansionTestApp* instance = stream->state;
|
||||||
|
|
||||||
|
size_t size_sent = 0;
|
||||||
|
|
||||||
|
while(size_sent < data_size) {
|
||||||
|
const size_t current_size = MIN(data_size - size_sent, EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||||
|
if(!expansion_test_app_send_data_request(instance, data + size_sent, current_size)) break;
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||||
|
size_sent += current_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return size_sent == data_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_send_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||||
|
pb_ostream_t stream = {
|
||||||
|
.callback = expansion_test_app_rpc_encode_callback,
|
||||||
|
.state = instance,
|
||||||
|
.max_size = SIZE_MAX,
|
||||||
|
.bytes_written = 0,
|
||||||
|
.errmsg = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
const bool success = pb_encode_ex(&stream, &PB_Main_msg, message, PB_ENCODE_DELIMITED);
|
||||||
|
pb_release(&PB_Main_msg, message);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_receive_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(!expansion_test_app_send_status_response(instance, ExpansionFrameErrorNone)) break;
|
||||||
|
if(instance->frame.header.type != ExpansionFrameTypeData) break;
|
||||||
|
pb_istream_t stream = pb_istream_from_buffer(
|
||||||
|
instance->frame.content.data.bytes, instance->frame.content.data.size);
|
||||||
|
if(!pb_decode_ex(&stream, &PB_Main_msg, message, PB_DECODE_DELIMITED)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_send_presence(ExpansionTestApp* instance) {
|
||||||
|
// Send pulses to emulate module insertion
|
||||||
|
const uint8_t init = 0xAA;
|
||||||
|
furi_hal_serial_tx(instance->handle, &init, sizeof(init));
|
||||||
|
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_wait_ready(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_handshake(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_baud_rate_request(instance, 230400)) break;
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||||
|
furi_hal_serial_set_br(instance->handle, 230400);
|
||||||
|
furi_delay_ms(EXPANSION_PROTOCOL_BAUD_CHANGE_DT_MS);
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_start_rpc(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStartRpc))
|
||||||
|
break;
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_rpc_mkdir(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
instance->msg.command_id++;
|
||||||
|
instance->msg.command_status = PB_CommandStatus_OK;
|
||||||
|
instance->msg.which_content = PB_Main_storage_mkdir_request_tag;
|
||||||
|
instance->msg.has_next = false;
|
||||||
|
instance->msg.content.storage_mkdir_request.path = TEST_DIR_PATH;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_rpc_write(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!storage_file_open(file, APP_ASSETS_PATH(TEST_FILE_NAME), FSAM_READ, FSOM_OPEN_EXISTING))
|
||||||
|
break;
|
||||||
|
|
||||||
|
const uint64_t file_size = storage_file_size(file);
|
||||||
|
|
||||||
|
instance->msg.command_id++;
|
||||||
|
instance->msg.command_status = PB_CommandStatus_OK;
|
||||||
|
instance->msg.which_content = PB_Main_storage_write_request_tag;
|
||||||
|
instance->msg.has_next = false;
|
||||||
|
instance->msg.content.storage_write_request.path = TEST_FILE_PATH;
|
||||||
|
instance->msg.content.storage_write_request.has_file = true;
|
||||||
|
instance->msg.content.storage_write_request.file.data =
|
||||||
|
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(file_size));
|
||||||
|
instance->msg.content.storage_write_request.file.data->size = file_size;
|
||||||
|
|
||||||
|
const size_t bytes_read = storage_file_read(
|
||||||
|
file, instance->msg.content.storage_write_request.file.data->bytes, file_size);
|
||||||
|
|
||||||
|
if(bytes_read != file_size) {
|
||||||
|
pb_release(&PB_Main_msg, &instance->msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
storage_file_free(file);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_rpc_alert(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
instance->msg.command_id++;
|
||||||
|
instance->msg.command_status = PB_CommandStatus_OK;
|
||||||
|
instance->msg.which_content = PB_Main_system_play_audiovisual_alert_request_tag;
|
||||||
|
instance->msg.has_next = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||||
|
if(instance->msg.which_content != PB_Main_empty_tag) break;
|
||||||
|
if(instance->msg.command_status != PB_CommandStatus_OK) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_idle(ExpansionTestApp* instance, uint32_t num_cycles) {
|
||||||
|
uint32_t num_cycles_done;
|
||||||
|
for(num_cycles_done = 0; num_cycles_done < num_cycles; ++num_cycles_done) {
|
||||||
|
if(!expansion_test_app_send_heartbeat(instance)) break;
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||||
|
furi_delay_ms(EXPANSION_PROTOCOL_TIMEOUT_MS - 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_cycles_done == num_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool expansion_test_app_stop_rpc(ExpansionTestApp* instance) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStopRpc))
|
||||||
|
break;
|
||||||
|
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||||
|
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t expansion_test_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
ExpansionTestApp* instance = expansion_test_app_alloc();
|
||||||
|
expansion_test_app_start(instance);
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!expansion_test_app_send_presence(instance)) break;
|
||||||
|
if(!expansion_test_app_wait_ready(instance)) break;
|
||||||
|
if(!expansion_test_app_handshake(instance)) break;
|
||||||
|
if(!expansion_test_app_start_rpc(instance)) break;
|
||||||
|
if(!expansion_test_app_rpc_mkdir(instance)) break;
|
||||||
|
if(!expansion_test_app_rpc_write(instance)) break;
|
||||||
|
if(!expansion_test_app_rpc_alert(instance)) break;
|
||||||
|
if(!expansion_test_app_idle(instance, 10)) break;
|
||||||
|
if(!expansion_test_app_stop_rpc(instance)) break;
|
||||||
|
if(!expansion_test_app_idle(instance, 10)) break;
|
||||||
|
success = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
expansion_test_app_stop(instance);
|
||||||
|
expansion_test_app_free(instance);
|
||||||
|
|
||||||
|
if(!success) {
|
||||||
|
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
notification_message(notification, &sequence_error);
|
||||||
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="File Browser Test",
|
name="File Browser Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="file_browser_app",
|
entry_point="file_browser_app",
|
||||||
cdefines=["APP_FILE_BROWSER_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
order=150,
|
order=150,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Keypad Test",
|
name="Keypad Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="keypad_test_app",
|
entry_point="keypad_test_app",
|
||||||
cdefines=["APP_KEYPAD_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=30,
|
order=30,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Locale Test",
|
name="Locale Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="locale_test_app",
|
entry_point="locale_test_app",
|
||||||
cdefines=["APP_LOCALE"],
|
|
||||||
requires=["gui", "locale"],
|
requires=["gui", "locale"],
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
order=70,
|
order=70,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ static void locale_test_view_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
}
|
}
|
||||||
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
|
canvas_draw_str(canvas, 0, 10, furi_string_get_cstr(tmp_string));
|
||||||
|
|
||||||
FuriHalRtcDateTime datetime;
|
DateTime datetime;
|
||||||
furi_hal_rtc_get_datetime(&datetime);
|
furi_hal_rtc_get_datetime(&datetime);
|
||||||
|
|
||||||
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
|
locale_format_time(tmp_string, &datetime, locale_get_time_format(), false);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Text Box Test",
|
name="Text Box Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="text_box_test_app",
|
entry_point="text_box_test_app",
|
||||||
cdefines=["APP_TEXT_BOX_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=140,
|
order=140,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="UART Echo",
|
name="UART Echo",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="uart_echo_app",
|
entry_point="uart_echo_app",
|
||||||
cdefines=["APP_UART_ECHO"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=2 * 1024,
|
stack_size=2 * 1024,
|
||||||
order=70,
|
order=70,
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <notification/notification.h>
|
|
||||||
#include <notification/notification_messages.h>
|
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <furi_hal_uart.h>
|
|
||||||
#include <furi_hal_console.h>
|
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
#include <gui/modules/dialog_ex.h>
|
#include <gui/modules/dialog_ex.h>
|
||||||
|
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
#define LINES_ON_SCREEN 6
|
#define LINES_ON_SCREEN 6
|
||||||
#define COLUMNS_ON_SCREEN 21
|
#define COLUMNS_ON_SCREEN 21
|
||||||
#define TAG "UartEcho"
|
#define TAG "UartEcho"
|
||||||
@@ -22,6 +23,7 @@ typedef struct {
|
|||||||
View* view;
|
View* view;
|
||||||
FuriThread* worker_thread;
|
FuriThread* worker_thread;
|
||||||
FuriStreamBuffer* rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
|
FuriHalSerialHandle* serial_handle;
|
||||||
} UartEchoApp;
|
} UartEchoApp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -39,10 +41,16 @@ struct UartDumpModel {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
||||||
WorkerEventStop = (1 << 1),
|
WorkerEventStop = (1 << 1),
|
||||||
WorkerEventRx = (1 << 2),
|
WorkerEventRxData = (1 << 2),
|
||||||
|
WorkerEventRxIdle = (1 << 3),
|
||||||
|
WorkerEventRxOverrunError = (1 << 4),
|
||||||
|
WorkerEventRxFramingError = (1 << 5),
|
||||||
|
WorkerEventRxNoiseError = (1 << 6),
|
||||||
} WorkerEventFlags;
|
} WorkerEventFlags;
|
||||||
|
|
||||||
#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
|
#define WORKER_EVENTS_MASK \
|
||||||
|
(WorkerEventStop | WorkerEventRxData | WorkerEventRxIdle | WorkerEventRxOverrunError | \
|
||||||
|
WorkerEventRxFramingError | WorkerEventRxNoiseError)
|
||||||
|
|
||||||
const NotificationSequence sequence_notification = {
|
const NotificationSequence sequence_notification = {
|
||||||
&message_display_backlight_on,
|
&message_display_backlight_on,
|
||||||
@@ -91,14 +99,39 @@ static uint32_t uart_echo_exit(void* context) {
|
|||||||
return VIEW_NONE;
|
return VIEW_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
static void
|
||||||
|
uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
UNUSED(handle);
|
||||||
UartEchoApp* app = context;
|
UartEchoApp* app = context;
|
||||||
|
volatile FuriHalSerialRxEvent event_copy = event;
|
||||||
|
UNUSED(event_copy);
|
||||||
|
|
||||||
if(ev == UartIrqEventRXNE) {
|
WorkerEventFlags flag = 0;
|
||||||
|
|
||||||
|
if(event & FuriHalSerialRxEventData) {
|
||||||
|
uint8_t data = furi_hal_serial_async_rx(handle);
|
||||||
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
flag |= WorkerEventRxData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(event & FuriHalSerialRxEventIdle) {
|
||||||
|
//idle line detected, packet transmission may have ended
|
||||||
|
flag |= WorkerEventRxIdle;
|
||||||
|
}
|
||||||
|
|
||||||
|
//error detected
|
||||||
|
if(event & FuriHalSerialRxEventFrameError) {
|
||||||
|
flag |= WorkerEventRxFramingError;
|
||||||
|
}
|
||||||
|
if(event & FuriHalSerialRxEventNoiseError) {
|
||||||
|
flag |= WorkerEventRxNoiseError;
|
||||||
|
}
|
||||||
|
if(event & FuriHalSerialRxEventOverrunError) {
|
||||||
|
flag |= WorkerEventRxOverrunError;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
|
static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
|
||||||
@@ -153,13 +186,13 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
furi_check((events & FuriFlagError) == 0);
|
furi_check((events & FuriFlagError) == 0);
|
||||||
|
|
||||||
if(events & WorkerEventStop) break;
|
if(events & WorkerEventStop) break;
|
||||||
if(events & WorkerEventRx) {
|
if(events & WorkerEventRxData) {
|
||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
do {
|
do {
|
||||||
uint8_t data[64];
|
uint8_t data[64];
|
||||||
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
||||||
if(length > 0) {
|
if(length > 0) {
|
||||||
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
furi_hal_serial_tx(app->serial_handle, data, length);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
app->view,
|
app->view,
|
||||||
UartDumpModel * model,
|
UartDumpModel * model,
|
||||||
@@ -176,6 +209,23 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
with_view_model(
|
with_view_model(
|
||||||
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(events & WorkerEventRxIdle) {
|
||||||
|
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect IDLE\r\n", 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(events &
|
||||||
|
(WorkerEventRxOverrunError | WorkerEventRxFramingError | WorkerEventRxNoiseError)) {
|
||||||
|
if(events & WorkerEventRxOverrunError) {
|
||||||
|
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect ORE\r\n", 14);
|
||||||
|
}
|
||||||
|
if(events & WorkerEventRxFramingError) {
|
||||||
|
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect FE\r\n", 13);
|
||||||
|
}
|
||||||
|
if(events & WorkerEventRxNoiseError) {
|
||||||
|
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect NE\r\n", 13);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -221,9 +271,11 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
|||||||
furi_thread_start(app->worker_thread);
|
furi_thread_start(app->worker_thread);
|
||||||
|
|
||||||
// Enable uart listener
|
// Enable uart listener
|
||||||
furi_hal_console_disable();
|
app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
|
||||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
|
furi_check(app->serial_handle);
|
||||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
furi_hal_serial_init(app->serial_handle, baudrate);
|
||||||
|
|
||||||
|
furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, true);
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
@@ -231,7 +283,9 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
|||||||
static void uart_echo_app_free(UartEchoApp* app) {
|
static void uart_echo_app_free(UartEchoApp* app) {
|
||||||
furi_assert(app);
|
furi_assert(app);
|
||||||
|
|
||||||
furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
|
furi_hal_serial_async_rx_stop(app->serial_handle);
|
||||||
|
furi_hal_serial_deinit(app->serial_handle);
|
||||||
|
furi_hal_serial_control_release(app->serial_handle);
|
||||||
|
|
||||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
|
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
|
||||||
furi_thread_join(app->worker_thread);
|
furi_thread_join(app->worker_thread);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
#include <lfrfid/tools/bit_lib.h>
|
#include <bit_lib/bit_lib.h>
|
||||||
|
|
||||||
MU_TEST(test_bit_lib_increment_index) {
|
MU_TEST(test_bit_lib_increment_index) {
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
@@ -218,6 +218,178 @@ MU_TEST(test_bit_lib_get_bits_32) {
|
|||||||
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_32(value, 0, 32));
|
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_32(value, 0, 32));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_get_bits_64) {
|
||||||
|
uint8_t value[8] = {
|
||||||
|
0b00001001,
|
||||||
|
0b10110001,
|
||||||
|
0b10001100,
|
||||||
|
0b01100010,
|
||||||
|
0b00001001,
|
||||||
|
0b10110001,
|
||||||
|
0b10001100,
|
||||||
|
0b01100010};
|
||||||
|
mu_assert_int_eq(0b0, bit_lib_get_bits_64(value, 0, 1));
|
||||||
|
mu_assert_int_eq(0b00, bit_lib_get_bits_64(value, 0, 2));
|
||||||
|
mu_assert_int_eq(0b000, bit_lib_get_bits_64(value, 0, 3));
|
||||||
|
mu_assert_int_eq(0b0000, bit_lib_get_bits_64(value, 0, 4));
|
||||||
|
mu_assert_int_eq(0b00001, bit_lib_get_bits_64(value, 0, 5));
|
||||||
|
mu_assert_int_eq(0b000010, bit_lib_get_bits_64(value, 0, 6));
|
||||||
|
mu_assert_int_eq(0b0000100, bit_lib_get_bits_64(value, 0, 7));
|
||||||
|
mu_assert_int_eq(0b00001001, bit_lib_get_bits_64(value, 0, 8));
|
||||||
|
mu_assert_int_eq(0b000010011, bit_lib_get_bits_64(value, 0, 9));
|
||||||
|
mu_assert_int_eq(0b0000100110, bit_lib_get_bits_64(value, 0, 10));
|
||||||
|
mu_assert_int_eq(0b00001001101, bit_lib_get_bits_64(value, 0, 11));
|
||||||
|
mu_assert_int_eq(0b000010011011, bit_lib_get_bits_64(value, 0, 12));
|
||||||
|
mu_assert_int_eq(0b0000100110110, bit_lib_get_bits_64(value, 0, 13));
|
||||||
|
mu_assert_int_eq(0b00001001101100, bit_lib_get_bits_64(value, 0, 14));
|
||||||
|
mu_assert_int_eq(0b000010011011000, bit_lib_get_bits_64(value, 0, 15));
|
||||||
|
mu_assert_int_eq(0b0000100110110001, bit_lib_get_bits_64(value, 0, 16));
|
||||||
|
mu_assert_int_eq(0b00001001101100011, bit_lib_get_bits_64(value, 0, 17));
|
||||||
|
mu_assert_int_eq(0b000010011011000110, bit_lib_get_bits_64(value, 0, 18));
|
||||||
|
mu_assert_int_eq(0b0000100110110001100, bit_lib_get_bits_64(value, 0, 19));
|
||||||
|
mu_assert_int_eq(0b00001001101100011000, bit_lib_get_bits_64(value, 0, 20));
|
||||||
|
mu_assert_int_eq(0b000010011011000110001, bit_lib_get_bits_64(value, 0, 21));
|
||||||
|
mu_assert_int_eq(0b0000100110110001100011, bit_lib_get_bits_64(value, 0, 22));
|
||||||
|
mu_assert_int_eq(0b00001001101100011000110, bit_lib_get_bits_64(value, 0, 23));
|
||||||
|
mu_assert_int_eq(0b000010011011000110001100, bit_lib_get_bits_64(value, 0, 24));
|
||||||
|
mu_assert_int_eq(0b0000100110110001100011000, bit_lib_get_bits_64(value, 0, 25));
|
||||||
|
mu_assert_int_eq(0b00001001101100011000110001, bit_lib_get_bits_64(value, 0, 26));
|
||||||
|
mu_assert_int_eq(0b000010011011000110001100011, bit_lib_get_bits_64(value, 0, 27));
|
||||||
|
mu_assert_int_eq(0b0000100110110001100011000110, bit_lib_get_bits_64(value, 0, 28));
|
||||||
|
mu_assert_int_eq(0b00001001101100011000110001100, bit_lib_get_bits_64(value, 0, 29));
|
||||||
|
mu_assert_int_eq(0b000010011011000110001100011000, bit_lib_get_bits_64(value, 0, 30));
|
||||||
|
mu_assert_int_eq(0b0000100110110001100011000110001, bit_lib_get_bits_64(value, 0, 31));
|
||||||
|
mu_assert_int_eq(0b00001001101100011000110001100010, bit_lib_get_bits_64(value, 0, 32));
|
||||||
|
|
||||||
|
uint64_t res = bit_lib_get_bits_64(value, 0, 33);
|
||||||
|
uint64_t expected = 0b000010011011000110001100011000100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 34);
|
||||||
|
expected = 0b0000100110110001100011000110001000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 35);
|
||||||
|
expected = 0b00001001101100011000110001100010000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 36);
|
||||||
|
expected = 0b000010011011000110001100011000100000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 37);
|
||||||
|
expected = 0b0000100110110001100011000110001000001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 38);
|
||||||
|
expected = 0b00001001101100011000110001100010000010;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 39);
|
||||||
|
expected = 0b000010011011000110001100011000100000100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 40);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 41);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 42);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 43);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 44);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 45);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 46);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 47);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 48);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 49);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 50);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000110;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 51);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 52);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 53);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000110001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 54);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001100011;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 55);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011000110;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 56);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000110001100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 57);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001100011000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 58);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011000110001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 59);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000110001100011;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 60);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001100011000110;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 61);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011000110001100;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 62);
|
||||||
|
expected = 0b00001001101100011000110001100010000010011011000110001100011000;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 63);
|
||||||
|
expected = 0b000010011011000110001100011000100000100110110001100011000110001;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
|
||||||
|
res = bit_lib_get_bits_64(value, 0, 64);
|
||||||
|
expected = 0b0000100110110001100011000110001000001001101100011000110001100010;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(test_bit_lib_test_parity_u32) {
|
MU_TEST(test_bit_lib_test_parity_u32) {
|
||||||
// test even parity
|
// test even parity
|
||||||
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityEven), 0);
|
mu_assert_int_eq(bit_lib_test_parity_32(0b00000000, BitLibParityEven), 0);
|
||||||
@@ -447,6 +619,95 @@ MU_TEST(test_bit_lib_crc16) {
|
|||||||
mu_assert_int_eq(0x31C3, bit_lib_crc16(data, data_size, 0x1021, 0x0000, false, false, 0x0000));
|
mu_assert_int_eq(0x31C3, bit_lib_crc16(data, data_size, 0x1021, 0x0000, false, false, 0x0000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_num_to_bytes_be) {
|
||||||
|
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||||
|
uint8_t dest[8];
|
||||||
|
|
||||||
|
bit_lib_num_to_bytes_be(0x01, 1, dest);
|
||||||
|
mu_assert_mem_eq(src, dest, sizeof(src[0]));
|
||||||
|
|
||||||
|
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 4, dest);
|
||||||
|
mu_assert_mem_eq(src + 4, dest, 4 * sizeof(src[0]));
|
||||||
|
|
||||||
|
bit_lib_num_to_bytes_be(0x0123456789ABCDEF, 8, dest);
|
||||||
|
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
|
||||||
|
|
||||||
|
bit_lib_num_to_bytes_be(bit_lib_bytes_to_num_be(src, 8), 8, dest);
|
||||||
|
mu_assert_mem_eq(src, dest, 8 * sizeof(src[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_num_to_bytes_le) {
|
||||||
|
uint8_t dest[8];
|
||||||
|
|
||||||
|
uint8_t n2b_le_expected_1[] = {0x01};
|
||||||
|
bit_lib_num_to_bytes_le(0x01, 1, dest);
|
||||||
|
mu_assert_mem_eq(n2b_le_expected_1, dest, sizeof(n2b_le_expected_1[0]));
|
||||||
|
|
||||||
|
uint8_t n2b_le_expected_2[] = {0xEF, 0xCD, 0xAB, 0x89};
|
||||||
|
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 4, dest);
|
||||||
|
mu_assert_mem_eq(n2b_le_expected_2, dest, 4 * sizeof(n2b_le_expected_2[0]));
|
||||||
|
|
||||||
|
uint8_t n2b_le_expected_3[] = {0xEF, 0xCD, 0xAB, 0x89, 0x67, 0x45, 0x23, 0x01};
|
||||||
|
bit_lib_num_to_bytes_le(0x0123456789ABCDEF, 8, dest);
|
||||||
|
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
|
||||||
|
|
||||||
|
bit_lib_num_to_bytes_le(bit_lib_bytes_to_num_le(n2b_le_expected_3, 8), 8, dest);
|
||||||
|
mu_assert_mem_eq(n2b_le_expected_3, dest, 8 * sizeof(n2b_le_expected_3[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_bytes_to_num_be) {
|
||||||
|
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||||
|
uint64_t res;
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_be(src, 1);
|
||||||
|
mu_assert_int_eq(0x01, res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_be(src, 4);
|
||||||
|
mu_assert_int_eq(0x01234567, res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_be(src, 8);
|
||||||
|
uint64_t expected = 0x0123456789ABCDEF;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_bytes_to_num_le) {
|
||||||
|
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||||
|
uint64_t res;
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_le(src, 1);
|
||||||
|
mu_assert_int_eq(0x01, res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_le(src, 4);
|
||||||
|
mu_assert_int_eq(0x67452301, res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_le(src, 8);
|
||||||
|
uint64_t expected = 0xEFCDAB8967452301;
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_bit_lib_bytes_to_num_bcd) {
|
||||||
|
uint8_t src[8] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
|
||||||
|
uint64_t res;
|
||||||
|
bool is_bcd_res;
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_bcd(src, 1, &is_bcd_res);
|
||||||
|
mu_assert_int_eq(01, res);
|
||||||
|
mu_assert_int_eq(true, is_bcd_res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_bcd(src, 4, &is_bcd_res);
|
||||||
|
mu_assert_int_eq(1234567, res);
|
||||||
|
mu_assert_int_eq(true, is_bcd_res);
|
||||||
|
|
||||||
|
uint8_t digits[5] = {0x98, 0x76, 0x54, 0x32, 0x10};
|
||||||
|
uint64_t expected = 9876543210;
|
||||||
|
res = bit_lib_bytes_to_num_bcd(digits, 5, &is_bcd_res);
|
||||||
|
mu_assert_mem_eq(&expected, &res, sizeof(expected));
|
||||||
|
mu_assert_int_eq(true, is_bcd_res);
|
||||||
|
|
||||||
|
res = bit_lib_bytes_to_num_bcd(src, 8, &is_bcd_res);
|
||||||
|
mu_assert_int_eq(false, is_bcd_res);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(test_bit_lib) {
|
MU_TEST_SUITE(test_bit_lib) {
|
||||||
MU_RUN_TEST(test_bit_lib_increment_index);
|
MU_RUN_TEST(test_bit_lib_increment_index);
|
||||||
MU_RUN_TEST(test_bit_lib_is_set);
|
MU_RUN_TEST(test_bit_lib_is_set);
|
||||||
@@ -457,6 +718,7 @@ MU_TEST_SUITE(test_bit_lib) {
|
|||||||
MU_RUN_TEST(test_bit_lib_get_bits);
|
MU_RUN_TEST(test_bit_lib_get_bits);
|
||||||
MU_RUN_TEST(test_bit_lib_get_bits_16);
|
MU_RUN_TEST(test_bit_lib_get_bits_16);
|
||||||
MU_RUN_TEST(test_bit_lib_get_bits_32);
|
MU_RUN_TEST(test_bit_lib_get_bits_32);
|
||||||
|
MU_RUN_TEST(test_bit_lib_get_bits_64);
|
||||||
MU_RUN_TEST(test_bit_lib_test_parity_u32);
|
MU_RUN_TEST(test_bit_lib_test_parity_u32);
|
||||||
MU_RUN_TEST(test_bit_lib_test_parity);
|
MU_RUN_TEST(test_bit_lib_test_parity);
|
||||||
MU_RUN_TEST(test_bit_lib_remove_bit_every_nth);
|
MU_RUN_TEST(test_bit_lib_remove_bit_every_nth);
|
||||||
@@ -465,6 +727,11 @@ MU_TEST_SUITE(test_bit_lib) {
|
|||||||
MU_RUN_TEST(test_bit_lib_get_bit_count);
|
MU_RUN_TEST(test_bit_lib_get_bit_count);
|
||||||
MU_RUN_TEST(test_bit_lib_reverse_16_fast);
|
MU_RUN_TEST(test_bit_lib_reverse_16_fast);
|
||||||
MU_RUN_TEST(test_bit_lib_crc16);
|
MU_RUN_TEST(test_bit_lib_crc16);
|
||||||
|
MU_RUN_TEST(test_bit_lib_num_to_bytes_be);
|
||||||
|
MU_RUN_TEST(test_bit_lib_num_to_bytes_le);
|
||||||
|
MU_RUN_TEST(test_bit_lib_bytes_to_num_be);
|
||||||
|
MU_RUN_TEST(test_bit_lib_bytes_to_num_le);
|
||||||
|
MU_RUN_TEST(test_bit_lib_bytes_to_num_bcd);
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_minunit_test_bit_lib() {
|
int run_minunit_test_bit_lib() {
|
||||||
191
applications/debug/unit_tests/datetimelib/datetimelib_test.c
Normal file
191
applications/debug/unit_tests/datetimelib/datetimelib_test.c
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
#include <datetime/datetime.h>
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_correct_min) {
|
||||||
|
DateTime correct_min = {0, 0, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&correct_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_correct_max) {
|
||||||
|
DateTime correct_max = {23, 59, 59, 31, 12, 2099, 7};
|
||||||
|
bool result = datetime_validate_datetime(&correct_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(true, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_second) {
|
||||||
|
DateTime incorrect_sec = {0, 0, 60, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_sec);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_minute) {
|
||||||
|
DateTime incorrect_min = {0, 60, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_hour) {
|
||||||
|
DateTime incorrect_hour = {24, 0, 0, 1, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_hour);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_day_min) {
|
||||||
|
DateTime incorrect_day_min = {0, 0, 0, 0, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_day_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_day_max) {
|
||||||
|
DateTime incorrect_day_max = {0, 0, 0, 32, 1, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_day_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_month_min) {
|
||||||
|
DateTime incorrect_month_min = {0, 0, 0, 1, 0, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_month_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_month_max) {
|
||||||
|
DateTime incorrect_month_max = {0, 0, 0, 1, 13, 2000, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_month_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_year_min) {
|
||||||
|
DateTime incorrect_year_min = {0, 0, 0, 1, 1, 1999, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_year_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_year_max) {
|
||||||
|
DateTime incorrect_year_max = {0, 0, 0, 1, 1, 2100, 1};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_year_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_min) {
|
||||||
|
DateTime incorrect_weekday_min = {0, 0, 0, 1, 1, 2000, 0};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_weekday_min);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_validate_datetime_incorrect_weekday_max) {
|
||||||
|
DateTime incorrect_weekday_max = {0, 0, 0, 1, 1, 2000, 8};
|
||||||
|
bool result = datetime_validate_datetime(&incorrect_weekday_max);
|
||||||
|
|
||||||
|
mu_assert_int_eq(false, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_validate_datetime) {
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_correct_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_correct_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_second);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_minute);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_hour);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_day_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_month_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_year_max);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_min);
|
||||||
|
MU_RUN_TEST(test_datetime_validate_datetime_incorrect_weekday_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_min) {
|
||||||
|
uint32_t test_value = 0;
|
||||||
|
DateTime min_datetime_expected = {0, 0, 0, 1, 1, 1970, 4};
|
||||||
|
|
||||||
|
DateTime result = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &result);
|
||||||
|
|
||||||
|
mu_assert_mem_eq(&min_datetime_expected, &result, sizeof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_max) {
|
||||||
|
uint32_t test_value = UINT32_MAX;
|
||||||
|
DateTime max_datetime_expected = {6, 28, 15, 7, 2, 2106, 7};
|
||||||
|
|
||||||
|
DateTime result = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &result);
|
||||||
|
|
||||||
|
mu_assert_mem_eq(&max_datetime_expected, &result, sizeof(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_to_timestamp) {
|
||||||
|
uint32_t test_value = random();
|
||||||
|
|
||||||
|
DateTime datetime = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &datetime);
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&datetime);
|
||||||
|
|
||||||
|
mu_assert_int_eq(test_value, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_timestamp_to_datetime_weekday) {
|
||||||
|
uint32_t test_value = 1709748421; // Wed Mar 06 18:07:01 2024 UTC
|
||||||
|
|
||||||
|
DateTime datetime = {0};
|
||||||
|
datetime_timestamp_to_datetime(test_value, &datetime);
|
||||||
|
|
||||||
|
mu_assert_int_eq(datetime.hour, 18);
|
||||||
|
mu_assert_int_eq(datetime.minute, 7);
|
||||||
|
mu_assert_int_eq(datetime.second, 1);
|
||||||
|
mu_assert_int_eq(datetime.day, 6);
|
||||||
|
mu_assert_int_eq(datetime.month, 3);
|
||||||
|
mu_assert_int_eq(datetime.weekday, 3);
|
||||||
|
mu_assert_int_eq(datetime.year, 2024);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_timestamp_to_datetime_suite) {
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_min);
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_max);
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_to_timestamp);
|
||||||
|
MU_RUN_TEST(test_datetime_timestamp_to_datetime_weekday);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_datetime_to_timestamp_min) {
|
||||||
|
DateTime min_datetime = {0, 0, 0, 1, 1, 1970, 0};
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&min_datetime);
|
||||||
|
mu_assert_int_eq(0, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_datetime_datetime_to_timestamp_max) {
|
||||||
|
DateTime max_datetime = {6, 28, 15, 7, 2, 2106, 0};
|
||||||
|
|
||||||
|
uint32_t result = datetime_datetime_to_timestamp(&max_datetime);
|
||||||
|
mu_assert_int_eq(UINT32_MAX, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_datetime_datetime_to_timestamp_suite) {
|
||||||
|
MU_RUN_TEST(test_datetime_datetime_to_timestamp_min);
|
||||||
|
MU_RUN_TEST(test_datetime_datetime_to_timestamp_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_minunit_test_datetime() {
|
||||||
|
MU_RUN_SUITE(test_datetime_timestamp_to_datetime_suite);
|
||||||
|
MU_RUN_SUITE(test_datetime_datetime_to_timestamp_suite);
|
||||||
|
MU_RUN_SUITE(test_datetime_validate_datetime);
|
||||||
|
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
200
applications/debug/unit_tests/expansion/expansion_test.c
Normal file
200
applications/debug/unit_tests/expansion/expansion_test.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal_random.h>
|
||||||
|
|
||||||
|
#include <expansion/expansion_protocol.h>
|
||||||
|
|
||||||
|
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
||||||
|
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
||||||
|
#define EXPANSION_TEST_GARBAGE_ITERATIONS (100U)
|
||||||
|
|
||||||
|
MU_TEST(test_expansion_encoded_size) {
|
||||||
|
ExpansionFrame frame = {};
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeHeartbeat;
|
||||||
|
mu_assert_int_eq(1, expansion_frame_get_encoded_size(&frame));
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeStatus;
|
||||||
|
mu_assert_int_eq(2, expansion_frame_get_encoded_size(&frame));
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeBaudRate;
|
||||||
|
mu_assert_int_eq(5, expansion_frame_get_encoded_size(&frame));
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeControl;
|
||||||
|
mu_assert_int_eq(2, expansion_frame_get_encoded_size(&frame));
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeData;
|
||||||
|
for(size_t i = 0; i <= EXPANSION_PROTOCOL_MAX_DATA_SIZE; ++i) {
|
||||||
|
frame.content.data.size = i;
|
||||||
|
mu_assert_int_eq(i + 2, expansion_frame_get_encoded_size(&frame));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_expansion_remaining_size) {
|
||||||
|
ExpansionFrame frame = {};
|
||||||
|
|
||||||
|
size_t remaining_size;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeHeartbeat;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeStatus;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeBaudRate;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||||
|
mu_assert_int_eq(4, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 5, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeControl;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
|
||||||
|
frame.header.type = ExpansionFrameTypeData;
|
||||||
|
frame.content.data.size = EXPANSION_PROTOCOL_MAX_DATA_SIZE;
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 0, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 1, &remaining_size));
|
||||||
|
mu_assert_int_eq(1, remaining_size);
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 2, &remaining_size));
|
||||||
|
mu_assert_int_eq(EXPANSION_PROTOCOL_MAX_DATA_SIZE, remaining_size);
|
||||||
|
for(size_t i = 0; i <= EXPANSION_PROTOCOL_MAX_DATA_SIZE; ++i) {
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, i + 2, &remaining_size));
|
||||||
|
mu_assert_int_eq(EXPANSION_PROTOCOL_MAX_DATA_SIZE - i, remaining_size);
|
||||||
|
}
|
||||||
|
mu_check(expansion_frame_get_remaining_size(&frame, 100, &remaining_size));
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* data_out;
|
||||||
|
size_t size_available;
|
||||||
|
size_t size_sent;
|
||||||
|
} TestExpansionSendStream;
|
||||||
|
|
||||||
|
static size_t test_expansion_send_callback(const uint8_t* data, size_t data_size, void* context) {
|
||||||
|
TestExpansionSendStream* stream = context;
|
||||||
|
const size_t size_sent = MIN(data_size, stream->size_available);
|
||||||
|
|
||||||
|
memcpy(stream->data_out + stream->size_sent, data, size_sent);
|
||||||
|
|
||||||
|
stream->size_available -= size_sent;
|
||||||
|
stream->size_sent += size_sent;
|
||||||
|
|
||||||
|
return size_sent;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const void* data_in;
|
||||||
|
size_t size_available;
|
||||||
|
size_t size_received;
|
||||||
|
} TestExpansionReceiveStream;
|
||||||
|
|
||||||
|
static size_t test_expansion_receive_callback(uint8_t* data, size_t data_size, void* context) {
|
||||||
|
TestExpansionReceiveStream* stream = context;
|
||||||
|
const size_t size_received = MIN(data_size, stream->size_available);
|
||||||
|
|
||||||
|
memcpy(data, stream->data_in + stream->size_received, size_received);
|
||||||
|
|
||||||
|
stream->size_available -= size_received;
|
||||||
|
stream->size_received += size_received;
|
||||||
|
|
||||||
|
return size_received;
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_expansion_encode_decode_frame) {
|
||||||
|
const ExpansionFrame frame_in = {
|
||||||
|
.header.type = ExpansionFrameTypeData,
|
||||||
|
.content.data.size = 8,
|
||||||
|
.content.data.bytes = {0xde, 0xad, 0xbe, 0xef, 0xfe, 0xed, 0xca, 0xfe},
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t encoded_data[sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum)];
|
||||||
|
memset(encoded_data, 0, sizeof(encoded_data));
|
||||||
|
|
||||||
|
TestExpansionSendStream send_stream = {
|
||||||
|
.data_out = &encoded_data,
|
||||||
|
.size_available = sizeof(encoded_data),
|
||||||
|
.size_sent = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const size_t encoded_size = expansion_frame_get_encoded_size(&frame_in);
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
expansion_protocol_encode(&frame_in, test_expansion_send_callback, &send_stream),
|
||||||
|
ExpansionProtocolStatusOk);
|
||||||
|
mu_assert_int_eq(encoded_size + sizeof(ExpansionFrameChecksum), send_stream.size_sent);
|
||||||
|
mu_assert_int_eq(
|
||||||
|
expansion_protocol_get_checksum((const uint8_t*)&frame_in, encoded_size),
|
||||||
|
encoded_data[encoded_size]);
|
||||||
|
mu_assert_mem_eq(&frame_in, &encoded_data, encoded_size);
|
||||||
|
|
||||||
|
TestExpansionReceiveStream stream = {
|
||||||
|
.data_in = encoded_data,
|
||||||
|
.size_available = send_stream.size_sent,
|
||||||
|
.size_received = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
ExpansionFrame frame_out;
|
||||||
|
|
||||||
|
mu_assert_int_eq(
|
||||||
|
expansion_protocol_decode(&frame_out, test_expansion_receive_callback, &stream),
|
||||||
|
ExpansionProtocolStatusOk);
|
||||||
|
mu_assert_int_eq(encoded_size + sizeof(ExpansionFrameChecksum), stream.size_received);
|
||||||
|
mu_assert_mem_eq(&frame_in, &frame_out, encoded_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_expansion_garbage_input) {
|
||||||
|
uint8_t garbage_data[EXPANSION_TEST_GARBAGE_BUF_SIZE];
|
||||||
|
for(uint32_t i = 0; i < EXPANSION_TEST_GARBAGE_ITERATIONS; ++i) {
|
||||||
|
furi_hal_random_fill_buf(garbage_data, sizeof(garbage_data));
|
||||||
|
size_t remaining_size = EXPANSION_TEST_GARBAGE_MAGIC;
|
||||||
|
if(expansion_frame_get_remaining_size(
|
||||||
|
(ExpansionFrame*)garbage_data, sizeof(garbage_data), &remaining_size)) {
|
||||||
|
// If by chance the garbage data is a valid frame, then the result
|
||||||
|
// must be 0 because the amount of data provided is more than enough
|
||||||
|
mu_assert_int_eq(0, remaining_size);
|
||||||
|
} else {
|
||||||
|
// If the frame is invalid, the remaining_size parameter should be untouched
|
||||||
|
mu_assert_int_eq(EXPANSION_TEST_GARBAGE_MAGIC, remaining_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(test_expansion_suite) {
|
||||||
|
MU_RUN_TEST(test_expansion_encoded_size);
|
||||||
|
MU_RUN_TEST(test_expansion_remaining_size);
|
||||||
|
MU_RUN_TEST(test_expansion_encode_decode_frame);
|
||||||
|
MU_RUN_TEST(test_expansion_garbage_input);
|
||||||
|
}
|
||||||
|
|
||||||
|
int run_minunit_test_expansion() {
|
||||||
|
MU_RUN_SUITE(test_expansion_suite);
|
||||||
|
return MU_EXIT_CODE;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
void test_furi_memmgr() {
|
void test_furi_memmgr() {
|
||||||
void* ptr;
|
void* ptr;
|
||||||
|
|||||||
@@ -3,18 +3,29 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
|
|
||||||
void test_furi_create_open() {
|
#define TEST_RECORD_NAME "test/holding"
|
||||||
// 1. Create record
|
|
||||||
uint8_t test_data = 0;
|
|
||||||
furi_record_create("test/holding", (void*)&test_data);
|
|
||||||
|
|
||||||
// 2. Open it
|
void test_furi_create_open() {
|
||||||
void* record = furi_record_open("test/holding");
|
// Test that record does not exist
|
||||||
|
mu_check(furi_record_exists(TEST_RECORD_NAME) == false);
|
||||||
|
|
||||||
|
// Create record
|
||||||
|
uint8_t test_data = 0;
|
||||||
|
furi_record_create(TEST_RECORD_NAME, (void*)&test_data);
|
||||||
|
|
||||||
|
// Test that record exists
|
||||||
|
mu_check(furi_record_exists(TEST_RECORD_NAME) == true);
|
||||||
|
|
||||||
|
// Open it
|
||||||
|
void* record = furi_record_open(TEST_RECORD_NAME);
|
||||||
mu_assert_pointers_eq(record, &test_data);
|
mu_assert_pointers_eq(record, &test_data);
|
||||||
|
|
||||||
// 3. Close it
|
// Close it
|
||||||
furi_record_close("test/holding");
|
furi_record_close(TEST_RECORD_NAME);
|
||||||
|
|
||||||
// 4. Clean up
|
// Clean up
|
||||||
furi_record_destroy("test/holding");
|
furi_record_destroy(TEST_RECORD_NAME);
|
||||||
|
|
||||||
|
// Test that record does not exist
|
||||||
|
mu_check(furi_record_exists(TEST_RECORD_NAME) == false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
#include "furi_hal_rtc.h"
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <lp5562_reg.h>
|
#include <lp5562_reg.h>
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define DATA_SIZE 4
|
#define DATA_SIZE 4
|
||||||
#define EEPROM_ADDRESS 0b10101000
|
#define EEPROM_ADDRESS 0b10101000
|
||||||
|
|||||||
@@ -426,53 +426,53 @@ MU_TEST(infrared_test_decoder_mixed) {
|
|||||||
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);
|
infrared_test_run_decoder(InfraredProtocolRCA, 1);
|
||||||
|
infrared_test_run_decoder(InfraredProtocolPioneer, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_nec) {
|
MU_TEST(infrared_test_decoder_nec) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
for(uint32_t i = 1; i <= 3; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 3);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_unexpected_end_in_sequence) {
|
MU_TEST(infrared_test_decoder_unexpected_end_in_sequence) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
for(uint32_t i = 1; i <= 2; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 1);
|
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
infrared_test_run_decoder(InfraredProtocolNEC, i);
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC, 2);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_necext1) {
|
MU_TEST(infrared_test_decoder_necext1) {
|
||||||
|
for(uint32_t i = 0; i < 2; ++i) {
|
||||||
|
UNUSED(i);
|
||||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
||||||
infrared_test_run_decoder(InfraredProtocolNECext, 1);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_long_packets_with_nec_start) {
|
MU_TEST(infrared_test_decoder_long_packets_with_nec_start) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 1);
|
for(uint32_t i = 1; i <= 2; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolNEC42ext, 2);
|
infrared_test_run_decoder(InfraredProtocolNEC42ext, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_encoder_sirc) {
|
MU_TEST(infrared_test_encoder_sirc) {
|
||||||
infrared_test_run_encoder(InfraredProtocolSIRC, 1);
|
for(uint32_t i = 1; i <= 2; ++i) {
|
||||||
infrared_test_run_encoder(InfraredProtocolSIRC, 2);
|
infrared_test_run_encoder(InfraredProtocolSIRC, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_sirc) {
|
MU_TEST(infrared_test_decoder_sirc) {
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 3);
|
for(uint32_t i = 1; i <= 5; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 1);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 2);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 4);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
infrared_test_run_decoder(InfraredProtocolSIRC, 5);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_rc5) {
|
MU_TEST(infrared_test_decoder_rc5) {
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5X, 1);
|
infrared_test_run_decoder(InfraredProtocolRC5X, 1);
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 1);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 2);
|
for(uint32_t i = 1; i <= 7; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 3);
|
infrared_test_run_decoder(InfraredProtocolRC5, i);
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 4);
|
}
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 5);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 6);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolRC5, 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_encoder_rc5x) {
|
MU_TEST(infrared_test_encoder_rc5x) {
|
||||||
@@ -492,21 +492,21 @@ MU_TEST(infrared_test_encoder_rc6) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_kaseikyo) {
|
MU_TEST(infrared_test_decoder_kaseikyo) {
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 1);
|
for(uint32_t i = 1; i <= 6; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 2);
|
infrared_test_run_decoder(InfraredProtocolKaseikyo, i);
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 3);
|
}
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 4);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 5);
|
|
||||||
infrared_test_run_decoder(InfraredProtocolKaseikyo, 6);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_decoder_rca) {
|
MU_TEST(infrared_test_decoder_rca) {
|
||||||
infrared_test_run_decoder(InfraredProtocolRCA, 1);
|
for(uint32_t i = 1; i <= 6; ++i) {
|
||||||
infrared_test_run_decoder(InfraredProtocolRCA, 2);
|
infrared_test_run_decoder(InfraredProtocolRCA, i);
|
||||||
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_decoder_pioneer) {
|
||||||
|
for(uint32_t i = 1; i <= 11; ++i) {
|
||||||
|
infrared_test_run_decoder(InfraredProtocolPioneer, i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(infrared_test_encoder_decoder_all) {
|
MU_TEST(infrared_test_encoder_decoder_all) {
|
||||||
@@ -520,6 +520,7 @@ MU_TEST(infrared_test_encoder_decoder_all) {
|
|||||||
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);
|
infrared_test_run_encoder_decoder(InfraredProtocolRCA, 1);
|
||||||
|
infrared_test_run_encoder_decoder(InfraredProtocolPioneer, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(infrared_test) {
|
MU_TEST_SUITE(infrared_test) {
|
||||||
@@ -539,6 +540,7 @@ MU_TEST_SUITE(infrared_test) {
|
|||||||
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_rca);
|
||||||
|
MU_RUN_TEST(infrared_test_decoder_pioneer);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -209,6 +209,25 @@ const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = {
|
|||||||
-1, 1, -1, 1, -1, 1, -1, 1,
|
-1, 1, -1, 1, -1, 1, -1, 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FDXB_TEST_DATA \
|
||||||
|
{ 0x44, 0x88, 0x23, 0xF2, 0x5A, 0x6F, 0x00, 0x01, 0x00, 0x00, 0x00 }
|
||||||
|
#define FDXB_TEST_DATA_SIZE 11
|
||||||
|
#define FDXB_TEST_EMULATION_TIMINGS_COUNT (206)
|
||||||
|
|
||||||
|
const int8_t fdxb_test_timings[FDXB_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||||
|
32, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16,
|
||||||
|
-16, 16, -32, 16, -16, 32, -16, 16, -16, 16, -16, 16, -32, 16, -16, 16, -16, 32, -32,
|
||||||
|
16, -16, 16, -16, 16, -16, 32, -16, 16, -16, 16, -16, 16, -32, 16, -16, 16, -16, 32,
|
||||||
|
-16, 16, -16, 16, -16, 16, -32, 32, -32, 32, -32, 32, -32, 16, -16, 16, -16, 32, -16,
|
||||||
|
16, -32, 16, -16, 32, -16, 16, -32, 32, -16, 16, -32, 16, -16, 32, -16, 16, -32, 32,
|
||||||
|
-16, 16, -32, 32, -32, 32, -32, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16,
|
||||||
|
16, -16, 16, -16, 32, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16,
|
||||||
|
-32, 32, -32, 32, -32, 32, -32, 16, -16, 32, -32, 32, -16, 16, -16, 16, -32, 32, -32,
|
||||||
|
32, -32, 32, -32, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16,
|
||||||
|
-16, 32, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -32,
|
||||||
|
16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16, 16, -16,
|
||||||
|
};
|
||||||
|
|
||||||
MU_TEST(test_lfrfid_protocol_em_read_simple) {
|
MU_TEST(test_lfrfid_protocol_em_read_simple) {
|
||||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||||
mu_assert_int_eq(EM_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolEM4100));
|
mu_assert_int_eq(EM_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolEM4100));
|
||||||
@@ -445,6 +464,73 @@ MU_TEST(test_lfrfid_protocol_inadala26_emulate_simple) {
|
|||||||
protocol_dict_free(dict);
|
protocol_dict_free(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_lfrfid_protocol_fdxb_emulate_simple) {
|
||||||
|
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||||
|
mu_assert_int_eq(FDXB_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolFDXB));
|
||||||
|
mu_assert_string_eq("FDX-B", protocol_dict_get_name(dict, LFRFIDProtocolFDXB));
|
||||||
|
mu_assert_string_eq("ISO", protocol_dict_get_manufacturer(dict, LFRFIDProtocolFDXB));
|
||||||
|
|
||||||
|
const uint8_t data[FDXB_TEST_DATA_SIZE] = FDXB_TEST_DATA;
|
||||||
|
|
||||||
|
protocol_dict_set_data(dict, LFRFIDProtocolFDXB, data, FDXB_TEST_DATA_SIZE);
|
||||||
|
mu_check(protocol_dict_encoder_start(dict, LFRFIDProtocolFDXB));
|
||||||
|
|
||||||
|
for(size_t i = 0; i < FDXB_TEST_EMULATION_TIMINGS_COUNT; i++) {
|
||||||
|
LevelDuration level_duration = protocol_dict_encoder_yield(dict, LFRFIDProtocolFDXB);
|
||||||
|
|
||||||
|
if(level_duration_get_level(level_duration)) {
|
||||||
|
mu_assert_int_eq(fdxb_test_timings[i], level_duration_get_duration(level_duration));
|
||||||
|
} else {
|
||||||
|
mu_assert_int_eq(fdxb_test_timings[i], -level_duration_get_duration(level_duration));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protocol_dict_free(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(test_lfrfid_protocol_fdxb_read_simple) {
|
||||||
|
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||||
|
mu_assert_int_eq(FDXB_TEST_DATA_SIZE, protocol_dict_get_data_size(dict, LFRFIDProtocolFDXB));
|
||||||
|
mu_assert_string_eq("FDX-B", protocol_dict_get_name(dict, LFRFIDProtocolFDXB));
|
||||||
|
mu_assert_string_eq("ISO", protocol_dict_get_manufacturer(dict, LFRFIDProtocolFDXB));
|
||||||
|
|
||||||
|
const uint8_t data[FDXB_TEST_DATA_SIZE] = FDXB_TEST_DATA;
|
||||||
|
|
||||||
|
protocol_dict_decoders_start(dict);
|
||||||
|
|
||||||
|
ProtocolId protocol = PROTOCOL_NO;
|
||||||
|
PulseGlue* pulse_glue = pulse_glue_alloc();
|
||||||
|
|
||||||
|
for(size_t i = 0; i < FDXB_TEST_EMULATION_TIMINGS_COUNT * 10; i++) {
|
||||||
|
bool pulse_pop = pulse_glue_push(
|
||||||
|
pulse_glue,
|
||||||
|
fdxb_test_timings[i % FDXB_TEST_EMULATION_TIMINGS_COUNT] >= 0,
|
||||||
|
abs(fdxb_test_timings[i % FDXB_TEST_EMULATION_TIMINGS_COUNT]) *
|
||||||
|
LF_RFID_READ_TIMING_MULTIPLIER);
|
||||||
|
|
||||||
|
if(pulse_pop) {
|
||||||
|
uint32_t length, period;
|
||||||
|
pulse_glue_pop(pulse_glue, &length, &period);
|
||||||
|
|
||||||
|
protocol = protocol_dict_decoders_feed(dict, true, period);
|
||||||
|
if(protocol != PROTOCOL_NO) break;
|
||||||
|
|
||||||
|
protocol = protocol_dict_decoders_feed(dict, false, length - period);
|
||||||
|
if(protocol != PROTOCOL_NO) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pulse_glue_free(pulse_glue);
|
||||||
|
|
||||||
|
mu_assert_int_eq(LFRFIDProtocolFDXB, protocol);
|
||||||
|
uint8_t received_data[FDXB_TEST_DATA_SIZE] = {0};
|
||||||
|
protocol_dict_get_data(dict, protocol, received_data, FDXB_TEST_DATA_SIZE);
|
||||||
|
|
||||||
|
mu_assert_mem_eq(data, received_data, FDXB_TEST_DATA_SIZE);
|
||||||
|
|
||||||
|
protocol_dict_free(dict);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(test_lfrfid_protocols_suite) {
|
MU_TEST_SUITE(test_lfrfid_protocols_suite) {
|
||||||
MU_RUN_TEST(test_lfrfid_protocol_em_read_simple);
|
MU_RUN_TEST(test_lfrfid_protocol_em_read_simple);
|
||||||
MU_RUN_TEST(test_lfrfid_protocol_em_emulate_simple);
|
MU_RUN_TEST(test_lfrfid_protocol_em_emulate_simple);
|
||||||
@@ -456,6 +542,9 @@ MU_TEST_SUITE(test_lfrfid_protocols_suite) {
|
|||||||
MU_RUN_TEST(test_lfrfid_protocol_ioprox_xsf_emulate_simple);
|
MU_RUN_TEST(test_lfrfid_protocol_ioprox_xsf_emulate_simple);
|
||||||
|
|
||||||
MU_RUN_TEST(test_lfrfid_protocol_inadala26_emulate_simple);
|
MU_RUN_TEST(test_lfrfid_protocol_inadala26_emulate_simple);
|
||||||
|
|
||||||
|
MU_RUN_TEST(test_lfrfid_protocol_fdxb_read_simple);
|
||||||
|
MU_RUN_TEST(test_lfrfid_protocol_fdxb_emulate_simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
int run_minunit_test_lfrfid_protocols() {
|
int run_minunit_test_lfrfid_protocols() {
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ __attribute__((unused)) static void (*minunit_teardown)(void) = NULL;
|
|||||||
|
|
||||||
void minunit_print_progress(void);
|
void minunit_print_progress(void);
|
||||||
void minunit_print_fail(const char* error);
|
void minunit_print_fail(const char* error);
|
||||||
|
void minunit_printf_warning(const char* format, ...);
|
||||||
|
|
||||||
/* Definitions */
|
/* Definitions */
|
||||||
#define MU_TEST(method_name) static void method_name(void)
|
#define MU_TEST(method_name) static void method_name(void)
|
||||||
@@ -150,6 +151,10 @@ void minunit_print_fail(const char* error);
|
|||||||
minunit_end_proc_timer - minunit_proc_timer);)
|
minunit_end_proc_timer - minunit_proc_timer);)
|
||||||
#define MU_EXIT_CODE minunit_fail
|
#define MU_EXIT_CODE minunit_fail
|
||||||
|
|
||||||
|
/* Warnings */
|
||||||
|
#define mu_warn(message) \
|
||||||
|
MU__SAFE_BLOCK(minunit_printf_warning("%s:%d: %s", __FILE__, __LINE__, message);)
|
||||||
|
|
||||||
/* Assertions */
|
/* Assertions */
|
||||||
#define mu_check(test) \
|
#define mu_check(test) \
|
||||||
MU__SAFE_BLOCK( \
|
MU__SAFE_BLOCK( \
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
#include <nfc/nfc_poller.h>
|
#include <nfc/nfc_poller.h>
|
||||||
#include <nfc/nfc_listener.h>
|
#include <nfc/nfc_listener.h>
|
||||||
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||||
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller_sync_api.h>
|
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller_sync.h>
|
||||||
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
|
||||||
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync_api.h>
|
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_sync.h>
|
||||||
#include <nfc/protocols/mf_classic/mf_classic_poller_sync_api.h>
|
#include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
|
||||||
|
|
||||||
#include <nfc/helpers/nfc_dict.h>
|
#include <toolbox/keys_dict.h>
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
@@ -182,8 +182,8 @@ MU_TEST(iso14443_3a_reader) {
|
|||||||
|
|
||||||
Iso14443_3aData iso14443_3a_poller_data = {};
|
Iso14443_3aData iso14443_3a_poller_data = {};
|
||||||
mu_assert(
|
mu_assert(
|
||||||
iso14443_3a_poller_read(poller, &iso14443_3a_poller_data) == Iso14443_3aErrorNone,
|
iso14443_3a_poller_sync_read(poller, &iso14443_3a_poller_data) == Iso14443_3aErrorNone,
|
||||||
"iso14443_3a_poller_read() failed");
|
"iso14443_3a_poller_sync_read() failed");
|
||||||
|
|
||||||
nfc_listener_stop(iso3_listener);
|
nfc_listener_stop(iso3_listener);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
@@ -203,15 +203,26 @@ static void mf_ultralight_reader_test(const char* path) {
|
|||||||
NfcDevice* nfc_device = nfc_device_alloc();
|
NfcDevice* nfc_device = nfc_device_alloc();
|
||||||
mu_assert(nfc_device_load(nfc_device, path), "nfc_device_load() failed\r\n");
|
mu_assert(nfc_device_load(nfc_device, path), "nfc_device_load() failed\r\n");
|
||||||
|
|
||||||
NfcListener* mfu_listener = nfc_listener_alloc(
|
MfUltralightData* data =
|
||||||
listener,
|
(MfUltralightData*)nfc_device_get_data(nfc_device, NfcProtocolMfUltralight);
|
||||||
NfcProtocolMfUltralight,
|
|
||||||
nfc_device_get_data(nfc_device, NfcProtocolMfUltralight));
|
uint32_t features = mf_ultralight_get_feature_support_set(data->type);
|
||||||
|
bool pwd_supported =
|
||||||
|
mf_ultralight_support_feature(features, MfUltralightFeatureSupportPasswordAuth);
|
||||||
|
uint8_t pwd_num = mf_ultralight_get_pwd_page_num(data->type);
|
||||||
|
const uint8_t zero_pwd[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
|
if(pwd_supported && !memcmp(data->page[pwd_num].data, zero_pwd, sizeof(zero_pwd))) {
|
||||||
|
data->pages_read -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcListener* mfu_listener = nfc_listener_alloc(listener, NfcProtocolMfUltralight, data);
|
||||||
|
|
||||||
nfc_listener_start(mfu_listener, NULL, NULL);
|
nfc_listener_start(mfu_listener, NULL, NULL);
|
||||||
|
|
||||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||||
MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
|
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
|
||||||
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
|
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
|
||||||
|
|
||||||
nfc_listener_stop(mfu_listener);
|
nfc_listener_stop(mfu_listener);
|
||||||
nfc_listener_free(mfu_listener);
|
nfc_listener_free(mfu_listener);
|
||||||
@@ -259,8 +270,8 @@ MU_TEST(ntag_213_locked_reader) {
|
|||||||
nfc_listener_start(mfu_listener, NULL, NULL);
|
nfc_listener_start(mfu_listener, NULL, NULL);
|
||||||
|
|
||||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||||
MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
|
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
|
||||||
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
|
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
|
||||||
|
|
||||||
nfc_listener_stop(mfu_listener);
|
nfc_listener_stop(mfu_listener);
|
||||||
nfc_listener_free(mfu_listener);
|
nfc_listener_free(mfu_listener);
|
||||||
@@ -297,8 +308,8 @@ static void mf_ultralight_write() {
|
|||||||
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
MfUltralightData* mfu_data = mf_ultralight_alloc();
|
||||||
|
|
||||||
// Initial read
|
// Initial read
|
||||||
MfUltralightError error = mf_ultralight_poller_read_card(poller, mfu_data);
|
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
|
||||||
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
|
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
|
||||||
|
|
||||||
mu_assert(
|
mu_assert(
|
||||||
mf_ultralight_is_equal(mfu_data, nfc_device_get_data(nfc_device, NfcProtocolMfUltralight)),
|
mf_ultralight_is_equal(mfu_data, nfc_device_get_data(nfc_device, NfcProtocolMfUltralight)),
|
||||||
@@ -310,13 +321,13 @@ static void mf_ultralight_write() {
|
|||||||
FURI_LOG_D(TAG, "Writing page %d", i);
|
FURI_LOG_D(TAG, "Writing page %d", i);
|
||||||
furi_hal_random_fill_buf(page.data, sizeof(MfUltralightPage));
|
furi_hal_random_fill_buf(page.data, sizeof(MfUltralightPage));
|
||||||
mfu_data->page[i] = page;
|
mfu_data->page[i] = page;
|
||||||
error = mf_ultralight_poller_write_page(poller, i, &page);
|
error = mf_ultralight_poller_sync_write_page(poller, i, &page);
|
||||||
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_write_page() failed");
|
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_write_page() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verification read
|
// Verification read
|
||||||
error = mf_ultralight_poller_read_card(poller, mfu_data);
|
error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
|
||||||
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_read_card() failed");
|
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
|
||||||
|
|
||||||
nfc_listener_stop(mfu_listener);
|
nfc_listener_stop(mfu_listener);
|
||||||
const MfUltralightData* mfu_listener_data =
|
const MfUltralightData* mfu_listener_data =
|
||||||
@@ -344,7 +355,7 @@ static void mf_classic_reader() {
|
|||||||
MfClassicBlock block = {};
|
MfClassicBlock block = {};
|
||||||
MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||||
|
|
||||||
mf_classic_poller_read_block(poller, 0, &key, MfClassicKeyTypeA, &block);
|
mf_classic_poller_sync_read_block(poller, 0, &key, MfClassicKeyTypeA, &block);
|
||||||
|
|
||||||
nfc_listener_stop(mfc_listener);
|
nfc_listener_stop(mfc_listener);
|
||||||
nfc_listener_free(mfc_listener);
|
nfc_listener_free(mfc_listener);
|
||||||
@@ -372,8 +383,8 @@ static void mf_classic_write() {
|
|||||||
furi_hal_random_fill_buf(block_write.data, sizeof(MfClassicBlock));
|
furi_hal_random_fill_buf(block_write.data, sizeof(MfClassicBlock));
|
||||||
MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
MfClassicKey key = {.data = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
|
||||||
|
|
||||||
mf_classic_poller_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
|
mf_classic_poller_sync_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
|
||||||
mf_classic_poller_read_block(poller, 1, &key, MfClassicKeyTypeA, &block_read);
|
mf_classic_poller_sync_read_block(poller, 1, &key, MfClassicKeyTypeA, &block_read);
|
||||||
|
|
||||||
nfc_listener_stop(mfc_listener);
|
nfc_listener_stop(mfc_listener);
|
||||||
nfc_listener_free(mfc_listener);
|
nfc_listener_free(mfc_listener);
|
||||||
@@ -402,16 +413,18 @@ static void mf_classic_value_block() {
|
|||||||
mf_classic_value_to_block(value, 1, &block_write);
|
mf_classic_value_to_block(value, 1, &block_write);
|
||||||
|
|
||||||
MfClassicError error = MfClassicErrorNone;
|
MfClassicError error = MfClassicErrorNone;
|
||||||
error = mf_classic_poller_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
|
error = mf_classic_poller_sync_write_block(poller, 1, &key, MfClassicKeyTypeA, &block_write);
|
||||||
mu_assert(error == MfClassicErrorNone, "Write failed");
|
mu_assert(error == MfClassicErrorNone, "Write failed");
|
||||||
|
|
||||||
int32_t data = 200;
|
int32_t data = 200;
|
||||||
int32_t new_value = 0;
|
int32_t new_value = 0;
|
||||||
error = mf_classic_poller_change_value(poller, 1, &key, MfClassicKeyTypeA, data, &new_value);
|
error =
|
||||||
|
mf_classic_poller_sync_change_value(poller, 1, &key, MfClassicKeyTypeA, data, &new_value);
|
||||||
mu_assert(error == MfClassicErrorNone, "Value increment failed");
|
mu_assert(error == MfClassicErrorNone, "Value increment failed");
|
||||||
mu_assert(new_value == value + data, "Value not match");
|
mu_assert(new_value == value + data, "Value not match");
|
||||||
|
|
||||||
error = mf_classic_poller_change_value(poller, 1, &key, MfClassicKeyTypeA, -data, &new_value);
|
error =
|
||||||
|
mf_classic_poller_sync_change_value(poller, 1, &key, MfClassicKeyTypeA, -data, &new_value);
|
||||||
mu_assert(error == MfClassicErrorNone, "Value decrement failed");
|
mu_assert(error == MfClassicErrorNone, "Value decrement failed");
|
||||||
mu_assert(new_value == value, "Value not match");
|
mu_assert(new_value == value, "Value not match");
|
||||||
|
|
||||||
@@ -430,36 +443,36 @@ MU_TEST(mf_classic_dict_test) {
|
|||||||
"Remove test dict failed");
|
"Remove test dict failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
NfcDict* dict = nfc_dict_alloc(
|
KeysDict* dict = keys_dict_alloc(
|
||||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||||
mu_assert(dict != NULL, "nfc_dict_alloc() failed");
|
mu_assert(dict != NULL, "keys_dict_alloc() failed");
|
||||||
|
|
||||||
size_t dict_keys_total = nfc_dict_get_total_keys(dict);
|
size_t dict_keys_total = keys_dict_get_total_keys(dict);
|
||||||
mu_assert(dict_keys_total == 0, "nfc_dict_keys_total() failed");
|
mu_assert(dict_keys_total == 0, "keys_dict_keys_total() failed");
|
||||||
|
|
||||||
const uint32_t test_key_num = 30;
|
const uint32_t test_key_num = 30;
|
||||||
MfClassicKey* key_arr_ref = malloc(test_key_num * sizeof(MfClassicKey));
|
MfClassicKey* key_arr_ref = malloc(test_key_num * sizeof(MfClassicKey));
|
||||||
for(size_t i = 0; i < test_key_num; i++) {
|
for(size_t i = 0; i < test_key_num; i++) {
|
||||||
furi_hal_random_fill_buf(key_arr_ref[i].data, sizeof(MfClassicKey));
|
furi_hal_random_fill_buf(key_arr_ref[i].data, sizeof(MfClassicKey));
|
||||||
mu_assert(
|
mu_assert(
|
||||||
nfc_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed");
|
keys_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed");
|
||||||
|
|
||||||
size_t dict_keys_total = nfc_dict_get_total_keys(dict);
|
size_t dict_keys_total = keys_dict_get_total_keys(dict);
|
||||||
mu_assert(dict_keys_total == (i + 1), "nfc_dict_keys_total() failed");
|
mu_assert(dict_keys_total == (i + 1), "keys_dict_keys_total() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
nfc_dict_free(dict);
|
keys_dict_free(dict);
|
||||||
|
|
||||||
dict = nfc_dict_alloc(
|
dict = keys_dict_alloc(
|
||||||
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey));
|
NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey));
|
||||||
mu_assert(dict != NULL, "nfc_dict_alloc() failed");
|
mu_assert(dict != NULL, "keys_dict_alloc() failed");
|
||||||
|
|
||||||
dict_keys_total = nfc_dict_get_total_keys(dict);
|
dict_keys_total = keys_dict_get_total_keys(dict);
|
||||||
mu_assert(dict_keys_total == test_key_num, "nfc_dict_keys_total() failed");
|
mu_assert(dict_keys_total == test_key_num, "keys_dict_keys_total() failed");
|
||||||
|
|
||||||
MfClassicKey key_dut = {};
|
MfClassicKey key_dut = {};
|
||||||
size_t key_idx = 0;
|
size_t key_idx = 0;
|
||||||
while(nfc_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) {
|
while(keys_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
memcmp(key_arr_ref[key_idx].data, key_dut.data, sizeof(MfClassicKey)) == 0,
|
memcmp(key_arr_ref[key_idx].data, key_dut.data, sizeof(MfClassicKey)) == 0,
|
||||||
"Loaded key data mismatch");
|
"Loaded key data mismatch");
|
||||||
@@ -471,19 +484,19 @@ MU_TEST(mf_classic_dict_test) {
|
|||||||
for(size_t i = 0; i < COUNT_OF(delete_keys_idx); i++) {
|
for(size_t i = 0; i < COUNT_OF(delete_keys_idx); i++) {
|
||||||
MfClassicKey* key = &key_arr_ref[delete_keys_idx[i]];
|
MfClassicKey* key = &key_arr_ref[delete_keys_idx[i]];
|
||||||
mu_assert(
|
mu_assert(
|
||||||
nfc_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)),
|
keys_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)),
|
||||||
"nfc_dict_is_key_present() failed");
|
"keys_dict_is_key_present() failed");
|
||||||
mu_assert(
|
mu_assert(
|
||||||
nfc_dict_delete_key(dict, key->data, sizeof(MfClassicKey)),
|
keys_dict_delete_key(dict, key->data, sizeof(MfClassicKey)),
|
||||||
"nfc_dict_delete_key() failed");
|
"keys_dict_delete_key() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
dict_keys_total = nfc_dict_get_total_keys(dict);
|
dict_keys_total = keys_dict_get_total_keys(dict);
|
||||||
mu_assert(
|
mu_assert(
|
||||||
dict_keys_total == test_key_num - COUNT_OF(delete_keys_idx),
|
dict_keys_total == test_key_num - COUNT_OF(delete_keys_idx),
|
||||||
"nfc_dict_keys_total() failed");
|
"keys_dict_keys_total() failed");
|
||||||
|
|
||||||
nfc_dict_free(dict);
|
keys_dict_free(dict);
|
||||||
free(key_arr_ref);
|
free(key_arr_ref);
|
||||||
|
|
||||||
mu_assert(
|
mu_assert(
|
||||||
|
|||||||
@@ -455,4 +455,19 @@ NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) {
|
|||||||
return NfcErrorNone;
|
return NfcErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NfcError nfc_felica_listener_set_sensf_res_data(
|
||||||
|
Nfc* instance,
|
||||||
|
const uint8_t* idm,
|
||||||
|
const uint8_t idm_len,
|
||||||
|
const uint8_t* pmm,
|
||||||
|
const uint8_t pmm_len) {
|
||||||
|
furi_assert(instance);
|
||||||
|
furi_assert(idm);
|
||||||
|
furi_assert(pmm);
|
||||||
|
furi_assert(idm_len == 8);
|
||||||
|
furi_assert(pmm_len == 8);
|
||||||
|
|
||||||
|
return NfcErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
Filetype: IR tests file
|
||||||
|
Version: 1
|
||||||
|
#
|
||||||
|
name: decoder_input1
|
||||||
|
type: raw
|
||||||
|
data: 25557 8437 4188 571 1538 595 1514 567 1542 570 1539 573 501 565 1544 568 506 571 1539 573 501 565 509 568 508 569 506 571 1538 574 501 565 1543 569 506 571 504 573 1536 566 1544 568 506 592 1517 574 1535 567 507 570 505 572 1537 575 500 566 508 600 1509 572 503 574 501 565 1544 568 1540 593
|
||||||
|
#
|
||||||
|
name: decoder_expected1
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 36 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input2
|
||||||
|
type: raw
|
||||||
|
data: 25609 8444 4152 564 1568 544 1565 547 1561 541 1568 544 530 547 1536 566 510 567 1567 545 529 548 526 540 535 542 508 569 1539 573 527 539 1543 569 506 571 504 573 1561 541 508 569 507 570 1538 564 1545 567 507 570 505 572 1537 565 509 568 1541 571 1538 564 511 566 509 568 1539 573 1537 596
|
||||||
|
#
|
||||||
|
name: decoder_expected2
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 32 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input3
|
||||||
|
type: raw
|
||||||
|
data: 25582 8448 4176 571 1537 565 1544 568 1540 572 1537 575 500 566 1542 570 505 572 1537 575 500 566 508 569 506 571 504 573 1536 565 510 567 1542 570 504 573 1536 566 1543 569 506 571 504 573 1536 566 1543 569 506 571 504 573 502 575 500 566 1542 570 1539 573 502 575 500 566 1542 570 1540 572
|
||||||
|
#
|
||||||
|
name: decoder_expected3
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 33 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input4
|
||||||
|
type: raw
|
||||||
|
data: 25594 8443 4181 568 1542 570 505 572 1538 564 1545 567 508 569 1540 572 504 573 1536 566 510 567 1542 571 505 572 504 573 1562 540 510 567 1543 570 506 571 504 573 503 574 501 565 510 567 509 568 507 570 1539 573 502 565 1545 568 1542 571 1539 573 1536 566 1544 569 1541 572 503 574 1537 565
|
||||||
|
#
|
||||||
|
name: decoder_expected4
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 40 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input5
|
||||||
|
type: raw
|
||||||
|
data: 25556 8475 4150 597 1512 600 476 601 1509 603 1506 595 480 597 1512 600 476 601 1508 594 482 595 1515 597 478 599 477 600 1510 602 473 604 1506 595 480 597 1513 599 476 601 475 602 474 603 472 594 482 595 1514 598 477 600 476 601 1508 594 1516 596 1513 599 1510 602 1507 595 480 597 1513 599
|
||||||
|
#
|
||||||
|
name: decoder_expected5
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 41 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input6
|
||||||
|
type: raw
|
||||||
|
data: 25567 8471 4155 604 1506 596 480 597 1513 599 1510 603 473 594 1515 597 478 599 1511 602 474 603 1507 595 480 597 479 598 1511 602 474 603 1506 596 480 597 478 599 1511 602 474 603 472 594 481 596 479 598 1512 601 474 603 1506 596 479 598 1511 602 1508 594 1515 598 1512 600 475 602 1507 595
|
||||||
|
#
|
||||||
|
name: decoder_expected6
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 42 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input7
|
||||||
|
type: raw
|
||||||
|
data: 25584 8444 4180 569 1541 572 504 573 1536 566 1544 569 507 570 1539 574 501 566 1569 596 455 570 1540 573 502 575 501 565 1544 569 507 570 1565 548 503 574 1535 567 1543 570 506 571 529 548 502 565 511 566 1543 601 475 571 504 573 503 574 1536 566 1543 570 1539 574 1536 566 509 568 1541 572
|
||||||
|
#
|
||||||
|
name: decoder_expected7
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 43 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input8
|
||||||
|
type: raw
|
||||||
|
data: 25562 8445 4181 568 1543 570 505 572 1538 575 1535 567 508 569 1539 573 503 595 1514 567 508 600 1509 572 503 595 481 596 1513 568 507 601 1508 573 502 575 501 566 1543 570 506 571 504 573 1536 566 510 567 508 600 475 571 1539 573 502 575 1534 568 1542 571 505 572 1537 575 1534 568 1542 571
|
||||||
|
#
|
||||||
|
name: decoder_expected8
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 12 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input9
|
||||||
|
type: raw
|
||||||
|
data: 25558 8470 4152 597 1513 600 476 601 1508 594 1515 598 478 599 1509 593 483 594 1515 598 478 599 1510 603 474 592 482 595 1514 599 477 600 1509 593 483 594 481 596 1513 600 476 601 1508 594 1515 598 478 599 476 601 474 593 1517 596 479 598 1512 601 474 603 472 594 1515 598 1511 602 1508 594
|
||||||
|
#
|
||||||
|
name: decoder_expected9
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 1A 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input10
|
||||||
|
type: raw
|
||||||
|
data: 25587 8442 4179 601 1507 595 481 565 1544 600 1509 593 482 595 1513 568 507 570 1539 594 481 565 1544 600 476 570 505 593 1516 597 479 598 1511 591 484 593 481 575 1534 600 476 570 1539 595 480 597 478 599 476 570 505 593 1517 564 511 597 1511 602 474 572 1537 597 1513 600 1509 572 1537 565
|
||||||
|
#
|
||||||
|
name: decoder_expected10
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 0A 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: decoder_input11
|
||||||
|
type: raw
|
||||||
|
data: 25554 8474 4149 600 1510 603 472 594 1515 597 1512 601 475 602 1507 595 480 597 1513 599 475 602 1508 594 481 596 479 598 1512 601 474 603 1506 596 479 598 1512 601 1508 594 481 596 1513 599 476 601 474 603 472 594 481 596 480 597 478 599 1510 603 473 593 1515 597 1512 601 1509 603 1506 596
|
||||||
|
#
|
||||||
|
name: decoder_expected11
|
||||||
|
type: parsed_array
|
||||||
|
count: 1
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 0B 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
name: encoder_decoder_input1
|
||||||
|
type: parsed_array
|
||||||
|
count: 11
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 36 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 32 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AF 00 00 00
|
||||||
|
command: 33 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 40 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 41 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 42 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 43 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 12 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 1A 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 0A 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
|
protocol: Pioneer
|
||||||
|
address: AD 00 00 00
|
||||||
|
command: 0B 00 00 00
|
||||||
|
repeat: false
|
||||||
|
#
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
Filetype: Flipper SubGhz Key File
|
||||||
|
Version: 1
|
||||||
|
Frequency: 433920000
|
||||||
|
Preset: FuriHalSubGhzPresetOok270Async
|
||||||
|
Protocol: Mastercode
|
||||||
|
Bit: 36
|
||||||
|
Key: 00 00 00 0B 7E 00 3C 08
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Filetype: Flipper SubGhz RAW File
|
||||||
|
Version: 1
|
||||||
|
Frequency: 433920000
|
||||||
|
Preset: FuriHalSubGhzPresetOok270Async
|
||||||
|
Protocol: RAW
|
||||||
|
RAW_Data: 10389 -66 405095 -102 207 -106 1165 -130 963739 -1232 899 -2250 2003 -1190 2017 -1202 911 -2256 2021 -1162 2045 -1134 2047 -1164 2047 -1138 2031 -1180 2039 -1182 949 -2190 995 -2214 961 -2228 963 -2198 963 -2214 977 -2212 975 -2210 975 -2208 971 -2200 963 -2210 993 -2184 2075 -1130 2051 -1142 2055 -1136 2047 -1178 965 -2236 933 -2220 975 -2184 999 -2222 967 -2208 969 -2214 979 -2202 2027 -1156 975 -2242 943 -16080 2023 -1162 967 -2220 2057 -1114 2061 -1124 1007 -2242 2025 -1134 2055 -1168 2017 -1138 2075 -1134 2053 -1136 2075 -1130 979 -2214 979 -2174 999 -2182 1001 -2204 977 -2206 1003 -2188 979 -2176 999 -2182 1009 -2176 1009 -2176 1001 -2212 2029 -1116 2091 -1102 2109 -1092 2095 -1126 1001 -2150 1011 -2180 1011 -2180 1009 -2178 1009 -2172 1009 -2166 1001 -2198 2065 -1136 975 -2220 971 -16018 2097 -1166 951 -2240 2009 -1186 2011 -1160 979 -2208 2035 -1134 2053 -1138 2061 -1158 2045 -1152 2029 -1152 2051 -1166 963 -2188 993 -2222 951 -2214 963 -2220 965 -2212 979 -2212 977 -2180 1003 -2202 965 -2218 975 -2216 967 -2188 2061 -1124 2083 -1126 2071 -1130 2059 -1134 993 -2188 979 -2240 947 -2204 979 -2214 971 -2214 973 -2210 971 -2206 2053 -1130 979 -2216 969 -16056 2053 -1134 1001 -2224 2021 -1150 2051 -1154 953 -2240 2045 -1146 2023 -1168 2033 -1144 2065 -1146 2055 -1130 2071 -1160 961 -2192 973 -2190 1005 -2214 975 -2206 967 -2206 975 -2206 967 -2208 975 -2212 967 -2212 979 -2218 977 -2178 2063 -1156 2035 -1160 2061 -1126 2065 -1130 981 -2186 1003 -2210 977 -2208 973 -2202 977 -2200 965 -2248 943 -2206 2039 -1190 941 -48536 65 -7254 263 -68 363 -102 131 -232 263 -264 751 -230 225 -822 397 -634 231 -268 263 -134 267 -64 867 -132 305 -138 67 -100 331 -98 891 -66 455 -66 531 -100 299 -134 897 -98 693 -132 291 -132 333 -98 337 -68 331
|
||||||
@@ -1,27 +1,31 @@
|
|||||||
#include "flipper.pb.h"
|
|
||||||
#include <core/check.h>
|
#include <core/check.h>
|
||||||
#include <core/record.h>
|
#include <core/record.h>
|
||||||
#include "pb_decode.h"
|
|
||||||
#include <rpc/rpc.h>
|
|
||||||
#include "rpc/rpc_i.h"
|
|
||||||
#include "storage.pb.h"
|
|
||||||
#include "storage/filesystem_api_defines.h"
|
|
||||||
#include "storage/storage.h"
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "../minunit.h"
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <pb.h>
|
|
||||||
#include <pb_encode.h>
|
|
||||||
#include <m-list.h>
|
|
||||||
#include <lib/toolbox/md5_calc.h>
|
|
||||||
#include <lib/toolbox/path.h>
|
|
||||||
#include <cli/cli.h>
|
|
||||||
#include <loader/loader.h>
|
|
||||||
#include <protobuf_version.h>
|
|
||||||
|
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
#include <semphr.h>
|
#include <semphr.h>
|
||||||
|
|
||||||
|
#include <rpc/rpc.h>
|
||||||
|
#include <rpc/rpc_i.h>
|
||||||
|
#include <cli/cli.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <loader/loader.h>
|
||||||
|
#include <storage/filesystem_api_defines.h>
|
||||||
|
|
||||||
|
#include <lib/toolbox/md5_calc.h>
|
||||||
|
#include <lib/toolbox/path.h>
|
||||||
|
|
||||||
|
#include <m-list.h>
|
||||||
|
#include "../minunit.h"
|
||||||
|
|
||||||
|
#include <protobuf_version.h>
|
||||||
|
#include <pb.h>
|
||||||
|
#include <pb_encode.h>
|
||||||
|
#include <pb_decode.h>
|
||||||
|
#include <storage.pb.h>
|
||||||
|
#include <flipper.pb.h>
|
||||||
|
|
||||||
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
LIST_DEF(MsgList, PB_Main, M_POD_OPLIST)
|
||||||
#define M_OPL_MsgList_t() LIST_OPLIST(MsgList)
|
#define M_OPL_MsgList_t() LIST_OPLIST(MsgList)
|
||||||
|
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ static bool write_file_13DA(Storage* storage, const char* path) {
|
|||||||
File* file = storage_file_alloc(storage);
|
File* file = storage_file_alloc(storage);
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
if(storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS)) {
|
||||||
result = storage_file_write(file, "13DA", 4) == 4;
|
result = (storage_file_write(file, "13DA", 4) == 4);
|
||||||
}
|
}
|
||||||
storage_file_close(file);
|
storage_file_close(file);
|
||||||
storage_file_free(file);
|
storage_file_free(file);
|
||||||
|
|||||||
@@ -115,6 +115,66 @@ MU_TEST(storage_file_open_close) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool storage_file_read_write_test(File* file, uint8_t* data, size_t test_size) {
|
||||||
|
const char* filename = UNIT_TESTS_PATH("storage_chunk.test");
|
||||||
|
|
||||||
|
// fill with pattern
|
||||||
|
for(size_t i = 0; i < test_size; i++) {
|
||||||
|
data[i] = (i % 113);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
do {
|
||||||
|
if(!storage_file_open(file, filename, FSAM_WRITE, FSOM_CREATE_ALWAYS)) break;
|
||||||
|
if(test_size != storage_file_write(file, data, test_size)) break;
|
||||||
|
storage_file_close(file);
|
||||||
|
|
||||||
|
// reset data
|
||||||
|
memset(data, 0, test_size);
|
||||||
|
|
||||||
|
if(!storage_file_open(file, filename, FSAM_READ, FSOM_OPEN_EXISTING)) break;
|
||||||
|
if(test_size != storage_file_read(file, data, test_size)) break;
|
||||||
|
storage_file_close(file);
|
||||||
|
|
||||||
|
// check that data is correct
|
||||||
|
for(size_t i = 0; i < test_size; i++) {
|
||||||
|
if(data[i] != (i % 113)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(storage_file_read_write_64k) {
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
File* file = storage_file_alloc(storage);
|
||||||
|
|
||||||
|
size_t size_1k = 1024;
|
||||||
|
size_t size_64k = size_1k + size_1k * 63;
|
||||||
|
size_t size_65k = size_64k + size_1k;
|
||||||
|
size_t size_max = size_65k + 8;
|
||||||
|
|
||||||
|
size_t max_ram_block = memmgr_heap_get_max_free_block();
|
||||||
|
|
||||||
|
if(max_ram_block < size_max) {
|
||||||
|
mu_warn("Not enough RAM for >64k block test");
|
||||||
|
} else {
|
||||||
|
uint8_t* data = malloc(size_max);
|
||||||
|
mu_check(storage_file_read_write_test(file, data, size_1k));
|
||||||
|
mu_check(storage_file_read_write_test(file, data, size_64k));
|
||||||
|
mu_check(storage_file_read_write_test(file, data, size_65k));
|
||||||
|
mu_check(storage_file_read_write_test(file, data, size_max));
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
storage_file_free(file);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(storage_file) {
|
MU_TEST_SUITE(storage_file) {
|
||||||
storage_file_open_lock_setup();
|
storage_file_open_lock_setup();
|
||||||
MU_RUN_TEST(storage_file_open_close);
|
MU_RUN_TEST(storage_file_open_close);
|
||||||
@@ -122,6 +182,10 @@ MU_TEST_SUITE(storage_file) {
|
|||||||
storage_file_open_lock_teardown();
|
storage_file_open_lock_teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(storage_file_64k) {
|
||||||
|
MU_RUN_TEST(storage_file_read_write_64k);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(storage_dir_open_close) {
|
MU_TEST(storage_dir_open_close) {
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
File* file;
|
File* file;
|
||||||
@@ -640,6 +704,7 @@ MU_TEST_SUITE(test_md5_calc_suite) {
|
|||||||
|
|
||||||
int run_minunit_test_storage() {
|
int run_minunit_test_storage() {
|
||||||
MU_RUN_SUITE(storage_file);
|
MU_RUN_SUITE(storage_file);
|
||||||
|
MU_RUN_SUITE(storage_file_64k);
|
||||||
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_data_path);
|
||||||
|
|||||||
@@ -229,17 +229,17 @@ typedef struct {
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
} SubGhzHalAsyncTxTest;
|
} SubGhzHalAsyncTxTest;
|
||||||
|
|
||||||
#define SUBGHZ_HAL_TEST_DURATION 1
|
#define SUBGHZ_HAL_TEST_DURATION 3
|
||||||
|
|
||||||
static LevelDuration subghz_hal_async_tx_test_yield(void* context) {
|
static LevelDuration subghz_hal_async_tx_test_yield(void* context) {
|
||||||
SubGhzHalAsyncTxTest* test = context;
|
SubGhzHalAsyncTxTest* test = context;
|
||||||
bool is_odd = test->pos % 2;
|
bool is_odd = test->pos % 2;
|
||||||
|
|
||||||
if(test->type == SubGhzHalAsyncTxTestTypeNormal) {
|
if(test->type == SubGhzHalAsyncTxTestTypeNormal) {
|
||||||
if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
@@ -249,36 +249,36 @@ static LevelDuration subghz_hal_async_tx_test_yield(void* context) {
|
|||||||
if(test->pos == 0) {
|
if(test->pos == 0) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
furi_crash("Yield after reset");
|
furi_crash("Yield after reset");
|
||||||
}
|
}
|
||||||
} else if(test->type == SubGhzHalAsyncTxTestTypeInvalidMid) {
|
} else if(test->type == SubGhzHalAsyncTxTestTypeInvalidMid) {
|
||||||
if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
furi_crash("Yield after reset");
|
furi_crash("Yield after reset");
|
||||||
}
|
}
|
||||||
} else if(test->type == SubGhzHalAsyncTxTestTypeInvalidEnd) {
|
} else if(test->type == SubGhzHalAsyncTxTestTypeInvalidEnd) {
|
||||||
if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL - 1) {
|
if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL - 1) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(!is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL * 8) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
@@ -292,20 +292,20 @@ static LevelDuration subghz_hal_async_tx_test_yield(void* context) {
|
|||||||
furi_crash("Yield after reset");
|
furi_crash("Yield after reset");
|
||||||
}
|
}
|
||||||
} else if(test->type == SubGhzHalAsyncTxTestTypeResetMid) {
|
} else if(test->type == SubGhzHalAsyncTxTestTypeResetMid) {
|
||||||
if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_HALF / 2) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
furi_crash("Yield after reset");
|
furi_crash("Yield after reset");
|
||||||
}
|
}
|
||||||
} else if(test->type == SubGhzHalAsyncTxTestTypeResetEnd) {
|
} else if(test->type == SubGhzHalAsyncTxTestTypeResetEnd) {
|
||||||
if(test->pos < API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL - 1) {
|
if(test->pos < FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
return level_duration_make(is_odd, SUBGHZ_HAL_TEST_DURATION);
|
||||||
} else if(test->pos == API_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL - 1) {
|
} else if(test->pos == FURI_HAL_SUBGHZ_ASYNC_TX_BUFFER_FULL) {
|
||||||
test->pos++;
|
test->pos++;
|
||||||
return level_duration_reset();
|
return level_duration_reset();
|
||||||
} else {
|
} else {
|
||||||
@@ -324,6 +324,7 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) {
|
|||||||
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)) {
|
||||||
|
mu_warn("SubGHZ transmission is prohibited");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,6 +332,8 @@ bool subghz_hal_async_tx_test_run(SubGhzHalAsyncTxTestType type) {
|
|||||||
|
|
||||||
while(!furi_hal_subghz_is_async_tx_complete()) {
|
while(!furi_hal_subghz_is_async_tx_complete()) {
|
||||||
if(furi_hal_cortex_timer_is_expired(timer)) {
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
||||||
|
furi_hal_subghz_stop_async_tx();
|
||||||
|
furi_hal_subghz_sleep();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
furi_delay_ms(10);
|
furi_delay_ms(10);
|
||||||
@@ -652,6 +655,13 @@ MU_TEST(subghz_decoder_kinggates_stylo4k_test) {
|
|||||||
"Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n");
|
"Test decoder " SUBGHZ_PROTOCOL_KINGGATES_STYLO_4K_NAME " error\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(subghz_decoder_mastercode_test) {
|
||||||
|
mu_assert(
|
||||||
|
subghz_decoder_test(
|
||||||
|
EXT_PATH("unit_tests/subghz/mastercode_raw.sub"), SUBGHZ_PROTOCOL_MASTERCODE_NAME),
|
||||||
|
"Test decoder " SUBGHZ_PROTOCOL_MASTERCODE_NAME " error\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
//test encoders
|
//test encoders
|
||||||
MU_TEST(subghz_encoder_princeton_test) {
|
MU_TEST(subghz_encoder_princeton_test) {
|
||||||
mu_assert(
|
mu_assert(
|
||||||
@@ -803,6 +813,12 @@ MU_TEST(subghz_encoder_dooya_test) {
|
|||||||
"Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
|
"Test encoder " SUBGHZ_PROTOCOL_DOOYA_NAME " error\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(subghz_encoder_mastercode_test) {
|
||||||
|
mu_assert(
|
||||||
|
subghz_encoder_test(EXT_PATH("unit_tests/subghz/mastercode.sub")),
|
||||||
|
"Test encoder " SUBGHZ_PROTOCOL_MASTERCODE_NAME " error\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(subghz_random_test) {
|
MU_TEST(subghz_random_test) {
|
||||||
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
mu_assert(subghz_decode_random_test(TEST_RANDOM_DIR_NAME), "Random test error\r\n");
|
||||||
}
|
}
|
||||||
@@ -853,6 +869,7 @@ MU_TEST_SUITE(subghz) {
|
|||||||
MU_RUN_TEST(subghz_decoder_alutech_at_4n_test);
|
MU_RUN_TEST(subghz_decoder_alutech_at_4n_test);
|
||||||
MU_RUN_TEST(subghz_decoder_nice_one_test);
|
MU_RUN_TEST(subghz_decoder_nice_one_test);
|
||||||
MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test);
|
MU_RUN_TEST(subghz_decoder_kinggates_stylo4k_test);
|
||||||
|
MU_RUN_TEST(subghz_decoder_mastercode_test);
|
||||||
|
|
||||||
MU_RUN_TEST(subghz_encoder_princeton_test);
|
MU_RUN_TEST(subghz_encoder_princeton_test);
|
||||||
MU_RUN_TEST(subghz_encoder_came_test);
|
MU_RUN_TEST(subghz_encoder_came_test);
|
||||||
@@ -879,6 +896,7 @@ MU_TEST_SUITE(subghz) {
|
|||||||
MU_RUN_TEST(subghz_encoder_smc5326_test);
|
MU_RUN_TEST(subghz_encoder_smc5326_test);
|
||||||
MU_RUN_TEST(subghz_encoder_holtek_ht12x_test);
|
MU_RUN_TEST(subghz_encoder_holtek_ht12x_test);
|
||||||
MU_RUN_TEST(subghz_encoder_dooya_test);
|
MU_RUN_TEST(subghz_encoder_dooya_test);
|
||||||
|
MU_RUN_TEST(subghz_encoder_mastercode_test);
|
||||||
|
|
||||||
MU_RUN_TEST(subghz_random_test);
|
MU_RUN_TEST(subghz_random_test);
|
||||||
subghz_test_deinit();
|
subghz_test_deinit();
|
||||||
|
|||||||
@@ -26,9 +26,11 @@ int run_minunit_test_protocol_dict();
|
|||||||
int run_minunit_test_lfrfid_protocols();
|
int run_minunit_test_lfrfid_protocols();
|
||||||
int run_minunit_test_nfc();
|
int run_minunit_test_nfc();
|
||||||
int run_minunit_test_bit_lib();
|
int run_minunit_test_bit_lib();
|
||||||
|
int run_minunit_test_datetime();
|
||||||
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();
|
int run_minunit_test_dialogs_file_browser_options();
|
||||||
|
int run_minunit_test_expansion();
|
||||||
|
|
||||||
typedef int (*UnitTestEntry)();
|
typedef int (*UnitTestEntry)();
|
||||||
|
|
||||||
@@ -56,10 +58,12 @@ const UnitTest unit_tests[] = {
|
|||||||
{.name = "protocol_dict", .entry = run_minunit_test_protocol_dict},
|
{.name = "protocol_dict", .entry = run_minunit_test_protocol_dict},
|
||||||
{.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols},
|
{.name = "lfrfid", .entry = run_minunit_test_lfrfid_protocols},
|
||||||
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
{.name = "bit_lib", .entry = run_minunit_test_bit_lib},
|
||||||
|
{.name = "datetime", .entry = run_minunit_test_datetime},
|
||||||
{.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",
|
{.name = "dialogs_file_browser_options",
|
||||||
.entry = run_minunit_test_dialogs_file_browser_options},
|
.entry = run_minunit_test_dialogs_file_browser_options},
|
||||||
|
{.name = "expansion", .entry = run_minunit_test_expansion},
|
||||||
};
|
};
|
||||||
|
|
||||||
void minunit_print_progress() {
|
void minunit_print_progress() {
|
||||||
@@ -78,6 +82,16 @@ void minunit_print_fail(const char* str) {
|
|||||||
printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str);
|
printf(_FURI_LOG_CLR_E "%s\r\n" _FURI_LOG_CLR_RESET, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void minunit_printf_warning(const char* format, ...) {
|
||||||
|
FuriString* str = furi_string_alloc();
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
furi_string_vprintf(str, format, args);
|
||||||
|
va_end(args);
|
||||||
|
printf(_FURI_LOG_CLR_W "%s\r\n" _FURI_LOG_CLR_RESET, furi_string_get_cstr(str));
|
||||||
|
furi_string_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
void unit_tests_cli(Cli* cli, FuriString* args, void* context) {
|
||||||
UNUSED(cli);
|
UNUSED(cli);
|
||||||
UNUSED(args);
|
UNUSED(args);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="USB Mouse",
|
name="USB Mouse",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="usb_mouse_app",
|
entry_point="usb_mouse_app",
|
||||||
cdefines=["APP_USB_MOUSE"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=60,
|
order=60,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="USB Test",
|
name="USB Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="usb_test_app",
|
entry_point="usb_test_app",
|
||||||
cdefines=["APP_USB_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=50,
|
order=50,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ App(
|
|||||||
name="Vibro Test",
|
name="Vibro Test",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.DEBUG,
|
||||||
entry_point="vibro_test_app",
|
entry_point="vibro_test_app",
|
||||||
cdefines=["APP_VIBRO_TEST"],
|
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=20,
|
order=20,
|
||||||
|
|||||||
@@ -17,18 +17,18 @@
|
|||||||
|
|
||||||
#define TAG "SubGhzDeviceCc1101Ext"
|
#define TAG "SubGhzDeviceCc1101Ext"
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO &gpio_ext_pb2
|
#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_E07_AMP_GPIO &gpio_ext_pc3
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
||||||
|
|
||||||
/* DMA Channels definition */
|
/* DMA Channels definition */
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA DMA2
|
#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_CH3_CHANNEL (LL_DMA_CHANNEL_3)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL LL_DMA_CHANNEL_4
|
#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_CH5_CHANNEL (LL_DMA_CHANNEL_5)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ FuriHalInterruptIdDma2Ch3
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ (FuriHalInterruptIdDma2Ch3)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \
|
||||||
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \
|
||||||
@@ -37,10 +37,10 @@
|
|||||||
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL
|
||||||
|
|
||||||
/** Low level buffer dimensions and guard times */
|
/** 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_FULL (256u)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF \
|
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_HALF \
|
||||||
(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL / 2)
|
(SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL / 2)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME 999 << 1
|
#define SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME (999u >> 1)
|
||||||
|
|
||||||
/** SubGhz state */
|
/** SubGhz state */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -48,7 +48,6 @@ typedef enum {
|
|||||||
SubGhzDeviceCC1101ExtStateIdle, /**< Idle, energy save mode */
|
SubGhzDeviceCC1101ExtStateIdle, /**< Idle, energy save mode */
|
||||||
SubGhzDeviceCC1101ExtStateAsyncRx, /**< Async RX started */
|
SubGhzDeviceCC1101ExtStateAsyncRx, /**< Async RX started */
|
||||||
SubGhzDeviceCC1101ExtStateAsyncTx, /**< Async TX started, DMA and timer is on */
|
SubGhzDeviceCC1101ExtStateAsyncTx, /**< Async TX started, DMA and timer is on */
|
||||||
SubGhzDeviceCC1101ExtStateAsyncTxEnd, /**< Async TX complete, cleanup needed */
|
|
||||||
} SubGhzDeviceCC1101ExtState;
|
} SubGhzDeviceCC1101ExtState;
|
||||||
|
|
||||||
/** SubGhz regulation, receive transmission on the current frequency for the
|
/** SubGhz regulation, receive transmission on the current frequency for the
|
||||||
@@ -58,13 +57,25 @@ typedef enum {
|
|||||||
SubGhzDeviceCC1101ExtRegulationTxRx, /**TxRx*/
|
SubGhzDeviceCC1101ExtRegulationTxRx, /**TxRx*/
|
||||||
} SubGhzDeviceCC1101ExtRegulation;
|
} SubGhzDeviceCC1101ExtRegulation;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateIdle,
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateReset,
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateRun,
|
||||||
|
} SubGhzDeviceCC1101ExtAsyncTxMiddlewareState;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTxMiddlewareState state;
|
||||||
|
bool is_odd_level;
|
||||||
|
uint32_t adder_duration;
|
||||||
|
} SubGhzDeviceCC1101ExtAsyncTxMiddleware;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t* buffer;
|
uint32_t* buffer;
|
||||||
LevelDuration carry_ld;
|
|
||||||
SubGhzDeviceCC1101ExtCallback callback;
|
SubGhzDeviceCC1101ExtCallback callback;
|
||||||
void* callback_context;
|
void* callback_context;
|
||||||
uint32_t gpio_tx_buff[2];
|
uint32_t gpio_tx_buff[2];
|
||||||
uint32_t debug_gpio_buff[2];
|
uint32_t debug_gpio_buff[2];
|
||||||
|
SubGhzDeviceCC1101ExtAsyncTxMiddleware middleware;
|
||||||
} SubGhzDeviceCC1101ExtAsyncTx;
|
} SubGhzDeviceCC1101ExtAsyncTx;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -283,8 +294,8 @@ void subghz_device_cc1101_ext_dump_state() {
|
|||||||
|
|
||||||
void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data) {
|
void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data) {
|
||||||
//load config
|
//load config
|
||||||
|
subghz_device_cc1101_ext_reset();
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
uint8_t pa[8] = {0};
|
uint8_t pa[8] = {0};
|
||||||
while(preset_data[i]) {
|
while(preset_data[i]) {
|
||||||
@@ -313,8 +324,8 @@ void subghz_device_cc1101_ext_load_custom_preset(const uint8_t* preset_data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void subghz_device_cc1101_ext_load_registers(const uint8_t* data) {
|
void subghz_device_cc1101_ext_load_registers(const uint8_t* data) {
|
||||||
|
subghz_device_cc1101_ext_reset();
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
while(data[i]) {
|
while(data[i]) {
|
||||||
cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, data[i], data[i + 1]);
|
cc1101_write_reg(subghz_device_cc1101_ext->spi_bus_handle, data[i], data[i + 1]);
|
||||||
@@ -396,6 +407,7 @@ void subghz_device_cc1101_ext_reset() {
|
|||||||
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
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_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_reset(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
// Warning: push pull cc1101 clock output on GD0
|
||||||
cc1101_write_reg(
|
cc1101_write_reg(
|
||||||
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_IOCFG0, CC1101IocfgHighImpedance);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
@@ -404,6 +416,9 @@ void subghz_device_cc1101_ext_reset() {
|
|||||||
void subghz_device_cc1101_ext_idle() {
|
void subghz_device_cc1101_ext_idle() {
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_idle(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
//waiting for the chip to switch to IDLE mode
|
||||||
|
furi_check(cc1101_wait_status_state(
|
||||||
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101StateIDLE, 10000));
|
||||||
furi_hal_spi_release(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) {
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
||||||
@@ -413,6 +428,9 @@ void subghz_device_cc1101_ext_idle() {
|
|||||||
void subghz_device_cc1101_ext_rx() {
|
void subghz_device_cc1101_ext_rx() {
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_rx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
//waiting for the chip to switch to Rx mode
|
||||||
|
furi_check(
|
||||||
|
cc1101_wait_status_state(subghz_device_cc1101_ext->spi_bus_handle, CC1101StateRX, 10000));
|
||||||
furi_hal_spi_release(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) {
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 0);
|
||||||
@@ -423,6 +441,9 @@ bool subghz_device_cc1101_ext_tx() {
|
|||||||
if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false;
|
if(subghz_device_cc1101_ext->regulation != SubGhzDeviceCC1101ExtRegulationTxRx) return false;
|
||||||
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_acquire(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
cc1101_switch_to_tx(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
|
//waiting for the chip to switch to Tx mode
|
||||||
|
furi_check(
|
||||||
|
cc1101_wait_status_state(subghz_device_cc1101_ext->spi_bus_handle, CC1101StateTX, 10000));
|
||||||
furi_hal_spi_release(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) {
|
if(subghz_device_cc1101_ext->power_amp) {
|
||||||
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 1);
|
furi_hal_gpio_write(SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO, 1);
|
||||||
@@ -527,7 +548,8 @@ static bool subghz_device_cc1101_ext_stop_debug() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_device_cc1101_ext_capture_ISR() {
|
static void subghz_device_cc1101_ext_capture_ISR(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
if(!furi_hal_gpio_read(subghz_device_cc1101_ext->g0_pin)) {
|
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_rx.capture_callback) {
|
||||||
if(subghz_device_cc1101_ext->async_mirror_pin != NULL)
|
if(subghz_device_cc1101_ext->async_mirror_pin != NULL)
|
||||||
@@ -616,57 +638,98 @@ void subghz_device_cc1101_ext_stop_async_rx() {
|
|||||||
furi_hal_gpio_init(subghz_device_cc1101_ext->g0_pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
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) {
|
void subghz_device_cc1101_ext_async_tx_middleware_idle(
|
||||||
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
SubGhzDeviceCC1101ExtAsyncTxMiddleware* middleware) {
|
||||||
while(samples > 0) {
|
middleware->state = SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateIdle;
|
||||||
bool is_odd = samples % 2;
|
middleware->is_odd_level = false;
|
||||||
LevelDuration ld;
|
middleware->adder_duration = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
||||||
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)) {
|
static inline uint32_t subghz_device_cc1101_ext_async_tx_middleware_get_duration(
|
||||||
*buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
SubGhzDeviceCC1101ExtAsyncTxMiddleware* middleware,
|
||||||
buffer++;
|
SubGhzDeviceCC1101ExtCallback callback) {
|
||||||
samples--;
|
uint32_t ret = 0;
|
||||||
} else if(level_duration_is_reset(ld)) {
|
bool is_level = false;
|
||||||
|
|
||||||
|
if(middleware->state == SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateReset) return 0;
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
LevelDuration ld = callback(subghz_device_cc1101_ext->async_tx.callback_context);
|
||||||
|
if(level_duration_is_reset(ld)) {
|
||||||
|
middleware->state = SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateReset;
|
||||||
|
if(!middleware->is_odd_level) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return middleware->adder_duration;
|
||||||
|
}
|
||||||
|
} else if(level_duration_is_wait(ld)) {
|
||||||
|
middleware->is_odd_level = !middleware->is_odd_level;
|
||||||
|
ret = middleware->adder_duration + SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
||||||
|
middleware->adder_duration = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_level = level_duration_get_level(ld);
|
||||||
|
|
||||||
|
if(middleware->state == SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateIdle) {
|
||||||
|
if(is_level != middleware->is_odd_level) {
|
||||||
|
middleware->state = SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateRun;
|
||||||
|
middleware->is_odd_level = is_level;
|
||||||
|
middleware->adder_duration = level_duration_get_duration(ld);
|
||||||
|
return SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(middleware->state == SubGhzDeviceCC1101ExtAsyncTxMiddlewareStateRun) {
|
||||||
|
if(is_level == middleware->is_odd_level) {
|
||||||
|
middleware->adder_duration += level_duration_get_duration(ld);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
middleware->is_odd_level = is_level;
|
||||||
|
ret = middleware->adder_duration;
|
||||||
|
middleware->adder_duration = level_duration_get_duration(ld);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
volatile uint32_t duration = subghz_device_cc1101_ext_async_tx_middleware_get_duration(
|
||||||
|
&subghz_device_cc1101_ext->async_tx.middleware,
|
||||||
|
subghz_device_cc1101_ext->async_tx.callback);
|
||||||
|
if(duration == 0) {
|
||||||
*buffer = 0;
|
*buffer = 0;
|
||||||
buffer++;
|
buffer++;
|
||||||
samples--;
|
samples--;
|
||||||
LL_DMA_DisableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
LL_DMA_DisableIT_HT(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
LL_DMA_DisableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
LL_DMA_DisableIT_TC(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF);
|
||||||
LL_TIM_EnableIT_UPDATE(TIM17);
|
if(LL_DMA_IsActiveFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) {
|
||||||
|
LL_DMA_ClearFlag_HT3(SUBGHZ_DEVICE_CC1101_EXT_DMA);
|
||||||
|
}
|
||||||
|
if(LL_DMA_IsActiveFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA)) {
|
||||||
|
LL_DMA_ClearFlag_TC3(SUBGHZ_DEVICE_CC1101_EXT_DMA);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
bool level = level_duration_get_level(ld);
|
// Lowest possible value is 4us
|
||||||
|
if(duration < 4) duration = 4;
|
||||||
// Inject guard time if level is incorrect
|
// Divide by 2 since timer resolution is 2us
|
||||||
if(is_odd != level) {
|
// Subtract 1 since we counting from 0
|
||||||
*buffer = SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_GUARD_TIME;
|
*buffer = (duration >> 1) - 1;
|
||||||
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++;
|
buffer++;
|
||||||
samples--;
|
samples--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_device_cc1101_ext_async_tx_dma_isr() {
|
static void subghz_device_cc1101_ext_async_tx_dma_isr(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
||||||
|
|
||||||
#if SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL == LL_DMA_CHANNEL_3
|
#if SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL == LL_DMA_CHANNEL_3
|
||||||
@@ -688,20 +751,6 @@ static void subghz_device_cc1101_ext_async_tx_dma_isr() {
|
|||||||
#endif
|
#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) {
|
bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callback, void* context) {
|
||||||
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle);
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateIdle);
|
||||||
furi_assert(callback);
|
furi_assert(callback);
|
||||||
@@ -730,7 +779,7 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
|||||||
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF,
|
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF,
|
||||||
LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
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_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD |
|
||||||
LL_DMA_MODE_NORMAL);
|
LL_DMA_PRIORITY_VERYHIGH);
|
||||||
LL_DMA_SetDataLength(
|
LL_DMA_SetDataLength(
|
||||||
SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL);
|
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_SetPeriphRequest(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF, LL_DMAMUX_REQ_TIM17_UP);
|
||||||
@@ -746,16 +795,15 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
|||||||
|
|
||||||
// Configure TIM
|
// Configure TIM
|
||||||
// Set the timer resolution to 2 us
|
// Set the timer resolution to 2 us
|
||||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
|
||||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
|
||||||
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||||
|
LL_TIM_SetAutoReload(TIM17, 500);
|
||||||
|
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||||
LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL);
|
LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||||
LL_TIM_DisableARRPreload(TIM17);
|
LL_TIM_DisableARRPreload(TIM17);
|
||||||
|
|
||||||
furi_hal_interrupt_set_isr(
|
subghz_device_cc1101_ext_async_tx_middleware_idle(
|
||||||
FuriHalInterruptIdTim1TrgComTim17, subghz_device_cc1101_ext_async_tx_timer_isr, NULL);
|
&subghz_device_cc1101_ext->async_tx.middleware);
|
||||||
|
|
||||||
subghz_device_cc1101_ext_async_tx_refill(
|
subghz_device_cc1101_ext_async_tx_refill(
|
||||||
subghz_device_cc1101_ext->async_tx.buffer, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL);
|
subghz_device_cc1101_ext->async_tx.buffer, SUBGHZ_DEVICE_CC1101_EXT_ASYNC_TX_BUFFER_FULL);
|
||||||
|
|
||||||
@@ -801,7 +849,6 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
|||||||
|
|
||||||
// Start counter
|
// Start counter
|
||||||
LL_TIM_EnableDMAReq_UPDATE(TIM17);
|
LL_TIM_EnableDMAReq_UPDATE(TIM17);
|
||||||
LL_TIM_GenerateEvent_UPDATE(TIM17);
|
|
||||||
|
|
||||||
subghz_device_cc1101_ext_tx();
|
subghz_device_cc1101_ext_tx();
|
||||||
|
|
||||||
@@ -812,19 +859,22 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_device_cc1101_ext_is_async_tx_complete() {
|
bool subghz_device_cc1101_ext_is_async_tx_complete() {
|
||||||
return subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd;
|
return (
|
||||||
|
(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx) &&
|
||||||
|
(LL_TIM_GetAutoReload(TIM17) == 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_device_cc1101_ext_stop_async_tx() {
|
void subghz_device_cc1101_ext_stop_async_tx() {
|
||||||
furi_assert(
|
furi_assert(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx);
|
||||||
subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx ||
|
|
||||||
subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTxEnd);
|
|
||||||
|
|
||||||
// Shutdown radio
|
// Shutdown radio
|
||||||
subghz_device_cc1101_ext_idle();
|
subghz_device_cc1101_ext_idle();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Deinitialize Timer
|
// Deinitialize Timer
|
||||||
FURI_CRITICAL_ENTER();
|
|
||||||
furi_hal_bus_disable(FuriHalBusTIM17);
|
furi_hal_bus_disable(FuriHalBusTIM17);
|
||||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdTim1TrgComTim17, NULL, NULL);
|
furi_hal_interrupt_set_isr(FuriHalInterruptIdTim1TrgComTim17, NULL, NULL);
|
||||||
|
|
||||||
@@ -833,17 +883,11 @@ void subghz_device_cc1101_ext_stop_async_tx() {
|
|||||||
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_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);
|
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
|
// Stop debug
|
||||||
if(subghz_device_cc1101_ext_stop_debug()) {
|
if(subghz_device_cc1101_ext_stop_debug()) {
|
||||||
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF);
|
LL_DMA_DisableChannel(SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_DEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
FURI_CRITICAL_EXIT();
|
|
||||||
|
|
||||||
free(subghz_device_cc1101_ext->async_tx.buffer);
|
free(subghz_device_cc1101_ext->async_tx.buffer);
|
||||||
|
|
||||||
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle;
|
subghz_device_cc1101_ext->state = SubGhzDeviceCC1101ExtStateIdle;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* @file furi_hal_subghz.h
|
* @file cc1101_ext.h
|
||||||
* SubGhz HAL API
|
* @brief External CC1101 transceiver access API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
# Apps Assets folder Example
|
# Apps Assets folder Example {#example_app_assets}
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Source code for this example can be found [here](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/examples/example_apps_assets).
|
||||||
|
|
||||||
## What is the Apps Assets Folder?
|
## What is the Apps Assets Folder?
|
||||||
|
|
||||||
The **Apps Assets** folder is a folder where external applications unpack their assets.
|
The **Apps Assets** folder is a folder where external applications unpack their assets.
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @file example_apps_assets.c
|
||||||
|
* @brief Application assets example.
|
||||||
|
*/
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <toolbox/stream/stream.h>
|
#include <toolbox/stream/stream.h>
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
# Apps Data folder Example
|
# Apps Data folder Example {#example_app_data}
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Source code for this example can be found [here](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/examples/example_apps_data).
|
||||||
|
|
||||||
## What is the Apps Data Folder?
|
## 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 **Apps Data** folder is a folder used to store data for external apps that are not part of the main firmware.
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @file example_apps_data.c
|
||||||
|
* @brief Application data example.
|
||||||
|
*/
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
|||||||
11
applications/examples/example_ble_beacon/application.fam
Normal file
11
applications/examples/example_ble_beacon/application.fam
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
App(
|
||||||
|
appid="example_ble_beacon",
|
||||||
|
name="Example: BLE Beacon",
|
||||||
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
|
entry_point="ble_beacon_app",
|
||||||
|
requires=["gui"],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
fap_icon="example_ble_beacon_10px.png",
|
||||||
|
fap_category="Examples",
|
||||||
|
fap_icon_assets="images",
|
||||||
|
)
|
||||||
149
applications/examples/example_ble_beacon/ble_beacon_app.c
Normal file
149
applications/examples/example_ble_beacon/ble_beacon_app.c
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
#include "ble_beacon_app.h"
|
||||||
|
|
||||||
|
#include <extra_beacon.h>
|
||||||
|
#include <furi_hal_version.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define TAG "ble_beacon_app"
|
||||||
|
|
||||||
|
static bool ble_beacon_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
furi_assert(context);
|
||||||
|
BleBeaconApp* app = context;
|
||||||
|
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ble_beacon_app_back_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
BleBeaconApp* app = context;
|
||||||
|
return scene_manager_handle_back_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_beacon_app_tick_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
BleBeaconApp* app = context;
|
||||||
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_beacon_app_restore_beacon_state(BleBeaconApp* app) {
|
||||||
|
// Restore beacon data from service
|
||||||
|
GapExtraBeaconConfig* local_config = &app->beacon_config;
|
||||||
|
const GapExtraBeaconConfig* config = furi_hal_bt_extra_beacon_get_config();
|
||||||
|
if(config) {
|
||||||
|
// We have a config, copy it
|
||||||
|
memcpy(local_config, config, sizeof(app->beacon_config));
|
||||||
|
} else {
|
||||||
|
// No config, set up default values - they will stay until overriden or device is reset
|
||||||
|
local_config->min_adv_interval_ms = 50;
|
||||||
|
local_config->max_adv_interval_ms = 150;
|
||||||
|
|
||||||
|
local_config->adv_channel_map = GapAdvChannelMapAll;
|
||||||
|
local_config->adv_power_level = GapAdvPowerLevel_0dBm;
|
||||||
|
|
||||||
|
local_config->address_type = GapAddressTypePublic;
|
||||||
|
memcpy(
|
||||||
|
local_config->address, furi_hal_version_get_ble_mac(), sizeof(local_config->address));
|
||||||
|
// Modify MAC address to make it different from the one used by the main app
|
||||||
|
local_config->address[0] ^= 0xFF;
|
||||||
|
local_config->address[3] ^= 0xFF;
|
||||||
|
|
||||||
|
furi_check(furi_hal_bt_extra_beacon_set_config(local_config));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get beacon state
|
||||||
|
app->is_beacon_active = furi_hal_bt_extra_beacon_is_active();
|
||||||
|
|
||||||
|
// Restore last beacon data
|
||||||
|
app->beacon_data_len = furi_hal_bt_extra_beacon_get_data(app->beacon_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BleBeaconApp* ble_beacon_app_alloc() {
|
||||||
|
BleBeaconApp* app = malloc(sizeof(BleBeaconApp));
|
||||||
|
|
||||||
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
|
|
||||||
|
app->scene_manager = scene_manager_alloc(&ble_beacon_app_scene_handlers, app);
|
||||||
|
app->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
|
||||||
|
app->status_string = furi_string_alloc();
|
||||||
|
|
||||||
|
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||||
|
view_dispatcher_set_custom_event_callback(
|
||||||
|
app->view_dispatcher, ble_beacon_app_custom_event_callback);
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
app->view_dispatcher, ble_beacon_app_back_event_callback);
|
||||||
|
view_dispatcher_set_tick_event_callback(
|
||||||
|
app->view_dispatcher, ble_beacon_app_tick_event_callback, 100);
|
||||||
|
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||||
|
|
||||||
|
app->submenu = submenu_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, BleBeaconAppViewSubmenu, submenu_get_view(app->submenu));
|
||||||
|
|
||||||
|
app->dialog_ex = dialog_ex_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, BleBeaconAppViewDialog, dialog_ex_get_view(app->dialog_ex));
|
||||||
|
|
||||||
|
app->byte_input = byte_input_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
app->view_dispatcher, BleBeaconAppViewByteInput, byte_input_get_view(app->byte_input));
|
||||||
|
|
||||||
|
ble_beacon_app_restore_beacon_state(app);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ble_beacon_app_free(BleBeaconApp* app) {
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewByteInput);
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewSubmenu);
|
||||||
|
view_dispatcher_remove_view(app->view_dispatcher, BleBeaconAppViewDialog);
|
||||||
|
|
||||||
|
free(app->byte_input);
|
||||||
|
free(app->submenu);
|
||||||
|
free(app->dialog_ex);
|
||||||
|
|
||||||
|
free(app->scene_manager);
|
||||||
|
free(app->view_dispatcher);
|
||||||
|
|
||||||
|
free(app->status_string);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
app->gui = NULL;
|
||||||
|
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ble_beacon_app(void* args) {
|
||||||
|
UNUSED(args);
|
||||||
|
|
||||||
|
BleBeaconApp* app = ble_beacon_app_alloc();
|
||||||
|
|
||||||
|
scene_manager_next_scene(app->scene_manager, BleBeaconAppSceneRunBeacon);
|
||||||
|
|
||||||
|
view_dispatcher_run(app->view_dispatcher);
|
||||||
|
|
||||||
|
ble_beacon_app_free(app);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_update_state(BleBeaconApp* app) {
|
||||||
|
furi_hal_bt_extra_beacon_stop();
|
||||||
|
|
||||||
|
furi_check(furi_hal_bt_extra_beacon_set_config(&app->beacon_config));
|
||||||
|
|
||||||
|
app->beacon_data_len = 0;
|
||||||
|
while((app->beacon_data[app->beacon_data_len] != 0) &&
|
||||||
|
(app->beacon_data_len < sizeof(app->beacon_data))) {
|
||||||
|
app->beacon_data_len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "beacon_data_len: %d", app->beacon_data_len);
|
||||||
|
|
||||||
|
furi_check(furi_hal_bt_extra_beacon_set_data(app->beacon_data, app->beacon_data_len));
|
||||||
|
|
||||||
|
if(app->is_beacon_active) {
|
||||||
|
furi_check(furi_hal_bt_extra_beacon_start());
|
||||||
|
}
|
||||||
|
}
|
||||||
54
applications/examples/example_ble_beacon/ble_beacon_app.h
Normal file
54
applications/examples/example_ble_beacon/ble_beacon_app.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* @file ble_beacon_app.h
|
||||||
|
* @brief BLE beacon example.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "extra_beacon.h"
|
||||||
|
#include <furi.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
|
||||||
|
#include <gui/modules/widget.h>
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/modules/byte_input.h>
|
||||||
|
#include <gui/modules/dialog_ex.h>
|
||||||
|
|
||||||
|
#include <rpc/rpc_app.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
|
#include <furi_hal_bt.h>
|
||||||
|
|
||||||
|
#include "scenes/scenes.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
SceneManager* scene_manager;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
|
||||||
|
Submenu* submenu;
|
||||||
|
ByteInput* byte_input;
|
||||||
|
DialogEx* dialog_ex;
|
||||||
|
|
||||||
|
FuriString* status_string;
|
||||||
|
|
||||||
|
GapExtraBeaconConfig beacon_config;
|
||||||
|
uint8_t beacon_data[EXTRA_BEACON_MAX_DATA_SIZE];
|
||||||
|
uint8_t beacon_data_len;
|
||||||
|
bool is_beacon_active;
|
||||||
|
} BleBeaconApp;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BleBeaconAppViewSubmenu,
|
||||||
|
BleBeaconAppViewByteInput,
|
||||||
|
BleBeaconAppViewDialog,
|
||||||
|
} BleBeaconAppView;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BleBeaconAppCustomEventDataEditResult = 100,
|
||||||
|
} BleBeaconAppCustomEvent;
|
||||||
|
|
||||||
|
void ble_beacon_app_update_state(BleBeaconApp* app);
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 8.7 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
ADD_SCENE(ble_beacon_app, menu, Menu)
|
||||||
|
ADD_SCENE(ble_beacon_app, input_mac_addr, InputMacAddress)
|
||||||
|
ADD_SCENE(ble_beacon_app, input_beacon_data, InputBeaconData)
|
||||||
|
ADD_SCENE(ble_beacon_app, run_beacon, RunBeacon)
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "../ble_beacon_app.h"
|
||||||
|
|
||||||
|
static void ble_beacon_app_scene_add_type_byte_input_callback(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
view_dispatcher_send_custom_event(
|
||||||
|
ble_beacon->view_dispatcher, BleBeaconAppCustomEventDataEditResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_input_beacon_data_on_enter(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
byte_input_set_header_text(ble_beacon->byte_input, "Enter beacon data");
|
||||||
|
|
||||||
|
byte_input_set_result_callback(
|
||||||
|
ble_beacon->byte_input,
|
||||||
|
ble_beacon_app_scene_add_type_byte_input_callback,
|
||||||
|
NULL,
|
||||||
|
context,
|
||||||
|
ble_beacon->beacon_data,
|
||||||
|
sizeof(ble_beacon->beacon_data));
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewByteInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_beacon_app_scene_input_beacon_data_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
SceneManager* scene_manager = ble_beacon->scene_manager;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == BleBeaconAppCustomEventDataEditResult) {
|
||||||
|
ble_beacon_app_update_state(ble_beacon);
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_input_beacon_data_on_exit(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
|
||||||
|
byte_input_set_result_callback(ble_beacon->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||||
|
byte_input_set_header_text(ble_beacon->byte_input, NULL);
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#include "../ble_beacon_app.h"
|
||||||
|
|
||||||
|
static void ble_beacon_app_scene_add_type_byte_input_callback(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
view_dispatcher_send_custom_event(
|
||||||
|
ble_beacon->view_dispatcher, BleBeaconAppCustomEventDataEditResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_input_mac_addr_on_enter(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
byte_input_set_header_text(ble_beacon->byte_input, "Enter MAC (reversed)");
|
||||||
|
|
||||||
|
byte_input_set_result_callback(
|
||||||
|
ble_beacon->byte_input,
|
||||||
|
ble_beacon_app_scene_add_type_byte_input_callback,
|
||||||
|
NULL,
|
||||||
|
context,
|
||||||
|
ble_beacon->beacon_config.address,
|
||||||
|
sizeof(ble_beacon->beacon_config.address));
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewByteInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_beacon_app_scene_input_mac_addr_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
SceneManager* scene_manager = ble_beacon->scene_manager;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == BleBeaconAppCustomEventDataEditResult) {
|
||||||
|
ble_beacon_app_update_state(ble_beacon);
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_input_mac_addr_on_exit(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
|
||||||
|
byte_input_set_result_callback(ble_beacon->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||||
|
byte_input_set_header_text(ble_beacon->byte_input, NULL);
|
||||||
|
}
|
||||||
56
applications/examples/example_ble_beacon/scenes/scene_menu.c
Normal file
56
applications/examples/example_ble_beacon/scenes/scene_menu.c
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "../ble_beacon_app.h"
|
||||||
|
|
||||||
|
enum SubmenuIndex {
|
||||||
|
SubmenuIndexSetMac,
|
||||||
|
SubmenuIndexSetData,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ble_beacon_app_scene_menu_submenu_callback(void* context, uint32_t index) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
view_dispatcher_send_custom_event(ble_beacon->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_menu_on_enter(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
Submenu* submenu = ble_beacon->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Set MAC",
|
||||||
|
SubmenuIndexSetMac,
|
||||||
|
ble_beacon_app_scene_menu_submenu_callback,
|
||||||
|
ble_beacon);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Set Data",
|
||||||
|
SubmenuIndexSetData,
|
||||||
|
ble_beacon_app_scene_menu_submenu_callback,
|
||||||
|
ble_beacon);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_beacon_app_scene_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
SceneManager* scene_manager = ble_beacon->scene_manager;
|
||||||
|
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
const uint32_t submenu_index = event.event;
|
||||||
|
if(submenu_index == SubmenuIndexSetMac) {
|
||||||
|
scene_manager_next_scene(scene_manager, BleBeaconAppSceneInputMacAddress);
|
||||||
|
consumed = true;
|
||||||
|
} else if(submenu_index == SubmenuIndexSetData) {
|
||||||
|
scene_manager_next_scene(scene_manager, BleBeaconAppSceneInputBeaconData);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_menu_on_exit(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
submenu_reset(ble_beacon->submenu);
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
#include "../ble_beacon_app.h"
|
||||||
|
#include <example_ble_beacon_icons.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
ble_beacon_app_scene_run_beacon_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
|
||||||
|
view_dispatcher_send_custom_event(ble_beacon->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_status_text(BleBeaconApp* ble_beacon) {
|
||||||
|
DialogEx* dialog_ex = ble_beacon->dialog_ex;
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog_ex, "BLE Beacon Demo", 64, 0, AlignCenter, AlignTop);
|
||||||
|
|
||||||
|
FuriString* status = ble_beacon->status_string;
|
||||||
|
|
||||||
|
furi_string_reset(status);
|
||||||
|
|
||||||
|
furi_string_cat_str(status, "Status: ");
|
||||||
|
if(ble_beacon->is_beacon_active) {
|
||||||
|
furi_string_cat_str(status, "Running\n");
|
||||||
|
} else {
|
||||||
|
furi_string_cat_str(status, "Stopped\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output MAC in reverse order
|
||||||
|
for(int i = sizeof(ble_beacon->beacon_config.address) - 1; i >= 0; i--) {
|
||||||
|
furi_string_cat_printf(status, "%02X", ble_beacon->beacon_config.address[i]);
|
||||||
|
if(i > 0) {
|
||||||
|
furi_string_cat_str(status, ":");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_cat_printf(status, "\nData length: %d", ble_beacon->beacon_data_len);
|
||||||
|
|
||||||
|
dialog_ex_set_text(dialog_ex, furi_string_get_cstr(status), 0, 29, AlignLeft, AlignCenter);
|
||||||
|
|
||||||
|
dialog_ex_set_icon(dialog_ex, 93, 20, &I_lighthouse_35x44);
|
||||||
|
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, "Config");
|
||||||
|
|
||||||
|
dialog_ex_set_center_button_text(dialog_ex, ble_beacon->is_beacon_active ? "Stop" : "Start");
|
||||||
|
|
||||||
|
dialog_ex_set_result_callback(
|
||||||
|
dialog_ex, ble_beacon_app_scene_run_beacon_confirm_dialog_callback);
|
||||||
|
dialog_ex_set_context(dialog_ex, ble_beacon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_run_beacon_on_enter(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
|
||||||
|
update_status_text(ble_beacon);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ble_beacon->view_dispatcher, BleBeaconAppViewDialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_beacon_app_scene_run_beacon_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
SceneManager* scene_manager = ble_beacon->scene_manager;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == DialogExResultLeft) {
|
||||||
|
scene_manager_next_scene(scene_manager, BleBeaconAppSceneMenu);
|
||||||
|
return true;
|
||||||
|
} else if(event.event == DialogExResultCenter) {
|
||||||
|
ble_beacon->is_beacon_active = !ble_beacon->is_beacon_active;
|
||||||
|
ble_beacon_app_update_state(ble_beacon);
|
||||||
|
update_status_text(ble_beacon);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_beacon_app_scene_run_beacon_on_exit(void* context) {
|
||||||
|
BleBeaconApp* ble_beacon = context;
|
||||||
|
UNUSED(ble_beacon);
|
||||||
|
}
|
||||||
30
applications/examples/example_ble_beacon/scenes/scenes.c
Normal file
30
applications/examples/example_ble_beacon/scenes/scenes.c
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "scenes.h"
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||||
|
void (*const ble_beacon_app_on_enter_handlers[])(void*) = {
|
||||||
|
#include "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 ble_beacon_app_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||||
|
#include "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 ble_beacon_app_on_exit_handlers[])(void* context) = {
|
||||||
|
#include "scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Initialize scene handlers configuration structure
|
||||||
|
const SceneManagerHandlers ble_beacon_app_scene_handlers = {
|
||||||
|
.on_enter_handlers = ble_beacon_app_on_enter_handlers,
|
||||||
|
.on_event_handlers = ble_beacon_app_on_event_handlers,
|
||||||
|
.on_exit_handlers = ble_beacon_app_on_exit_handlers,
|
||||||
|
.scene_num = BleBeaconAppSceneNum,
|
||||||
|
};
|
||||||
29
applications/examples/example_ble_beacon/scenes/scenes.h
Normal file
29
applications/examples/example_ble_beacon/scenes/scenes.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
|
// Generate scene id and total number
|
||||||
|
#define ADD_SCENE(prefix, name, id) BleBeaconAppScene##id,
|
||||||
|
typedef enum {
|
||||||
|
#include "scene_config.h"
|
||||||
|
BleBeaconAppSceneNum,
|
||||||
|
} BleBeaconAppScene;
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
extern const SceneManagerHandlers ble_beacon_app_scene_handlers;
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||||
|
#include "scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) \
|
||||||
|
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||||
|
#include "scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||||
|
#include "scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
App(
|
App(
|
||||||
appid="example_custom_font",
|
appid="example_custom_font",
|
||||||
name="Example: custom font",
|
name="Example: custom font",
|
||||||
apptype=FlipperAppType.DEBUG,
|
apptype=FlipperAppType.EXTERNAL,
|
||||||
entry_point="example_custom_font_main",
|
entry_point="example_custom_font_main",
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
fap_category="Debug",
|
fap_category="Examples",
|
||||||
)
|
)
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @file example_custom_font.c
|
||||||
|
* @brief Custom font example.
|
||||||
|
*/
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
@@ -1,11 +1,21 @@
|
|||||||
# Application icons
|
# Application icons {#example_app_images}
|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Source code for this example can be found [here](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/examples/example_images).
|
||||||
|
|
||||||
|
## General principle
|
||||||
|
|
||||||
To use icons, do the following:
|
To use icons, do the following:
|
||||||
* add a line to the application manifest: `fap_icon_assets="folder"`, where `folder` points to the folder where your icons are located
|
|
||||||
* add `#include "application_id_icons.h"` to the application code, where `application_id` is the appid from the manifest
|
* Add a line to the application manifest: `fap_icon_assets="folder"`, where `folder` points to the folder where your icons are located
|
||||||
* every icon in the folder will be available as a `I_icon_name` variable, where `icon_name` is the name of the icon file without the extension
|
* Add `#include "application_id_icons.h"` to the application code, where `application_id` is the appid from the manifest
|
||||||
|
* Every icon in the folder will be available as a `I_icon_name` variable, where `icon_name` is the name of the icon file without the extension
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
We have an application with the following manifest:
|
We have an application with the following manifest:
|
||||||
|
|
||||||
```
|
```
|
||||||
App(
|
App(
|
||||||
appid="example_images",
|
appid="example_images",
|
||||||
@@ -17,6 +27,7 @@ App(
|
|||||||
So the icons are in the `images` folder and will be available in the generated `example_images_icons.h` file.
|
So the icons are in the `images` folder and will be available in the generated `example_images_icons.h` file.
|
||||||
|
|
||||||
The example code is located in `example_images_main.c` and contains the following line:
|
The example code is located in `example_images_main.c` and contains the following line:
|
||||||
|
|
||||||
```
|
```
|
||||||
#include "example_images_icons.h"
|
#include "example_images_icons.h"
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
/**
|
||||||
|
* @file example_images.c
|
||||||
|
* @brief Custom images example.
|
||||||
|
*/
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/**
|
||||||
* An example of a plugin host application.
|
* @file example_plugins.c
|
||||||
|
* @brief Plugin host application example.
|
||||||
|
*
|
||||||
* Loads a single plugin and calls its methods.
|
* Loads a single plugin and calls its methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/**
|
||||||
* An example of an advanced plugin host application.
|
* @file example_plugins_multi.c
|
||||||
|
* @brief Advanced plugin host application example.
|
||||||
|
*
|
||||||
* It uses PluginManager to load all plugins from a directory
|
* It uses PluginManager to load all plugins from a directory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
/* A simple plugin implementing example_plugins application's plugin interface */
|
/**
|
||||||
|
* @file plugin1.c
|
||||||
|
* @brief Plugin example 1.
|
||||||
|
*
|
||||||
|
* A simple plugin implementing example_plugins application's plugin interface
|
||||||
|
*/
|
||||||
|
|
||||||
#include "plugin_interface.h"
|
#include "plugin_interface.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
/* Second plugin implementing example_plugins application's plugin interface */
|
/**
|
||||||
|
* @file plugin2.c
|
||||||
|
* @brief Plugin example 2.
|
||||||
|
*
|
||||||
|
* Second plugin implementing example_plugins application's plugin interface
|
||||||
|
*/
|
||||||
|
|
||||||
#include "plugin_interface.h"
|
#include "plugin_interface.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @file plugin_interface.h
|
||||||
|
* @brief Example plugin interface.
|
||||||
|
*
|
||||||
|
* Common interface between a plugin and host application
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* Common interface between a plugin and host application */
|
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins"
|
#define PLUGIN_APP_ID "example_plugins"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
#pragma once
|
/**
|
||||||
|
* @file app_api.h
|
||||||
/*
|
* @brief Application API example.
|
||||||
|
*
|
||||||
* This file contains an API that is internally implemented by the application
|
* This file contains an API that is internally implemented by the application
|
||||||
* It is also exposed to plugins to allow them to use the application's API.
|
* It is also exposed to plugins to allow them to use the application's API.
|
||||||
*/
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ constexpr HashtableApiInterface applicaton_hashtable_api_interface{
|
|||||||
.resolver_callback = &elf_resolve_from_hashtable,
|
.resolver_callback = &elf_resolve_from_hashtable,
|
||||||
},
|
},
|
||||||
/* pointers to application's API table boundaries */
|
/* pointers to application's API table boundaries */
|
||||||
.table_cbegin = app_api_table.cbegin(),
|
app_api_table.cbegin(),
|
||||||
.table_cend = app_api_table.cend(),
|
app_api_table.cend(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Casting to generic resolver to use in Composite API resolver */
|
/* Casting to generic resolver to use in Composite API resolver */
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ App(
|
|||||||
entry_point="advanced_plugin1_ep",
|
entry_point="advanced_plugin1_ep",
|
||||||
requires=["example_advanced_plugins"],
|
requires=["example_advanced_plugins"],
|
||||||
sources=["plugin1.c"],
|
sources=["plugin1.c"],
|
||||||
|
fal_embedded=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
App(
|
App(
|
||||||
@@ -22,4 +23,5 @@ App(
|
|||||||
entry_point="advanced_plugin2_ep",
|
entry_point="advanced_plugin2_ep",
|
||||||
requires=["example_advanced_plugins"],
|
requires=["example_advanced_plugins"],
|
||||||
sources=["plugin2.c"],
|
sources=["plugin2.c"],
|
||||||
|
fal_embedded=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,10 @@ int32_t example_advanced_plugins_app(void* p) {
|
|||||||
PLUGIN_APP_ID, PLUGIN_API_VERSION, composite_api_resolver_get(resolver));
|
PLUGIN_APP_ID, PLUGIN_API_VERSION, composite_api_resolver_get(resolver));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(plugin_manager_load_all(manager, APP_DATA_PATH("plugins")) != PluginManagerErrorNone) {
|
// For built-in .fals (fal_embedded==True), use APP_ASSETS_PATH
|
||||||
|
// Otherwise, use APP_DATA_PATH
|
||||||
|
if(plugin_manager_load_all(manager, APP_ASSETS_PATH("plugins")) !=
|
||||||
|
PluginManagerErrorNone) {
|
||||||
FURI_LOG_E(TAG, "Failed to load all libs");
|
FURI_LOG_E(TAG, "Failed to load all libs");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/**
|
||||||
|
* @file plugin1.c
|
||||||
|
* @brief Plugin example 1.
|
||||||
|
*
|
||||||
* This plugin uses both firmware's API interface and private application headers.
|
* This plugin uses both firmware's API interface and private application headers.
|
||||||
* It can be loaded by a plugin manager that uses CompoundApiInterface,
|
* It can be loaded by a plugin manager that uses CompoundApiInterface,
|
||||||
* which combines both interfaces.
|
* which combines both interfaces.
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/**
|
||||||
|
* @file plugin2.c
|
||||||
|
* @brief Plugin example 2.
|
||||||
|
*
|
||||||
* This plugin uses both firmware's API interface and private application headers.
|
* This plugin uses both firmware's API interface and private application headers.
|
||||||
* It can be loaded by a plugin manager that uses CompoundApiInterface,
|
* It can be loaded by a plugin manager that uses CompoundApiInterface,
|
||||||
* which combines both interfaces.
|
* which combines both interfaces.
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* @file plugin_interface.h
|
||||||
|
* @brief Example plugin interface.
|
||||||
|
*
|
||||||
|
* Common interface between a plugin and host application
|
||||||
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
/* Common interface between a plugin and host application */
|
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins_advanced"
|
#define PLUGIN_APP_ID "example_plugins_advanced"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
# 1-Wire Thermometer
|
# 1-Wire Thermometer {#example_thermo}
|
||||||
|
|
||||||
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
|
This example application demonstrates the use of the 1-Wire library with a DS18B20 thermometer.
|
||||||
It also covers basic GUI, input handling, threads and localisation.
|
It also covers basic GUI, input handling, threads and localisation.
|
||||||
|
|
||||||
|
## Source code
|
||||||
|
|
||||||
|
Source code for this example can be found [here](https://github.com/flipperdevices/flipperzero-firmware/tree/dev/applications/examples/example_thermo).
|
||||||
|
|
||||||
## Electrical connections
|
## Electrical connections
|
||||||
|
|
||||||
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
|
Before launching the application, connect the sensor to Flipper's external GPIO according to the table below:
|
||||||
| DS18B20 | Flipper |
|
| DS18B20 | Flipper |
|
||||||
| :-----: | :-----: |
|
| :-----: | :-----: |
|
||||||
@@ -15,12 +21,14 @@ Before launching the application, connect the sensor to Flipper's external GPIO
|
|||||||
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
|
*NOTE 2*: For any other pin than 17, connect an external 4.7k pull-up resistor to pin 9.
|
||||||
|
|
||||||
## Launching the application
|
## Launching the application
|
||||||
|
|
||||||
In order to launch this demo, follow the steps below:
|
In order to launch this demo, follow the steps below:
|
||||||
1. Make sure your Flipper has an SD card installed.
|
1. Make sure your Flipper has an SD card installed.
|
||||||
2. Connect your Flipper to the computer via a USB cable.
|
2. Connect your Flipper to the computer via a USB cable.
|
||||||
3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice.
|
3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice.
|
||||||
|
|
||||||
## Changing the data pin
|
## Changing the data pin
|
||||||
|
|
||||||
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
|
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
/*
|
/**
|
||||||
|
* @file example_thermo.c
|
||||||
|
* @brief 1-Wire thermometer example.
|
||||||
|
*
|
||||||
* This file contains an example application that reads and displays
|
* This file contains an example application that reads and displays
|
||||||
* the temperature from a DS18B20 1-wire thermometer.
|
* the temperature from a DS18B20 1-wire thermometer.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "archive_files.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ArchiveAppTypeU2f,
|
ArchiveAppTypeU2f,
|
||||||
ArchiveAppTypeUnknown,
|
ArchiveAppTypeUnknown,
|
||||||
|
|||||||
@@ -153,7 +153,9 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
|||||||
|
|
||||||
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
||||||
|
|
||||||
if(!archive_file_get_array_size(browser) && archive_is_home(browser)) {
|
ArchiveTabEnum tab = archive_get_tab(browser);
|
||||||
|
if(!archive_file_get_array_size(browser) && archive_is_home(browser) &&
|
||||||
|
(tab != ArchiveTabBrowser)) {
|
||||||
archive_switch_tab(browser, TAB_LEFT);
|
archive_switch_tab(browser, TAB_LEFT);
|
||||||
} else {
|
} else {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
@@ -220,7 +222,8 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
|
|||||||
},
|
},
|
||||||
false);
|
false);
|
||||||
|
|
||||||
if((items_cnt == 0) && (archive_is_home(browser))) {
|
ArchiveTabEnum tab = archive_get_tab(browser);
|
||||||
|
if((items_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) {
|
||||||
archive_switch_tab(browser, TAB_LEFT);
|
archive_switch_tab(browser, TAB_LEFT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,11 @@ static const char* known_ext[] = {
|
|||||||
[ArchiveFileTypeBadUsb] = ".txt",
|
[ArchiveFileTypeBadUsb] = ".txt",
|
||||||
[ArchiveFileTypeU2f] = "?",
|
[ArchiveFileTypeU2f] = "?",
|
||||||
[ArchiveFileTypeApplication] = ".fap",
|
[ArchiveFileTypeApplication] = ".fap",
|
||||||
|
[ArchiveFileTypeJS] = ".js",
|
||||||
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
[ArchiveFileTypeUpdateManifest] = ".fuf",
|
||||||
[ArchiveFileTypeFolder] = "?",
|
[ArchiveFileTypeFolder] = "?",
|
||||||
[ArchiveFileTypeUnknown] = "*",
|
[ArchiveFileTypeUnknown] = "*",
|
||||||
|
[ArchiveFileTypeAppOrJs] = ".fap|.js",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const ArchiveFileTypeEnum known_type[] = {
|
static const ArchiveFileTypeEnum known_type[] = {
|
||||||
@@ -47,7 +49,7 @@ static const ArchiveFileTypeEnum known_type[] = {
|
|||||||
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
[ArchiveTabInfrared] = ArchiveFileTypeInfrared,
|
||||||
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
[ArchiveTabBadUsb] = ArchiveFileTypeBadUsb,
|
||||||
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
[ArchiveTabU2f] = ArchiveFileTypeU2f,
|
||||||
[ArchiveTabApplications] = ArchiveFileTypeApplication,
|
[ArchiveTabApplications] = ArchiveFileTypeAppOrJs,
|
||||||
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
[ArchiveTabInternal] = ArchiveFileTypeUnknown,
|
||||||
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
[ArchiveTabBrowser] = ArchiveFileTypeUnknown,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ static bool archive_favorites_read_line(File* file, FuriString* str_result) {
|
|||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
uint16_t read_count = storage_file_read(file, buffer, ARCHIVE_FAV_FILE_BUF_LEN);
|
size_t read_count = storage_file_read(file, buffer, ARCHIVE_FAV_FILE_BUF_LEN);
|
||||||
if(storage_file_get_error(file) != FSE_OK) {
|
if(storage_file_get_error(file) != FSE_OK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint16_t i = 0; i < read_count; i++) {
|
for(size_t i = 0; i < read_count; i++) {
|
||||||
if(buffer[i] == '\n') {
|
if(buffer[i] == '\n') {
|
||||||
uint32_t position = storage_file_tell(file);
|
uint32_t position = storage_file_tell(file);
|
||||||
if(storage_file_get_error(file) != FSE_OK) {
|
if(storage_file_get_error(file) != FSE_OK) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ void archive_set_file_type(ArchiveFile_t* file, const char* path, bool is_folder
|
|||||||
} else {
|
} else {
|
||||||
for(size_t i = 0; i < COUNT_OF(known_ext); i++) {
|
for(size_t i = 0; i < COUNT_OF(known_ext); i++) {
|
||||||
if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue;
|
if((known_ext[i][0] == '?') || (known_ext[i][0] == '*')) continue;
|
||||||
if(furi_string_search(file->path, known_ext[i], 0) != FURI_STRING_FAILURE) {
|
if(furi_string_end_with(file->path, known_ext[i])) {
|
||||||
if(i == ArchiveFileTypeBadUsb) {
|
if(i == ArchiveFileTypeBadUsb) {
|
||||||
if(furi_string_search(
|
if(furi_string_search(
|
||||||
file->path, archive_get_default_path(ArchiveTabBadUsb)) == 0) {
|
file->path, archive_get_default_path(ArchiveTabBadUsb)) == 0) {
|
||||||
|
|||||||
@@ -19,8 +19,10 @@ typedef enum {
|
|||||||
ArchiveFileTypeU2f,
|
ArchiveFileTypeU2f,
|
||||||
ArchiveFileTypeApplication,
|
ArchiveFileTypeApplication,
|
||||||
ArchiveFileTypeUpdateManifest,
|
ArchiveFileTypeUpdateManifest,
|
||||||
|
ArchiveFileTypeJS,
|
||||||
ArchiveFileTypeFolder,
|
ArchiveFileTypeFolder,
|
||||||
ArchiveFileTypeUnknown,
|
ArchiveFileTypeUnknown,
|
||||||
|
ArchiveFileTypeAppOrJs,
|
||||||
ArchiveFileTypeLoading,
|
ArchiveFileTypeLoading,
|
||||||
} ArchiveFileTypeEnum;
|
} ArchiveFileTypeEnum;
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
|
|||||||
return "U2F";
|
return "U2F";
|
||||||
case ArchiveFileTypeUpdateManifest:
|
case ArchiveFileTypeUpdateManifest:
|
||||||
return "UpdaterApp";
|
return "UpdaterApp";
|
||||||
|
case ArchiveFileTypeJS:
|
||||||
|
return "JS Runner";
|
||||||
default:
|
default:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -244,6 +246,7 @@ bool archive_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
|||||||
break;
|
break;
|
||||||
case ArchiveBrowserEventFileMenuDelete:
|
case ArchiveBrowserEventFileMenuDelete:
|
||||||
if(archive_get_tab(browser) != ArchiveTabFavorites) {
|
if(archive_get_tab(browser) != ArchiveTabFavorites) {
|
||||||
|
archive_show_file_menu(browser, false);
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(
|
||||||
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH);
|
archive->scene_manager, ArchiveAppSceneBrowser, SCENE_STATE_NEED_REFRESH);
|
||||||
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete);
|
scene_manager_next_scene(archive->scene_manager, ArchiveAppSceneDelete);
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ void archive_scene_delete_on_enter(void* context) {
|
|||||||
filename = furi_string_alloc();
|
filename = furi_string_alloc();
|
||||||
|
|
||||||
ArchiveFile_t* current = archive_get_current_file(app->browser);
|
ArchiveFile_t* current = archive_get_current_file(app->browser);
|
||||||
|
|
||||||
|
FuriString* filename_no_ext = furi_string_alloc();
|
||||||
|
path_extract_filename(current->path, filename_no_ext, true);
|
||||||
|
strlcpy(app->text_store, furi_string_get_cstr(filename_no_ext), MAX_NAME_LEN);
|
||||||
|
furi_string_free(filename_no_ext);
|
||||||
|
|
||||||
path_extract_filename(current->path, filename, false);
|
path_extract_filename(current->path, filename, false);
|
||||||
|
|
||||||
char delete_str[64];
|
char delete_str[64];
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user