Compare commits
2008 commits
Update-cod
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62453248a6 | ||
|
|
52c757ac36 | ||
|
|
f5fec0e46b | ||
|
|
009abaff09 | ||
|
|
f34bab8fd8 | ||
|
|
02dc51166e | ||
|
|
1edc2c70fd | ||
|
|
9f9d11ebc9 | ||
|
|
4aef934371 | ||
|
|
c810b4e2a1 | ||
|
|
8feb030e57 | ||
|
|
a48db8f2c2 | ||
|
|
992f57f2f6 | ||
|
|
18d5dbaf48 | ||
|
|
2fcfe4a686 | ||
|
|
900e93f146 | ||
|
|
f80086a15e | ||
|
|
5ad0efac9f | ||
|
|
46c942051d | ||
|
|
4fcd255f87 | ||
|
|
5fbb8d9277 | ||
|
|
8f89fe23c1 | ||
|
|
59fe2fb599 | ||
|
|
318448cc64 | ||
|
|
a011ecf509 | ||
|
|
d0cb33b6fc | ||
|
|
8a376de77e | ||
|
|
ec8fdd1cf6 | ||
|
|
fac7d8155e | ||
|
|
77bd7db8fe | ||
|
|
92ac6f3aa4 | ||
|
|
708341d067 | ||
|
|
015b1f321d | ||
|
|
7057bc7a1f | ||
|
|
5ac9e6cd2e | ||
|
|
4e9c1239de | ||
|
|
d4483b0d1d | ||
|
|
af83bf3cde | ||
|
|
0ef12d6fb2 | ||
|
|
5a18411aee | ||
|
|
3f902f837a | ||
|
|
3a7683e728 | ||
|
|
21ce0d8ae1 | ||
|
|
1daa2d72aa | ||
|
|
2a399b4f0f | ||
|
|
afabe616a2 | ||
|
|
a5a62a1584 | ||
|
|
4f153b0321 | ||
|
|
5b29480e9f | ||
|
|
06ccf1cc75 | ||
|
|
e804e240a6 | ||
|
|
4cf64fda77 | ||
|
|
a616a09177 | ||
|
|
fc5f3391cb | ||
|
|
e4690a4bdc | ||
|
|
53dce06f35 | ||
|
|
8fff1f5508 | ||
|
|
006fa45afc | ||
|
|
0892b2226f | ||
|
|
5e539a6626 | ||
|
|
a2a056457a | ||
|
|
d655c5892c | ||
|
|
c8273475d2 | ||
|
|
11fb234c19 | ||
|
|
667bb38009 | ||
|
|
934ad21830 | ||
|
|
4919e360c9 | ||
|
|
0fa89fd711 | ||
|
|
6a8f7a3841 | ||
|
|
6b2c4ee4f2 | ||
|
|
990b4eee37 | ||
|
|
9af149971f | ||
|
|
1cd99ab0fd | ||
|
|
78373685c1 | ||
|
|
1930a2ff6e | ||
|
|
371bd7ba16 | ||
|
|
20bcb16713 | ||
|
|
83402f3a1f | ||
|
|
4a80a4ac71 | ||
|
|
43d9f48009 | ||
|
|
1da3c7916a | ||
|
|
e44ae3524b | ||
|
|
f8c2b61fea | ||
|
|
f5f0805802 | ||
|
|
b036cc6252 | ||
|
|
d22c263f6f | ||
|
|
895120fd8c | ||
|
|
989db55caf | ||
|
|
c5510041a3 | ||
|
|
5dd86b8c17 | ||
|
|
bef5610af2 | ||
|
|
97cef46969 | ||
|
|
44e4cdd4d5 | ||
|
|
f4eee1ff6a | ||
|
|
0ecae41d6f | ||
|
|
8be7f75668 | ||
|
|
d628b2fa2d | ||
|
|
fc6bad3636 | ||
|
|
99f722ba6b | ||
|
|
be3293915c | ||
|
|
2dfcdd5fa2 | ||
|
|
475f919788 | ||
|
|
06a13af737 | ||
|
|
aada1d7b11 | ||
|
|
9b3ef79216 | ||
|
|
77ca9ce529 | ||
|
|
40573e41a8 | ||
|
|
8c4a1b3307 | ||
|
|
ec4ca90328 | ||
|
|
10b9ab827a | ||
|
|
02d7caf6a2 | ||
|
|
dff0bbb611 | ||
|
|
3c7e161f93 | ||
|
|
78cc309fdd | ||
|
|
6216a8a69e | ||
|
|
572e952434 | ||
|
|
a93818885f | ||
|
|
ea96a5dba3 | ||
|
|
aa83302a9b | ||
|
|
f245bf8838 | ||
|
|
d65ebe2b99 | ||
|
|
632b3f5d2c | ||
|
|
d1484a30b1 | ||
|
|
e579992b2f | ||
|
|
574bf886a5 | ||
|
|
00f6b46aa6 | ||
|
|
7c9ed24d5a | ||
|
|
8776b77ed6 | ||
|
|
064a654ef3 | ||
|
|
069a27ac4e | ||
|
|
6546f20d1e | ||
|
|
be14e2cff6 | ||
|
|
fd3535b6b1 | ||
|
|
cb3a07bb25 | ||
|
|
48a837c8ff | ||
|
|
b74bbaf033 | ||
|
|
e9b900c317 | ||
|
|
3efeca69df | ||
|
|
caffaec092 | ||
|
|
083883fbac | ||
|
|
85eb5522a2 | ||
|
|
31426aeddc | ||
|
|
235f0c4938 | ||
|
|
c6f4f3ad91 | ||
|
|
31240bf5aa | ||
|
|
0b0c4ebbbd | ||
|
|
62512cab4a | ||
|
|
a254b46192 | ||
|
|
60d17f12c8 | ||
|
|
b263b9684b | ||
|
|
2b4475bbc7 | ||
|
|
16145663c1 | ||
|
|
463ac6586b | ||
|
|
82e3a2adca | ||
|
|
f57629a8ae | ||
|
|
edfec3d15f | ||
|
|
8dae72946e | ||
|
|
6994ee09d3 | ||
|
|
d7cdb81494 | ||
|
|
043497405a | ||
|
|
f393f2762d | ||
|
|
dbf2a4301e | ||
|
|
5b4ba29cc2 | ||
|
|
748f988a52 | ||
|
|
d40ddef917 | ||
|
|
736bedf957 | ||
|
|
3d3d29ccc1 | ||
|
|
112721fecd | ||
|
|
57a70ad9e7 | ||
|
|
ebdcc74cf3 | ||
|
|
66e82e79d2 | ||
|
|
054e7c443c | ||
|
|
4d2c3e147c | ||
|
|
1fb7ac8df2 | ||
|
|
cee73a11c7 | ||
|
|
047f53e1ad | ||
|
|
50fff0047f | ||
|
|
15ae874841 | ||
|
|
41de6c47e0 | ||
|
|
64f2cb5c31 | ||
|
|
2c61160dbd | ||
|
|
1be135c607 | ||
|
|
2b0f7263de | ||
|
|
f3c46a4507 | ||
|
|
5a8650418c | ||
|
|
f2ede9c176 | ||
|
|
b793776adb | ||
|
|
177ee7a9b8 | ||
|
|
f476d0a6c6 | ||
|
|
07967a29c7 | ||
|
|
5eff1adaa8 | ||
|
|
5cd01c6116 | ||
|
|
e5c40eb8ce | ||
|
|
9bea106029 | ||
|
|
339e0d7780 | ||
|
|
da3b838314 | ||
|
|
8d0262f1d7 | ||
|
|
ed395b8276 | ||
|
|
8937ea355e | ||
|
|
7a910ab962 | ||
|
|
5df1fe038b | ||
|
|
ec541811cc | ||
|
|
95dbe2c665 | ||
|
|
834f226528 | ||
|
|
f3d3405272 | ||
|
|
bbd38c439e | ||
|
|
d2f16f8b7b | ||
|
|
02768500ad | ||
|
|
a87f6abb0b | ||
|
|
08dc8367c5 | ||
|
|
d1c09dcd61 | ||
|
|
d70fa56444 | ||
|
|
fedcf13bd5 | ||
|
|
63f3cc563a | ||
|
|
7dba79be85 | ||
|
|
b94d8a91fb | ||
|
|
4445aa72a2 | ||
|
|
05c57a9690 | ||
|
|
c9f04bd6c5 | ||
|
|
50d5fe5980 | ||
|
|
114ab9a304 | ||
|
|
e503ce1e93 | ||
|
|
f3b75557cf | ||
|
|
185cad9fad | ||
|
|
eb969fab97 | ||
|
|
0b7aa5dfcb | ||
|
|
84b025b1e7 | ||
|
|
7f89d19b5f | ||
|
|
54ab01fead | ||
|
|
b71c26e514 | ||
|
|
338447c6e7 | ||
|
|
11554113a0 | ||
|
|
531c15cd5f | ||
|
|
d1f5eac58e | ||
|
|
7765812f24 | ||
|
|
2ab43f179b | ||
|
|
f82ee27e21 | ||
|
|
508815e216 | ||
|
|
8d7141d02e | ||
|
|
f56a6fb93f | ||
|
|
f5041994ab | ||
|
|
565f1299d6 | ||
|
|
5efae78d0c | ||
|
|
208b435e98 | ||
|
|
9895057dd5 | ||
|
|
a30d244cf1 | ||
|
|
e467423fac | ||
|
|
f295b8b34d | ||
|
|
af5efebe65 | ||
|
|
afa65ff360 | ||
|
|
c5bec455de | ||
|
|
a9485dfec3 | ||
|
|
5ac268249b | ||
|
|
26d640d90e | ||
|
|
65e75e579f | ||
|
|
c65bf173de | ||
|
|
a92dde9884 | ||
|
|
3cba541938 | ||
|
|
e734c9c961 | ||
|
|
65842cdb9b | ||
|
|
a177c59bcc | ||
|
|
520f77ef0d | ||
|
|
74314751a8 | ||
|
|
198469c7f6 | ||
|
|
d44d654d39 | ||
|
|
37afebbd3f | ||
|
|
4b8feb23bc | ||
|
|
822de1266e | ||
|
|
f5d4123a0b | ||
|
|
7d22755433 | ||
|
|
7622520b69 | ||
|
|
7ca93c2a8e | ||
|
|
b8d94ec2db | ||
|
|
9010f17295 | ||
|
|
c300a38e95 | ||
|
|
fb4eee8158 | ||
|
|
b666b57c4a | ||
|
|
024885ed60 | ||
|
|
b8f605855c | ||
|
|
5fe76b9b3a | ||
|
|
c056b4e249 | ||
|
|
74a8f9c1c5 | ||
|
|
3378ed902d | ||
|
|
4ffdcba741 | ||
|
|
74b401d622 | ||
|
|
9cc428580a | ||
|
|
9288b996c4 | ||
|
|
3f0ed86c37 | ||
|
|
f91a3e6b52 | ||
|
|
6a9015c68e | ||
|
|
da43407a16 | ||
|
|
7edbbf2401 | ||
|
|
42ecec6928 | ||
|
|
3eaa064690 | ||
|
|
b415616277 | ||
|
|
00d5e27de7 | ||
|
|
5cc6a257d3 | ||
|
|
87c04e1c46 | ||
|
|
0cb30f6996 | ||
|
|
e94ba7e31f | ||
|
|
58e89f5b6e | ||
|
|
eca663c40c | ||
|
|
f8cb964c21 | ||
|
|
8140f4286e | ||
|
|
ef00664e14 | ||
|
|
86686fa817 | ||
|
|
c64dfdc9c3 | ||
|
|
6bce301f25 | ||
|
|
8d0ef9d35a | ||
|
|
c9b7193a22 | ||
|
|
8b940c95db | ||
|
|
b49083177b | ||
|
|
3357fefbb0 | ||
|
|
dceed82785 | ||
|
|
0332716490 | ||
|
|
f4d0dc75c2 | ||
|
|
f7e6c1fb3e | ||
|
|
6a9407744a | ||
|
|
70d15e1284 | ||
|
|
166852bff0 | ||
|
|
b7abaf52ee | ||
|
|
2642e48856 | ||
|
|
f94718eb4d | ||
|
|
0ad935f655 | ||
|
|
0f450b0718 | ||
|
|
5239baffaf | ||
|
|
ded8d0098e | ||
|
|
b2a98fe698 | ||
|
|
f9a414ddbc | ||
|
|
2b5fd71ab0 | ||
|
|
071c95b5b7 | ||
|
|
fb932a96ec | ||
|
|
76d2a5ae21 | ||
|
|
389027c9aa | ||
|
|
de887d18ea | ||
|
|
06fcc8e04c | ||
|
|
e05e3f928d | ||
|
|
7c19748b1b | ||
|
|
2ded43760f | ||
|
|
a5dbc3958d | ||
|
|
608253e0c8 | ||
|
|
a38cbfb13d | ||
|
|
b2371f2585 | ||
|
|
72517cf5cd | ||
|
|
564f99c7fb | ||
|
|
c16e76efa1 | ||
|
|
ec671a3ece | ||
|
|
0c2b9353a1 | ||
|
|
05b30667d5 | ||
|
|
2f156c65bc | ||
|
|
94ce0330c9 | ||
|
|
dc254f08db | ||
|
|
0107361db8 | ||
|
|
1f143abc19 | ||
|
|
c604b5d4ee | ||
|
|
1e76acf211 | ||
|
|
b4a7cf88bb | ||
|
|
d2abcbff2e | ||
|
|
3548bd13a4 | ||
|
|
83809937b1 | ||
|
|
aeaceaef7c | ||
|
|
f23741077e | ||
|
|
bd8b9de5e6 | ||
|
|
8636c1f1f2 | ||
|
|
371f7a40a9 | ||
|
|
ef9f2cc230 | ||
|
|
5a20f1cd72 | ||
|
|
923b6f24ce | ||
|
|
f037a7b937 | ||
|
|
65ced5837c | ||
|
|
06dded0371 | ||
|
|
592b33be07 | ||
|
|
53234f9932 | ||
|
|
bedfa656d8 | ||
|
|
9859b44e07 | ||
|
|
7406a2bb4a | ||
|
|
81fa01f589 | ||
|
|
2c78e713b5 | ||
| 7f6f1627b8 | |||
| 72b8e9743f | |||
| 6b9d4d87dc | |||
|
|
f327f68eb6 | ||
|
|
6c91cac0aa | ||
|
|
b38e2c29e3 | ||
| 9ebf8bc0e3 | |||
|
|
4f9be49545 | ||
| cf2f2b01ff | |||
|
|
c45d70e536 | ||
|
|
24261aa88e | ||
|
|
9dce1e3e2b | ||
|
|
75c5023819 | ||
|
|
9a5c2e37f4 | ||
|
|
906e10e481 | ||
|
|
e4aac8bdbb | ||
|
|
77710f445d | ||
|
|
02d49a92e7 | ||
|
|
1082a37124 | ||
|
|
05ca129522 | ||
|
|
2baf7aaa86 | ||
|
|
96fa902545 | ||
|
|
1bebd9ad51 | ||
|
|
e346383916 | ||
|
|
a2e7224702 | ||
|
|
2e54a0214d | ||
|
|
25db1babaa | ||
|
|
c322fbd036 | ||
|
|
f7041992ce | ||
|
|
a326077b38 | ||
|
|
1e54149f1a | ||
|
|
76045d0558 | ||
|
|
a216a61a40 | ||
|
|
0077f024ee | ||
|
|
8f0f5ef420 | ||
|
|
6f3542c9a3 | ||
|
|
1ae1defb25 | ||
|
|
721b62dda9 | ||
|
|
636ec27ada | ||
|
|
a11851d35a | ||
|
|
6b4cece80e | ||
|
|
549f248817 | ||
|
|
c1b20c7f13 | ||
|
|
1b0e08a316 | ||
|
|
82f6997347 | ||
|
|
6827024509 | ||
|
|
68aec70f4a | ||
|
|
15b4cc768b | ||
|
|
9d5ec334d1 | ||
|
|
b287f01401 | ||
|
|
e831125ec9 | ||
|
|
0d6babcecc | ||
|
|
cd29c39cf4 | ||
|
|
9836040c2b | ||
|
|
86866a45d0 | ||
|
|
10c616e797 | ||
|
|
20ee088f11 | ||
|
|
5d759b5fb8 | ||
|
|
0ad7f62f82 | ||
|
|
9f557683eb | ||
|
|
06d7ef1381 | ||
|
|
8e27ae82bd | ||
|
|
8c7957bc3f | ||
|
|
8327a4e941 | ||
|
|
831e2736e4 | ||
| 55eff111ad | |||
|
|
82a6e55c06 | ||
|
|
69502c1caa | ||
|
|
af36141979 | ||
|
|
ed8ea8d82c | ||
|
|
16c13435ec | ||
|
|
8282ba3d45 | ||
|
|
7681d5b70a | ||
|
|
7b2a3ba12a | ||
|
|
67a2acbbcd | ||
|
|
f32c65db2c | ||
|
|
069a57e1b4 | ||
|
|
726d0057f9 | ||
|
|
c77cc96973 | ||
|
|
5a4c1ced91 | ||
|
|
add7fcd7d2 | ||
|
|
269d72e4b5 | ||
|
|
75fe6a4047 | ||
|
|
fde91334de | ||
|
|
0a8de560b8 | ||
| a5cee34e60 | |||
| cb76498965 | |||
|
|
abe0acb3e7 | ||
|
|
dc43693f17 | ||
|
|
0e17763a29 | ||
|
|
aa2361d439 | ||
| 5a0e281ade | |||
| 4151751dd7 | |||
| a6851c595e | |||
|
|
b35069b3a9 | ||
|
|
02ccc6c1a2 | ||
|
|
f356fba7d8 | ||
|
|
bbaa4f5fbc | ||
|
|
70a7ca66e1 | ||
|
|
d9dd6f38d0 | ||
|
|
1554ea417e | ||
|
|
d8166ffec5 | ||
|
|
ced0b7a139 | ||
|
|
fc4e738f28 | ||
|
|
f521981f48 | ||
|
|
547a3315e6 | ||
|
|
dc7aaf2397 | ||
|
|
602ac644c3 | ||
|
|
7cc05f27f4 | ||
|
|
8b720619f8 | ||
|
|
1ae44de44f | ||
|
|
fc71e49d78 | ||
|
|
d110742ba9 | ||
|
|
3e33418828 | ||
|
|
4135617fea | ||
|
|
18a037deef | ||
|
|
52416a25f2 | ||
|
|
f1cf3ce157 | ||
|
|
109eebcb0f | ||
|
|
d64251b18a | ||
|
|
93c450259a | ||
|
|
e5757ccc0d | ||
|
|
802e54a0b5 | ||
|
|
ce98c5ee8d | ||
|
|
4eff77cd4e | ||
|
|
9c845aa13e | ||
|
|
3b1855030f | ||
|
|
8dab4866d0 | ||
|
|
c803cfea45 | ||
|
|
ad73b77f18 | ||
|
|
8550345e99 | ||
|
|
c58af8331c | ||
|
|
795ff05593 | ||
|
|
7779de188f | ||
|
|
108f763d40 | ||
|
|
c1c2897f2b | ||
|
|
fe9142a19c | ||
|
|
c1bbd3597b | ||
|
|
f0bf67e879 | ||
|
|
65e8e79950 | ||
|
|
15aa60f5a7 | ||
|
|
104df9166c | ||
|
|
ba9099d3a2 | ||
|
|
4965a40ef5 | ||
|
|
b20191babf | ||
|
|
2909bef561 | ||
|
|
dc09f0db47 | ||
|
|
0b6ed775d5 | ||
|
|
85c13fcbe3 | ||
|
|
37e93d87a6 | ||
|
|
c0d75b8432 | ||
|
|
c38a83ae3a | ||
|
|
b4601f92aa | ||
|
|
0c432cb85e | ||
|
|
3a476d56fb | ||
|
|
91db2f004c | ||
|
|
6204ca349c | ||
|
|
eae450908e | ||
|
|
62f367bc1e | ||
|
|
12bf9f8f6e | ||
|
|
7a43be2468 | ||
|
|
69ff3b8e31 | ||
|
|
9e1eaba7c8 | ||
|
|
c9f2d95e5a | ||
|
|
f70eaa5da4 | ||
|
|
38f661bf64 | ||
|
|
4c92b0400b | ||
|
|
8c1f2a5ac1 | ||
|
|
bfa39bedcf | ||
|
|
027433f781 | ||
|
|
88281cf5ee | ||
|
|
b3ddb74530 | ||
|
|
daa736c921 | ||
|
|
332efcb952 | ||
|
|
ff5fff5e38 | ||
|
|
94ce890eb2 | ||
|
|
b4778203df | ||
|
|
440f24271c | ||
|
|
09a89238cb | ||
|
|
ec4771b2e4 | ||
|
|
d37cdfa503 | ||
|
|
5524390a7c | ||
|
|
99d30da439 | ||
|
|
daa4e427e3 | ||
|
|
bde5ed3f2c | ||
|
|
366140c42d | ||
|
|
685d549701 | ||
|
|
8423dd4698 | ||
|
|
a596a555e8 | ||
|
|
acb4a1dd31 | ||
|
|
fbf893bdab | ||
|
|
a26563c8d1 | ||
|
|
1b9f08dad7 | ||
|
|
86f10f190f | ||
|
|
9b50b43d89 | ||
|
|
27427735ee | ||
|
|
30e081c593 | ||
|
|
091bead2f8 | ||
|
|
ce2bff085c | ||
|
|
5730b4f57d | ||
|
|
24f3c70814 | ||
|
|
b6a7df8c62 | ||
|
|
ec6d564fd3 | ||
|
|
a554b04cb0 | ||
|
|
c16c5b8590 | ||
|
|
268d946cb6 | ||
|
|
aa4d2f8649 | ||
|
|
4a6ded436c | ||
|
|
22ff05a1c9 | ||
|
|
4f2193e3c5 | ||
|
|
6e61f0003b | ||
|
|
89f56289ac | ||
|
|
4dd60a2ac0 | ||
|
|
ecc7378b98 | ||
|
|
c3bae1fe39 | ||
|
|
1a551101ef | ||
|
|
ef4c47e59c | ||
|
|
4e54490e82 | ||
|
|
0698cfe39d | ||
|
|
f670d957dd | ||
|
|
48f21c6508 | ||
|
|
fb6d389d3c | ||
|
|
de340e61fa | ||
|
|
e1ad62e874 | ||
|
|
d247e47115 | ||
|
|
fec74ba9be | ||
|
|
a27d5f2e5d | ||
|
|
122daa320c | ||
|
|
e4b7ff5e0e | ||
|
|
100a139d01 | ||
|
|
eec86c9a55 | ||
|
|
2264eef18a | ||
|
|
809475ece0 | ||
|
|
6be9a51f5c | ||
|
|
8e045c3340 | ||
|
|
41c84a4610 | ||
|
|
16f9f0ca71 | ||
|
|
5dc24ad4b3 | ||
|
|
46621d01b3 | ||
|
|
5532a6e33e | ||
|
|
2102b2a608 | ||
|
|
4b1479bc17 | ||
|
|
9e872fb23b | ||
|
|
2a2ff87d1d | ||
|
|
dc90899afa | ||
|
|
1e653e3290 | ||
|
|
e4369d29a0 | ||
|
|
815e584be9 | ||
|
|
76337d24b7 | ||
|
|
d9ce978dc7 | ||
|
|
025eace36e | ||
|
|
3caeb03f56 | ||
|
|
31ccb26ecc | ||
|
|
3356c6e10d | ||
|
|
85fc938f4a | ||
|
|
7c66c14506 | ||
|
|
b0c1fa194c | ||
|
|
694c9a9a9d | ||
|
|
edd126dcfb | ||
|
|
7b86eec85b | ||
|
|
5edc1f0932 | ||
|
|
81ba1ce023 | ||
|
|
36785e397c | ||
|
|
ed9f141ca6 | ||
|
|
11449b7aa8 | ||
|
|
3f27ef6ce9 | ||
|
|
54f75d6938 | ||
|
|
10b39d0ae8 | ||
|
|
bbee0bec10 | ||
|
|
328a9f9759 | ||
|
|
77e01f089d | ||
|
|
9b85a43eec | ||
|
|
60ecc7e56b | ||
|
|
02dddfd67e | ||
|
|
57f5b16f61 | ||
|
|
cf348e0156 | ||
|
|
6cb551cbe0 | ||
|
|
4b223c310b | ||
|
|
5ca431625d | ||
|
|
2e800843d8 | ||
|
|
c40878161d | ||
|
|
e4d189b00a | ||
|
|
d7b50d4a44 | ||
|
|
810c12d8d1 | ||
|
|
f6f6d30f24 | ||
|
|
f57cb124b9 | ||
|
|
f7d468c411 | ||
|
|
045afc1958 | ||
|
|
8a7026c5a9 | ||
|
|
7f0d2e03d9 | ||
|
|
41f3f0fcef | ||
|
|
1c4b493464 | ||
|
|
64a0ba8ba7 | ||
| bd80549170 | |||
|
|
8e74f2a28c | ||
|
|
8cf838f14b | ||
|
|
8d4a392e90 | ||
|
|
ebf338ddc7 | ||
|
|
b8ae5c3845 | ||
|
|
17c63eb4ae | ||
|
|
295153b39b | ||
|
|
f95073ed9a | ||
|
|
7818a3ebc5 | ||
|
|
60d26f98d3 | ||
|
|
2ab0856017 | ||
|
|
05581d6fae | ||
|
|
ea2aac8888 | ||
|
|
de62cdf3eb | ||
|
|
0168375d8b | ||
|
|
5f676e6e62 | ||
|
|
77ce50c320 | ||
|
|
ca60107d7b | ||
|
|
9b3bda1210 | ||
|
|
df884b48a8 | ||
|
|
eab4569a32 | ||
|
|
b2ac355beb | ||
|
|
1eb9dad994 | ||
|
|
e5f204213c | ||
|
|
cc5cbcca68 | ||
|
|
4d0a7174a3 | ||
|
|
e6043f98bb | ||
|
|
8311b12e17 | ||
|
|
9405bd254b | ||
|
|
3ec7e08881 | ||
| cd231d5aed | |||
|
|
c974936792 | ||
|
|
32df9b8813 | ||
| 3c828cb669 | |||
|
|
9aadd89df9 | ||
|
|
245259ca84 | ||
|
|
1164297323 | ||
|
|
f8e920e451 | ||
|
|
9f79661501 | ||
|
|
eac10af0cf | ||
|
|
cc08a5430f | ||
|
|
78cff5e023 | ||
|
|
9591fa1da8 | ||
|
|
b25a79bb8b | ||
|
|
8495261c6e | ||
|
|
bd9285fd34 | ||
|
|
e7a994933b | ||
|
|
0d75e9c9cc | ||
|
|
4c7517f03d | ||
|
|
71cfcedc99 | ||
|
|
a5e63d86ce | ||
|
|
b59621d297 | ||
|
|
11aace8fc0 | ||
|
|
3a93a5e6b8 | ||
|
|
24406bfb99 | ||
|
|
35a860806f | ||
|
|
99ca7416e0 | ||
|
|
d71dd92eb7 | ||
|
|
7309df1b16 | ||
|
|
f9377c671f | ||
|
|
ea006a7801 | ||
|
|
5d50d6921f | ||
|
|
8aaa60103b | ||
|
|
9210da3106 | ||
|
|
6bdc53cf98 | ||
|
|
fb0b540278 | ||
|
|
7601d79245 | ||
|
|
0d7939c401 | ||
|
|
906b88a2e4 | ||
|
|
344d7f79a2 | ||
|
|
40a0ccbdf3 | ||
|
|
e810d3f23d | ||
|
|
44a599230f | ||
|
|
c181cb221d | ||
|
|
8bce2e1b5c | ||
|
|
cc9d8c18c9 | ||
|
|
881ab47517 | ||
|
|
ccaf807c94 | ||
|
|
f6081e8407 | ||
|
|
c5e1f5b11b | ||
|
|
0170bbcf23 | ||
|
|
9f2f2b9bc6 | ||
|
|
695724c605 | ||
|
|
171be2c018 | ||
|
|
60904c301f | ||
|
|
8d7863b718 | ||
|
|
42af17d20a | ||
|
|
676ee67803 | ||
|
|
68dc78de19 | ||
|
|
b02cc99d9a | ||
|
|
c3a4509bf3 | ||
|
|
8fcd9c06cf | ||
|
|
cc19eef888 | ||
|
|
51ddbd3019 | ||
|
|
854ee39fa2 | ||
|
|
440b1ba294 | ||
|
|
a14e92ba08 | ||
|
|
4db61f558f | ||
|
|
b4aa60735b | ||
|
|
d92d3a6630 | ||
|
|
75b7348115 | ||
|
|
fd2baf3f99 | ||
|
|
644c91c3e1 | ||
|
|
955c655bf2 | ||
|
|
9968f6c556 | ||
|
|
0217c1b612 | ||
|
|
24457b8a7b | ||
|
|
071d755f05 | ||
|
|
2b88f8d8e6 | ||
|
|
b41b012e13 | ||
|
|
0071dd569a | ||
|
|
88f2a58e47 | ||
|
|
1d7f02f514 | ||
|
|
96455052dc | ||
|
|
16c38168e9 | ||
|
|
94706109e0 | ||
|
|
1e62b17ce5 | ||
|
|
eedd124d43 | ||
|
|
12f449bae4 | ||
|
|
db37f2c53d | ||
|
|
8593c16d42 | ||
|
|
df22e21825 | ||
|
|
54eb946bdf | ||
|
|
0eba9f248a | ||
|
|
c4e22b3be0 | ||
|
|
de3e878437 | ||
|
|
1831ab7ce9 | ||
|
|
d062c103bb | ||
|
|
15dbd2fa80 | ||
|
|
979191aabe | ||
|
|
3bfc11d72e | ||
|
|
1b3480b2e4 | ||
|
|
7d8fd34e13 | ||
|
|
1c286f4ab9 | ||
|
|
d013839776 | ||
|
|
a3be3357a6 | ||
|
|
7dbfc24ff1 | ||
|
|
d78a6563a5 | ||
|
|
eaa554565a | ||
|
|
dd9f95b3be | ||
|
|
9fd7bf6c24 | ||
|
|
52213faa6d | ||
|
|
a9952b79a5 | ||
|
|
0f644af801 | ||
|
|
02b3dc8391 | ||
|
|
86f66dd251 | ||
|
|
ca878d0875 | ||
|
|
bb759ddae6 | ||
|
|
237cb1a952 | ||
|
|
81613ea763 | ||
|
|
879a24557b | ||
|
|
b5ee85acea | ||
|
|
4aa63fd4ec | ||
|
|
4df862a98c | ||
|
|
21f1186eb1 | ||
|
|
cd779f7f80 | ||
| 30bafae71b | |||
|
|
dd6e7c2630 | ||
|
|
355d9a8819 | ||
|
|
a5d6e23668 | ||
|
|
f6b4b387a4 | ||
|
|
b8e4a6ae02 | ||
|
|
200babd284 | ||
|
|
c3e61afd83 | ||
|
|
032056d78e | ||
|
|
b4ed28d1bb | ||
|
|
9b92851d3e | ||
|
|
67eccd1652 | ||
|
|
749d43e635 | ||
|
|
bc5742ca2f | ||
|
|
be531417cf | ||
|
|
c1e1c6cc9d | ||
|
|
474c37b137 | ||
|
|
51f4a4a148 | ||
|
|
e3f43d715f | ||
|
|
2c5f5d7a18 | ||
|
|
690f3a01cf | ||
|
|
768256cfe0 | ||
|
|
12205b8b55 | ||
|
|
125f760d5c | ||
|
|
45e7e8e5b6 | ||
|
|
8f9a1bb02b | ||
|
|
03bd7c15be | ||
|
|
537cf66a40 | ||
|
|
c73b419ed0 | ||
|
|
bdbb93e521 | ||
| 67d74be0e2 | |||
| aaf08919ce | |||
| 461a52fadb | |||
|
|
fa5d53887f | ||
| 827b431bf6 | |||
| b58ddfe0ad | |||
| cf9263932a | |||
| 3dcb2f28fe | |||
| b7cc998f6b | |||
| d5b100829a | |||
|
|
f00ff213fd | ||
|
|
bb67c12bde | ||
|
|
53dacbbe9d | ||
|
|
f831f81834 | ||
|
|
2cc9d2afae | ||
|
|
72f5880410 | ||
|
|
56ba6b1af9 | ||
|
|
8de5b7a9fe | ||
|
|
ad042d2498 | ||
|
|
16e4fc0255 | ||
|
|
b4d8dd5287 | ||
|
|
799581c08d | ||
|
|
8a08dcf862 | ||
|
|
2a1da0fefd | ||
|
|
825a1039c0 | ||
|
|
ed6aa2b8ea | ||
|
|
3fcffd1d92 | ||
|
|
000d4d18a9 | ||
|
|
e539fcb783 | ||
|
|
8fec3a5a29 | ||
|
|
22f911ab6e | ||
|
|
557db82675 | ||
|
|
6252a417ea | ||
|
|
71946c4c49 | ||
|
|
6bf3658e54 | ||
|
|
fcf40b57e7 | ||
|
|
102ed595e3 | ||
|
|
de1eec5e09 | ||
|
|
6e7c8d89e1 | ||
|
|
aabdb4e1ff | ||
|
|
8dd940da3d | ||
|
|
024cb0859c | ||
|
|
0997d95c9e | ||
|
|
3c410fd6ea | ||
|
|
1f6540c912 | ||
|
|
21123b6011 | ||
|
|
cbed6e3267 | ||
|
|
583969ffe5 | ||
|
|
b29d422550 | ||
|
|
b3d09e64b4 | ||
|
|
4c375a1b8e | ||
|
|
10311e1b1f | ||
|
|
87d83ca0bf | ||
|
|
4b134e0109 | ||
|
|
f7159b6c23 | ||
|
|
481778c4ee | ||
|
|
a4f069bf1f | ||
|
|
ec15ff3be0 | ||
|
|
c6e020d0b1 | ||
|
|
c28be073dd | ||
|
|
a27ab4b21a | ||
|
|
3becea104b | ||
|
|
9c59573a0c | ||
|
|
163a3a9f4e | ||
|
|
0a1fb9e2b2 | ||
|
|
ae9efe71ca | ||
|
|
10583997d0 | ||
|
|
6c93e1018b | ||
|
|
3887691783 | ||
|
|
d3fb47fb36 | ||
|
|
51b6510a94 | ||
|
|
134bb849a0 | ||
|
|
d24ca791c5 | ||
|
|
443285e716 | ||
|
|
f401d4c985 | ||
|
|
6afa924815 | ||
|
|
0cd69abe06 | ||
|
|
80ed5a352b | ||
|
|
5b5a4da45c | ||
|
|
02fe2d2b39 | ||
|
|
bd50fcc73e | ||
|
|
12b89e7a92 | ||
|
|
1f6c843a94 | ||
|
|
a6ff27899e | ||
|
|
b1bc30a6cf | ||
|
|
bc31f2d518 | ||
|
|
56bf5f6276 | ||
|
|
465fe5a399 | ||
|
|
c2c4c9160e | ||
|
|
f43b59dc42 | ||
|
|
178a1a1b22 | ||
|
|
a4f549354f | ||
|
|
814642e012 | ||
|
|
bc2a09c839 | ||
|
|
92729b957b | ||
|
|
21ca6d820b | ||
|
|
d082245cf4 | ||
|
|
812dbf8d9e | ||
|
|
6bfdbd656d | ||
|
|
ca525c0e34 | ||
|
|
c102b1fa54 | ||
|
|
c2888cf63a | ||
|
|
5102e9d6d9 | ||
|
|
32186d192e | ||
|
|
8f288c4385 | ||
|
|
d09369e1bf | ||
|
|
584cc5b123 | ||
|
|
46550a403d | ||
|
|
5c2fcda37e | ||
|
|
d6402b02fc | ||
|
|
fd1e1f78a2 | ||
|
|
fd34db74c6 | ||
|
|
9eca690075 | ||
|
|
eaa77c85b9 | ||
|
|
bc507a7104 | ||
|
|
989cd9ff09 | ||
|
|
ea790e9284 | ||
|
|
3970513457 | ||
|
|
463a9b966a | ||
|
|
eabee0b457 | ||
|
|
564c3ad6bb | ||
| 8248744092 | |||
|
|
63f023a4e3 | ||
|
|
4fcfeaaedb | ||
|
|
33456edce4 | ||
|
|
e88f652a04 | ||
|
|
3aaf91d640 | ||
|
|
2a58a1797a | ||
|
|
b3935350c1 | ||
|
|
8eee1467c3 | ||
|
|
6c06002b56 | ||
|
|
f3b651ff6c | ||
|
|
e2b43f353e | ||
|
|
9fda4e298a | ||
|
|
439c9be319 | ||
|
|
5a7bd9dd76 | ||
|
|
f86824cd24 | ||
|
|
cf4872dd50 | ||
|
|
55cf6fc00e | ||
|
|
15f0e83ca0 | ||
|
|
3d2da42319 | ||
|
|
9142c83df3 | ||
|
|
5325095d51 | ||
|
|
f801e29667 | ||
|
|
297910abbf | ||
|
|
738b887bf8 | ||
|
|
116a41db55 | ||
|
|
ebfdeb7b8c | ||
|
|
033c5303ac | ||
|
|
ad46a98c4b | ||
|
|
0267a4ec9a | ||
|
|
b31cb65f4f | ||
|
|
389d364729 | ||
|
|
2d34f1205e | ||
|
|
1a6049f0fb | ||
|
|
cf8764a1d7 | ||
|
|
3c2bbe0775 | ||
|
|
d8361eacf3 | ||
|
|
507000f681 | ||
|
|
d3dd8cdcdc | ||
|
|
758f916540 | ||
|
|
cb3f0dbabd | ||
|
|
b6d127c9db | ||
|
|
702166c514 | ||
|
|
d41a8560af | ||
|
|
74968912c3 | ||
|
|
1629031acf | ||
|
|
1afc27f9b1 | ||
|
|
79fa13db39 | ||
|
|
56fd748b19 | ||
|
|
2d9416bd58 | ||
|
|
f44a0ac095 | ||
|
|
daaa77345f | ||
|
|
613895cf3d | ||
|
|
c6b26959c0 | ||
|
|
f92d93dbcb | ||
|
|
75e8cf2995 | ||
|
|
7f949978a3 | ||
|
|
fc80f36526 | ||
|
|
e96290cd37 | ||
|
|
d415f03502 | ||
|
|
cf6ffd5ca0 | ||
|
|
52abcb8702 | ||
|
|
e45243f024 | ||
|
|
7f25c224ed | ||
|
|
c676edc66b | ||
|
|
6686a6cddd | ||
|
|
88d94c09a7 | ||
|
|
a9b15cbe69 | ||
|
|
05b4d3b2cd | ||
|
|
7f2cceb671 | ||
|
|
8cf91e6f24 | ||
|
|
7e8150b210 | ||
|
|
34a9f51424 | ||
|
|
18a3fc5b1c | ||
|
|
76cd05be8f | ||
|
|
8f7b5afc54 | ||
|
|
e1071956eb | ||
|
|
411e256955 | ||
|
|
9c6f62bae6 | ||
|
|
d6267a104c | ||
|
|
c354179e0c | ||
|
|
5047c10377 | ||
|
|
50ef265651 | ||
|
|
5c042d2c94 | ||
|
|
99a7ece77f | ||
| 818abfb42a | |||
| f7b72318eb | |||
| ce2461197b | |||
|
|
96ed6bf17e | ||
|
|
0437b6b619 | ||
|
|
49ee608e36 | ||
| a1905b5bfc | |||
|
|
690447cb1d | ||
|
|
69c50a5653 | ||
|
|
403d536f6a | ||
|
|
17ae30608e | ||
|
|
8e19b0d229 | ||
|
|
6f5d24630b | ||
|
|
24a0bdec05 | ||
|
|
93d32ea0bb | ||
|
|
03da135cd7 | ||
|
|
fe175e7acb | ||
|
|
74eaa1b1d2 | ||
|
|
53f5f23e66 | ||
|
|
44a84c575b | ||
|
|
440e0198a3 | ||
|
|
4168e1c766 | ||
|
|
f49f34f4b0 | ||
|
|
52b8af140a | ||
|
|
40d73b21cc | ||
|
|
34466ae7a1 | ||
|
|
45500df488 | ||
|
|
acbdd7e8c9 | ||
|
|
52dedd759b | ||
|
|
1b83a7d2d3 | ||
|
|
fdc082887e | ||
|
|
496185381a | ||
|
|
b4d59e0c60 | ||
|
|
56c9b775fd | ||
|
|
99e514db0f | ||
|
|
a80e7db98e | ||
|
|
f4721fcd25 | ||
|
|
270354bfba | ||
|
|
2d4f747dad | ||
|
|
6965241cbb | ||
|
|
f46ef2ec65 | ||
|
|
78d149d1c5 | ||
|
|
03b078ba8b | ||
|
|
6564b693c1 | ||
|
|
85e851d86f | ||
|
|
bca3bab5a9 | ||
|
|
2c3ce0c410 | ||
|
|
adb084d2b5 | ||
|
|
7b505c04b3 | ||
|
|
a91941e7b7 | ||
|
|
351884b01e | ||
|
|
aa384f0e39 | ||
|
|
5adbfc424e | ||
|
|
082126a83b | ||
|
|
e4bec650c9 | ||
|
|
35eea9f2e0 | ||
|
|
6ac92d9379 | ||
|
|
88027a15dc | ||
|
|
959066cc2f | ||
|
|
189c23b4cc | ||
|
|
85c0557821 | ||
|
|
238c3f41c6 | ||
|
|
52a8f2a46a | ||
|
|
41afe52292 | ||
|
|
d33b157a31 | ||
|
|
d00ae450bb | ||
|
|
a364295859 | ||
|
|
6267879344 | ||
|
|
efdbe9ddd3 | ||
|
|
263c366c72 | ||
|
|
e38569759c | ||
|
|
8854568566 | ||
|
|
00e455ff18 | ||
|
|
3b07ba638d | ||
|
|
678f47c028 | ||
|
|
b784306cc9 | ||
|
|
f0eda69a6c | ||
|
|
21c0ae35b2 | ||
|
|
6f4c208ede | ||
|
|
9d1bec9f23 | ||
|
|
dc64e09d61 | ||
|
|
ae08e5704c | ||
|
|
f2815d4afe | ||
|
|
f75851f474 | ||
|
|
886cb60c1e | ||
|
|
ec23fb301d | ||
|
|
32487e0a9a | ||
|
|
dfbd56cec8 | ||
|
|
a29547cc22 | ||
|
|
46924af0c8 | ||
|
|
80f5ae293c | ||
|
|
3a28acd2c6 | ||
|
|
f25004c257 | ||
|
|
17d8ec9437 | ||
|
|
92898c54a0 | ||
|
|
889647b905 | ||
|
|
2367684583 | ||
|
|
e947db6e6b | ||
|
|
a51e749227 | ||
|
|
cc40d4b779 | ||
|
|
4d3513ace6 | ||
|
|
a95eee1808 | ||
|
|
dba919198c | ||
|
|
3c7b70735d | ||
|
|
bc7dffd168 | ||
|
|
b171407e56 | ||
|
|
50adb94758 | ||
|
|
4e8fff3afe | ||
|
|
043aacb985 | ||
|
|
3065a90041 | ||
|
|
dbe4a1960a | ||
|
|
c28596f344 | ||
|
|
fe3963858a | ||
|
|
e2f476f53b | ||
|
|
ede1dd8951 | ||
|
|
f08869e235 | ||
|
|
956adc1a6c | ||
|
|
78dcb6facb | ||
|
|
4033e68073 | ||
| 79a9e0f707 | |||
|
|
b36c88a9f8 | ||
|
|
1a6de73033 | ||
|
|
02314e5642 | ||
|
|
01edce8037 | ||
|
|
ff94835bb6 | ||
|
|
43a842b0eb | ||
|
|
745405b57d | ||
|
|
706fbf496a | ||
|
|
21d565396a | ||
|
|
0eeaf75fa2 | ||
|
|
8fceaeb757 | ||
| d6fafcb2d0 | |||
| 4c2af96047 | |||
|
|
831548081b | ||
|
|
0dfa0995db | ||
|
|
ce2a50383d | ||
|
|
f2f1ced82b | ||
|
|
697c5b5469 | ||
|
|
a55a80296d | ||
|
|
ca95364fff | ||
|
|
83e706eaba | ||
|
|
3c63086bcf | ||
|
|
ac9f36c19d | ||
|
|
6292092bc6 | ||
|
|
d9bc565990 | ||
|
|
cdb71d4ffd | ||
|
|
0bca8003e3 | ||
|
|
f55e7cedd0 | ||
|
|
f5da0ca0d9 | ||
|
|
27cba4514d | ||
|
|
d7a1005a79 | ||
|
|
9bd795b034 | ||
|
|
2614d98a67 | ||
|
|
22a1e03d26 | ||
|
|
c4b6dd62e8 | ||
|
|
e28ec7d683 | ||
|
|
774aa1316c | ||
|
|
b9a7ca0f64 | ||
|
|
63149d2c86 | ||
|
|
b595f4bd12 | ||
|
|
be00272d41 | ||
|
|
fc36f2beee | ||
|
|
9ef3d2830b | ||
|
|
1cacbf5934 | ||
|
|
62d63b4be0 | ||
|
|
891d085153 | ||
|
|
df67eb6be5 | ||
|
|
cb55f61505 | ||
|
|
2e698aadef | ||
|
|
458db753e0 | ||
|
|
4005e5f2bd | ||
|
|
e7fdf5fe4f | ||
|
|
c5c550370a | ||
|
|
69e1b82a69 | ||
|
|
2532909072 | ||
|
|
3a880dcfcb | ||
|
|
1fad27db0a | ||
|
|
c7fcb49e00 | ||
|
|
d811541ea3 | ||
|
|
56e39c74a6 | ||
|
|
d041b3a6a2 | ||
|
|
eaf7ea2f50 | ||
|
|
763739c837 | ||
|
|
82d99d2118 | ||
|
|
bca8bd6ade | ||
|
|
ae56f1a498 | ||
|
|
dad7a33346 | ||
|
|
b96dd79725 | ||
|
|
92813152f9 | ||
|
|
acd781d910 | ||
|
|
dba53b305f | ||
|
|
8ea00f2bca | ||
|
|
5c7509c2a9 | ||
|
|
13dd48bd0c | ||
|
|
4ff18d18d0 | ||
|
|
8442538d6c | ||
|
|
024d991a24 | ||
|
|
9de211fb39 | ||
|
|
09f76d38cc | ||
|
|
ab6bca7150 | ||
|
|
7c9dc3c61a | ||
|
|
a4d7d0cb72 | ||
|
|
b91cb84e58 | ||
|
|
3d79a5ec81 | ||
|
|
bb2b0cae55 | ||
|
|
ebe3387689 | ||
|
|
150c09756e | ||
|
|
5b96167ac7 | ||
|
|
9761f26837 | ||
|
|
f9c17fba38 | ||
|
|
9c592cbeec | ||
|
|
8cb888956b | ||
|
|
b8bdd85415 | ||
|
|
941f4228ae | ||
|
|
5351d70c7a | ||
|
|
97480d1f89 | ||
|
|
084d2ef45d | ||
|
|
130fe89e70 | ||
|
|
8e6490df4a | ||
|
|
cf20041276 | ||
|
|
9e6e6371c6 | ||
|
|
9f74726241 | ||
|
|
456b6c7dea | ||
|
|
712d55969a | ||
|
|
0e45e17fac | ||
|
|
4078feee94 | ||
|
|
92633f7e03 | ||
|
|
98f0a2b826 | ||
|
|
2b5f016ccb | ||
|
|
040a25e016 | ||
|
|
09e159bb11 | ||
|
|
88ada9e4ef | ||
|
|
0d13222dad | ||
|
|
792616e49a | ||
|
|
3fb6fd00ea | ||
|
|
2ab4189054 | ||
|
|
8d91dad006 | ||
|
|
abaa5d6d9b | ||
|
|
e64d7ef0de | ||
|
|
3fcf8aea08 | ||
|
|
985b31c55c | ||
|
|
a842cc3f53 | ||
|
|
32467f8749 | ||
|
|
fca97b2439 | ||
|
|
5460ea6b67 | ||
|
|
84644e55ad | ||
|
|
bb121a15cb | ||
|
|
705d956521 | ||
|
|
85d1c7d95f | ||
|
|
d91008929e | ||
|
|
6f28675947 | ||
|
|
4ddc1f5e8d | ||
|
|
446d00e69a | ||
|
|
65c0d0ff93 | ||
|
|
94a17bc20f | ||
|
|
8d1568fa7f | ||
|
|
27fb9008b1 | ||
|
|
9d02f94994 | ||
|
|
16a3d2052b | ||
|
|
1f7367cdf5 | ||
|
|
97aedccaf7 | ||
|
|
a1f3dba84e | ||
|
|
ccf9c12bc4 | ||
|
|
8c10cf65f8 | ||
|
|
6e9b42bf65 | ||
|
|
de13b3e91d | ||
|
|
801b523137 | ||
|
|
5d047d9804 | ||
|
|
9b730902bc | ||
|
|
5a341a444a | ||
|
|
9c81e882a5 | ||
|
|
663a94ba36 | ||
|
|
2dd34aeb56 | ||
|
|
2d4ca5515c | ||
|
|
79ce736b3e | ||
|
|
30e4bf0168 | ||
|
|
f770ad0e30 | ||
|
|
bf30dd6c41 | ||
|
|
f812548982 | ||
|
|
1e3d593937 | ||
|
|
41485ea5b6 | ||
|
|
5e38bc1fd8 | ||
|
|
cc424d60d3 | ||
|
|
d76cd68e00 | ||
|
|
6cc224429f | ||
|
|
fde611205f | ||
|
|
3a738907ac | ||
|
|
26a9795f44 | ||
|
|
86532fa1ce | ||
|
|
e6296b12a7 | ||
|
|
5352e15cdf | ||
|
|
ad5c48b57f | ||
|
|
c1adfab753 | ||
|
|
c6594e58e6 | ||
|
|
64dafb0846 | ||
|
|
a5316a3637 | ||
|
|
05ab1e7c1b | ||
|
|
43df6099e2 | ||
|
|
93fff1fd5a | ||
|
|
537dd7dd42 | ||
|
|
266b80d011 | ||
|
|
448ae58349 | ||
|
|
a604216fbb | ||
|
|
ff4d7a48be | ||
|
|
0a5d34d88d | ||
|
|
1ebbc3bba2 | ||
|
|
3a650b6d04 | ||
|
|
ecc5d4dba7 | ||
|
|
5914860cba | ||
|
|
956fa2c490 | ||
|
|
6cbf7ecce4 | ||
|
|
3df559ef02 | ||
|
|
7ac214b86c | ||
|
|
7e3726497d | ||
|
|
7e514ac4fa | ||
|
|
6a8012ca38 | ||
|
|
26ed99bb66 | ||
|
|
033aaf1dc7 | ||
|
|
2a9653db33 | ||
|
|
e326fda0a1 | ||
|
|
e8e837e0bf | ||
|
|
7e064d5be9 | ||
|
|
a56d5d5bd7 | ||
|
|
96bc373d5f | ||
|
|
89e3823e94 | ||
|
|
cd58ff8dfa | ||
|
|
7fa8cd2759 | ||
|
|
1e0a4fb2a7 | ||
|
|
fb1aa0793b | ||
|
|
fbf4c845ae | ||
|
|
2bae131ed6 | ||
|
|
5d40c9d568 | ||
|
|
9250270713 | ||
|
|
b3a0746e23 | ||
|
|
95254871a5 | ||
|
|
f316859324 | ||
|
|
00c431d614 | ||
|
|
df7c0fae67 | ||
|
|
1c627ded6b | ||
|
|
e6a246c555 | ||
|
|
b4c3c05a3d | ||
|
|
358039b86c | ||
|
|
5c952b7ad0 | ||
|
|
4c411efe29 | ||
|
|
71bc93722c | ||
|
|
23c79df995 | ||
|
|
956b146094 | ||
|
|
5a7d0868af | ||
|
|
db8387892a | ||
|
|
77c6ad609c | ||
|
|
c78934a160 | ||
|
|
7259b72db4 | ||
|
|
d1d87e690a | ||
|
|
d8484666a5 | ||
|
|
ecd84e28a0 | ||
|
|
900b2f0fc5 | ||
|
|
495f80c4df | ||
|
|
a980f68b14 | ||
|
|
8732b70333 | ||
|
|
c6ddbde458 | ||
|
|
684bb6d613 | ||
|
|
c2057566cf | ||
|
|
ae5e8c18ff | ||
|
|
8834e11d42 | ||
|
|
45f170470c | ||
|
|
ca24d8b71d | ||
|
|
135648b285 | ||
|
|
b92b2f4047 | ||
|
|
3886113390 | ||
|
|
f3ac025445 | ||
|
|
74f5d77fa9 | ||
|
|
f4defbba14 | ||
|
|
e098dfcb4c | ||
|
|
49d71b7778 | ||
|
|
31013d44c2 | ||
|
|
2ee27f92eb | ||
|
|
182c20f5ca | ||
|
|
669ee3f8ef | ||
|
|
6f314bccc2 | ||
|
|
f65afb52ca | ||
|
|
fcb192829e | ||
|
|
f3d8cd3e09 | ||
|
|
9685a374a2 | ||
|
|
f38603c5b1 | ||
|
|
3d9b38bb6c | ||
|
|
cba57f608e | ||
|
|
adcfcb5462 | ||
|
|
d4e301050c | ||
|
|
0bf8de1dfc | ||
|
|
5eaa7a15a4 | ||
|
|
b88c0a9f46 | ||
|
|
474cb9566a | ||
|
|
e8a2feeee6 | ||
|
|
a85a2033de | ||
|
|
af70b110ef | ||
|
|
f821708c92 | ||
|
|
d17a78b10f | ||
|
|
9ebdad6d68 | ||
|
|
fb083c832e | ||
|
|
64d7df9a3f | ||
|
|
61c29b5f32 | ||
|
|
4bce9de6dc | ||
|
|
a170ca7488 | ||
|
|
208176df9d | ||
|
|
6b400e0b96 | ||
|
|
ffc83152ef | ||
|
|
dd205f6bb3 | ||
|
|
a5c51e8871 | ||
|
|
441221704e | ||
|
|
64cbe840f5 | ||
|
|
e50f69e7c2 | ||
|
|
3041731457 | ||
|
|
1c7e81dc93 | ||
|
|
a589413440 | ||
|
|
eee23b6cab | ||
|
|
73a514a175 | ||
|
|
1adf38a2cb | ||
|
|
72d12ebc09 | ||
|
|
35f1608138 | ||
|
|
dd2460c546 | ||
|
|
8fdb8fa391 | ||
|
|
e6091208dd | ||
|
|
d427d40d3c | ||
|
|
9e339cc1a6 | ||
|
|
8a4a463dc6 | ||
|
|
be7de354e1 | ||
|
|
8d7f385c55 | ||
|
|
6c97f080d1 | ||
|
|
ca9e1e3d16 | ||
|
|
faf47c6862 | ||
|
|
b5b8810af6 | ||
|
|
42d6c1f26a | ||
|
|
d3ac7bd3d6 | ||
|
|
f68edbaf97 | ||
|
|
e6d6794a38 | ||
|
|
19b12e9d2f | ||
|
|
aa6da23a32 | ||
|
|
70d280aae2 | ||
|
|
46719a6a2e | ||
|
|
9af8603dff | ||
|
|
8c2a578976 | ||
| 62ab21f4dc | |||
|
|
0f50d831a9 | ||
|
|
d00b87c851 | ||
|
|
3ca8f9a715 | ||
|
|
b5eb25620a | ||
|
|
2c5449756e | ||
|
|
d453e1f1e1 | ||
|
|
c8035738b4 | ||
|
|
329a3c9c3f | ||
|
|
23a14e88b8 | ||
|
|
726c835078 | ||
|
|
f9495e0736 | ||
|
|
16497b25c0 | ||
|
|
b75b68d8dd | ||
|
|
bd68c1cd16 | ||
|
|
90d617f288 | ||
|
|
0206a1b83f | ||
|
|
7b3ee27adf | ||
|
|
a50e7baa37 | ||
|
|
40bd8bc0f2 | ||
|
|
e24599c964 | ||
|
|
9dd517ee81 | ||
|
|
d2e9ff09de | ||
|
|
02c3d30da0 | ||
|
|
5abe218e82 | ||
|
|
225fbc302a | ||
|
|
177395b943 | ||
|
|
81640397c1 | ||
|
|
206efbd42d | ||
|
|
d973b71048 | ||
|
|
55dd6382c6 | ||
|
|
4c85553696 | ||
|
|
442b4a78ad | ||
|
|
949e0ba3eb | ||
|
|
8706ad643a | ||
|
|
a74f97394a | ||
|
|
d2a74dacfe | ||
|
|
436fc7a274 | ||
|
|
8975d4b7e6 | ||
|
|
982075e135 | ||
|
|
736e02e821 | ||
|
|
3a09f79cf5 | ||
|
|
123a190bc1 | ||
|
|
6c65402412 | ||
|
|
dc4d862732 | ||
|
|
48c40524be | ||
|
|
c858d19154 | ||
|
|
f29376db16 | ||
|
|
76d29b86a3 | ||
|
|
11c5ab903e | ||
|
|
a8a4f7537f | ||
|
|
008e4bee53 | ||
|
|
05248c1bdb | ||
|
|
bcea600768 | ||
|
|
22ea4883fc | ||
|
|
15f9eadb07 | ||
|
|
6802359f8d | ||
|
|
c3923f6005 | ||
|
|
3fb85ec726 | ||
|
|
1ef9a97a02 | ||
|
|
a568043ee6 | ||
|
|
01e76fd3f8 | ||
|
|
0095402f7e | ||
|
|
287fd7ace0 | ||
|
|
96e8b343a0 | ||
|
|
91716bf246 | ||
|
|
51a15ab3ed | ||
|
|
7c1eba4e64 | ||
|
|
e8b0cd81d7 | ||
|
|
7715e7ce0e | ||
|
|
44dbda027e | ||
|
|
b0c5574bd8 | ||
|
|
27abda1c82 | ||
|
|
9da272602e | ||
|
|
713487baa4 | ||
|
|
6d3c540e8e | ||
|
|
bf7ad9d266 | ||
|
|
053f9c63b8 | ||
|
|
c37fce14a6 | ||
|
|
300b1ebaa8 | ||
|
|
80b3ea3fed | ||
|
|
563d2ceae7 | ||
|
|
2c63cdcc9a | ||
|
|
a9b8928a38 | ||
|
|
88fd01055e | ||
|
|
0e7c08a57a | ||
|
|
780fabfa39 | ||
|
|
f0c0af9b64 | ||
|
|
73d65fd482 | ||
|
|
154f01b017 | ||
|
|
3d083094fd | ||
|
|
31a05e1ce7 | ||
|
|
9eab7c704f | ||
|
|
780a6e23d7 | ||
|
|
62a5a4de99 | ||
|
|
5f2ea6233d | ||
|
|
97a3150ca8 | ||
|
|
c04d5b9275 | ||
|
|
6d1293c965 | ||
|
|
e2101a4d09 | ||
|
|
39139752e1 | ||
|
|
f6c533932e | ||
|
|
108dbea146 | ||
|
|
7f1493f854 | ||
|
|
035a6775de | ||
|
|
407c2bb4d1 | ||
|
|
8b73118252 | ||
|
|
7c4097e81c | ||
|
|
13e893a053 | ||
|
|
a1a011243e | ||
| 0fa8f9ab4e | |||
|
|
ee64d15307 | ||
|
|
ad353524a2 | ||
|
|
63ef5066fc | ||
|
|
f67db29dbd | ||
|
|
644f4516d9 | ||
|
|
020ddf44b0 | ||
|
|
16c63d9179 | ||
|
|
39d175cd09 | ||
|
|
35b11bb6b9 | ||
|
|
caa231c9d4 | ||
|
|
50aa81d1b1 | ||
|
|
ca7e16fcd8 | ||
|
|
24a78d63e8 | ||
|
|
9caf603693 | ||
|
|
9bf95115f9 | ||
|
|
7c5d4f672d | ||
|
|
f6cda88c6b | ||
|
|
c91f54051d | ||
|
|
38e6c13866 | ||
|
|
fb80908daf | ||
|
|
6ea5c0eedb | ||
|
|
2717b7e5f6 | ||
|
|
4a58ad4e03 | ||
|
|
3250637318 | ||
|
|
d9680e0686 | ||
|
|
326030ffc7 | ||
|
|
ea7c6337fc | ||
|
|
6a0094f4dd | ||
|
|
0db85a589b | ||
|
|
64a03f4950 | ||
|
|
7f9bbaca67 | ||
|
|
e659987db5 | ||
|
|
ea66fcb157 | ||
|
|
e9c4c622cf | ||
|
|
5005b1770e | ||
|
|
3309034617 | ||
|
|
5aede71093 | ||
|
|
cbbd75ec25 | ||
|
|
2a688db59d | ||
|
|
4c2bc8ea91 | ||
|
|
9cd344a94a | ||
| 4de9363e81 | |||
| b217211737 | |||
| 64a0efdff3 | |||
| 777a840e4b | |||
| 8ff1fc799e | |||
| 5e84c3ee99 | |||
| 419565a535 | |||
| b9a7773ea4 | |||
| 5ea06709df | |||
| 5d13e6f88b | |||
| 00afc4cc05 | |||
|
|
8719a60b9b | ||
|
|
1081357f8b | ||
|
|
73f42d881a | ||
|
|
cfdb0e35ea | ||
|
|
aa40afb03c | ||
|
|
e7549f2976 | ||
|
|
6312aa5584 | ||
|
|
1b16ced5af | ||
|
|
84a7cedaa2 | ||
|
|
ddc7333306 | ||
|
|
2a10dffffc | ||
|
|
b5f0d01dfe | ||
|
|
ff5a172400 | ||
|
|
2fb8574af7 | ||
| 4dea249f49 | |||
| 759607877b | |||
|
|
f4213db2a5 | ||
|
|
430c918b57 | ||
|
|
e29df3366c | ||
|
|
20b3c4a856 | ||
|
|
774c940bcf | ||
| 3cfe1c3ae2 | |||
|
|
f31a8a93a5 | ||
| 652233df4f | |||
|
|
102b740932 | ||
|
|
eb8e8287e5 | ||
|
|
e5a0806a9b | ||
|
|
b77743b490 | ||
|
|
d9cf8ee133 | ||
|
|
32cbb2c506 | ||
|
|
17ffff6e64 | ||
|
|
aa56f6fa50 | ||
|
|
c0a94930d3 | ||
|
|
b08299b856 | ||
|
|
a3f079bd52 | ||
|
|
74699c2387 | ||
|
|
2c9341f516 | ||
|
|
d9c4351e07 | ||
|
|
ab72e5d630 | ||
|
|
4362352e4e | ||
|
|
3e20735bb1 | ||
|
|
df49d2561b | ||
|
|
eaf839f829 | ||
|
|
3c9ee493b5 | ||
|
|
560437e92f | ||
|
|
1f658a6d8b | ||
|
|
d5230581e0 | ||
|
|
51b97d1716 | ||
|
|
46e0936dcd | ||
|
|
2375d4b9e1 | ||
|
|
62efc2266a | ||
|
|
005a944259 | ||
|
|
4167c6f371 | ||
|
|
d529158862 | ||
|
|
11e3fe87ff | ||
|
|
494cf6ba37 | ||
|
|
75afd23d0c | ||
|
|
f7e8bbe6ad | ||
|
|
3e1a059536 | ||
|
|
5a15eae7d4 | ||
|
|
9ccddf574e | ||
|
|
ceb3a02473 | ||
|
|
efaccc8cfe | ||
|
|
5fd92c01f2 | ||
|
|
0c51a0ffab | ||
|
|
794210fea2 | ||
|
|
fd4e3444dd | ||
|
|
004a4da42a | ||
|
|
b15ee3d787 | ||
|
|
7fe50f8800 | ||
|
|
597e7dddb1 | ||
|
|
1dfd0a6f60 | ||
|
|
41f35ec3b1 | ||
|
|
7598f832c4 | ||
|
|
dc6ce45c81 | ||
|
|
d1488fb7d9 | ||
|
|
8fe1d49f7f | ||
|
|
3802df1eee | ||
|
|
41c8cfe2a1 | ||
|
|
e259c609c4 | ||
|
|
1720def3cf | ||
|
|
47da437bce | ||
|
|
8d6c5e034e | ||
|
|
8a202738e2 | ||
|
|
2735149eb5 | ||
|
|
fa59f8315f | ||
|
|
d0305f09b4 | ||
|
|
bd8bf1a8ab | ||
|
|
f7f13e3b49 | ||
|
|
19d0978f12 | ||
|
|
a2a19ed0ad | ||
|
|
41fdec9ad9 | ||
|
|
7a3cc031f0 | ||
|
|
9e0eacaaaf | ||
|
|
2e8b236de3 | ||
|
|
4ae722bca3 | ||
|
|
226ec259a9 | ||
|
|
306dfc877a | ||
|
|
0a1ee78b8e | ||
|
|
7c650e0fba | ||
|
|
08a83c89c9 | ||
|
|
b3fd880a3f | ||
|
|
67d18d5300 | ||
|
|
9293dfcf1d | ||
|
|
98d1cdc04a | ||
|
|
1be521e0be | ||
|
|
90b274a807 | ||
|
|
da286cebce | ||
|
|
af6e673b43 | ||
|
|
1469ec39ed | ||
|
|
6c8497815c | ||
|
|
2220e3d668 | ||
|
|
7517167074 | ||
|
|
4a1f32403a | ||
|
|
8e12d6c721 | ||
|
|
f3e1d6b81a | ||
|
|
23b2a4f779 | ||
|
|
bd7c3cb8ab | ||
|
|
4f6e4ea25e | ||
|
|
47c79e8174 | ||
|
|
7697e57136 | ||
|
|
1598b52aaa | ||
|
|
69b82645b9 | ||
|
|
94511f1276 | ||
|
|
591a209bdb | ||
|
|
cbb0b20a44 | ||
|
|
1876c00e5c | ||
|
|
7df93e4d0d | ||
|
|
00e4481e14 | ||
|
|
2fbba95105 | ||
|
|
5c68552f12 | ||
|
|
025ddf25f4 | ||
|
|
7915389f10 | ||
|
|
708ae2d9ef | ||
|
|
d74e01f964 | ||
|
|
e6d56151a4 | ||
|
|
e3d4a7172f | ||
|
|
360557a439 | ||
|
|
d71531e18f | ||
|
|
beef3e03ca | ||
|
|
0c3a01afeb | ||
|
|
542d546532 | ||
|
|
35dd446cc1 | ||
|
|
17f9688420 | ||
|
|
d4c9d6adb6 | ||
|
|
5ace47ad46 | ||
|
|
5cabdec926 | ||
|
|
9d57d9112a | ||
|
|
4d8d7098c3 | ||
|
|
52cee1edcc | ||
|
|
93f6f8a2f3 | ||
|
|
22579f8705 | ||
|
|
9769d29ca1 | ||
|
|
5a2f223ef4 | ||
|
|
ab1e603c1d | ||
|
|
03899795f8 | ||
|
|
2d124d1582 | ||
|
|
3234a04726 | ||
|
|
f4742cd7c6 | ||
|
|
e05bc617d7 | ||
|
|
a9f82824cf | ||
|
|
fcff874f53 | ||
|
|
fa110ca434 | ||
|
|
ba5799fce3 | ||
|
|
f14c120d98 | ||
|
|
2105ebed55 | ||
|
|
c510c6dcd5 | ||
|
|
34133785e2 | ||
|
|
9dcb4631a6 | ||
|
|
81345f5590 | ||
|
|
0b4d0feb4f | ||
|
|
6b04b76f73 | ||
|
|
a70240599e | ||
|
|
f658ced40f | ||
|
|
863b0f30e6 | ||
|
|
f3edbb18d2 | ||
|
|
552d0a6582 | ||
|
|
805202de6b | ||
|
|
49fa3c2641 | ||
|
|
6f3243fe46 | ||
|
|
421c1d77ca | ||
|
|
b1951eb5ce | ||
|
|
789a64903a | ||
|
|
0ecab7b543 | ||
|
|
13cc2c7fc2 | ||
|
|
eb2f428c36 | ||
|
|
d8a35f2cba | ||
|
|
eea188dc58 | ||
| d6fbb2ebb4 | |||
|
|
c513644921 | ||
| 72e52b0d7f | |||
| c2bb89fcb8 | |||
|
|
78ba3deecf | ||
|
|
a783741357 | ||
|
|
fb2029472f | ||
|
|
1463b64d12 | ||
| 037976e191 | |||
| a6814b9c0e | |||
| b4d30a2fbc | |||
| 952c3345a9 | |||
|
|
cfa4f61604 | ||
|
|
098fe94205 | ||
|
|
2f401b7b7a | ||
| e1bcf07614 | |||
|
|
de54ad562b | ||
|
|
81b2f97cc3 | ||
|
|
e651ff865b | ||
|
|
32498fe1ed | ||
|
|
476c73896f | ||
|
|
14d3756fbe | ||
|
|
18792afc8c | ||
|
|
a5df1c9656 | ||
|
|
fcf8786537 | ||
|
|
d6b6de8f64 | ||
|
|
75c8c8eef0 | ||
|
|
31d792a73d | ||
|
|
f839b3a43b | ||
|
|
0c6efa2fe7 | ||
|
|
9bca118f59 | ||
|
|
5d5ac9750a | ||
|
|
30dd7f806c | ||
|
|
a2a29163d1 | ||
|
|
62563b02a4 | ||
| a10eb63057 | |||
|
|
0180bb4672 | ||
|
|
b7275d4fc5 | ||
|
|
1872ce7f21 | ||
|
|
f1bbae39c4 | ||
|
|
60431b808c | ||
|
|
7b5029c721 | ||
|
|
fbb1cdd58d | ||
|
|
b5f808678c | ||
|
|
a3fd1012f6 | ||
|
|
7c86dc8984 | ||
|
|
ad59d3f514 | ||
| e804e29cab | |||
| 64a134bb52 | |||
| c3899a01b6 | |||
| 0a9d2cc8c7 | |||
| 413e0da3a4 | |||
| 1c8a86f08f | |||
| 25953d69f0 | |||
|
|
f9be51b204 | ||
|
|
3cf494220a | ||
|
|
1eef56a5fb | ||
|
|
d9af575340 | ||
| f96841c025 | |||
|
|
0ba59ff228 | ||
|
|
4692dcab12 | ||
|
|
d9cb8b2077 | ||
|
|
c9b9328008 | ||
|
|
db9408c1bf | ||
|
|
3a1edef655 | ||
|
|
77212804bc | ||
|
|
b25f7ef3c3 | ||
|
|
4a06a058a2 | ||
|
|
d9b38346a4 | ||
|
|
765d40217b | ||
|
|
fa18a19e98 | ||
|
|
3b61545371 | ||
|
|
f354a53718 | ||
|
|
8411ba6295 | ||
|
|
368ab7d7c6 | ||
|
|
829e027cc4 | ||
|
|
6f006a26c7 | ||
|
|
f1758dc56b | ||
|
|
0c4256acc4 | ||
|
|
f3443e70f3 | ||
|
|
36cc5f4a33 | ||
|
|
f81492395a | ||
|
|
dcf231f5fc | ||
|
|
74cd746b06 | ||
|
|
a6c346fa61 | ||
|
|
c25124d86f | ||
| b587e23ae3 | |||
|
|
f0771c1f94 | ||
|
|
ac2641e279 | ||
| dccf6f92f0 | |||
|
|
498f3f0fb6 | ||
|
|
28d500b49b | ||
|
|
9b0d02cd05 | ||
|
|
be3fc76533 | ||
|
|
478ebcca9e | ||
|
|
57fdf5951b | ||
|
|
6172c7a3f4 | ||
|
|
c5caa75392 | ||
|
|
d262553f9a | ||
|
|
a094e80371 | ||
|
|
c7056f0d88 | ||
|
|
0a883974b5 | ||
|
|
31d3b15054 | ||
|
|
c33c478c70 | ||
|
|
0804d363e5 | ||
|
|
11819ee7c5 | ||
|
|
fa2633e47e | ||
|
|
3e8b211afd | ||
|
|
d2a630e799 | ||
|
|
b8c1bce065 | ||
|
|
363678d8af | ||
|
|
f8bbe6110b | ||
|
|
1fd58d657e | ||
|
|
4380b22136 | ||
|
|
5b534a64a8 | ||
| f450e770c9 | |||
| a2454f84f8 | |||
| c4b79a11ae | |||
| 751422b7fe | |||
|
|
e0a0722e85 | ||
|
|
7f8d65cb63 | ||
|
|
d12f3c6e9a | ||
|
|
db558df584 | ||
|
|
d900c1153c | ||
|
|
96adb6c647 | ||
|
|
1967623556 | ||
|
|
fd05209c1a | ||
|
|
fa4f6b14ac | ||
|
|
183041ff50 | ||
|
|
8cdfb60805 | ||
|
|
38cb803bc4 | ||
|
|
6fc13980e9 | ||
|
|
6196472f77 | ||
|
|
d36bae83d5 | ||
|
|
e10577866b | ||
|
|
c18eab1aed | ||
|
|
436240f539 | ||
|
|
39c8bc728d | ||
|
|
6239098129 | ||
|
|
40abf6569c | ||
|
|
a85ac676e3 | ||
|
|
b7b3c8ad48 | ||
| 541f533143 | |||
| b184fe33f2 | |||
|
|
9aeeef9d24 | ||
|
|
f5db43ed6f | ||
|
|
ab621fe74a | ||
|
|
278a472f30 | ||
|
|
ed18ab7908 | ||
|
|
ad3a0dabf3 | ||
|
|
c01e78be60 | ||
|
|
704ed23543 |
3465 changed files with 553749 additions and 9806 deletions
134
.github/workflows/arduino_cron.yml
vendored
Normal file
134
.github/workflows/arduino_cron.yml
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
name: Arduino Library CI
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
|
||||
|
||||
jobs:
|
||||
check-if-needed:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
answer: ${{ steps.is-needed.outputs.answer }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Check if run by adabot
|
||||
id: check-cron
|
||||
run: |
|
||||
iscron=false
|
||||
[[ "${{ github.event_name }}" == "push" && "${{ github.actor }}" == "adafruit-adabot" ]] && iscron=true
|
||||
echo "status=$iscron" >> "$GITHUB_OUTPUT"
|
||||
- name: Check if dispatched
|
||||
id: check-dispatch
|
||||
run: |
|
||||
isdispatch=false
|
||||
[[ "${{ github.event_name }}" == "workflow_dispatch" ]] && isdispatch=true
|
||||
echo "status=$isdispatch" >> "$GITHUB_OUTPUT"
|
||||
- name: Check for Arduino file updates
|
||||
id: check-updated
|
||||
if: ${{ steps.check-cron.outputs.status }} == false && ${{ steps.check-dispatch.outputs.status }} == false
|
||||
run: |
|
||||
changedfiles=$(git diff --name-only -r HEAD^1 HEAD)
|
||||
ischanged=false
|
||||
for changedfile in ${changedfiles[*]}; do
|
||||
echo $changedfile
|
||||
if [[ $changedfile == *.c ]] ||
|
||||
[[ $changedfile == *.cpp ]] ||
|
||||
[[ $changedfile == *.h ]] ||
|
||||
[[ $changedfile == *.hpp ]] ||
|
||||
[[ $changedfile == *.ino ]] ||
|
||||
[[ $changedfile == *.yml ]]; then
|
||||
ischanged=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
echo "status=$ischanged" >> "$GITHUB_OUTPUT"
|
||||
- name: Output Arduino needed
|
||||
id: is-needed
|
||||
run: |
|
||||
isneeded=false
|
||||
if [[ ${{ steps.check-cron.outputs.status }} == true ]] ||
|
||||
[[ ${{ steps.check-dispatch.outputs.status }} == true ]] ||
|
||||
[[ ${{ steps.check-updated.outputs.status }} == true ]]; then
|
||||
isneeded=true
|
||||
fi
|
||||
echo "answer=$isneeded" >> "$GITHUB_OUTPUT"
|
||||
|
||||
arduino:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform: ["cpb", "cpc", "cpx_ada", "esp32", "esp8266", "feather32u4", "feather_esp32c6", "feather_m0_express", "feather_m4_express", "feather_rp2040", "feather_rp2040_adalogger", "feather_rp2350", "flora", "fruit_jam_tinyusb", "funhouse", "gemma", "gemma_m0", "hallowing_m0", "hallowing_m4_tinyusb", "ledglasses_nrf52840", "magtag", "metro_m0", "metro_m0_tinyusb", "metro_m4", "metro_m4_tinyusb", "monster_m4sk", "monster_m4sk_tinyusb", "metro_rp2350", "neokeytrinkey_m0", "neotrellis_m4", "nrf52832", "nrf52840", "pixeltrinkey_m0", "protrinket_5v", "proxlighttrinkey_m0", "pybadge", "pycamera_s3", "pygamer", "pyportal", "qualia_s3_rgb666", "qt2040_trinkey", "qtpy_m0", "qtpy_esp32s2", "rotarytrinkey_m0", "sht4xtrinkey_m0", "slidetrinkey_m0", "trinket_5v", "trinket_m0", "uno"]
|
||||
runs-on: ubuntu-latest
|
||||
if: needs.check-if-needed.outputs.answer == 'true'
|
||||
needs: check-if-needed
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
# Checkout the learn repo itself
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Checkout the CI scripts
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
# manually install some libraries
|
||||
- name: extra libraries
|
||||
run: |
|
||||
git clone --quiet https://github.com/adafruit/Cryptosuite.git /home/runner/Arduino/libraries/Cryptosuite
|
||||
git clone --quiet https://github.com/adafruit/WiFiNINA.git /home/runner/Arduino/libraries/WiFiNINA
|
||||
git clone --quiet https://github.com/adafruit/Adafruit_LSM303.git /home/runner/Arduino/libraries/Adafruit_LSM303
|
||||
git clone --quiet https://github.com/moderndevice/CapSense.git /home/runner/Arduino/libraries/CapSense
|
||||
git clone --quiet https://github.com/PaintYourDragon/ffft.git /home/runner/Arduino/libraries/ffft
|
||||
git clone --quiet https://github.com/adafruit/RadioHead.git /home/runner/Arduino/libraries/RadioHead
|
||||
git clone --quiet https://github.com/me-no-dev/ESPAsyncTCP /home/runner/Arduino/libraries/ESPAsyncTCP
|
||||
git clone --quiet https://github.com/adafruit/Talkie /home/runner/Arduino/libraries/Talkie
|
||||
git clone --quiet https://github.com/Infineon/arduino-optiga-trust-m /home/runner/Arduino/libraries/arduinoOptigaTrustM
|
||||
git clone --quiet https://github.com/adafruit/HID /home/runner/Arduino/libraries/HID_Project
|
||||
rm -rf /home/runner/Arduino/libraries/ArduinoHttpClient
|
||||
git clone --quiet https://github.com/arduino-libraries/ArduinoHttpClient.git /home/runner/Arduino/libraries/ArduinoHttpClient
|
||||
git clone --quiet https://github.com/pschatzmann/ESP32-A2DP /home/runner/Arduino/libraries/ESP32-A2DP
|
||||
git clone --quiet https://github.com/pschatzmann/arduino-audio-tools /home/runner/Arduino/libraries/arduino-audio-tools
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ github.event.repository.name }}.${{ github.sha }}
|
||||
path: |
|
||||
build/*.hex
|
||||
build/*.bin
|
||||
build/*.uf2
|
||||
|
||||
- name: Zip release files
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
if [ -d build ]; then
|
||||
(
|
||||
echo "Built from Adafruit Learning System Guides `git describe --tags` for ${{ matrix.arduino-platform }}"
|
||||
echo "Source code: https://github.com/adafruit/"
|
||||
echo "Adafruit Learning System: https://learn.adafruit.com/"
|
||||
) > build/README.txt
|
||||
cd build && zip -9 -o ${{ matrix.arduino-platform }}.zip *.hex *.bin *.uf2 *.txt
|
||||
fi
|
||||
|
||||
- name: Create release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: build/${{ matrix.arduino-platform }}.zip
|
||||
fail_on_unmatched_files: false
|
||||
body: "Select the zip file corresponding to your board from the list below."
|
||||
79
.github/workflows/githubci.yml
vendored
79
.github/workflows/githubci.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Arduino Library CI
|
||||
name: SPDX and Pylint
|
||||
|
||||
on: [pull_request, push, repository_dispatch]
|
||||
|
||||
|
|
@ -6,89 +6,20 @@ jobs:
|
|||
spdx:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: check SPDX licensing
|
||||
run: python ./SPDX.py
|
||||
|
||||
arduino:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform: ["cpb", "cpc", "cpx_ada", "esp32", "esp8266", "feather32u4", "feather_m0_express", "feather_m4_express", "feather_rp2040", "flora", "funhouse", "gemma", "gemma_m0", "hallowing_m0", "hallowing_m4_tinyusb", "magtag", "metro_m0", "metro_m0_tinyusb", "metro_m4", "metro_m4_tinyusb", "monster_m4sk", "monster_m4sk_tinyusb", "neokeytrinkey_m0", "neotrellis_m4", "nrf52832", "nrf52840", "protrinket_5v", "proxlighttrinkey_m0", "pybadge", "pygamer", "pyportal", "qt2040_trinkey", "qtpy_m0", "qtpy_esp32s2", "rotarytrinkey_m0", "slidetrinkey_m0", "trinket_m0", "uno", "trinket_5v", "ledglasses_nrf52840" ]
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
# manually install some libraries
|
||||
- name: extra libraries
|
||||
run: |
|
||||
git clone --quiet https://github.com/adafruit/Cryptosuite.git /home/runner/Arduino/libraries/Cryptosuite
|
||||
git clone --quiet https://github.com/adafruit/WiFiNINA.git /home/runner/Arduino/libraries/WiFiNINA
|
||||
git clone --quiet https://github.com/adafruit/Adafruit_LSM303.git /home/runner/Arduino/libraries/Adafruit_LSM303
|
||||
git clone --quiet https://github.com/moderndevice/CapSense.git /home/runner/Arduino/libraries/CapSense
|
||||
git clone --quiet https://github.com/PaintYourDragon/ffft.git /home/runner/Arduino/libraries/ffft
|
||||
git clone --quiet https://github.com/adafruit/RadioHead.git /home/runner/Arduino/libraries/RadioHead
|
||||
git clone --quiet https://github.com/me-no-dev/ESPAsyncTCP /home/runner/Arduino/libraries/ESPAsyncTCP
|
||||
git clone --quiet https://github.com/adafruit/Talkie /home/runner/Arduino/libraries/Talkie
|
||||
git clone --quiet https://github.com/Infineon/arduino-optiga-trust-m /home/runner/Arduino/libraries/arduinoOptigaTrustM
|
||||
git clone --quiet https://github.com/adafruit/HID /home/runner/Arduino/libraries/HID_Project
|
||||
rm -rf /home/runner/Arduino/libraries/ArduinoHttpClient
|
||||
git clone --quiet https://github.com/arduino-libraries/ArduinoHttpClient.git /home/runner/Arduino/libraries/ArduinoHttpClient
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
||||
|
||||
- name: Upload build artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ github.event.repository.name }}.${{ github.sha }}
|
||||
path: |
|
||||
build/*.hex
|
||||
build/*.bin
|
||||
build/*.uf2
|
||||
|
||||
- name: Zip release files
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: |
|
||||
if [ -d build ]; then
|
||||
(
|
||||
echo "Built from Adafruit Learning System Guides `git describe --tags` for ${{ matrix.arduino-platform }}"
|
||||
echo "Source code: https://github.com/adafruit/"
|
||||
echo "Adafruit Learning System: https://learn.adafruit.com/"
|
||||
) > build/README.txt
|
||||
cd build && zip -9 -o ${{ matrix.arduino-platform }}.zip *.hex *.bin *.uf2 *.txt
|
||||
fi
|
||||
|
||||
- name: Create release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: build/${{ matrix.arduino-platform }}.zip
|
||||
fail_on_unmatched_files: false
|
||||
body: "Select the zip file corresponding to your board from the list below."
|
||||
|
||||
pylint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Python 3.10
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Versions
|
||||
|
|
@ -98,7 +29,7 @@ jobs:
|
|||
run: |
|
||||
pip install --force-reinstall pylint==2.7.1
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: lint
|
||||
run: ./pylint_check.sh
|
||||
|
|
|
|||
4
.github/workflows/images.yml
vendored
4
.github/workflows/images.yml
vendored
|
|
@ -21,10 +21,10 @@ jobs:
|
|||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python 3.x
|
||||
uses: actions/setup-python@v4
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
|
|
|
|||
622
16bit_hello_picowbell_dvi/16bit_hello_picowbell_dvi.ino
Normal file
622
16bit_hello_picowbell_dvi/16bit_hello_picowbell_dvi.ino
Normal file
|
|
@ -0,0 +1,622 @@
|
|||
// SPDX-FileCopyrightText: 2023 Phil B. for Adafruit Industries
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Basic full-color PicoDVI test. Provides a 16-bit color video framebuffer to
|
||||
// which Adafruit_GFX calls can be made. It's based on the EYESPI_Test.ino sketch.
|
||||
|
||||
#include <PicoDVI.h> // Core display & graphics library
|
||||
#include <Fonts/FreeSansBold18pt7b.h> // A custom font
|
||||
|
||||
// Here's how a 320x240 16-bit color framebuffer is declared. Double-buffering
|
||||
// is not an option in 16-bit color mode, just not enough RAM; all drawing
|
||||
// operations are shown as they occur. Second argument is a hardware
|
||||
// configuration -- examples are written for Adafruit Feather RP2040 DVI, but
|
||||
// that's easily switched out for boards like the Pimoroni Pico DV (use
|
||||
// 'pimoroni_demo_hdmi_cfg') or Pico DVI Sock ('pico_sock_cfg').
|
||||
DVIGFX16 display(DVI_RES_320x240p60, adafruit_dvibell_cfg);
|
||||
|
||||
// A 400x240 mode is possible but pushes overclocking even higher than
|
||||
// 320x240 mode. SOME BOARDS MIGHT SIMPLY NOT BE COMPATIBLE WITH THIS.
|
||||
// May require selecting QSPI div4 clock (Tools menu) to slow down flash
|
||||
// accesses, may require further over-volting the CPU to 1.25 or 1.3 V.
|
||||
//DVIGFX16 display(DVI_RES_400x240p60, adafruit_feather_dvi_cfg);
|
||||
|
||||
void setup() { // Runs once on startup
|
||||
if (!display.begin()) { // Blink LED if insufficient RAM
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
#define PAUSE 2000 // Delay (milliseconds) between examples
|
||||
uint8_t rotate = 0; // Current screen orientation (0-3)
|
||||
#define CORNER_RADIUS 0
|
||||
|
||||
void loop() {
|
||||
// Each of these functions demonstrates a different Adafruit_GFX concept:
|
||||
show_shapes();
|
||||
show_charts();
|
||||
show_basic_text();
|
||||
show_char_map();
|
||||
show_custom_text();
|
||||
show_bitmap();
|
||||
show_canvas();
|
||||
|
||||
if (++rotate > 3) rotate = 0; // Cycle through screen rotations 0-3
|
||||
display.setRotation(rotate); // Takes effect on next drawing command
|
||||
}
|
||||
|
||||
// BASIC SHAPES EXAMPLE ----------------------------------------------------
|
||||
|
||||
void show_shapes() {
|
||||
// Draw outlined and filled shapes. This demonstrates:
|
||||
// - Enclosed shapes supported by GFX (points & lines are shown later).
|
||||
// - Adapting to different-sized displays, and to rounded corners.
|
||||
|
||||
const int16_t cx = display.width() / 2; // Center of screen =
|
||||
const int16_t cy = display.height() / 2; // half of width, height
|
||||
int16_t minor = min(cx, cy); // Lesser of half width or height
|
||||
// Shapes will be drawn in a square region centered on the screen. But one
|
||||
// particular screen -- rounded 240x280 ST7789 -- has VERY rounded corners
|
||||
// that would clip a couple of shapes if drawn full size. If using that
|
||||
// screen type, reduce area by a few pixels to avoid drawing in corners.
|
||||
if (CORNER_RADIUS > 40) minor -= 4;
|
||||
const uint8_t pad = 5; // Space between shapes is 2X this
|
||||
const int16_t size = minor - pad; // Shapes are this width & height
|
||||
const int16_t half = size / 2; // 1/2 of shape size
|
||||
|
||||
display.fillScreen(0); // Start by clearing the screen; color 0 = black
|
||||
|
||||
// Draw outline version of basic shapes: rectangle, triangle, circle and
|
||||
// rounded rectangle in different colors. Rather than hardcoded numbers
|
||||
// for position and size, some arithmetic helps adapt to screen dimensions.
|
||||
display.drawRect(cx - minor, cy - minor, size, size, 0xF800);
|
||||
display.drawTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
|
||||
cx + minor - 1, cy - pad, 0x07E0);
|
||||
display.drawCircle(cx - pad - half, cy + pad + half, half, 0x001F);
|
||||
display.drawRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
|
||||
delay(PAUSE);
|
||||
|
||||
// Draw same shapes, same positions, but filled this time.
|
||||
display.fillRect(cx - minor, cy - minor, size, size, 0xF800);
|
||||
display.fillTriangle(cx + pad, cy - pad, cx + pad + half, cy - minor,
|
||||
cx + minor - 1, cy - pad, 0x07E0);
|
||||
display.fillCircle(cx - pad - half, cy + pad + half, half, 0x001F);
|
||||
display.fillRoundRect(cx + pad, cy + pad, size, size, size / 5, 0xFFE0);
|
||||
delay(PAUSE);
|
||||
} // END SHAPE EXAMPLE
|
||||
|
||||
// CHART EXAMPLES ----------------------------------------------------------
|
||||
|
||||
void show_charts() {
|
||||
// Draw some graphs and charts. GFX library doesn't handle these as native
|
||||
// object types, but it only takes a little code to build them from simple
|
||||
// shapes. This demonstrates:
|
||||
// - Drawing points and horizontal, vertical and arbitrary lines.
|
||||
// - Adapting to different-sized displays.
|
||||
// - Graphics being clipped off edge.
|
||||
// - Use of negative values to draw shapes "backward" from an anchor point.
|
||||
// - C technique for finding array size at runtime (vs hardcoding).
|
||||
|
||||
display.fillScreen(0); // Clear screen
|
||||
|
||||
const int16_t cx = display.width() / 2; // Center of screen =
|
||||
const int16_t cy = display.height() / 2; // half of width, height
|
||||
const int16_t minor = min(cx, cy); // Lesser of half width or height
|
||||
const int16_t major = max(cx, cy); // Greater of half width or height
|
||||
|
||||
// Let's start with a relatively simple sine wave graph with axes.
|
||||
// Draw graph axes centered on screen. drawFastHLine() and drawFastVLine()
|
||||
// need fewer arguments than normal 2-point line drawing shown later.
|
||||
display.drawFastHLine(0, cy, display.width(), 0x0210); // Dark blue
|
||||
display.drawFastVLine(cx, 0, display.height(), 0x0210);
|
||||
|
||||
// Then draw some tick marks along the axes. To keep this code simple,
|
||||
// these aren't to any particular scale, but a real program may want that.
|
||||
// The loop here draws them from the center outward and pays no mind
|
||||
// whether the screen is rectangular; any ticks that go off-screen will
|
||||
// be clipped by the library.
|
||||
for (uint8_t i=1; i<=10; i++) {
|
||||
// The Arduino map() function scales an input value (e.g. "i") from an
|
||||
// input range (0-10 here) to an output range (0 to major-1 here).
|
||||
// Very handy for making graphics adjust to different screens!
|
||||
int16_t n = map(i, 0, 10, 0, major - 1); // Tick offset relative to center point
|
||||
display.drawFastVLine(cx - n, cy - 5, 11, 0x210);
|
||||
display.drawFastVLine(cx + n, cy - 5, 11, 0x210);
|
||||
display.drawFastHLine(cx - 5, cy - n, 11, 0x210);
|
||||
display.drawFastHLine(cx - 5, cy + n, 11, 0x210);
|
||||
}
|
||||
|
||||
// Then draw sine wave over this using GFX drawPixel() function.
|
||||
for (int16_t x=0; x<display.width(); x++) { // Each column of screen...
|
||||
// Note the inverted Y axis here (cy-value rather than cy+value)
|
||||
// because GFX, like most graphics libraries, has +Y heading down,
|
||||
// vs. classic Cartesian coords which have +Y heading up.
|
||||
int16_t y = cy - (int16_t)(sin((x - cx) * 0.05) * (float)minor * 0.5);
|
||||
display.drawPixel(x, y, 0xFFFF);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
// Next, let's draw some charts...
|
||||
// NOTE: some other examples in this code take extra steps to avoid placing
|
||||
// anything off in the rounded corners of certain displays. The charts do
|
||||
// not. It's *possible* but would introduce a lot of complexity into code
|
||||
// that's trying to show the basics. We'll leave the clipped charts here as
|
||||
// a teachable moment: not all content suits all displays.
|
||||
|
||||
// A list of data to plot. These are Y values only; X assumed equidistant.
|
||||
const uint8_t data[] = { 31, 42, 36, 58, 67, 88 }; // Percentages, 0-100
|
||||
const uint8_t num_points = sizeof data / sizeof data[0]; // Length of data[] list
|
||||
|
||||
display.fillScreen(0); // Clear screen
|
||||
display.setFont(); // Use default (built-in) font
|
||||
display.setTextSize(2); // and 2X size for chart label
|
||||
|
||||
// Chart label is centered manually; 144 is the width in pixels of
|
||||
// "Widget Sales" at 2X scale (12 chars * 6 px * 2 = 144). A later example
|
||||
// shows automated centering based on string.
|
||||
display.setCursor((display.width() - 144) / 2, 0);
|
||||
display.print(F("Widget Sales")); // F("string") is in program memory, not RAM
|
||||
// The chart-drawing code is then written to skip the top 20 rows where
|
||||
// this label is located.
|
||||
|
||||
// First, a line chart, connecting the values point-to-point:
|
||||
|
||||
// Draw a grid of lines to provide scale & an interesting background.
|
||||
for (uint8_t i=0; i<11; i++) {
|
||||
int16_t x = map(i, 0, 10, 0, display.width() - 1); // Scale grid X to screen
|
||||
display.drawFastVLine(x, 20, display.height(), 0x001F);
|
||||
int16_t y = map(i, 0, 10, 20, display.height() - 1); // Scale grid Y to screen
|
||||
display.drawFastHLine(0, y, display.width(), 0x001F);
|
||||
}
|
||||
// And then draw lines connecting data points. Load up the first point...
|
||||
int16_t prev_x = 0;
|
||||
int16_t prev_y = map(data[0], 0, 100, display.height() - 1, 20);
|
||||
// Then connect lines to each subsequent point...
|
||||
for (uint8_t i=1; i<num_points; i++) {
|
||||
int16_t new_x = map(i, 0, num_points - 1, 0, display.width() - 1);
|
||||
int16_t new_y = map(data[i], 0, 100, display.height() - 1, 20);
|
||||
display.drawLine(prev_x, prev_y, new_x, new_y, 0x07FF);
|
||||
prev_x = new_x;
|
||||
prev_y = new_y;
|
||||
}
|
||||
// For visual interest, let's add a circle around each data point. This is
|
||||
// done in a second pass so the circles are always drawn "on top" of lines.
|
||||
for (uint8_t i=0; i<num_points; i++) {
|
||||
int16_t x = map(i, 0, num_points - 1, 0, display.width() - 1);
|
||||
int16_t y = map(data[i], 0, 100, display.height() - 1, 20);
|
||||
display.drawCircle(x, y, 5, 0xFFFF);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
// Then a bar chart of the same data...
|
||||
|
||||
// Erase the old chart but keep the label at top.
|
||||
display.fillRect(0, 20, display.width(), display.height() - 20, 0);
|
||||
|
||||
// Just draw the Y axis lines; bar chart doesn't really need X lines.
|
||||
for (uint8_t i=0; i<11; i++) {
|
||||
int16_t y = map(i, 0, 10, 20, display.height() - 1);
|
||||
display.drawFastHLine(0, y, display.width(), 0x001F);
|
||||
}
|
||||
|
||||
int bar_width = display.width() / num_points - 4; // 2px pad to either side
|
||||
for (uint8_t i=0; i<num_points; i++) {
|
||||
int16_t x = map(i, 0, num_points, 0, display.width()) + 2; // Left edge of bar
|
||||
int16_t height = map(data[i], 0, 100, 0, display.height() - 20);
|
||||
// Some GFX functions (rects, H/V lines and similar) can accept negative
|
||||
// width/height values. What this does is anchor the shape at the right or
|
||||
// bottom coordinate (rather than the usual left/top) and draw back from
|
||||
// there, hence the -height here (bar is anchored at bottom of screen):
|
||||
display.fillRect(x, display.height() - 1, bar_width, -height, 0xFFE0);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
|
||||
} // END CHART EXAMPLES
|
||||
|
||||
// TEXT ALIGN FUNCTIONS ----------------------------------------------------
|
||||
|
||||
// Adafruit_GFX only handles left-aligned text. This is normal and by design;
|
||||
// it's a rare need that would further strain AVR by incurring a ton of extra
|
||||
// code to properly handle, and some details would confuse. If needed, these
|
||||
// functions give a fair approximation, with the "gotchas" that multi-line
|
||||
// input won't work, and this operates only as a println(), not print()
|
||||
// (though, unlike println(), cursor X does not reset to column 0, instead
|
||||
// returning to initial column and downward by font's line spacing). If you
|
||||
// can work with those constraints, it's a modest amount of code to copy
|
||||
// into a project. Or, if your project only needs one or two aligned strings,
|
||||
// simply use getTextBounds() for a bounding box and work from there.
|
||||
// DO NOT ATTEMPT TO MAKE THIS A GFX-NATIVE FEATURE, EVERYTHING WILL BREAK.
|
||||
|
||||
typedef enum { // Alignment options passed to functions below
|
||||
GFX_ALIGN_LEFT,
|
||||
GFX_ALIGN_CENTER,
|
||||
GFX_ALIGN_RIGHT
|
||||
} GFXalign;
|
||||
|
||||
// Draw text aligned relative to current cursor position. Arguments:
|
||||
// gfx : An Adafruit_GFX-derived type (e.g. display or canvas object).
|
||||
// str : String to print (as a char *).
|
||||
// align : One of the GFXalign values declared above.
|
||||
// GFX_ALIGN_LEFT is normal left-aligned println() behavior.
|
||||
// GFX_ALIGN_CENTER prints centered on cursor pos.
|
||||
// GFX_ALIGN_RIGHT prints right-aligned to cursor pos.
|
||||
// Cursor advances down one line a la println(). Column is unchanged.
|
||||
void print_aligned(Adafruit_GFX &gfx, const char *str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
uint16_t w, h;
|
||||
int16_t x, y, cursor_x, cursor_x_save;
|
||||
cursor_x = cursor_x_save = gfx.getCursorX();
|
||||
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
|
||||
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
|
||||
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
|
||||
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
|
||||
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
|
||||
gfx.println(str);
|
||||
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
|
||||
}
|
||||
|
||||
// Equivalent function for strings in flash memory (e.g. F("Foo")). Body
|
||||
// appears identical to above function, but with C++ overloading it it works
|
||||
// from flash instead of RAM. Any changes should be made in both places.
|
||||
void print_aligned(Adafruit_GFX &gfx, const __FlashStringHelper *str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
uint16_t w, h;
|
||||
int16_t x, y, cursor_x, cursor_x_save;
|
||||
cursor_x = cursor_x_save = gfx.getCursorX();
|
||||
gfx.getTextBounds(str, 0, gfx.getCursorY(), &x, &y, &w, &h);
|
||||
if (align == GFX_ALIGN_RIGHT) cursor_x -= w;
|
||||
else if (align == GFX_ALIGN_CENTER) cursor_x -= w / 2;
|
||||
//gfx.drawRect(cursor_x, y, w, h, 0xF800); // Debug rect
|
||||
gfx.setCursor(cursor_x - x, gfx.getCursorY()); // Center/right align
|
||||
gfx.println(str);
|
||||
gfx.setCursor(cursor_x_save, gfx.getCursorY()); // Restore cursor X
|
||||
}
|
||||
|
||||
// Equivalent function for Arduino Strings; converts to C string (char *)
|
||||
// and calls corresponding print_aligned() implementation.
|
||||
void print_aligned(Adafruit_GFX &gfx, const String &str,
|
||||
GFXalign align = GFX_ALIGN_LEFT) {
|
||||
print_aligned(gfx, const_cast<char *>(str.c_str()));
|
||||
}
|
||||
|
||||
// TEXT EXAMPLES -----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - Using the default 5x7 built-in font, including scaling in each axis.
|
||||
// - How to access all characters of this font, including symbols.
|
||||
// - Using a custom font, including alignment techniques that aren't a normal
|
||||
// part of the GFX library (uses functions above).
|
||||
|
||||
void show_basic_text() {
|
||||
// Show text scaling with built-in font.
|
||||
display.fillScreen(0);
|
||||
display.setFont(); // Use default font
|
||||
display.setCursor(0, CORNER_RADIUS); // Initial cursor position
|
||||
display.setTextSize(1); // Default size
|
||||
display.println(F("Standard built-in font"));
|
||||
display.setTextSize(2);
|
||||
display.println(F("BIG TEXT"));
|
||||
display.setTextSize(3);
|
||||
// "BIGGER TEXT" won't fit on narrow screens, so abbreviate there.
|
||||
display.println((display.width() >= 200) ? F("BIGGER TEXT") : F("BIGGER"));
|
||||
display.setTextSize(2, 4);
|
||||
display.println(F("TALL and"));
|
||||
display.setTextSize(4, 2);
|
||||
display.println(F("WIDE"));
|
||||
|
||||
delay(PAUSE);
|
||||
} // END BASIC TEXT EXAMPLE
|
||||
|
||||
void show_char_map() {
|
||||
// "Code Page 437" is a name given to the original IBM PC character set.
|
||||
// Despite age and limited language support, still seen in small embedded
|
||||
// settings as it has some useful symbols and accented characters. The
|
||||
// default 5x7 pixel font of Adafruit_GFX is modeled after CP437. This
|
||||
// function draws a table of all the characters & explains some issues.
|
||||
|
||||
// There are 256 characters in all. Draw table as 16 rows of 16 columns,
|
||||
// plus hexadecimal row & column labels. How big can each cell be drawn?
|
||||
const int cell_size = min(display.width(), display.height()) / 17;
|
||||
if (cell_size < 8) return; // Screen is too small for table, skip example.
|
||||
const int total_size = cell_size * 17; // 16 cells + 1 row or column label
|
||||
|
||||
// Set up for default 5x7 font at 1:1 scale. Custom fonts are NOT used
|
||||
// here as most are only 128 characters to save space (the "7b" at the
|
||||
// end of many GFX font names means "7 bits," i.e. 128 characters).
|
||||
display.setFont();
|
||||
display.setTextSize(1);
|
||||
|
||||
// Early Adafruit_GFX was missing one symbol, throwing off some indices!
|
||||
// But fixing the library would break MANY existing sketches that relied
|
||||
// on the degrees symbol and others. The default behavior is thus "broken"
|
||||
// to keep older code working. New code can access the CORRECT full CP437
|
||||
// table by calling this function like so:
|
||||
display.cp437(true);
|
||||
|
||||
display.fillScreen(0);
|
||||
|
||||
const int16_t x = (display.width() - total_size) / 2; // Upper left corner of
|
||||
int16_t y = (display.height() - total_size) / 2; // table centered on screen
|
||||
if (y >= 4) { // If there's a little extra space above & below, scoot table
|
||||
y += 4; // down a few pixels and show a message centered at top.
|
||||
display.setCursor((display.width() - 114) / 2, 0); // 114 = pixel width
|
||||
display.print(F("CP437 Character Map")); // of this message
|
||||
}
|
||||
|
||||
const int16_t inset_x = (cell_size - 5) / 2; // To center each character within cell,
|
||||
const int16_t inset_y = (cell_size - 8) / 2; // compute X & Y offset from corner.
|
||||
|
||||
for (uint8_t row=0; row<16; row++) { // 16 down...
|
||||
// Draw row and columm headings as hexadecimal single digits. To get the
|
||||
// hex value for a specific character, combine the left & top labels,
|
||||
// e.g. Pi symbol is row E, column 3, thus: display.print((char)0xE3);
|
||||
display.setCursor(x + (row + 1) * cell_size + inset_x, y + inset_y);
|
||||
display.print(row, HEX); // This actually draws column labels
|
||||
display.setCursor(x + inset_x, y + (row + 1) * cell_size + inset_y);
|
||||
display.print(row, HEX); // and THIS is the row labels
|
||||
for (uint8_t col=0; col<16; col++) { // 16 across...
|
||||
if ((row + col) & 1) { // Fill alternating cells w/gray
|
||||
display.fillRect(x + (col + 1) * cell_size, y + (row + 1) * cell_size,
|
||||
cell_size, cell_size, 0x630C);
|
||||
}
|
||||
// drawChar() bypasses usual cursor positioning to go direct to an X/Y
|
||||
// location. If foreground & background match, it's drawn transparent.
|
||||
display.drawChar(x + (col + 1) * cell_size + inset_x,
|
||||
y + (row + 1) * cell_size + inset_y, row * 16 + col,
|
||||
0xFFFF, 0xFFFF, 1);
|
||||
}
|
||||
}
|
||||
|
||||
delay(PAUSE * 2);
|
||||
} // END CHAR MAP EXAMPLE
|
||||
|
||||
void show_custom_text() {
|
||||
// Show use of custom fonts, plus how to do center or right alignment
|
||||
// using some additional functions provided earlier.
|
||||
|
||||
display.fillScreen(0);
|
||||
display.setFont(&FreeSansBold18pt7b);
|
||||
display.setTextSize(1);
|
||||
display.setTextWrap(false); // Allow text off edges
|
||||
|
||||
// Get "M height" of custom font and move initial base line there:
|
||||
uint16_t w, h;
|
||||
int16_t x, y;
|
||||
display.getTextBounds("M", 0, 0, &x, &y, &w, &h);
|
||||
// On rounded 240x280 display in tall orientation, "Custom Font" gets
|
||||
// clipped by top corners. Scoot text down a few pixels in that one case.
|
||||
if (CORNER_RADIUS && (display.height() == 280)) h += 20;
|
||||
display.setCursor(display.width() / 2, h);
|
||||
|
||||
if (display.width() >= 200) {
|
||||
print_aligned(display, F("Custom Font"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(0, display.getCursorY() + 10);
|
||||
print_aligned(display, F("Align Left"), GFX_ALIGN_LEFT);
|
||||
display.setCursor(display.width() / 2, display.getCursorY());
|
||||
print_aligned(display, F("Centered"), GFX_ALIGN_CENTER);
|
||||
// Small rounded screen, when oriented the wide way, "Right" gets
|
||||
// clipped by bottom right corner. Scoot left to compensate.
|
||||
int16_t x_offset = (CORNER_RADIUS && (display.height() < 200)) ? 15 : 0;
|
||||
display.setCursor(display.width() - x_offset, display.getCursorY());
|
||||
print_aligned(display, F("Align Right"), GFX_ALIGN_RIGHT);
|
||||
} else {
|
||||
// On narrow screens, use abbreviated messages
|
||||
print_aligned(display, F("Font &"), GFX_ALIGN_CENTER);
|
||||
print_aligned(display, F("Align"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(0, display.getCursorY() + 10);
|
||||
print_aligned(display, F("Left"), GFX_ALIGN_LEFT);
|
||||
display.setCursor(display.width() / 2, display.getCursorY());
|
||||
print_aligned(display, F("Center"), GFX_ALIGN_CENTER);
|
||||
display.setCursor(display.width(), display.getCursorY());
|
||||
print_aligned(display, F("Right"), GFX_ALIGN_RIGHT);
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
} // END CUSTOM FONT EXAMPLE
|
||||
|
||||
// BITMAP EXAMPLE ----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - Embedding a small bitmap in the code (flash memory).
|
||||
// - Drawing that bitmap in various colors, and transparently (only '1' bits
|
||||
// are drawn; '0' bits are skipped, leaving screen contents in place).
|
||||
// - Use of the color565() function to decimate 24-bit RGB to 16 bits.
|
||||
|
||||
#define HEX_WIDTH 16 // Bitmap width in pixels
|
||||
#define HEX_HEIGHT 16 // Bitmap height in pixels
|
||||
// Bitmap data. PROGMEM ensures it's in flash memory (not RAM). And while
|
||||
// it would be valid to leave the brackets empty here (i.e. hex_bitmap[]),
|
||||
// having dimensions with a little math makes the compiler verify the
|
||||
// correct number of bytes are present in the list.
|
||||
PROGMEM const uint8_t hex_bitmap[(HEX_WIDTH + 7) / 8 * HEX_HEIGHT] = {
|
||||
0b00000001, 0b10000000,
|
||||
0b00000111, 0b11100000,
|
||||
0b00011111, 0b11111000,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b01111111, 0b11111110,
|
||||
0b00011111, 0b11111000,
|
||||
0b00000111, 0b11100000,
|
||||
0b00000001, 0b10000000,
|
||||
};
|
||||
#define Y_SPACING (HEX_HEIGHT - 2) // Used by code below for positioning
|
||||
|
||||
void show_bitmap() {
|
||||
display.fillScreen(0);
|
||||
|
||||
// Not screen center, but UL coordinates of center hexagon bitmap
|
||||
const int16_t center_x = (display.width() - HEX_WIDTH) / 2;
|
||||
const int16_t center_y = (display.height() - HEX_HEIGHT) / 2;
|
||||
const uint8_t steps = min((display.height() - HEX_HEIGHT) / Y_SPACING,
|
||||
display.width() / HEX_WIDTH - 1) / 2;
|
||||
|
||||
display.drawBitmap(center_x, center_y, hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
0xFFFF); // Draw center hexagon in white
|
||||
|
||||
// Tile the hexagon bitmap repeatedly in a range of hues. Don't mind the
|
||||
// bit of repetition in the math, the optimizer easily picks this up.
|
||||
// Also, if math looks odd, keep in mind "PEMDAS" operator precedence;
|
||||
// multiplication and division occur before addition and subtraction.
|
||||
for (uint8_t a=0; a<=steps; a++) {
|
||||
for (uint8_t b=1; b<=steps; b++) {
|
||||
display.drawBitmap( // Right section centered red: a = green, b = blue
|
||||
center_x + (a + b) * HEX_WIDTH / 2,
|
||||
center_y + (a - b) * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255, 255 - 255 * a / steps, 255 - 255 * b / steps));
|
||||
display.drawBitmap( // UL section centered green: a = blue, b = red
|
||||
center_x - b * HEX_WIDTH + a * HEX_WIDTH / 2,
|
||||
center_y - a * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255 - 255 * b / steps, 255, 255 - 255 * a / steps));
|
||||
display.drawBitmap( // LL section centered blue: a = red, b = green
|
||||
center_x - a * HEX_WIDTH + b * HEX_WIDTH / 2,
|
||||
center_y + b * Y_SPACING,
|
||||
hex_bitmap, HEX_WIDTH, HEX_HEIGHT,
|
||||
display.color565(255 - 255 * a / steps, 255 - 255 * b / steps, 255));
|
||||
}
|
||||
}
|
||||
|
||||
delay(PAUSE);
|
||||
} // END BITMAP EXAMPLE
|
||||
|
||||
// CANVAS EXAMPLE ----------------------------------------------------------
|
||||
|
||||
// This section demonstrates:
|
||||
// - How to refresh changing values onscreen without erase/redraw flicker.
|
||||
// - Using an offscreen canvas. It's similar to a bitmap above, but rather
|
||||
// than a fixed pattern in flash memory, it's drawable like the screen.
|
||||
// - More tips on text alignment, and adapting to different screen sizes.
|
||||
|
||||
#define PADDING 6 // Pixels between axis label and value
|
||||
|
||||
void show_canvas() {
|
||||
// For this example, let's suppose we want to display live readings from a
|
||||
// sensor such as a three-axis accelerometer, something like:
|
||||
// X: (number)
|
||||
// Y: (number)
|
||||
// Z: (number)
|
||||
// To look extra classy, we want a custom font, and the labels for each
|
||||
// axis are right-aligned so the ':' characters line up...
|
||||
|
||||
display.setFont(&FreeSansBold18pt7b); // Use a custom font
|
||||
display.setTextSize(1); // and reset to 1:1 scale
|
||||
|
||||
char *label[] = { "X:", "Y:", "Z:" }; // Labels for each axis
|
||||
const uint16_t color[] = { 0xF800, 0x07E0, 0x001F }; // Colors for each value
|
||||
|
||||
// To get the labels right-aligned, one option would be simple trial and
|
||||
// error to find a column that looks good and doesn't clip anything off.
|
||||
// Let's do this dynamically though, so it adapts to any font or labels!
|
||||
// Start by finding the widest of the label strings:
|
||||
uint16_t w, h, max_w = 0;
|
||||
int16_t x, y;
|
||||
for (uint8_t i=0; i<3; i++) { // For each label...
|
||||
display.getTextBounds(label[i], 0, 0, &x, &y, &w, &h);
|
||||
if (w > max_w) max_w = w; // Keep track of widest label
|
||||
}
|
||||
|
||||
// Rounded corners throwing us a curve again. If needed, scoot everything
|
||||
// to the right a bit on wide displays, down a bit on tall ones.
|
||||
int16_t y_offset = 0;
|
||||
if (display.width() > display.height()) max_w += CORNER_RADIUS;
|
||||
else y_offset = CORNER_RADIUS;
|
||||
|
||||
// Now we have max_w for right-aligning the labels. Before we draw them
|
||||
// though...in order to perform flicker-free updates, the numbers we show
|
||||
// will be rendered in either a GFXcanvas1 or GFXcanvas16 object; a 1-bit
|
||||
// or 16-bit offscreen bitmap, RAM permitting. The correct size for this
|
||||
// canvas could also be trial-and-errored, but again let's make this adapt
|
||||
// automatically. The width of the canvas will span from max_w (plus a few
|
||||
// pixels for padding) to the right edge. But the height? Looking at an
|
||||
// uppercase 'M' can work in many situations, but some fonts have ascenders
|
||||
// and descenders on digits, and in some locales a comma (extending below
|
||||
// the baseline) is the decimal separator. Feed ALL the numeric chars into
|
||||
// getTextBounds() for a cumulative height:
|
||||
display.setTextWrap(false); // Keep on one line
|
||||
display.getTextBounds(F("0123456789.,-"), 0, 0, &x, &y, &w, &h);
|
||||
|
||||
// Now declare a GFXcanvas16 object based on the computed width & height:
|
||||
GFXcanvas16 canvas16(display.width() - max_w - PADDING, h);
|
||||
|
||||
// Small devices (e.g. ATmega328p) will almost certainly lack enough RAM
|
||||
// for the canvas. Check if canvas buffer exists. If not, fall back on
|
||||
// using a 1-bit (rather than 16-bit) canvas. Much more RAM friendly, but
|
||||
// not as fast to draw. If a project doesn't require super interactive
|
||||
// updates, consider just going straight for the more compact Canvas1.
|
||||
if (canvas16.getBuffer()) {
|
||||
// If here, 16-bit canvas allocated successfully! Point of interest,
|
||||
// only one canvas is needed for this example, we can reuse it for all
|
||||
// three numbers because the regions are the same size.
|
||||
|
||||
// display and canvas are independent drawable objects; must explicitly
|
||||
// set the same custom font to use on the canvas now:
|
||||
canvas16.setFont(&FreeSansBold18pt7b);
|
||||
|
||||
// Clear display and print labels. Once drawn, these remain untouched.
|
||||
display.fillScreen(0);
|
||||
display.setCursor(max_w, -y + y_offset); // Set baseline for first row
|
||||
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
|
||||
|
||||
// Last part now is to print numbers on the canvas and copy the canvas to
|
||||
// the display, repeating for several seconds...
|
||||
uint32_t elapsed, startTime = millis();
|
||||
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
|
||||
for (uint8_t i=0; i<3; i++) { // For each label...
|
||||
canvas16.fillScreen(0); // fillScreen() in this case clears canvas
|
||||
canvas16.setCursor(0, -y); // Reset baseline for custom font
|
||||
canvas16.setTextColor(color[i]);
|
||||
// These aren't real accelerometer readings, just cool-looking numbers.
|
||||
// Notice we print to the canvas, NOT the display:
|
||||
canvas16.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
|
||||
// And HERE is the secret sauce to flicker-free updates. Canvas details
|
||||
// can be passed to the drawRGBBitmap() function, which fully overwrites
|
||||
// prior screen contents in that area. yAdvance is font line spacing.
|
||||
display.drawRGBBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
|
||||
y_offset, canvas16.getBuffer(), canvas16.width(),
|
||||
canvas16.height());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Insufficient RAM for Canvas16. Try declaring a 1-bit canvas instead...
|
||||
GFXcanvas1 canvas1(display.width() - max_w - PADDING, h);
|
||||
// If even this smaller object fails, can't proceed, cancel this example.
|
||||
if (!canvas1.getBuffer()) return;
|
||||
|
||||
// Remainder here is nearly identical to the code above, simply using a
|
||||
// different canvas type. It's stripped of most comments for brevity.
|
||||
canvas1.setFont(&FreeSansBold18pt7b);
|
||||
display.fillScreen(0);
|
||||
display.setCursor(max_w, -y + y_offset);
|
||||
for (uint8_t i=0; i<3; i++) print_aligned(display, label[i], GFX_ALIGN_RIGHT);
|
||||
uint32_t elapsed, startTime = millis();
|
||||
while ((elapsed = (millis() - startTime)) <= PAUSE * 2) {
|
||||
for (uint8_t i=0; i<3; i++) {
|
||||
canvas1.fillScreen(0);
|
||||
canvas1.setCursor(0, -y);
|
||||
canvas1.print(sin(elapsed / 200.0 + (float)i * M_PI * 2.0 / 3.0), 5);
|
||||
// Here's the secret sauce to flicker-free updates with GFXcanvas1.
|
||||
// Canvas details can be passed to the drawBitmap() function, and by
|
||||
// specifying both a foreground AND BACKGROUND color (0), this will fully
|
||||
// overwrite/erase prior screen contents in that area (vs transparent).
|
||||
display.drawBitmap(max_w + PADDING, i * FreeSansBold18pt7b.yAdvance +
|
||||
y_offset, canvas1.getBuffer(), canvas1.width(),
|
||||
canvas1.height(), color[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Because canvas object was declared locally to this function, it's freed
|
||||
// automatically when the function returns; no explicit delete needed.
|
||||
} // END CANVAS EXAMPLE
|
||||
|
|
@ -27,11 +27,19 @@ bool show_new_year = true;
|
|||
#define SHAKE_PERIOD 2000 // Period (in ms) when SHAKE_EVENTS must happen
|
||||
#define SAND_TIME 6000 // Time (in ms) to run simulation before restarting
|
||||
|
||||
#if defined(_VARIANT_MATRIXPORTAL_M4_) // MatrixPortal M4
|
||||
uint8_t rgbPins[] = {7, 8, 9, 10, 11, 12};
|
||||
uint8_t addrPins[] = {17, 18, 19, 20};
|
||||
uint8_t addrPins[] = {17, 18, 19, 20, 21};
|
||||
uint8_t clockPin = 14;
|
||||
uint8_t latchPin = 15;
|
||||
uint8_t oePin = 16;
|
||||
#else // MatrixPortal ESP32-S3
|
||||
uint8_t rgbPins[] = {42, 41, 40, 38, 39, 37};
|
||||
uint8_t addrPins[] = {35, 36, 48, 45, 21};
|
||||
uint8_t clockPin = 2;
|
||||
uint8_t latchPin = 47;
|
||||
uint8_t oePin = 14;
|
||||
#endif
|
||||
|
||||
// 64x32 pixel matrix, 6-bit depth
|
||||
Adafruit_Protomatter matrix(
|
||||
|
|
|
|||
BIN
4x4_MIDI_Messenger/OCRA_small.pcf
Normal file
BIN
4x4_MIDI_Messenger/OCRA_small.pcf
Normal file
Binary file not shown.
310
4x4_MIDI_Messenger/code.py
Normal file
310
4x4_MIDI_Messenger/code.py
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import asyncio
|
||||
import board
|
||||
import digitalio
|
||||
from rainbowio import colorwheel
|
||||
import keypad
|
||||
import displayio
|
||||
import i2cdisplaybus
|
||||
import busio
|
||||
import adafruit_seesaw.seesaw
|
||||
import adafruit_seesaw.neopixel
|
||||
import adafruit_seesaw.rotaryio
|
||||
import adafruit_seesaw.digitalio
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text import label
|
||||
import adafruit_displayio_ssd1306
|
||||
import adafruit_midi
|
||||
from adafruit_midi.control_change import ControlChange
|
||||
import neopixel
|
||||
|
||||
# default MIDI channel (1-16)
|
||||
midi_in_channel = 2
|
||||
midi_out_channel = 2
|
||||
|
||||
# MIDI CC messages, values and names assigned to each encoder
|
||||
cc_values = [
|
||||
{'cc_val': (0, 127), 'cc_message': (14), 'cc_name': "Volume"},
|
||||
{'cc_val': (0, 127), 'cc_message': (15), 'cc_name': "Repeats"},
|
||||
{'cc_val': (0, 127), 'cc_message': (16), 'cc_name': "Size"},
|
||||
{'cc_val': (0, 127), 'cc_message': (17), 'cc_name': "Mod"},
|
||||
{'cc_val': (0, 127), 'cc_message': (18), 'cc_name': "Spread"},
|
||||
{'cc_val': (0, 127), 'cc_message': (19), 'cc_name': "Scan"},
|
||||
{'cc_val': (0, 127), 'cc_message': (20), 'cc_name': "Ramp"},
|
||||
{'cc_val': (1, 3), 'cc_message': (21), 'cc_name': "Mod Number"},
|
||||
{'cc_val': (1, 3), 'cc_message': (22), 'cc_name': "Mod Bank"},
|
||||
{'cc_val': (1, 3), 'cc_message': (23), 'cc_name': "Mode"},
|
||||
{'cc_val': (0, 1), 'cc_message': (102), 'cc_name': "Bypass/Engage"},
|
||||
{'cc_val': (0, 127), 'cc_message': (93), 'cc_name': "Tap Tempo"},
|
||||
{'cc_val': (0, 1), 'cc_message': (24), 'cc_name': "Loop (R Hold)"},
|
||||
{'cc_val': (0, 1), 'cc_message': (25), 'cc_name': "Scan (L Hold)"},
|
||||
{'cc_val': (0, 127), 'cc_message': (26), 'cc_name': "Clear (Both Hold)"},
|
||||
{'cc_val': (0, 1), 'cc_message': (51), 'cc_name': "MIDI Clock Ignore"}
|
||||
]
|
||||
|
||||
displayio.release_displays()
|
||||
|
||||
oled_reset = board.D13
|
||||
|
||||
i2c = board.STEMMA_I2C()
|
||||
# STEMMA OLED setup
|
||||
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3D, reset=oled_reset)
|
||||
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=64)
|
||||
|
||||
splash = displayio.Group()
|
||||
display.root_group = splash
|
||||
font = bitmap_font.load_font('/OCRA_small.pcf')
|
||||
# main label/MIDI message name text; centered
|
||||
main_area = label.Label(
|
||||
font, text="4x4 MIDI Messenger", color=0xFFFFFF)
|
||||
main_area.anchor_point = (0.5, 0.0)
|
||||
main_area.anchored_position = (display.width / 2, 0)
|
||||
# MIDI message number text
|
||||
msg_area = label.Label(
|
||||
font, text="CC Msg: 10", color=0xFFFFFF)
|
||||
msg_area.anchor_point = (0.0, 0.5)
|
||||
msg_area.anchored_position = (0, display.height / 2)
|
||||
# MIDI message value text
|
||||
val_area = label.Label(
|
||||
font, text="CC Val: 50", color=0xFFFFFF)
|
||||
val_area.anchor_point = (0.0, 1.0)
|
||||
val_area.anchored_position = (0, display.height)
|
||||
# MIDI message status text
|
||||
status_area = label.Label(
|
||||
font, text="Sent!", color=0xFFFFFF)
|
||||
status_area.anchor_point = (1.0, 1.0)
|
||||
status_area.anchored_position = (display.width, display.height)
|
||||
|
||||
splash.append(main_area)
|
||||
splash.append(msg_area)
|
||||
splash.append(val_area)
|
||||
splash.append(status_area)
|
||||
# MIDI over UART setup for MIDI FeatherWing
|
||||
uart = busio.UART(board.TX, board.RX, baudrate=31250, timeout=0.001)
|
||||
midi = adafruit_midi.MIDI(
|
||||
midi_in=uart,
|
||||
midi_out=uart,
|
||||
in_channel=(midi_in_channel - 1),
|
||||
out_channel=(midi_out_channel - 1),
|
||||
debug=False,
|
||||
)
|
||||
# quad rotary encoder setup
|
||||
ss0 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x49)
|
||||
ss1 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4A)
|
||||
ss2 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4B)
|
||||
ss3 = adafruit_seesaw.seesaw.Seesaw(i2c, 0x4C)
|
||||
# button pins for the encoders
|
||||
pins = [12, 14, 17, 9]
|
||||
# interrupts for the button pins. pins are passed as a bitmask
|
||||
ss0.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
|
||||
ss1.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
|
||||
ss2.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
|
||||
ss3.set_GPIO_interrupts(1 << pins[0] | 1 << pins[1] | 1 << pins[2] | 1 << pins[3], True)
|
||||
# arrays for the encoders and switches
|
||||
enc0 = []
|
||||
enc1 = []
|
||||
enc2 = []
|
||||
enc3 = []
|
||||
sw0 = []
|
||||
sw1 = []
|
||||
sw2 = []
|
||||
sw3 = []
|
||||
# creating encoders and switches, enabling interrupts for encoders
|
||||
for i in range(4):
|
||||
enc0.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss0, i))
|
||||
enc1.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss1, i))
|
||||
enc2.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss2, i))
|
||||
enc3.append(adafruit_seesaw.rotaryio.IncrementalEncoder(ss3, i))
|
||||
sw0.append(adafruit_seesaw.digitalio.DigitalIO(ss0, pins[i]))
|
||||
sw0[i].switch_to_input(digitalio.Pull.UP)
|
||||
sw1.append(adafruit_seesaw.digitalio.DigitalIO(ss1, pins[i]))
|
||||
sw1[i].switch_to_input(digitalio.Pull.UP)
|
||||
sw2.append(adafruit_seesaw.digitalio.DigitalIO(ss2, pins[i]))
|
||||
sw2[i].switch_to_input(digitalio.Pull.UP)
|
||||
sw3.append(adafruit_seesaw.digitalio.DigitalIO(ss3, pins[i]))
|
||||
sw3[i].switch_to_input(digitalio.Pull.UP)
|
||||
ss0.enable_encoder_interrupt(encoder=i)
|
||||
ss1.enable_encoder_interrupt(encoder=i)
|
||||
ss2.enable_encoder_interrupt(encoder=i)
|
||||
ss3.enable_encoder_interrupt(encoder=i)
|
||||
# neopixels on each PCB
|
||||
pix0 = adafruit_seesaw.neopixel.NeoPixel(ss0, 18, 4, auto_write = True)
|
||||
pix0.brightness = 0.5
|
||||
pix1 = adafruit_seesaw.neopixel.NeoPixel(ss1, 18, 4, auto_write = True)
|
||||
pix1.brightness = 0.5
|
||||
pix2 = adafruit_seesaw.neopixel.NeoPixel(ss2, 18, 4, auto_write = True)
|
||||
pix2.brightness = 0.5
|
||||
pix3 = adafruit_seesaw.neopixel.NeoPixel(ss3, 18, 4, auto_write = True)
|
||||
pix3.brightness = 0.5
|
||||
# onboard Feather neopixel
|
||||
pix_feather = neopixel.NeoPixel(board.NEOPIXEL, 1, auto_write = True)
|
||||
pix_feather.brightness = 0.5
|
||||
# encoder position arrays
|
||||
last_pos0 = [60, 60, 60, 60]
|
||||
last_pos1 = [60, 60, 60, 0]
|
||||
last_pos2 = [0, 0, 0, 120]
|
||||
last_pos3 = [0, 0, 0, 0]
|
||||
pos0 = [60, 60, 60, 60]
|
||||
pos1 = [60, 60, 60, 0]
|
||||
pos2 = [0, 0, 0, 120]
|
||||
pos3 = [0, 0, 0, 0]
|
||||
# color arrays for the neopixels
|
||||
c0 = [0, 16, 32, 48]
|
||||
c1 = [64, 80, 96, 112]
|
||||
c2 = [128, 144, 160, 176]
|
||||
c3 = [192, 208, 224, 240]
|
||||
# setting starting colors for neopixels
|
||||
for r in range(4):
|
||||
pix0[r] = colorwheel(c0[r])
|
||||
pix1[r] = colorwheel(c1[r])
|
||||
pix2[r] = colorwheel(c2[r])
|
||||
pix3[r] = colorwheel(c3[r])
|
||||
# feather neopixel color
|
||||
c_feather = 0
|
||||
pix_feather[0] = colorwheel(c_feather)
|
||||
# array of all 16 encoder positions
|
||||
encoder_posititions = [60, 60, 60, 60, 60, 60, 60, 60, 0, 0, 0, 120, 0, 0, 0, 0]
|
||||
|
||||
class MIDI_Messages:
|
||||
# tracks sending a message and index 0-15
|
||||
def __init__(self):
|
||||
self.send_msg = False
|
||||
self.midi_index = 0
|
||||
|
||||
class NeoPixel_Attributes:
|
||||
# tracks color, neopixel index and seesaw
|
||||
def __init__(self):
|
||||
self.color = c0
|
||||
self.index = 0
|
||||
self.strip = pix0
|
||||
self.feather_color = c_feather
|
||||
|
||||
async def send_midi(midi_msg):
|
||||
# sends MIDI message if send_msg is True/button pressed
|
||||
while True:
|
||||
if midi_msg.send_msg is True:
|
||||
m = midi_msg.midi_index
|
||||
main_area.text = f"{cc_values[m]['cc_name']}"
|
||||
msg_area.text = f"CC Msg: {cc_values[m]['cc_message']}"
|
||||
val_area.text = f"CC Val: {encoder_posititions[m]}"
|
||||
midi.send(ControlChange(cc_values[m]['cc_message'], encoder_posititions[m]))
|
||||
status_area.text = "Sent!"
|
||||
print(f"sending midi: {m}, {encoder_posititions[m]}, {cc_values[m]['cc_message']}")
|
||||
time.sleep(1)
|
||||
midi_msg.send_msg = False
|
||||
else:
|
||||
status_area.text = " "
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async def rainbows(the_color):
|
||||
# Updates colors of the neopixels to scroll through rainbow
|
||||
while True:
|
||||
the_color.feather_color += 8
|
||||
the_color.strip[the_color.index] = colorwheel(the_color.color[the_color.index])
|
||||
pix_feather[0] = colorwheel(the_color.feather_color)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async def monitor_interrupts(pin0, pin1, pin2, pin3, the_color, midi_msg): #pylint: disable=too-many-statements
|
||||
# function to keep encoder value pinned between CC value range
|
||||
def normalize(val, min_v, max_v):
|
||||
return max(min(max_v, val), min_v)
|
||||
# read encoder function
|
||||
def read_encoder(enc_group, pos, last_pos, pix, colors, index_diff):
|
||||
# check all four encoders if interrupt is detected
|
||||
for p in range(4):
|
||||
pos[p] = enc_group[p].position
|
||||
if pos[p] != last_pos[p]:
|
||||
main_index = p + index_diff
|
||||
# update CC value
|
||||
if pos[p] > last_pos[p]:
|
||||
colors[p] += 8
|
||||
encoder_posititions[main_index] = encoder_posititions[main_index] + 1
|
||||
else:
|
||||
colors[p] -= 8
|
||||
encoder_posititions[main_index] = encoder_posititions[main_index] - 1
|
||||
encoder_posititions[main_index] = normalize(encoder_posititions[main_index],
|
||||
cc_values[main_index]['cc_val'][0],
|
||||
cc_values[main_index]['cc_val'][1])
|
||||
colors[p] = (colors[p] + 256) % 256 # wrap around to 0-256
|
||||
print(main_index, encoder_posititions[main_index])
|
||||
main_area.text = f"{cc_values[main_index]['cc_name']}"
|
||||
msg_area.text = f"CC Msg: {cc_values[main_index]['cc_message']}"
|
||||
val_area.text = f"CC Val: {encoder_posititions[main_index]}"
|
||||
last_pos[p] = pos[p]
|
||||
# update NeoPixel colors
|
||||
the_color.color = colors
|
||||
the_color.index = p
|
||||
the_color.strip = pix
|
||||
# function to read button press
|
||||
def press_switches(sw, index):
|
||||
if not sw[index].value:
|
||||
# signals that a MIDI message should be sent
|
||||
midi_msg.send_msg = True
|
||||
midi_msg.midi_index = index
|
||||
print(f"button {index} pressed")
|
||||
# interrupt pins are passed as a keypad
|
||||
with keypad.Keys(
|
||||
(pin0, pin1, pin2, pin3,), value_when_pressed=False, pull=True
|
||||
) as keys:
|
||||
while True:
|
||||
key_event = keys.events.get()
|
||||
if key_event and key_event.pressed:
|
||||
key_number = key_event.key_number
|
||||
# seesaw 0
|
||||
if key_number == 0:
|
||||
read_encoder(enc0, pos0, last_pos0, pix0, c0, 0)
|
||||
press_switches(sw0, 0)
|
||||
press_switches(sw0, 1)
|
||||
press_switches(sw0, 2)
|
||||
press_switches(sw0, 3)
|
||||
# seesaw 1
|
||||
elif key_number == 1:
|
||||
read_encoder(enc1, pos1, last_pos1, pix1, c1, 4)
|
||||
press_switches(sw1, 0)
|
||||
press_switches(sw1, 1)
|
||||
press_switches(sw1, 2)
|
||||
press_switches(sw1, 3)
|
||||
# update index to 4-7
|
||||
midi_msg.midi_index = midi_msg.midi_index + 4
|
||||
# seesaw 2
|
||||
elif key_number == 2:
|
||||
read_encoder(enc2, pos2, last_pos2, pix2, c2, 8)
|
||||
press_switches(sw2, 0)
|
||||
press_switches(sw2, 1)
|
||||
press_switches(sw2, 2)
|
||||
press_switches(sw2, 3)
|
||||
# update index 8-11
|
||||
midi_msg.midi_index = midi_msg.midi_index + 8
|
||||
# seesaw 3
|
||||
else:
|
||||
read_encoder(enc3, pos3, last_pos3, pix3, c3, 12)
|
||||
press_switches(sw3, 0)
|
||||
press_switches(sw3, 1)
|
||||
press_switches(sw3, 2)
|
||||
press_switches(sw3, 3)
|
||||
# update index 12-15
|
||||
midi_msg.midi_index = midi_msg.midi_index + 12
|
||||
# clear interrupt flag to reset interrupt pin
|
||||
ss0.get_GPIO_interrupt_flag()
|
||||
ss1.get_GPIO_interrupt_flag()
|
||||
ss2.get_GPIO_interrupt_flag()
|
||||
ss3.get_GPIO_interrupt_flag()
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async def main():
|
||||
the_color = NeoPixel_Attributes()
|
||||
midi_msg = MIDI_Messages()
|
||||
# interrupt listener task
|
||||
interrupt_task = asyncio.create_task(monitor_interrupts(board.D5, board.D6, board.D9,
|
||||
board.D10, the_color, midi_msg))
|
||||
# neopixel task
|
||||
pixels_task = asyncio.create_task(rainbows(the_color))
|
||||
# midi task
|
||||
midi_task = asyncio.create_task(send_midi(midi_msg))
|
||||
|
||||
await asyncio.gather(interrupt_task, pixels_task, midi_task)
|
||||
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_MCP23X17.h>
|
||||
|
||||
#define NOID_1 0 // MCP23XXX pin LED is attached to
|
||||
#define NOID_2 4 // MCP23XXX pin LED is attached to
|
||||
|
||||
Adafruit_MCP23X17 mcp;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
Serial.println("8 Channel Solenoid Driver Demo");
|
||||
if (!mcp.begin_I2C()) {
|
||||
Serial.println("Couldn't find MCP23017..");
|
||||
while (1);
|
||||
}
|
||||
mcp.pinMode(NOID_1, OUTPUT);
|
||||
mcp.pinMode(NOID_2, OUTPUT);
|
||||
|
||||
Serial.println("Found MCP23017, looping...");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.println("Solenoid 1!");
|
||||
mcp.digitalWrite(NOID_1, HIGH);
|
||||
delay(500);
|
||||
mcp.digitalWrite(NOID_1, LOW);
|
||||
delay(500);
|
||||
Serial.println("Solenoid 2!");
|
||||
mcp.digitalWrite(NOID_2, HIGH);
|
||||
delay(500);
|
||||
mcp.digitalWrite(NOID_2, LOW);
|
||||
delay(500);
|
||||
Serial.println("Together!");
|
||||
mcp.digitalWrite(NOID_1, HIGH);
|
||||
mcp.digitalWrite(NOID_2, HIGH);
|
||||
delay(1000);
|
||||
mcp.digitalWrite(NOID_1, LOW);
|
||||
mcp.digitalWrite(NOID_2, LOW);
|
||||
delay(2000);
|
||||
Serial.println("Repeat!");
|
||||
Serial.println();
|
||||
delay(500);
|
||||
}
|
||||
38
8_Channel_Solenoid_Driver/CircuitPython/code.py
Normal file
38
8_Channel_Solenoid_Driver/CircuitPython/code.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# SPDX-FileCopyrightText: 2025 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
from adafruit_mcp230xx.mcp23017 import MCP23017
|
||||
|
||||
i2c = board.STEMMA_I2C()
|
||||
|
||||
mcp = MCP23017(i2c)
|
||||
|
||||
noid_1 = mcp.get_pin(0)
|
||||
noid_2 = mcp.get_pin(4)
|
||||
noid_1.switch_to_output(value=False)
|
||||
noid_2.switch_to_output(value=False)
|
||||
|
||||
while True:
|
||||
noid_1.value = True
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(0.2)
|
||||
noid_1.value = False
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(0.2)
|
||||
noid_2.value = True
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(0.2)
|
||||
noid_2.value = False
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(1)
|
||||
noid_1.value = True
|
||||
noid_2.value = True
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(1)
|
||||
noid_1.value = False
|
||||
noid_2.value = False
|
||||
print(f"Solenoid 1: {noid_1.value}, Solenoid 2: {noid_2.value}")
|
||||
time.sleep(2)
|
||||
31
A4988_Examples/Arduino_A4988/Arduino_A4988.ino
Normal file
31
A4988_Examples/Arduino_A4988/Arduino_A4988.ino
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
const int DIR = 5;
|
||||
const int STEP = 6;
|
||||
const int microMode = 16; // microstep mode, default is 1/16 so 16; ex: 1/4 would be 4
|
||||
// full rotation * microstep divider
|
||||
const int steps = 200 * microMode;
|
||||
|
||||
void setup()
|
||||
{
|
||||
// setup step and dir pins as outputs
|
||||
pinMode(STEP, OUTPUT);
|
||||
pinMode(DIR, OUTPUT);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// change direction every loop
|
||||
digitalWrite(DIR, !digitalRead(DIR));
|
||||
// toggle STEP to move
|
||||
for(int x = 0; x < steps; x++)
|
||||
{
|
||||
digitalWrite(STEP, HIGH);
|
||||
delay(2);
|
||||
digitalWrite(STEP, LOW);
|
||||
delay(2);
|
||||
}
|
||||
delay(1000); // 1 second delay
|
||||
}
|
||||
32
A4988_Examples/CircuitPython_A4988/code.py
Normal file
32
A4988_Examples/CircuitPython_A4988/code.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
from digitalio import DigitalInOut, Direction
|
||||
|
||||
# direction and step pins as outputs
|
||||
DIR = DigitalInOut(board.D5)
|
||||
DIR.direction = Direction.OUTPUT
|
||||
STEP = DigitalInOut(board.D6)
|
||||
STEP.direction = Direction.OUTPUT
|
||||
|
||||
# microstep mode, default is 1/16 so 16
|
||||
# another ex: 1/4 microstep would be 4
|
||||
microMode = 16
|
||||
# full rotation multiplied by the microstep divider
|
||||
steps = 200 * microMode
|
||||
|
||||
while True:
|
||||
# change direction every loop
|
||||
DIR.value = not DIR.value
|
||||
# toggle STEP pin to move the motor
|
||||
for i in range(steps):
|
||||
STEP.value = True
|
||||
time.sleep(0.001)
|
||||
STEP.value = False
|
||||
time.sleep(0.001)
|
||||
print("rotated! now reverse")
|
||||
# 1 second delay before starting again
|
||||
time.sleep(1)
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_ADG72x.h>
|
||||
|
||||
Adafruit_ADG72x adg72x;
|
||||
|
||||
bool isADG728 = false; // which chip are we connected to?
|
||||
|
||||
int analogIn = A0;
|
||||
int analogValue = 0;
|
||||
unsigned long switchTimer = 1000; // 1000 ms = 1 second for channel switch
|
||||
unsigned long readTimer = 10; // 10 ms for analog read
|
||||
unsigned long lastSwitchTime = 0; // Last time the channels were switched
|
||||
unsigned long lastReadTime = 0; // Last time the analog was read
|
||||
uint8_t currentChannel = 0; // Current channel being selected
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Wait for serial port to open
|
||||
while (!Serial) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Try with the ADG728 default address first...
|
||||
if (adg72x.begin(ADG728_DEFAULT_ADDR, &Wire)) {
|
||||
Serial.println("ADG728 found!");
|
||||
isADG728 = true;
|
||||
}
|
||||
// Maybe they have an ADG729?
|
||||
else if (adg72x.begin(ADG729_DEFAULT_ADDR, &Wire)) {
|
||||
Serial.println("ADG729 found!");
|
||||
isADG728 = false;
|
||||
}
|
||||
else {
|
||||
Serial.println("No ADG device found? Check wiring!");
|
||||
while (1); // Stop here if no device was found
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// read and print analog value every 10ms
|
||||
if ((currentTime - lastReadTime) >= readTimer) {
|
||||
analogValue = analogRead(analogIn);
|
||||
Serial.println(analogValue);
|
||||
lastReadTime = currentTime;
|
||||
}
|
||||
|
||||
// switch channels every 1 second
|
||||
if ((currentTime - lastSwitchTime) >= switchTimer) {
|
||||
uint8_t bits = 1 << currentChannel; // Shift a '1' from LSB to MSB
|
||||
if (!adg72x.selectChannels(bits)) {
|
||||
Serial.println("Failed to set channels...");
|
||||
}
|
||||
/*Serial.print((currentChannel % 4) + 1);
|
||||
if (currentChannel < 4) Serial.println("A");
|
||||
else Serial.println("B");*/
|
||||
currentChannel = (currentChannel + 1) % 8; // Move to the next channel, wrap around at 8
|
||||
lastSwitchTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Adafruit_ADG72x.h>
|
||||
|
||||
Adafruit_ADG72x adg72x;
|
||||
|
||||
int analogInA0 = A0;
|
||||
int analogInA1 = A1;
|
||||
int analogValueDA = 0;
|
||||
int analogValueDB = 0;
|
||||
unsigned long switchTimer = 1000; // 1000 ms = 1 second for channel switch
|
||||
unsigned long readTimer = 10; // 10 ms for analog read
|
||||
unsigned long lastSwitchTime = 0; // Last time the channels were switched
|
||||
unsigned long lastReadTime = 0; // Last time the analog was read
|
||||
uint8_t currentChannel = 0; // Current channel being selected
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Wait for serial port to open
|
||||
while (!Serial) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
// Try with the ADG728 default address first...
|
||||
if (adg72x.begin(ADG728_DEFAULT_ADDR, &Wire)) {
|
||||
//Serial.println("ADG728 found!");
|
||||
}
|
||||
// Maybe they have an ADG729?
|
||||
else if (adg72x.begin(ADG729_DEFAULT_ADDR, &Wire)) {
|
||||
//Serial.println("ADG729 found!");
|
||||
}
|
||||
else {
|
||||
Serial.println("No ADG72x device found? Check wiring!");
|
||||
while (1); // Stop here if no device was found
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long currentTime = millis();
|
||||
|
||||
// read and print analog value every 10ms
|
||||
if ((currentTime - lastReadTime) >= readTimer) {
|
||||
analogValueDA = analogRead(analogInA0);
|
||||
analogValueDB = analogRead(analogInA1);
|
||||
Serial.print(analogValueDA);
|
||||
Serial.print(",");
|
||||
Serial.println(analogValueDB);
|
||||
lastReadTime = currentTime;
|
||||
}
|
||||
|
||||
// switch channels every 1 second
|
||||
if ((currentTime - lastSwitchTime) >= switchTimer) {
|
||||
uint8_t bits = 1 << currentChannel; // Shift a '1' from LSB to MSB
|
||||
if (!adg72x.selectChannels(bits)) {
|
||||
Serial.println("Failed to set channels...");
|
||||
}
|
||||
/*Serial.print((currentChannel % 4) + 1);
|
||||
if (currentChannel < 4) Serial.println("A");
|
||||
else Serial.println("B");*/
|
||||
currentChannel = (currentChannel + 1) % 8; // Move to the next channel, wrap around at 8
|
||||
lastSwitchTime = currentTime;
|
||||
}
|
||||
}
|
||||
26
ADG72x_Examples/CircuitPython_ADG728/code.py
Normal file
26
ADG72x_Examples/CircuitPython_ADG728/code.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2024 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import adafruit_adg72x
|
||||
from analogio import AnalogIn
|
||||
|
||||
analog_in = AnalogIn(board.A0)
|
||||
|
||||
i2c = board.I2C()
|
||||
switch = adafruit_adg72x.ADG72x(i2c)
|
||||
|
||||
c = 0
|
||||
switch_time = 2
|
||||
channels = [0, 4]
|
||||
clock = time.monotonic()
|
||||
while True:
|
||||
if (time.monotonic() - clock) > switch_time:
|
||||
print(f"Selecting channel {channels[c] + 1}")
|
||||
switch.channel = channels[c]
|
||||
c = (c + 1) % 2
|
||||
clock = time.monotonic()
|
||||
print((analog_in.value,))
|
||||
time.sleep(0.1)
|
||||
31
ADG72x_Examples/CircuitPython_ADG729/code.py
Normal file
31
ADG72x_Examples/CircuitPython_ADG729/code.py
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2024 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import adafruit_adg72x
|
||||
from analogio import AnalogIn
|
||||
|
||||
analog_in_DA = AnalogIn(board.A0)
|
||||
analog_in_DB = AnalogIn(board.A1)
|
||||
|
||||
i2c = board.I2C()
|
||||
switch = adafruit_adg72x.ADG72x(i2c, 0x44)
|
||||
|
||||
c = 0
|
||||
switch_time = 3
|
||||
clock = time.monotonic()
|
||||
|
||||
while True:
|
||||
if (time.monotonic() - clock) > switch_time:
|
||||
if c < 4:
|
||||
channels = "A"
|
||||
else:
|
||||
channels = "B"
|
||||
print(f"Selecting channel {(c % 4) + 1}{channels}")
|
||||
switch.channel = c
|
||||
c = (c + 1) % 8
|
||||
clock = time.monotonic()
|
||||
print((analog_in_DA.value, analog_in_DB.value,))
|
||||
time.sleep(0.1)
|
||||
|
|
@ -11,6 +11,7 @@ import adafruit_ahtx0
|
|||
|
||||
# OLED
|
||||
import displayio
|
||||
import i2cdisplaybus
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
import adafruit_displayio_ssd1306
|
||||
|
|
@ -25,12 +26,12 @@ aht20 = adafruit_ahtx0.AHTx0(i2c)
|
|||
|
||||
|
||||
#OLED
|
||||
display_bus = displayio.I2CDisplay(i2c, device_address=0x3C)
|
||||
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3C)
|
||||
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32)
|
||||
|
||||
# Make the display context
|
||||
splash = displayio.Group()
|
||||
display.show(splash)
|
||||
display.root_group = splash
|
||||
|
||||
text = "hello world"
|
||||
text_area = label.Label(terminalio.FONT, color=0xFFFF00, x=15, y=0)
|
||||
|
|
|
|||
740
ANO_Rotary_Encoder_Synth/code.py
Normal file
740
ANO_Rotary_Encoder_Synth/code.py
Normal file
|
|
@ -0,0 +1,740 @@
|
|||
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from random import randint
|
||||
import ulab.numpy as np
|
||||
import board
|
||||
import audiobusio
|
||||
import audiomixer
|
||||
import synthio
|
||||
import simpleio
|
||||
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
|
||||
from adafruit_ht16k33 import segments
|
||||
from adafruit_ht16k33.matrix import Matrix8x8x2
|
||||
from adafruit_seesaw import seesaw, rotaryio, digitalio
|
||||
|
||||
SAMPLE_RATE = 44100
|
||||
SAMPLE_SIZE = 256
|
||||
VOLUME = 5000
|
||||
|
||||
# waveforms, envelopes and synth setup
|
||||
|
||||
square = np.concatenate((np.ones(SAMPLE_SIZE//2, dtype=np.int16)*VOLUME,np.ones(SAMPLE_SIZE//2,
|
||||
dtype=np.int16)*-VOLUME))
|
||||
sine = np.array(np.sin(np.linspace(0, 4*np.pi, SAMPLE_SIZE, endpoint=False)) * VOLUME,
|
||||
dtype=np.int16)
|
||||
saw = np.linspace(VOLUME, -VOLUME, num=SAMPLE_SIZE, dtype=np.int16)
|
||||
noise = np.array([randint(-VOLUME, VOLUME) for i in range(SAMPLE_SIZE)], dtype=np.int16)
|
||||
|
||||
lfo = synthio.LFO(rate = .5, waveform = sine)
|
||||
|
||||
amp_env0 = synthio.Envelope(attack_time=0.1, decay_time = 0.1, release_time=0.1,
|
||||
attack_level=1, sustain_level=0.05)
|
||||
amp_env1 = synthio.Envelope(attack_time=0.05, decay_time = 0.1, release_time=0.1,
|
||||
attack_level=1, sustain_level=0.05)
|
||||
|
||||
# synth plays the notes
|
||||
synth = synthio.Synthesizer(sample_rate=SAMPLE_RATE)
|
||||
|
||||
# these are the notes
|
||||
synth0 = synthio.Note(frequency = 0.0, envelope=amp_env0, waveform=square, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth1 = synthio.Note(frequency = 0.0, envelope=amp_env1, waveform=sine, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth2 = synthio.Note(frequency = 0.0, envelope=amp_env0, waveform=square, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
synth3 = synthio.Note(frequency = 0.0, envelope=amp_env1, waveform=sine, ring_frequency = 0,
|
||||
ring_bend = lfo, ring_waveform = sine)
|
||||
|
||||
synths = [synth0, synth1, synth2, synth3]
|
||||
wave_names = ["SQUR", "SINE", "SAW ", "NOIZ"]
|
||||
waveforms = [square, sine, saw, noise]
|
||||
synth0_wave = 0
|
||||
synth1_wave = 1
|
||||
synth2_wave = 0
|
||||
synth3_wave = 1
|
||||
|
||||
# i2s amp setup
|
||||
audio = audiobusio.I2SOut(bit_clock=board.D10, word_select=board.D11, data=board.D9)
|
||||
mixer = audiomixer.Mixer(voice_count=4, sample_rate=SAMPLE_RATE, channel_count=1,
|
||||
bits_per_sample=16, samples_signed=True, buffer_size=2048 )
|
||||
audio.play(mixer)
|
||||
vol_val = 2
|
||||
mixer.voice[0].play(synth)
|
||||
mixer.voice[0].level = 0.3
|
||||
|
||||
# these are the triads, all major
|
||||
c_tones = [130.81, 164.81, 196.00]
|
||||
g_tones = [196.00, 246.94, 293.66]
|
||||
d_tones = [146.83, 185.00, 220.00]
|
||||
a_tones = [220.00, 277.18, 329.63]
|
||||
e_tones = [164.81, 207.65, 246.94]
|
||||
b_tones = [246.94, 311.13, 369.99]
|
||||
fsharp_tones = [185.00, 233.08, 277.18]
|
||||
csharp_tones = [138.59, 174.61, 207.65]
|
||||
aflat_tones = [207.65, 261.63, 311.13]
|
||||
eflat_tones = [155.56, 196.00, 233.08]
|
||||
bflat_tones = [233.08, 293.66, 349.23]
|
||||
f_tones = [174.61, 220.00, 261.63]
|
||||
|
||||
# names for the alphanumeric displays
|
||||
chord_names = ["Cmaj", "Gmaj", "Dmaj", "Amaj", "Emaj", "Bmaj",
|
||||
"F#ma", "C#ma", "Abma", "Ebma", "Bbma", "Fmaj"]
|
||||
chords = [c_tones, g_tones, d_tones, a_tones, e_tones, b_tones, fsharp_tones, csharp_tones,
|
||||
aflat_tones, eflat_tones, bflat_tones, f_tones]
|
||||
|
||||
# i2c setup
|
||||
i2c = board.I2C()
|
||||
# the encoders
|
||||
seesaw0 = seesaw.Seesaw(i2c, addr=0x49)
|
||||
seesaw1 = seesaw.Seesaw(i2c, addr=0x4A)
|
||||
seesaw2 = seesaw.Seesaw(i2c, addr=0x4B)
|
||||
seesaw3 = seesaw.Seesaw(i2c, addr=0x4C)
|
||||
menu_seesaw = seesaw.Seesaw(i2c, addr=0x4D)
|
||||
# the alphanumeric displays
|
||||
display0 = segments.Seg14x4(i2c, address=0x70)
|
||||
display1 = segments.Seg14x4(i2c, address=0x71)
|
||||
display2 = segments.Seg14x4(i2c, address=0x72)
|
||||
display3 = segments.Seg14x4(i2c, address=0x73)
|
||||
menu_display = segments.Seg14x4(i2c, address=0x74)
|
||||
# the matrix
|
||||
matrix0 = Matrix8x8x2(i2c, address=0x75)
|
||||
|
||||
seesaws = [seesaw0, seesaw1, seesaw2, seesaw3, menu_seesaw]
|
||||
buttons0 = []
|
||||
buttons1 = []
|
||||
buttons2 = []
|
||||
buttons3 = []
|
||||
menu_buttons = []
|
||||
button0_states = []
|
||||
button1_states = []
|
||||
button2_states = []
|
||||
button3_states = []
|
||||
menu_states = []
|
||||
button0_names = ["Select", "Up", "Left", "Down", "Right"]
|
||||
|
||||
# setup the buttons on all of the encoders
|
||||
for i in range(1, 6):
|
||||
seesaw0.pin_mode(i, seesaw0.INPUT_PULLUP)
|
||||
seesaw1.pin_mode(i, seesaw1.INPUT_PULLUP)
|
||||
seesaw2.pin_mode(i, seesaw2.INPUT_PULLUP)
|
||||
seesaw3.pin_mode(i, seesaw3.INPUT_PULLUP)
|
||||
menu_seesaw.pin_mode(i, menu_seesaw.INPUT_PULLUP)
|
||||
buttons0.append(digitalio.DigitalIO(seesaw0, i))
|
||||
buttons1.append(digitalio.DigitalIO(seesaw1, i))
|
||||
buttons2.append(digitalio.DigitalIO(seesaw2, i))
|
||||
buttons3.append(digitalio.DigitalIO(seesaw3, i))
|
||||
menu_buttons.append(digitalio.DigitalIO(menu_seesaw, i))
|
||||
button0_states.append(False)
|
||||
button1_states.append(False)
|
||||
button2_states.append(False)
|
||||
button3_states.append(False)
|
||||
menu_states.append(False)
|
||||
|
||||
# make all of the encoders
|
||||
encoder0 = rotaryio.IncrementalEncoder(seesaw0)
|
||||
last_position0 = 0
|
||||
encoder1 = rotaryio.IncrementalEncoder(seesaw1)
|
||||
last_position1 = 0
|
||||
encoder2 = rotaryio.IncrementalEncoder(seesaw2)
|
||||
last_position2 = 0
|
||||
encoder3 = rotaryio.IncrementalEncoder(seesaw3)
|
||||
last_position3 = 0
|
||||
menu_enc = rotaryio.IncrementalEncoder(menu_seesaw)
|
||||
last_menuPosition = 0
|
||||
|
||||
# Python Implementation of Björklund's Algorithm by Brian House
|
||||
# MIT License 2011
|
||||
# https://github.com/brianhouse/bjorklund
|
||||
|
||||
def bjorklund(steps, pulses):
|
||||
steps = int(steps)
|
||||
pulses = int(pulses)
|
||||
if pulses > steps:
|
||||
raise ValueError
|
||||
pattern = []
|
||||
counts = []
|
||||
remainders = []
|
||||
divisor = steps - pulses
|
||||
remainders.append(pulses)
|
||||
level = 0
|
||||
while True:
|
||||
counts.append(divisor // remainders[level])
|
||||
remainders.append(divisor % remainders[level])
|
||||
divisor = remainders[level]
|
||||
level = level + 1
|
||||
if remainders[level] <= 1:
|
||||
break
|
||||
counts.append(divisor)
|
||||
|
||||
def build(level):
|
||||
if level == -1:
|
||||
pattern.append(0)
|
||||
elif level == -2:
|
||||
pattern.append(1)
|
||||
else:
|
||||
for _ in range(0, counts[level]):
|
||||
build(level - 1)
|
||||
if remainders[level] != 0:
|
||||
build(level - 2)
|
||||
|
||||
build(level)
|
||||
p = pattern.index(1)
|
||||
pattern = pattern[p:] + pattern[0:p]
|
||||
return pattern
|
||||
|
||||
# using ticks for time tracking
|
||||
clock = ticks_ms()
|
||||
|
||||
# default BPM
|
||||
bpm = 120
|
||||
|
||||
# beat divison
|
||||
beat_div = [15, 30, 60, 120, 240]
|
||||
beat_index = 2
|
||||
beat_names = ["1/16", "1/8 ", "1/4 ", "1/2 ", "HOLE"]
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
|
||||
# variables for euclidean
|
||||
c0 = 0
|
||||
c1 = 0
|
||||
c2 = 0
|
||||
c3 = 0
|
||||
r0 = 0
|
||||
r1 = 0
|
||||
r2 = 0
|
||||
r3 = 0
|
||||
last_r0 = 0
|
||||
last_r1 = 0
|
||||
last_r2 = 0
|
||||
last_r3 = 0
|
||||
|
||||
euclid0_steps = 8
|
||||
euclid0_pulses = 4
|
||||
euclid1_steps = 8
|
||||
euclid1_pulses = 4
|
||||
euclid2_steps = 8
|
||||
euclid2_pulses = 4
|
||||
euclid3_steps = 8
|
||||
euclid3_pulses = 4
|
||||
|
||||
rhythm0 = bjorklund(euclid0_steps, euclid0_pulses)
|
||||
rhythm1 = bjorklund(euclid1_steps, euclid1_pulses)
|
||||
rhythm2 = bjorklund(euclid2_steps, euclid2_pulses)
|
||||
rhythm3 = bjorklund(euclid3_steps, euclid3_pulses)
|
||||
|
||||
# read buttons to update Euclidean rhythms
|
||||
# pylint: disable=too-many-branches
|
||||
def read_buttons(button_array, button_states, euc, e_step, e_pulse, the_step):
|
||||
for b in range(5):
|
||||
if not button_array[b].value and button_states[b] is False:
|
||||
button_states[b] = True
|
||||
if button0_names[b] == "Select":
|
||||
e_step = 8
|
||||
e_pulse = 4
|
||||
if the_step >= e_step:
|
||||
the_step = 0
|
||||
elif button0_names[b] == "Up":
|
||||
if e_step > 16:
|
||||
e_step = 16
|
||||
else:
|
||||
e_step += 1
|
||||
elif button0_names[b] == "Down":
|
||||
if e_step < 1:
|
||||
e_step = 1
|
||||
else:
|
||||
e_step -= 1
|
||||
if the_step >= e_step:
|
||||
the_step = 0
|
||||
elif button0_names[b] == "Left":
|
||||
e_pulse -= 1
|
||||
e_pulse = max(e_pulse, 1)
|
||||
else:
|
||||
e_pulse += 1
|
||||
e_pulse = min(e_pulse, e_step)
|
||||
euc = bjorklund(e_step, e_pulse)
|
||||
if button_array[b].value and button_states[b] is True:
|
||||
button_states[b] = False
|
||||
if button0_names[b] in ("Select", "Up", "Down"):
|
||||
matrix0.fill(matrix0.LED_OFF)
|
||||
draw_steps(euclid0_steps, 0)
|
||||
draw_steps(euclid1_steps, 2)
|
||||
draw_steps(euclid2_steps, 4)
|
||||
draw_steps(euclid3_steps, 6)
|
||||
return euc, e_step, e_pulse, the_step
|
||||
|
||||
# play euclidean rhythms and update matrix
|
||||
def play_euclidean(this_synth, n, the_rhythm, rhythm_count, last_count, c, matrix_slot):
|
||||
if last_count <= 7:
|
||||
matrix0[matrix_slot, last_count] = matrix0.LED_GREEN
|
||||
else:
|
||||
c -= 1
|
||||
matrix0[matrix_slot + 1, (last_count - last_count) + c] = matrix0.LED_GREEN
|
||||
c += 1
|
||||
|
||||
if the_rhythm[rhythm_count] == 1:
|
||||
this_synth.frequency = n[randint(0, 2)]
|
||||
synth.press(this_synth)
|
||||
if rhythm_count <= 7:
|
||||
matrix0[matrix_slot, rhythm_count] = matrix0.LED_RED
|
||||
else:
|
||||
matrix0[matrix_slot + 1, (rhythm_count - rhythm_count) + c] = matrix0.LED_RED
|
||||
c += 1
|
||||
else:
|
||||
synth.release(this_synth)
|
||||
if rhythm_count > 7:
|
||||
c += 1
|
||||
last_count = rhythm_count
|
||||
|
||||
rhythm_count += 1
|
||||
if rhythm_count >= len(the_rhythm):
|
||||
rhythm_count = 0
|
||||
if rhythm_count == 1:
|
||||
c = 0
|
||||
return rhythm_count, last_count, c
|
||||
|
||||
# initial matrix draw
|
||||
def draw_steps(euc_steps, col):
|
||||
dif = 0
|
||||
for m in range(euc_steps):
|
||||
if m <= 7:
|
||||
matrix0[col, m] = matrix0.LED_GREEN
|
||||
else:
|
||||
matrix0[col + 1, (m - m) + dif] = matrix0.LED_GREEN
|
||||
dif += 1
|
||||
draw_steps(euclid0_steps, 0)
|
||||
draw_steps(euclid1_steps, 2)
|
||||
draw_steps(euclid2_steps, 4)
|
||||
draw_steps(euclid3_steps, 6)
|
||||
|
||||
# clocks for playing euclidean and reading menu encoder
|
||||
enc_clock = ticks_ms()
|
||||
menu_clock = ticks_ms()
|
||||
|
||||
# the modes menu
|
||||
modes = ["PLAY", "EUC ", "BPM ", "BEAT", "ADSR", "WAVE", "RING", "LFO ", "VOL "]
|
||||
mode_index = 0
|
||||
mode = modes[mode_index]
|
||||
menu_display.print(f" {mode}")
|
||||
|
||||
# default chords
|
||||
chord0_sel = 0
|
||||
chord1_sel = 1
|
||||
chord2_sel = 0
|
||||
chord3_sel = 1
|
||||
|
||||
display0.print(chord_names[chord0_sel])
|
||||
display1.print(chord_names[chord1_sel])
|
||||
display2.print(chord_names[chord2_sel])
|
||||
display3.print(chord_names[chord3_sel])
|
||||
|
||||
# arrays of individual buttons
|
||||
|
||||
select_buttons = [buttons0[0], buttons1[0], buttons2[0], buttons3[0]]
|
||||
left_buttons = [buttons0[2], buttons1[2], buttons2[2], buttons3[2]]
|
||||
right_buttons = [buttons0[4], buttons1[4], buttons2[4], buttons3[4]]
|
||||
select_states = [button0_states[0], button1_states[0], button2_states[0], button3_states[0]]
|
||||
left_states = [button0_states[2], button1_states[2], button2_states[2], button3_states[2]]
|
||||
right_states = [button0_states[4], button1_states[4], button2_states[4], button3_states[4]]
|
||||
select_index = 0
|
||||
left_index = 0
|
||||
right_index = 0
|
||||
|
||||
# adsr mode
|
||||
adsr_names = ["A", "D", "S", "R"]
|
||||
|
||||
synth_adsr_indexes = [0, 0, 0, 0]
|
||||
|
||||
adsr_properties = [0, 1, 4, 2]
|
||||
|
||||
adsr0_values = [amp_env0.attack_time, amp_env0.decay_time,
|
||||
amp_env0.sustain_level, amp_env0.release_time]
|
||||
adsr1_values = [amp_env1.attack_time, amp_env1.decay_time,
|
||||
amp_env1.sustain_level, amp_env1.release_time]
|
||||
adsr2_values = [amp_env0.attack_time, amp_env0.decay_time,
|
||||
amp_env0.sustain_level, amp_env0.release_time]
|
||||
adsr3_values = [amp_env1.attack_time, amp_env1.decay_time,
|
||||
amp_env1.sustain_level, amp_env1.release_time]
|
||||
|
||||
all_adsr_values = [adsr0_values, adsr1_values, adsr2_values, adsr3_values]
|
||||
|
||||
adsr0_val = int(simpleio.map_range(amp_env0.attack_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr1_val = int(simpleio.map_range(amp_env0.decay_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr2_val = int(simpleio.map_range(amp_env0.sustain_level, 0.0, 1.0, 0, 19))
|
||||
|
||||
adsr3_val = int(simpleio.map_range(amp_env0.release_time, 0.0, 1.0, 0, 19))
|
||||
|
||||
clock_stretch = False
|
||||
|
||||
ring0_val = 0
|
||||
ring1_val = 0
|
||||
ring2_val = 0
|
||||
ring3_val = 0
|
||||
|
||||
lfo_val = 0
|
||||
|
||||
# used to play/pause
|
||||
play_states = [True, True, True, True]
|
||||
|
||||
while True:
|
||||
# rotary encoder reading
|
||||
if ticks_diff(ticks_ms(), enc_clock) >= 100:
|
||||
position0 = encoder0.position
|
||||
position1 = encoder1.position
|
||||
position2 = encoder2.position
|
||||
position3 = encoder3.position
|
||||
menuPosition = menu_enc.position
|
||||
# menu changes mode
|
||||
if menuPosition != last_menuPosition:
|
||||
if menuPosition > last_menuPosition:
|
||||
mode_index = (mode_index + 1) % len(modes)
|
||||
else:
|
||||
mode_index = (mode_index - 1) % len(modes)
|
||||
if mode in ("EUC ", "ADSR"):
|
||||
clock_stretch = True
|
||||
if mode in ("PLAY", "BPM ", "BEAT", "WAVE") and clock_stretch:
|
||||
clock = ticks_ms()
|
||||
clock_stretch = False
|
||||
mode = modes[mode_index]
|
||||
menu_display.print(f" {mode}")
|
||||
last_menuPosition = menuPosition
|
||||
# encoder functionality depends on mode
|
||||
# encoder 0 has most functionality
|
||||
if position0 != last_position0:
|
||||
if position0 > last_position0:
|
||||
if mode == "PLAY":
|
||||
chord0_sel = (chord0_sel + 1) % len(chords)
|
||||
display0.print(chord_names[chord0_sel])
|
||||
elif mode == "BEAT":
|
||||
beat_index = (beat_index + 1) % 5
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
elif mode == "BPM ":
|
||||
bpm += 1
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {bpm}")
|
||||
elif mode == "ADSR":
|
||||
adsr0_val = (adsr0_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr0_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[0][synth_adsr_indexes[0]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[0][0],
|
||||
decay_time = all_adsr_values[0][1],
|
||||
release_time=all_adsr_values[0][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[0][2])
|
||||
synth0.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth0_wave = (synth0_wave + 1) % len(wave_names)
|
||||
synth0.waveform = waveforms[synth0_wave]
|
||||
elif mode == "RING":
|
||||
ring0_val = (ring0_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring0_val, 0, 24, 0.0, 220.0)
|
||||
synth0.ring_frequency = mapped_val
|
||||
elif mode == "LFO ":
|
||||
lfo_val = (lfo_val + 1) % 10
|
||||
mapped_val = simpleio.map_range(lfo_val, 0, 9, 0.0, 5.0)
|
||||
lfo.rate = mapped_val
|
||||
elif mode == "VOL ":
|
||||
vol_val = (vol_val + 1) % 10
|
||||
mapped_val = simpleio.map_range(vol_val, 0, 9, 0.0, 1.0)
|
||||
mixer.voice[0].level = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord0_sel = (chord0_sel - 1) % len(chords)
|
||||
display0.print(chord_names[chord0_sel])
|
||||
elif mode == "BEAT":
|
||||
beat_index = (beat_index - 1) % 5
|
||||
delay = int((beat_div[beat_index] / bpm) * 1000)
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
elif mode == "BPM ":
|
||||
bpm -= 1
|
||||
display0.print(f" {bpm}")
|
||||
elif mode == "ADSR":
|
||||
adsr0_val = (adsr0_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr0_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[0][synth_adsr_indexes[0]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[0][0],
|
||||
decay_time = all_adsr_values[0][1],
|
||||
release_time=all_adsr_values[0][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[0][2])
|
||||
synth0.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth0_wave = (synth0_wave - 1) % len(wave_names)
|
||||
synth0.waveform = waveforms[synth0_wave]
|
||||
elif mode == "RING":
|
||||
ring0_val = (ring0_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring0_val, 0, 24, 0.0, 220.0)
|
||||
synth0.ring_frequency = mapped_val
|
||||
elif mode == "LFO ":
|
||||
lfo_val = (lfo_val - 1) % 10
|
||||
mapped_val = simpleio.map_range(lfo_val, 0, 9, 0.0, 5.0)
|
||||
lfo.rate = mapped_val
|
||||
elif mode == "VOL ":
|
||||
vol_val = (vol_val - 1) % 10
|
||||
mapped_val = simpleio.map_range(vol_val, 0, 9, 0.0, 1.0)
|
||||
mixer.voice[0].level = mapped_val
|
||||
last_position0 = position0
|
||||
if position1 != last_position1:
|
||||
if position1 > last_position1:
|
||||
if mode == "PLAY":
|
||||
chord1_sel = (chord1_sel + 1) % len(chords)
|
||||
display1.print(chord_names[chord1_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr1_val = (adsr1_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr1_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[1][synth_adsr_indexes[1]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[1][0],
|
||||
decay_time = all_adsr_values[1][1],
|
||||
release_time=all_adsr_values[1][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[1][2])
|
||||
synth1.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth1_wave = (synth1_wave + 1) % len(wave_names)
|
||||
synth1.waveform = waveforms[synth1_wave]
|
||||
elif mode == "RING":
|
||||
ring1_val = (ring1_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring1_val, 0, 24, 0.0, 220.0)
|
||||
synth1.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord1_sel = (chord1_sel - 1) % len(chords)
|
||||
display1.print(chord_names[chord1_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr1_val = (adsr1_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr1_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[1][synth_adsr_indexes[1]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[1][0],
|
||||
decay_time = all_adsr_values[1][1],
|
||||
release_time=all_adsr_values[1][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[1][2])
|
||||
synth1.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth1_wave = (synth1_wave - 1) % len(wave_names)
|
||||
synth1.waveform = waveforms[synth1_wave]
|
||||
elif mode == "RING":
|
||||
ring1_val = (ring1_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring1_val, 0, 24, 0.0, 220.0)
|
||||
synth1.ring_frequency = mapped_val
|
||||
last_position1 = position1
|
||||
if position2 != last_position2:
|
||||
if position2 > last_position2:
|
||||
if mode == "PLAY":
|
||||
chord2_sel = (chord2_sel + 1) % len(chords)
|
||||
elif mode == "ADSR":
|
||||
adsr2_val = (adsr2_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr2_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[2][synth_adsr_indexes[2]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[2][0],
|
||||
decay_time = all_adsr_values[2][1],
|
||||
release_time=all_adsr_values[2][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[2][2])
|
||||
synth2.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth2_wave = (synth2_wave + 1) % len(wave_names)
|
||||
synth2.waveform = waveforms[synth2_wave]
|
||||
elif mode == "RING":
|
||||
ring2_val = (ring2_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring2_val, 0, 24, 0.0, 220.0)
|
||||
synth2.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord2_sel = (chord2_sel - 1) % len(chords)
|
||||
display2.print(chord_names[chord2_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr2_val = (adsr2_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr2_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[2][synth_adsr_indexes[2]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[2][0],
|
||||
decay_time = all_adsr_values[2][1],
|
||||
release_time=all_adsr_values[2][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[2][2])
|
||||
synth2.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth2_wave = (synth2_wave - 1) % len(wave_names)
|
||||
synth2.waveform = waveforms[synth2_wave]
|
||||
elif mode == "RING":
|
||||
ring2_val = (ring2_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring2_val, 0, 24, 0.0, 220.0)
|
||||
synth2.ring_frequency = mapped_val
|
||||
last_position2 = position2
|
||||
if position3 != last_position3:
|
||||
if position3 > last_position3:
|
||||
if mode == "PLAY":
|
||||
chord3_sel = (chord3_sel + 1) % len(chords)
|
||||
display3.print(chord_names[chord3_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr3_val = (adsr3_val + 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr3_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[3][synth_adsr_indexes[3]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[3][0],
|
||||
decay_time = all_adsr_values[3][1],
|
||||
release_time=all_adsr_values[3][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[3][2])
|
||||
synth3.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth3_wave = (synth3_wave + 1) % len(wave_names)
|
||||
synth3.waveform = waveforms[synth3_wave]
|
||||
elif mode == "RING":
|
||||
ring3_val = (ring3_val + 1) % 25
|
||||
mapped_val = simpleio.map_range(ring3_val, 0, 24, 0.0, 220.0)
|
||||
synth3.ring_frequency = mapped_val
|
||||
else:
|
||||
if mode == "PLAY":
|
||||
chord3_sel = (chord3_sel - 1) % len(chords)
|
||||
display3.print(chord_names[chord3_sel])
|
||||
elif mode == "ADSR":
|
||||
adsr3_val = (adsr3_val - 1) % 20
|
||||
mapped_val = simpleio.map_range(adsr3_val, 0, 19, 0.0, 1.0)
|
||||
all_adsr_values[3][synth_adsr_indexes[3]] = mapped_val
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[3][0],
|
||||
decay_time = all_adsr_values[3][1],
|
||||
release_time=all_adsr_values[3][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[3][2])
|
||||
synth3.envelope = the_env
|
||||
elif mode == "WAVE":
|
||||
synth3_wave = (synth3_wave - 1) % len(wave_names)
|
||||
synth3.waveform = waveforms[synth3_wave]
|
||||
elif mode == "RING":
|
||||
ring3_val = (ring3_val - 1) % 25
|
||||
mapped_val = simpleio.map_range(ring3_val, 0, 24, 0.0, 220.0)
|
||||
synth3.ring_frequency = mapped_val
|
||||
last_position3 = position3
|
||||
enc_clock = ticks_add(enc_clock, 100)
|
||||
|
||||
# synth plays based on ticks timing
|
||||
if ticks_diff(ticks_ms(), clock) >= delay:
|
||||
if play_states[0] is True:
|
||||
r0, last_r0, c0 = play_euclidean(synth0, chords[chord0_sel],
|
||||
rhythm0, r0, last_r0, c0, 0)
|
||||
if play_states[1] is True:
|
||||
r1, last_r1, c1 = play_euclidean(synth1, chords[chord1_sel],
|
||||
rhythm1, r1, last_r1, c1, 2)
|
||||
if play_states[2] is True:
|
||||
r2, last_r2, c2 = play_euclidean(synth2, chords[chord2_sel],
|
||||
rhythm2, r2, last_r2, c2, 4)
|
||||
if play_states[3] is True:
|
||||
r3, last_r3, c3 = play_euclidean(synth3, chords[chord3_sel],
|
||||
rhythm3, r3, last_r3, c3, 6)
|
||||
clock = ticks_add(clock, delay)
|
||||
# in PLAY select button controls play/pause
|
||||
if mode == "PLAY":
|
||||
for i in range(4):
|
||||
if not select_buttons[i].value and select_states[i] is False:
|
||||
select_states[i] = True
|
||||
if play_states[i] is True:
|
||||
synth.release(synths[i])
|
||||
play_states[i] = False
|
||||
else:
|
||||
play_states[i] = True
|
||||
if select_buttons[i].value and select_states[i] is True:
|
||||
select_states[i] = False
|
||||
display0.print(chord_names[chord0_sel])
|
||||
display1.print(chord_names[chord1_sel])
|
||||
display2.print(chord_names[chord2_sel])
|
||||
display3.print(chord_names[chord3_sel])
|
||||
# EUC menu select resets cycle count
|
||||
elif mode == "EUC ":
|
||||
if not menu_buttons[0].value and menu_states[0] is False:
|
||||
r0 = 0
|
||||
r1 = 0
|
||||
r2 = 0
|
||||
r3 = 0
|
||||
menu_states[0] = True
|
||||
if menu_buttons[0].value and menu_states[0] is True:
|
||||
menu_states[0] = False
|
||||
rhythm0, euclid0_steps, euclid0_pulses, r0 = read_buttons(buttons0, button0_states,
|
||||
rhythm0, euclid0_steps,
|
||||
euclid0_pulses, r0)
|
||||
rhythm1, euclid1_steps, euclid1_pulses, r1 = read_buttons(buttons1, button1_states,
|
||||
rhythm1, euclid1_steps,
|
||||
euclid1_pulses, r1)
|
||||
rhythm2, euclid2_steps, euclid2_pulses, r2 = read_buttons(buttons2, button2_states,
|
||||
rhythm2, euclid2_steps,
|
||||
euclid2_pulses, r2)
|
||||
rhythm3, euclid3_steps, euclid3_pulses, r3 = read_buttons(buttons3, button3_states,
|
||||
rhythm3, euclid3_steps,
|
||||
euclid3_pulses, r3)
|
||||
display0.print(f" {euclid0_pulses}")
|
||||
display1.print(f" {euclid1_pulses}")
|
||||
display2.print(f" {euclid2_pulses}")
|
||||
display3.print(f" {euclid3_pulses}")
|
||||
# BPM is adjusted
|
||||
elif mode == "BPM ":
|
||||
if not select_buttons[0].value and select_states[0] is False:
|
||||
bpm = 120
|
||||
select_states[0] = True
|
||||
if select_buttons[0].value and select_states[0] is True:
|
||||
select_states[0] = False
|
||||
display0.print(f" {bpm}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# beat division is changed
|
||||
elif mode == "BEAT":
|
||||
if not select_buttons[0].value and select_states[0] is False:
|
||||
beat_names[beat_index] = 2
|
||||
select_states[0] = True
|
||||
if select_buttons[0].value and select_states[0] is True:
|
||||
select_states[0] = False
|
||||
display0.print(f" {beat_names[beat_index]}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# adsr for each voice
|
||||
elif mode == "ADSR":
|
||||
for i in range(4):
|
||||
if not left_buttons[i].value and left_states[i] is False:
|
||||
synth_adsr_indexes[i] = (synth_adsr_indexes[i] - 1) % 4
|
||||
left_states[i] = True
|
||||
the_synth = synths[i]
|
||||
if left_buttons[i].value and left_states[i] is True:
|
||||
left_states[i] = False
|
||||
if not right_buttons[i].value and right_states[i] is False:
|
||||
synth_adsr_indexes[i] = (synth_adsr_indexes[i] + 1) % 4
|
||||
right_states[i] = True
|
||||
if right_buttons[i].value and right_states[i] is True:
|
||||
right_states[i] = False
|
||||
if not select_buttons[i].value and select_states[i] is False:
|
||||
the_synth = synths[i]
|
||||
all_adsr_values[i][0] = 0.1
|
||||
all_adsr_values[i][1] = 0.1
|
||||
all_adsr_values[i][3] = 0.1
|
||||
all_adsr_values[i][2] = 0.05
|
||||
the_env = synthio.Envelope(attack_time=all_adsr_values[i][0],
|
||||
decay_time = all_adsr_values[i][1],
|
||||
release_time=all_adsr_values[i][3],
|
||||
attack_level=1, sustain_level=all_adsr_values[i][2])
|
||||
the_synth.envelope = the_env
|
||||
select_states[i] = True
|
||||
if select_buttons[i].value and select_states[i] is True:
|
||||
select_states[i] = False
|
||||
# pylint: disable=line-too-long
|
||||
display0.print(f"{adsr_names[synth_adsr_indexes[0]]}{synth0.envelope[adsr_properties[synth_adsr_indexes[0]]]:.2f}")
|
||||
display1.print(f"{adsr_names[synth_adsr_indexes[1]]}{synth1.envelope[adsr_properties[synth_adsr_indexes[1]]]:.2f}")
|
||||
display2.print(f"{adsr_names[synth_adsr_indexes[2]]}{synth2.envelope[adsr_properties[synth_adsr_indexes[2]]]:.2f}")
|
||||
display3.print(f"{adsr_names[synth_adsr_indexes[3]]}{synth3.envelope[adsr_properties[synth_adsr_indexes[3]]]:.2f}")
|
||||
# change waveform
|
||||
elif mode == "WAVE":
|
||||
display0.print(f" {wave_names[synth0_wave]}")
|
||||
display1.print(f" {wave_names[synth1_wave]}")
|
||||
display2.print(f" {wave_names[synth2_wave]}")
|
||||
display3.print(f" {wave_names[synth3_wave]}")
|
||||
# adjust ring modulation
|
||||
elif mode == "RING":
|
||||
display0.print(f" {synth0.ring_frequency:.1f}")
|
||||
display1.print(f" {synth1.ring_frequency:.1f}")
|
||||
display2.print(f" {synth2.ring_frequency:.1f}")
|
||||
display3.print(f" {synth3.ring_frequency:.1f}")
|
||||
# adjust lfo rate used for ring modulation
|
||||
elif mode == "LFO ":
|
||||
display0.print("RATE")
|
||||
display1.print(f" {lfo.rate:.1f}")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
# overall volume 0.0 - 1.0
|
||||
elif mode == "VOL ":
|
||||
display0.print(f" {mixer.voice[0].level:.1f}")
|
||||
display1.print(" ")
|
||||
display2.print(" ")
|
||||
display3.print(" ")
|
||||
43
AS5600_Magnetic_Encoder/code.py
Normal file
43
AS5600_Magnetic_Encoder/code.py
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2025 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""AS5600 Encoder"""
|
||||
import usb_hid
|
||||
import board
|
||||
from adafruit_hid.consumer_control import ConsumerControl
|
||||
from adafruit_hid.consumer_control_code import ConsumerControlCode
|
||||
import adafruit_as5600
|
||||
|
||||
i2c = board.STEMMA_I2C()
|
||||
sensor = adafruit_as5600.AS5600(i2c)
|
||||
enc_inc = ConsumerControlCode.VOLUME_INCREMENT
|
||||
enc_dec = ConsumerControlCode.VOLUME_DECREMENT
|
||||
cc = ConsumerControl(usb_hid.devices)
|
||||
|
||||
last_val = sensor.angle
|
||||
|
||||
THRESHOLD = sensor.max_angle // 2 # default max_angle is 4095
|
||||
# you can change the max_angle. ex: sensor.max_angle = 1000
|
||||
|
||||
MIN_CHANGE = 25 # minimum change to register as movement
|
||||
# increase to make less sensitive, decrease to make more sensitive
|
||||
|
||||
while True:
|
||||
enc_val = sensor.angle
|
||||
if abs(enc_val - last_val) >= MIN_CHANGE or abs(enc_val - last_val) > THRESHOLD:
|
||||
# Calculate the difference
|
||||
diff = enc_val - last_val
|
||||
# Check for wraparound
|
||||
if diff > THRESHOLD:
|
||||
# Wrapped from ~4095 to ~0 (actually turning backwards)
|
||||
cc.send(enc_dec)
|
||||
elif diff < -THRESHOLD:
|
||||
# Wrapped from ~0 to ~4095 (actually turning forwards)
|
||||
cc.send(enc_inc)
|
||||
elif diff > 0:
|
||||
# Normal forward rotation
|
||||
cc.send(enc_inc)
|
||||
else:
|
||||
# Normal backward rotation (diff < 0)
|
||||
cc.send(enc_dec)
|
||||
last_val = enc_val
|
||||
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/adabot.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/adabot.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/circuits.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/circuits.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/database.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/database.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/didibreaksomething.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/didibreaksomething.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/doyoureadme.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/doyoureadme.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/electrons.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/electrons.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/excellent.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/excellent.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/hearsome.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/hearsome.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/hello.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/hello.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/interesting.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/interesting.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/lemonade.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/lemonade.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/meetyou.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/meetyou.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/moodmusic.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/moodmusic.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/operational.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/operational.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/powerful.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/powerful.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/uhoh.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/uhoh.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/whhaatt.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/whhaatt.wav
Normal file
Binary file not shown.
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/whowork.wav
Normal file
BIN
Adabot_RP2040_Prop-Maker_Feather/WAVs/whowork.wav
Normal file
Binary file not shown.
149
Adabot_RP2040_Prop-Maker_Feather/code.py
Normal file
149
Adabot_RP2040_Prop-Maker_Feather/code.py
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
# SPDX-FileCopyrightText: 2023 Liz Clark for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import os
|
||||
import random
|
||||
import board
|
||||
import audiocore
|
||||
import audiobusio
|
||||
import audiomixer
|
||||
import pwmio
|
||||
import neopixel
|
||||
import adafruit_lis3dh
|
||||
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
|
||||
from digitalio import DigitalInOut, Direction, Pull
|
||||
from adafruit_motor import servo
|
||||
from adafruit_led_animation.animation.comet import Comet
|
||||
from adafruit_led_animation.animation.pulse import Pulse
|
||||
from adafruit_led_animation.animation.sparkle import Sparkle
|
||||
from adafruit_led_animation.color import RED, BLUE, BLACK
|
||||
|
||||
# enable external power pin
|
||||
# provides power to the external components
|
||||
external_power = DigitalInOut(board.EXTERNAL_POWER)
|
||||
external_power.direction = Direction.OUTPUT
|
||||
external_power.value = True
|
||||
|
||||
i2c = board.I2C()
|
||||
int1 = DigitalInOut(board.ACCELEROMETER_INTERRUPT)
|
||||
lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, int1=int1)
|
||||
lis3dh.range = adafruit_lis3dh.RANGE_2_G
|
||||
|
||||
switch = DigitalInOut(board.EXTERNAL_BUTTON)
|
||||
switch.direction = Direction.INPUT
|
||||
switch.pull = Pull.UP
|
||||
switch_state = False
|
||||
|
||||
wavs = []
|
||||
for filename in os.listdir('/WAVs'):
|
||||
if filename.lower().endswith('.wav') and not filename.startswith('.'):
|
||||
wavs.append("/WAVs/"+filename)
|
||||
|
||||
audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)
|
||||
mixer = audiomixer.Mixer(voice_count=1, sample_rate=22050, channel_count=1,
|
||||
bits_per_sample=16, samples_signed=True, buffer_size=32768)
|
||||
|
||||
mixer.voice[0].level = 1
|
||||
track_number = 0
|
||||
wav_filename = wavs[track_number]
|
||||
wav_file = open(wav_filename, "rb")
|
||||
wave = audiocore.WaveFile(wav_file)
|
||||
audio.play(mixer)
|
||||
mixer.voice[0].play(wave)
|
||||
|
||||
def open_audio(num):
|
||||
n = wavs[num]
|
||||
f = open(n, "rb")
|
||||
w = audiocore.WaveFile(f)
|
||||
return w
|
||||
|
||||
PIXEL_PIN = board.EXTERNAL_NEOPIXELS
|
||||
SERVO_PIN = board.EXTERNAL_SERVO
|
||||
NUM_PIXELS = 8
|
||||
ORDER = neopixel.GRB
|
||||
BRIGHTNESS = 0.3
|
||||
|
||||
PWM = pwmio.PWMOut(SERVO_PIN, duty_cycle=2 ** 15, frequency=50)
|
||||
SERVO = servo.Servo(PWM)
|
||||
|
||||
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
|
||||
pixel.brightness = 1
|
||||
|
||||
PIXELS = neopixel.NeoPixel(PIXEL_PIN, NUM_PIXELS, auto_write=False,
|
||||
pixel_order=ORDER)
|
||||
LARSON = Comet(PIXELS, bounce=True, speed=0.07,
|
||||
tail_length=NUM_PIXELS//2,
|
||||
color=(BLUE[0] * BRIGHTNESS,
|
||||
BLUE[1] * BRIGHTNESS,
|
||||
BLUE[2] * BRIGHTNESS))
|
||||
pulse = Pulse(PIXELS, speed=0.05,
|
||||
color=(BLUE[0] * BRIGHTNESS,
|
||||
BLUE[1] * BRIGHTNESS,
|
||||
BLUE[2] * BRIGHTNESS), period=3)
|
||||
sparkle = Sparkle(PIXELS, speed=0.2,
|
||||
color=(RED[0] * BRIGHTNESS,
|
||||
RED[1] * BRIGHTNESS,
|
||||
RED[2] * BRIGHTNESS), num_sparkles=10)
|
||||
|
||||
SERVO.angle = POSITION = NEXT_POSITION = 90
|
||||
MOVING = False
|
||||
START_TIME = ticks_ms()
|
||||
DURATION = 1000
|
||||
|
||||
adabot_talk = False
|
||||
|
||||
clock = ticks_ms()
|
||||
prop_time = 1000
|
||||
adabot_nap = False
|
||||
|
||||
mixer.voice[0].play(wave)
|
||||
while mixer.playing:
|
||||
LARSON.animate()
|
||||
|
||||
while True:
|
||||
if ticks_diff(ticks_ms(), clock) >= prop_time:
|
||||
x, y, z = [
|
||||
value / adafruit_lis3dh.STANDARD_GRAVITY for value in lis3dh.acceleration
|
||||
]
|
||||
if z > 0.9:
|
||||
adabot_nap = True
|
||||
SERVO.angle = POSITION = NEXT_POSITION = 90
|
||||
else:
|
||||
adabot_nap = False
|
||||
if not adabot_nap:
|
||||
MOVING = not MOVING
|
||||
if MOVING:
|
||||
POSITION = NEXT_POSITION
|
||||
while abs(POSITION - NEXT_POSITION) < 10:
|
||||
NEXT_POSITION = random.uniform(0, 180)
|
||||
DURATION = 0.2 + 0.6 * abs(POSITION - NEXT_POSITION) / 180
|
||||
else:
|
||||
SERVO.angle = NEXT_POSITION
|
||||
DURATION = random.uniform(0.5, 2.5)
|
||||
clock = ticks_add(clock, prop_time)
|
||||
if MOVING:
|
||||
FRACTION = 0.0 / DURATION
|
||||
FRACTION = (3 * FRACTION ** 2) - (2 * FRACTION ** 3)
|
||||
SERVO.angle = POSITION + (NEXT_POSITION - POSITION) * FRACTION
|
||||
if adabot_talk:
|
||||
wave = open_audio(random.randint(1, 17))
|
||||
mixer.voice[0].play(wave)
|
||||
while mixer.playing:
|
||||
sparkle.animate()
|
||||
if not mixer.playing:
|
||||
adabot_talk = False
|
||||
PIXELS.fill(BLACK)
|
||||
PIXELS.show()
|
||||
elif adabot_nap:
|
||||
pulse.animate()
|
||||
else:
|
||||
LARSON.animate()
|
||||
|
||||
if not switch.value and switch_state is False:
|
||||
PIXELS.fill(BLACK)
|
||||
PIXELS.show()
|
||||
adabot_talk = True
|
||||
switch_state = True
|
||||
if switch.value and switch_state is True:
|
||||
switch_state = False
|
||||
40
Adafruit_DRV8833/arduino/drv8833_onoff/drv8833_onoff.ino
Normal file
40
Adafruit_DRV8833/arduino/drv8833_onoff/drv8833_onoff.ino
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
// SPDX-FileCopyrightText: 2025 Carter Nelson for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Basic ON/OFF control of DC motor via DRV8833
|
||||
|
||||
#define AIN1 5
|
||||
#define AIN2 6
|
||||
#define SLP 7
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Adafruit DRV8833 DC Motor Example - ON/OFF");
|
||||
|
||||
// configure pins
|
||||
pinMode(AIN1, OUTPUT);
|
||||
pinMode(AIN2, OUTPUT);
|
||||
pinMode(SLP, OUTPUT);
|
||||
|
||||
// enable DRV8833
|
||||
digitalWrite(SLP, HIGH);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//
|
||||
// FORWARD
|
||||
//
|
||||
Serial.println("Forward");
|
||||
digitalWrite(AIN1, HIGH);
|
||||
digitalWrite(AIN2, LOW);
|
||||
delay(1000);
|
||||
|
||||
//
|
||||
// REVERSE
|
||||
//
|
||||
Serial.println("Reverse");
|
||||
digitalWrite(AIN1, LOW);
|
||||
digitalWrite(AIN2, HIGH);
|
||||
delay(1000);
|
||||
}
|
||||
60
Adafruit_DRV8833/arduino/drv8833_pwm/drv8833_pwm.ino
Normal file
60
Adafruit_DRV8833/arduino/drv8833_pwm/drv8833_pwm.ino
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
// SPDX-FileCopyrightText: 2025 Carter Nelson for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// PWM speed control of DC motor via DRV8833
|
||||
|
||||
#define AIN1 5
|
||||
#define AIN2 6
|
||||
#define SLP 7
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Adafruit DRV8833 DC Motor Example - PWM");
|
||||
|
||||
// configure pins
|
||||
pinMode(AIN1, OUTPUT);
|
||||
pinMode(AIN2, OUTPUT);
|
||||
pinMode(SLP, OUTPUT);
|
||||
|
||||
// enable DRV8833
|
||||
digitalWrite(SLP, HIGH);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
//
|
||||
// FORWARD
|
||||
//
|
||||
Serial.println("Forward");
|
||||
digitalWrite(AIN2, LOW);
|
||||
// ramp speed up
|
||||
Serial.println(" ramping up");
|
||||
for (int duty_cycle=0; duty_cycle<256; duty_cycle++) {
|
||||
analogWrite(AIN1, duty_cycle);
|
||||
delay(10);
|
||||
}
|
||||
// ramp speed down
|
||||
Serial.println(" ramping down");
|
||||
for (int duty_cycle=255; duty_cycle>=0; duty_cycle--) {
|
||||
analogWrite(AIN1, duty_cycle);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
//
|
||||
// REVERSE
|
||||
//
|
||||
Serial.println("Reverse");
|
||||
digitalWrite(AIN1, LOW);
|
||||
// ramp speed up
|
||||
Serial.println(" ramping up");
|
||||
for (int duty_cycle=0; duty_cycle<256; duty_cycle++) {
|
||||
analogWrite(AIN2, duty_cycle);
|
||||
delay(10);
|
||||
}
|
||||
// ramp speed down
|
||||
Serial.println(" ramping down");
|
||||
for (int duty_cycle=255; duty_cycle>=0; duty_cycle--) {
|
||||
analogWrite(AIN2, duty_cycle);
|
||||
delay(10);
|
||||
}
|
||||
}
|
||||
30
Adafruit_DRV8833/arduino/drv8833_stepper/drv8833_stepper.ino
Normal file
30
Adafruit_DRV8833/arduino/drv8833_stepper/drv8833_stepper.ino
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// SPDX-FileCopyrightText: 2025 lady ada for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <Stepper.h>
|
||||
|
||||
// change this to the number of steps on your motor
|
||||
#define STEPS 200
|
||||
|
||||
// create an instance of the stepper class, specifying
|
||||
// the number of steps of the motor and the pins it's
|
||||
// attached to
|
||||
Stepper stepper(STEPS, 4, 5, 6, 7);
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println("Stepper test!");
|
||||
// set the speed of the motor to 30 RPMs
|
||||
stepper.setSpeed(60);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
Serial.println("Forward");
|
||||
stepper.step(STEPS);
|
||||
Serial.println("Backward");
|
||||
stepper.step(-STEPS);
|
||||
}
|
||||
37
Adafruit_DRV8833/circuitpython/onoff/code.py
Normal file
37
Adafruit_DRV8833/circuitpython/onoff/code.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-FileCopyrightText: 2025 Carter Nelson for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import digitalio
|
||||
|
||||
# Configure pins
|
||||
AIN1 = digitalio.DigitalInOut(board.D5)
|
||||
AIN2 = digitalio.DigitalInOut(board.D6)
|
||||
SLP = digitalio.DigitalInOut(board.D7)
|
||||
|
||||
AIN1.switch_to_output()
|
||||
AIN2.switch_to_output()
|
||||
SLP.switch_to_output()
|
||||
|
||||
# Enable DRV8833
|
||||
SLP.value = True
|
||||
|
||||
# Loop forever
|
||||
while True:
|
||||
#
|
||||
# FORWARD
|
||||
#
|
||||
print("Forward")
|
||||
AIN1.value = True
|
||||
AIN2.value = False
|
||||
time.sleep(1)
|
||||
|
||||
#
|
||||
# REVERSE
|
||||
#
|
||||
print("Reverse")
|
||||
AIN1.value = False
|
||||
AIN2.value = True
|
||||
time.sleep(1)
|
||||
48
Adafruit_DRV8833/circuitpython/pwm/code.py
Normal file
48
Adafruit_DRV8833/circuitpython/pwm/code.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# SPDX-FileCopyrightText: 2025 Carter Nelson for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import time
|
||||
import board
|
||||
import digitalio
|
||||
import pwmio
|
||||
|
||||
# Configure pins
|
||||
AIN1 = pwmio.PWMOut(board.D5, frequency=2000)
|
||||
AIN2 = pwmio.PWMOut(board.D6, frequency=2000)
|
||||
SLP = digitalio.DigitalInOut(board.D7)
|
||||
|
||||
SLP.switch_to_output()
|
||||
|
||||
# Enable DRV8833
|
||||
SLP.value = True
|
||||
|
||||
# Loop forever
|
||||
while True:
|
||||
#
|
||||
# FORWARD
|
||||
#
|
||||
print("Forward")
|
||||
AIN2.duty_cycle = 0
|
||||
print(" ramping up")
|
||||
for duty_cycle in range(0, 65536, 100):
|
||||
AIN1.duty_cycle = duty_cycle
|
||||
time.sleep(0.01)
|
||||
print(" ramping down")
|
||||
for duty_cycle in range(65535, -1, -100):
|
||||
AIN1.duty_cycle = duty_cycle
|
||||
time.sleep(0.01)
|
||||
|
||||
#
|
||||
# REVERSE
|
||||
#
|
||||
print("Reverse")
|
||||
AIN1.duty_cycle = 0
|
||||
print(" ramping up")
|
||||
for duty_cycle in range(0, 65536, 100):
|
||||
AIN2.duty_cycle = duty_cycle
|
||||
time.sleep(0.01)
|
||||
print(" ramping down")
|
||||
for duty_cycle in range(65535, -1, -100):
|
||||
AIN2.duty_cycle = duty_cycle
|
||||
time.sleep(0.01)
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
//#define ADAFRUIT_FEATHER_ESP32_V2
|
||||
|
||||
// then these pins will be defined for us
|
||||
#if defined(ADAFRUIT_FEATHER_ESP32_V2)
|
||||
#if defined(ADAFRUIT_FEATHER_ESP32_V2) or defined(ARDUINO_ADAFRUIT_ITSYBITSY_ESP32)
|
||||
#define PIN_NEOPIXEL 0
|
||||
#define NEOPIXEL_I2C_POWER 2
|
||||
#endif
|
||||
|
|
@ -93,7 +93,7 @@ void disableInternalPower() {
|
|||
#endif
|
||||
|
||||
#if defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2)
|
||||
// turn on the I2C power by setting pin to rest state (off)
|
||||
// turn off the I2C power by setting pin to rest state (off)
|
||||
pinMode(PIN_I2C_POWER, INPUT);
|
||||
pinMode(NEOPIXEL_POWER, OUTPUT);
|
||||
digitalWrite(NEOPIXEL_POWER, LOW);
|
||||
|
|
|
|||
|
|
@ -109,16 +109,32 @@ void setup() {
|
|||
digitalWrite(ESP32_RESETN, HIGH);
|
||||
pixel.setPixelColor(0, 20, 20, 0); pixel.show();
|
||||
delay(100);
|
||||
|
||||
#if defined(LED_BUILTIN)
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (Serial.available()) {
|
||||
#if defined(ARDUINO_ARCH_RP2040) // Neopixel is blocking and this annoys esptool
|
||||
#if defined(LED_BUILTIN)
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
#endif
|
||||
#else
|
||||
pixel.setPixelColor(0, 10, 0, 0); pixel.show();
|
||||
#endif
|
||||
SerialESP32.write(Serial.read());
|
||||
}
|
||||
|
||||
while (SerialESP32.available()) {
|
||||
#if defined(ARDUINO_ARCH_RP2040) // Neopixel is blocking and this annoys esptool
|
||||
#if defined(LED_BUILTIN)
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
#endif
|
||||
#else
|
||||
pixel.setPixelColor(0, 0, 0, 10); pixel.show();
|
||||
#endif
|
||||
Serial.write(SerialESP32.read());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
#include "config.h"
|
||||
#include <Adafruit_BME280.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
|
||||
Adafruit_BME280 bme; // I2C
|
||||
|
||||
AdafruitIO_Feed *temperature = io.feed("temperature");
|
||||
AdafruitIO_Feed *humidity = io.feed("humidity");
|
||||
AdafruitIO_Feed *pressure = io.feed("pressure");
|
||||
float temp, humid, pres;
|
||||
|
||||
Adafruit_NeoPixel pixel(1, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, HIGH);
|
||||
|
||||
// wait for serial monitor to open
|
||||
//while(! Serial);
|
||||
|
||||
// turn on neopixel
|
||||
pinMode(NEOPIXEL_POWER, OUTPUT);
|
||||
digitalWrite(NEOPIXEL_POWER, HIGH);
|
||||
pixel.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
|
||||
pixel.setBrightness(10); // not so bright
|
||||
|
||||
pixel.setPixelColor(0, 0xFF0000); // red
|
||||
pixel.show();
|
||||
|
||||
if (! bme.begin()) {
|
||||
Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
|
||||
deepSleep();
|
||||
}
|
||||
Serial.println("Found BME280");
|
||||
float temp = bme.readTemperature();
|
||||
float pres = bme.readPressure() / 100.0F;
|
||||
float hum = bme.readHumidity();
|
||||
// shhh time to close your eyes
|
||||
bme.setSampling(Adafruit_BME280::MODE_SLEEP,
|
||||
Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::SAMPLING_X16, Adafruit_BME280::SAMPLING_X16,
|
||||
Adafruit_BME280::FILTER_OFF,
|
||||
Adafruit_BME280::STANDBY_MS_1000);
|
||||
|
||||
Serial.print("Connecting to Adafruit IO");
|
||||
|
||||
pixel.setPixelColor(0, 0xFFFF00); // yellow
|
||||
pixel.show();
|
||||
|
||||
// connect to io.adafruit.com
|
||||
io.connect();
|
||||
|
||||
// wait for a connection
|
||||
while(io.status() < AIO_CONNECTED) {
|
||||
Serial.print(".");
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// we are connected
|
||||
pixel.setPixelColor(0, 0x00FF00); // green
|
||||
pixel.show();
|
||||
Serial.println();
|
||||
Serial.println(io.statusText());
|
||||
|
||||
io.run();
|
||||
|
||||
temp = temp * 9.0 / 5.0 + 32;
|
||||
Serial.print("Temperature = ");
|
||||
Serial.print(temp);
|
||||
Serial.println(" *F");
|
||||
temperature->save(temp);
|
||||
|
||||
Serial.print("Pressure = ");
|
||||
Serial.print(pres);
|
||||
Serial.println(" hPa");
|
||||
pressure->save(pres);
|
||||
|
||||
Serial.print("Humidity = ");
|
||||
Serial.print(hum);
|
||||
Serial.println(" %");
|
||||
humidity->save(hum);
|
||||
|
||||
Serial.println();
|
||||
|
||||
deepSleep();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// we never get here!
|
||||
}
|
||||
|
||||
|
||||
void deepSleep() {
|
||||
pinMode(NEOPIXEL_POWER, OUTPUT);
|
||||
digitalWrite(NEOPIXEL_POWER, LOW); // off
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
|
||||
esp_sleep_enable_timer_wakeup(300000000); // 5 minutes
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2025 Limor Fried for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
#define IO_USERNAME "your-aio-username"
|
||||
#define IO_KEY "your-aio-token"
|
||||
#define WIFI_SSID "your-wifi-ssid"
|
||||
#define WIFI_PASS "your-wifi-pass"
|
||||
|
||||
#include "AdafruitIO_WiFi.h"
|
||||
AdafruitIO_WiFi io(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS);
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
"""
|
||||
CircuitPython Adafruit IO Example for BME280 and LC709203 Sensors
|
||||
"""
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import ssl
|
||||
import alarm
|
||||
|
|
@ -14,11 +16,21 @@ import adafruit_requests
|
|||
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
|
||||
from adafruit_lc709203f import LC709203F, PackSize
|
||||
from adafruit_bme280 import basic as adafruit_bme280
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi and Adafruit IO credentials are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
if None in [ssid, password, aio_username, aio_key]:
|
||||
raise RuntimeError(
|
||||
"WiFi and Adafruit IO settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
|
||||
)
|
||||
|
||||
# Duration of sleep in seconds. Default is 600 seconds (10 minutes).
|
||||
# Feather will sleep for this duration between sensor readings / sending data to AdafruitIO
|
||||
|
|
@ -78,9 +90,9 @@ def send_io_data(feed, value):
|
|||
# Wi-Fi connections can have issues! This ensures the code will continue to run.
|
||||
try:
|
||||
# Connect to Wi-Fi
|
||||
wifi.radio.connect(secrets["ssid"], secrets["password"])
|
||||
print("Connected to {}!".format(secrets["ssid"]))
|
||||
print("IP:", wifi.radio.ipv4_address)
|
||||
wifi.radio.connect(ssid, password)
|
||||
print(f"Connected to {ssid}!")
|
||||
print(f"IP: {wifi.radio.ipv4_address}")
|
||||
|
||||
pool = socketpool.SocketPool(wifi.radio)
|
||||
requests = adafruit_requests.Session(pool, ssl.create_default_context())
|
||||
|
|
@ -90,12 +102,6 @@ except Exception as e: # pylint: disable=broad-except
|
|||
print(e)
|
||||
go_to_sleep(60)
|
||||
|
||||
# Set your Adafruit IO Username and Key in secrets.py
|
||||
# (visit io.adafruit.com if you need to create an account,
|
||||
# or if you need your Adafruit IO key.)
|
||||
aio_username = secrets["aio_username"]
|
||||
aio_key = secrets["aio_key"]
|
||||
|
||||
# Initialize an Adafruit IO HTTP API object
|
||||
io = IO_HTTP(aio_username, aio_key, requests)
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ CircuitPython Simple Example for BME280 and LC709203 Sensors
|
|||
"""
|
||||
import time
|
||||
import board
|
||||
from adafruit_bme280 import basic as adafruit_bme280
|
||||
from adafruit_lc709203f import LC709203F, PackSize
|
||||
from adafruit_bme280 import basic as adafruit_bme280
|
||||
|
||||
# Create sensor objects, using the board's default I2C bus.
|
||||
i2c = board.I2C() # uses board.SCL and board.SDA
|
||||
|
|
|
|||
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2025 Tim Cocks for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython example for deep sleep and BME280 sensor sending data
|
||||
to Adafruit IO.
|
||||
"""
|
||||
from os import getenv
|
||||
import time
|
||||
import alarm
|
||||
import board
|
||||
import digitalio
|
||||
import neopixel
|
||||
import wifi
|
||||
|
||||
from adafruit_bme280 import advanced as adafruit_bme280
|
||||
import adafruit_connection_manager
|
||||
import adafruit_requests
|
||||
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
|
||||
|
||||
|
||||
# enable power to NeoPixels.
|
||||
np_power = digitalio.DigitalInOut(board.NEOPIXEL_POWER)
|
||||
np_power.switch_to_output(value=True)
|
||||
|
||||
# standard LED
|
||||
builtin_led = digitalio.DigitalInOut(board.LED)
|
||||
builtin_led.switch_to_output(value=True)
|
||||
|
||||
# neopixel to use for status
|
||||
status_pixel = neopixel.NeoPixel(
|
||||
board.NEOPIXEL, 1, brightness=0.1, pixel_order=neopixel.GRB, auto_write=True
|
||||
)
|
||||
status_pixel[0] = 0xFF0000
|
||||
|
||||
# Create sensor object, using the board's default I2C bus.
|
||||
i2c = board.I2C() # uses board.SCL and board.SDA
|
||||
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
|
||||
print("Found BME280")
|
||||
# change this to match the location's pressure (hPa) at sea level
|
||||
bme280.sea_level_pressure = 1013.25
|
||||
|
||||
# temperature converted to F
|
||||
temperature = bme280.temperature * 9 / 5 + 32
|
||||
humidity = bme280.relative_humidity
|
||||
pressure = bme280.pressure
|
||||
print("\nTemperature: %0.1f F" % temperature)
|
||||
print("Humidity: %0.1f %%" % humidity)
|
||||
print("Pressure: %0.1f hPa" % pressure)
|
||||
|
||||
bme280.mode = adafruit_bme280.MODE_SLEEP
|
||||
bme280.overscan_temperature = adafruit_bme280.OVERSCAN_X16
|
||||
bme280.overscan_humidity = adafruit_bme280.OVERSCAN_X16
|
||||
bme280.overscan_pressure = adafruit_bme280.OVERSCAN_X16
|
||||
bme280.iir_filter = adafruit_bme280.IIR_FILTER_DISABLE
|
||||
bme280.standby_period = adafruit_bme280.STANDBY_TC_1000
|
||||
|
||||
# set status pixel to yellow
|
||||
status_pixel[0] = 0xFFFF00
|
||||
|
||||
print("Connecting to AdafruitIO")
|
||||
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("WIFI_SSID")
|
||||
password = getenv("WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
print("Connecting to %s" % ssid)
|
||||
wifi.radio.connect(ssid, password)
|
||||
print("Connected to %s!" % ssid)
|
||||
|
||||
# setup socket pool and requests session
|
||||
pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio)
|
||||
ssl_context = adafruit_connection_manager.get_radio_ssl_context(wifi.radio)
|
||||
requests = adafruit_requests.Session(pool, ssl_context)
|
||||
|
||||
# Initialize an Adafruit IO HTTP API object
|
||||
io = IO_HTTP(aio_username, aio_key, requests)
|
||||
|
||||
# set status pixel to green
|
||||
status_pixel[0] = 0x00FF00
|
||||
|
||||
try:
|
||||
# Get the feeds from Adafruit IO
|
||||
temperature_feed = io.get_feed("temperature")
|
||||
humidity_feed = io.get_feed("humidity")
|
||||
pressure_feed = io.get_feed("pressure")
|
||||
|
||||
# send data to the feeds
|
||||
io.send_data(temperature_feed["key"], temperature)
|
||||
io.send_data(humidity_feed["key"], humidity)
|
||||
io.send_data(pressure_feed["key"], pressure)
|
||||
|
||||
except AdafruitIO_RequestError as e:
|
||||
print(e)
|
||||
print(
|
||||
"You must create feeds on AdafruitIO for: temperature, humidity, and pressure"
|
||||
)
|
||||
|
||||
# turn off the neopixel and builtin LED
|
||||
np_power.value = False
|
||||
builtin_led.value = False
|
||||
|
||||
# Create an alarm that will trigger 5 minutes from now.
|
||||
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + (5 * 60))
|
||||
# Exit the program, and then deep sleep until the alarm wakes us.
|
||||
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
|
||||
# Does not return, so we never get here.
|
||||
57
Adafruit_Feather_ESP32-S2_Reverse_TFT/display/code.py
Normal file
57
Adafruit_Feather_ESP32-S2_Reverse_TFT/display/code.py
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
This test will initialize the display using displayio and draw a solid green
|
||||
background, a smaller purple rectangle, and some yellow text.
|
||||
"""
|
||||
import board
|
||||
import terminalio
|
||||
import displayio
|
||||
from adafruit_display_text import label
|
||||
|
||||
# First set some parameters used for shapes and text
|
||||
BORDER = 20
|
||||
FONTSCALE = 2
|
||||
BACKGROUND_COLOR = 0x00FF00 # Bright Green
|
||||
FOREGROUND_COLOR = 0xAA0088 # Purple
|
||||
TEXT_COLOR = 0xFFFF00
|
||||
|
||||
display = board.DISPLAY
|
||||
|
||||
# Make the display context
|
||||
splash = displayio.Group()
|
||||
display.root_group = splash
|
||||
|
||||
color_bitmap = displayio.Bitmap(display.width, display.height, 1)
|
||||
color_palette = displayio.Palette(1)
|
||||
color_palette[0] = BACKGROUND_COLOR
|
||||
|
||||
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
|
||||
splash.append(bg_sprite)
|
||||
|
||||
# Draw a smaller inner rectangle
|
||||
inner_bitmap = displayio.Bitmap(
|
||||
display.width - BORDER * 2, display.height - BORDER * 2, 1
|
||||
)
|
||||
inner_palette = displayio.Palette(1)
|
||||
inner_palette[0] = FOREGROUND_COLOR
|
||||
inner_sprite = displayio.TileGrid(
|
||||
inner_bitmap, pixel_shader=inner_palette, x=BORDER, y=BORDER
|
||||
)
|
||||
splash.append(inner_sprite)
|
||||
|
||||
# Draw a label
|
||||
text = "Hello World!"
|
||||
text_area = label.Label(terminalio.FONT, text=text, color=TEXT_COLOR)
|
||||
text_width = text_area.bounding_box[2] * FONTSCALE
|
||||
text_group = displayio.Group(
|
||||
scale=FONTSCALE,
|
||||
x=display.width // 2 - text_width // 2,
|
||||
y=display.height // 2,
|
||||
)
|
||||
text_group.append(text_area) # Subgroup for text scaling
|
||||
splash.append(text_group)
|
||||
|
||||
while True:
|
||||
pass
|
||||
29
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_tone/code.py
Normal file
29
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_tone/code.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S Tone playback example.
|
||||
Plays a tone for one second on, one
|
||||
second off, in a loop.
|
||||
"""
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
tone_volume = 0.1 # Increase this to increase the volume of the tone.
|
||||
frequency = 440 # Set this to the Hz of the tone you want to generate.
|
||||
length = 8000 // frequency
|
||||
sine_wave = array.array("h", [0] * length)
|
||||
for i in range(length):
|
||||
sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * tone_volume * (2 ** 15 - 1))
|
||||
sine_wave_sample = audiocore.RawSample(sine_wave)
|
||||
|
||||
while True:
|
||||
audio.play(sine_wave_sample, loop=True)
|
||||
time.sleep(1)
|
||||
audio.stop()
|
||||
time.sleep(1)
|
||||
BIN
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_wav/StreetChicken.wav
Executable file
BIN
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_wav/StreetChicken.wav
Executable file
Binary file not shown.
21
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_wav/code.py
Normal file
21
Adafruit_Feather_ESP32-S2_Reverse_TFT/i2s_wav/code.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S WAV file playback.
|
||||
Plays a WAV file once.
|
||||
"""
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
with open("StreetChicken.wav", "rb") as wave_file:
|
||||
wav = audiocore.WaveFile(wave_file)
|
||||
|
||||
print("Playing wav file!")
|
||||
audio.play(wav)
|
||||
while audio.playing:
|
||||
pass
|
||||
|
||||
print("Done!")
|
||||
28
Adafruit_Feather_RP2040_DVI/I2S/Tone/code.py
Normal file
28
Adafruit_Feather_RP2040_DVI/I2S/Tone/code.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S Tone playback example.
|
||||
Plays a tone for one second on, one second off, in a loop.
|
||||
"""
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
tone_volume = 0.1 # Increase this to increase the volume of the tone.
|
||||
frequency = 440 # Set this to the Hz of the tone you want to generate.
|
||||
length = 8000 // frequency
|
||||
sine_wave = array.array("h", [0] * length)
|
||||
for i in range(length):
|
||||
sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * tone_volume * (2 ** 15 - 1))
|
||||
sine_wave_sample = audiocore.RawSample(sine_wave)
|
||||
|
||||
while True:
|
||||
audio.play(sine_wave_sample, loop=True)
|
||||
time.sleep(1)
|
||||
audio.stop()
|
||||
time.sleep(1)
|
||||
BIN
Adafruit_Feather_RP2040_DVI/I2S/WAV/StreetChicken.wav
Normal file
BIN
Adafruit_Feather_RP2040_DVI/I2S/WAV/StreetChicken.wav
Normal file
Binary file not shown.
21
Adafruit_Feather_RP2040_DVI/I2S/WAV/code.py
Normal file
21
Adafruit_Feather_RP2040_DVI/I2S/WAV/code.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S WAV file playback.
|
||||
Plays a WAV file once.
|
||||
"""
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
with open("StreetChicken.wav", "rb") as wave_file:
|
||||
wav = audiocore.WaveFile(wave_file)
|
||||
|
||||
print("Playing wav file!")
|
||||
audio.play(wav)
|
||||
while audio.playing:
|
||||
pass
|
||||
|
||||
print("Done!")
|
||||
14
Adafruit_Feather_RP2040_DVI/Storage/code.py
Normal file
14
Adafruit_Feather_RP2040_DVI/Storage/code.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython Essentials Storage CP Filesystem boot.py file
|
||||
"""
|
||||
import board
|
||||
import digitalio
|
||||
import storage
|
||||
|
||||
button = digitalio.DigitalInOut(board.BUTTON)
|
||||
button.switch_to_input(pull=digitalio.Pull.UP)
|
||||
|
||||
# If the button is connected to ground, the filesystem is writable by CircuitPython
|
||||
storage.remount("/", readonly=button.value)
|
||||
80
Adafruit_Feather_RP2040_DVI/asyncio/code.py
Normal file
80
Adafruit_Feather_RP2040_DVI/asyncio/code.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2023 Kattni Rembor for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython asyncio example for two NeoPixel rings and one button.
|
||||
"""
|
||||
import asyncio
|
||||
import board
|
||||
import neopixel
|
||||
import keypad
|
||||
from rainbowio import colorwheel
|
||||
|
||||
button_pin = board.BUTTON # The pin the button is connected to.
|
||||
num_pixels = 16 # The number of NeoPixels on a single ring.
|
||||
brightness = 0.2 # The LED brightness.
|
||||
|
||||
# Set up NeoPixel rings.
|
||||
ring_one = neopixel.NeoPixel(board.A1, num_pixels, brightness=brightness, auto_write=False)
|
||||
ring_two = neopixel.NeoPixel(board.A2, num_pixels, brightness=brightness, auto_write=False)
|
||||
|
||||
|
||||
class AnimationControls:
|
||||
"""The controls to allow you to vary the rainbow and blink animations."""
|
||||
def __init__(self):
|
||||
self.reverse = False
|
||||
self.wait = 0.0
|
||||
self.delay = 0.5
|
||||
|
||||
|
||||
async def rainbow_cycle(controls):
|
||||
"""Rainbow cycle animation on ring one."""
|
||||
while True:
|
||||
for j in range(255, -1, -1) if controls.reverse else range(0, 256, 1):
|
||||
for i in range(num_pixels):
|
||||
rc_index = (i * 256 // num_pixels) + j
|
||||
ring_one[i] = colorwheel(rc_index & 255)
|
||||
ring_one.show()
|
||||
await asyncio.sleep(controls.wait)
|
||||
|
||||
|
||||
async def blink(controls):
|
||||
"""Blink animation on ring two."""
|
||||
while True:
|
||||
ring_two.fill((0, 0, 255))
|
||||
ring_two.show()
|
||||
await asyncio.sleep(controls.delay)
|
||||
ring_two.fill((0, 0, 0))
|
||||
ring_two.show()
|
||||
await asyncio.sleep(controls.delay)
|
||||
await asyncio.sleep(controls.wait)
|
||||
|
||||
|
||||
async def monitor_button(button, controls):
|
||||
"""Monitor button that reverses rainbow direction and changes blink speed.
|
||||
Assume button is active low.
|
||||
"""
|
||||
with keypad.Keys((button,), value_when_pressed=False, pull=True) as key:
|
||||
while True:
|
||||
key_event = key.events.get()
|
||||
if key_event:
|
||||
if key_event.pressed:
|
||||
controls.reverse = True
|
||||
controls.delay = 0.1
|
||||
elif key_event.released:
|
||||
controls.reverse = False
|
||||
controls.delay = 0.5
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
async def main():
|
||||
animation_controls = AnimationControls()
|
||||
button_task = asyncio.create_task(monitor_button(button_pin, animation_controls))
|
||||
animation_task = asyncio.create_task(rainbow_cycle(animation_controls))
|
||||
blink_task = asyncio.create_task(blink(animation_controls))
|
||||
|
||||
# This will run forever, because no tasks ever finish.
|
||||
await asyncio.gather(button_task, animation_task, blink_task)
|
||||
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython Capacitive Touch Pin Example - Print to the serial console when one pin is touched.
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import touchio
|
||||
|
||||
touch = touchio.TouchIn(board.A3)
|
||||
|
||||
while True:
|
||||
if touch.value:
|
||||
print("Pin touched!")
|
||||
time.sleep(0.1)
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython Capacitive Two Touch Pin Example - Print to the serial console when a pin is touched.
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import touchio
|
||||
|
||||
touch_one = touchio.TouchIn(board.A3)
|
||||
touch_two = touchio.TouchIn(board.D24)
|
||||
|
||||
while True:
|
||||
if touch_one.value:
|
||||
print("Pin one touched!")
|
||||
if touch_two.value:
|
||||
print("Pin two touched!")
|
||||
time.sleep(0.1)
|
||||
29
Adafruit_Feather_RP2040_RFM69/I2S/Tone/code.py
Normal file
29
Adafruit_Feather_RP2040_RFM69/I2S/Tone/code.py
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S Tone playback example.
|
||||
Plays a tone for one second on, one
|
||||
second off, in a loop.
|
||||
"""
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
tone_volume = 0.1 # Increase this to increase the volume of the tone.
|
||||
frequency = 440 # Set this to the Hz of the tone you want to generate.
|
||||
length = 8000 // frequency
|
||||
sine_wave = array.array("h", [0] * length)
|
||||
for i in range(length):
|
||||
sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * tone_volume * (2 ** 15 - 1))
|
||||
sine_wave_sample = audiocore.RawSample(sine_wave)
|
||||
|
||||
while True:
|
||||
audio.play(sine_wave_sample, loop=True)
|
||||
time.sleep(1)
|
||||
audio.stop()
|
||||
time.sleep(1)
|
||||
BIN
Adafruit_Feather_RP2040_RFM69/I2S/WAV/StreetChicken.wav
Normal file
BIN
Adafruit_Feather_RP2040_RFM69/I2S/WAV/StreetChicken.wav
Normal file
Binary file not shown.
21
Adafruit_Feather_RP2040_RFM69/I2S/WAV/code.py
Normal file
21
Adafruit_Feather_RP2040_RFM69/I2S/WAV/code.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S WAV file playback.
|
||||
Plays a WAV file once.
|
||||
"""
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
audio = audiobusio.I2SOut(board.A0, board.A1, board.A2)
|
||||
|
||||
with open("StreetChicken.wav", "rb") as wave_file:
|
||||
wav = audiocore.WaveFile(wave_file)
|
||||
|
||||
print("Playing wav file!")
|
||||
audio.play(wav)
|
||||
while audio.playing:
|
||||
pass
|
||||
|
||||
print("Done!")
|
||||
56
Adafruit_Feather_RP2040_RFM69/Send_and_Receive_Demo/Receive_Demo/code.py
Executable file
56
Adafruit_Feather_RP2040_RFM69/Send_and_Receive_Demo/Receive_Demo/code.py
Executable file
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
CircuitPython Feather RP2040 RFM69 Packet Receive Demo
|
||||
|
||||
This demo waits for a "button" packet. When the first packet is received, the NeoPixel LED
|
||||
lights up red. The next packet changes it to green. The next packet changes it to blue.
|
||||
Subsequent button packets cycle through the same colors in the same order.
|
||||
|
||||
This example is meant to be paired with the Packet Send Demo code running
|
||||
on a second Feather RP2040 RFM69 board.
|
||||
"""
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import neopixel
|
||||
import adafruit_rfm69
|
||||
|
||||
# Set up NeoPixel.
|
||||
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
|
||||
pixel.brightness = 0.5
|
||||
|
||||
# Define the possible NeoPixel colors. You can add as many colors to this list as you like!
|
||||
# Simply follow the format shown below. Make sure you include the comma after the color tuple!
|
||||
color_values = [
|
||||
(255, 0, 0),
|
||||
(0, 255, 0),
|
||||
(0, 0, 255),
|
||||
]
|
||||
|
||||
# Define radio frequency in MHz. Must match your
|
||||
# module. Can be a value like 915.0, 433.0, etc.
|
||||
RADIO_FREQ_MHZ = 915.0
|
||||
|
||||
# Define Chip Select and Reset pins for the radio module.
|
||||
CS = digitalio.DigitalInOut(board.RFM_CS)
|
||||
RESET = digitalio.DigitalInOut(board.RFM_RST)
|
||||
|
||||
# Initialise RFM69 radio
|
||||
rfm69 = adafruit_rfm69.RFM69(board.SPI(), CS, RESET, RADIO_FREQ_MHZ)
|
||||
|
||||
color_index = 0
|
||||
# Wait to receive packets.
|
||||
print("Waiting for packets...")
|
||||
while True:
|
||||
# Look for a new packet - wait up to 5 seconds:
|
||||
packet = rfm69.receive(timeout=5.0)
|
||||
# If no packet was received during the timeout then None is returned.
|
||||
if packet is not None:
|
||||
print("Received a packet!")
|
||||
# If the received packet is b'button'...
|
||||
if packet == b'button':
|
||||
# ...cycle the NeoPixel LED color through the color_values list.
|
||||
pixel.fill(color_values[color_index])
|
||||
color_index = (color_index + 1) % len(color_values)
|
||||
36
Adafruit_Feather_RP2040_RFM69/Send_and_Receive_Demo/Send_Demo/code.py
Executable file
36
Adafruit_Feather_RP2040_RFM69/Send_and_Receive_Demo/Send_Demo/code.py
Executable file
|
|
@ -0,0 +1,36 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
CircuitPython Feather RP2040 RFM69 Packet Send Demo
|
||||
|
||||
This demo sends a "button" packet when the Boot button is pressed.
|
||||
|
||||
This example is meant to be paired with the Packet Receive Demo code running
|
||||
on a second Feather RP2040 RFM69 board.
|
||||
"""
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import keypad
|
||||
import adafruit_rfm69
|
||||
|
||||
# Set up button using keypad module.
|
||||
button = keypad.Keys((board.BUTTON,), value_when_pressed=False)
|
||||
|
||||
# Define radio frequency in MHz. Must match your
|
||||
# module. Can be a value like 915.0, 433.0, etc.
|
||||
RADIO_FREQ_MHZ = 915.0
|
||||
|
||||
# Define Chip Select and Reset pins for the radio module.
|
||||
CS = digitalio.DigitalInOut(board.RFM_CS)
|
||||
RESET = digitalio.DigitalInOut(board.RFM_RST)
|
||||
|
||||
# Initialise RFM69 radio
|
||||
rfm69 = adafruit_rfm69.RFM69(board.SPI(), CS, RESET, RADIO_FREQ_MHZ)
|
||||
|
||||
while True:
|
||||
button_press = button.events.get()
|
||||
if button_press:
|
||||
if button_press.pressed:
|
||||
rfm69.send(bytes("button", "UTF-8"))
|
||||
14
Adafruit_Feather_RP2040_RFM69/Storage/boot.py
Normal file
14
Adafruit_Feather_RP2040_RFM69/Storage/boot.py
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython Essentials Storage CP Filesystem boot.py file
|
||||
"""
|
||||
import board
|
||||
import digitalio
|
||||
import storage
|
||||
|
||||
button = digitalio.DigitalInOut(board.BUTTON)
|
||||
button.switch_to_input(pull=digitalio.Pull.UP)
|
||||
|
||||
# If the OBJECT_NAME is connected to ground, the filesystem is writable by CircuitPython
|
||||
storage.remount("/", readonly=button.value)
|
||||
37
Adafruit_Feather_RP2040_RFM69/Storage/code.py
Normal file
37
Adafruit_Feather_RP2040_RFM69/Storage/code.py
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython Essentials Storage CP Filesystem code.py file
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import digitalio
|
||||
import microcontroller
|
||||
|
||||
led = digitalio.DigitalInOut(board.LED)
|
||||
led.switch_to_output()
|
||||
|
||||
try:
|
||||
with open("/temperature.txt", "a") as temp_log:
|
||||
while True:
|
||||
# The microcontroller temperature in Celsius. Include the
|
||||
# math to do the C to F conversion here, if desired.
|
||||
temperature = microcontroller.cpu.temperature
|
||||
|
||||
# Write the temperature to the temperature.txt file every 10 seconds.
|
||||
temp_log.write('{0:.2f}\n'.format(temperature))
|
||||
temp_log.flush()
|
||||
|
||||
# Blink the LED on every write...
|
||||
led.value = True
|
||||
time.sleep(1) # ...for one second.
|
||||
led.value = False # Then turn it off...
|
||||
time.sleep(9) # ...for the other 9 seconds.
|
||||
|
||||
except OSError as e: # When the filesystem is NOT writable by CircuitPython...
|
||||
delay = 0.5 # ...blink the LED every half second.
|
||||
if e.args[0] == 28: # If the file system is full...
|
||||
delay = 0.15 # ...blink the LED every 0.15 seconds!
|
||||
while True:
|
||||
led.value = not led.value
|
||||
time.sleep(delay)
|
||||
80
Adafruit_Feather_RP2040_RFM69/asyncio/code.py
Normal file
80
Adafruit_Feather_RP2040_RFM69/asyncio/code.py
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# SPDX-FileCopyrightText: Copyright (c) 2022 Dan Halbert for Adafruit Industries
|
||||
# SPDX-FileCopyrightText: Copyright (c) 2023 Kattni Rembor for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython asyncio example for two NeoPixel rings and one button.
|
||||
"""
|
||||
import asyncio
|
||||
import board
|
||||
import neopixel
|
||||
import keypad
|
||||
from rainbowio import colorwheel
|
||||
|
||||
button_pin = board.BUTTON # The pin the button is connected to.
|
||||
num_pixels = 16 # The number of NeoPixels on a single ring.
|
||||
brightness = 0.2 # The LED brightness.
|
||||
|
||||
# Set up NeoPixel rings.
|
||||
ring_one = neopixel.NeoPixel(board.A1, num_pixels, brightness=brightness, auto_write=False)
|
||||
ring_two = neopixel.NeoPixel(board.A2, num_pixels, brightness=brightness, auto_write=False)
|
||||
|
||||
|
||||
class AnimationControls:
|
||||
"""The controls to allow you to vary the rainbow and blink animations."""
|
||||
def __init__(self):
|
||||
self.reverse = False
|
||||
self.wait = 0.0
|
||||
self.delay = 0.5
|
||||
|
||||
|
||||
async def rainbow_cycle(controls):
|
||||
"""Rainbow cycle animation on ring one."""
|
||||
while True:
|
||||
for j in range(255, -1, -1) if controls.reverse else range(0, 256, 1):
|
||||
for i in range(num_pixels):
|
||||
rc_index = (i * 256 // num_pixels) + j
|
||||
ring_one[i] = colorwheel(rc_index & 255)
|
||||
ring_one.show()
|
||||
await asyncio.sleep(controls.wait)
|
||||
|
||||
|
||||
async def blink(controls):
|
||||
"""Blink animation on ring two."""
|
||||
while True:
|
||||
ring_two.fill((0, 0, 255))
|
||||
ring_two.show()
|
||||
await asyncio.sleep(controls.delay)
|
||||
ring_two.fill((0, 0, 0))
|
||||
ring_two.show()
|
||||
await asyncio.sleep(controls.delay)
|
||||
await asyncio.sleep(controls.wait)
|
||||
|
||||
|
||||
async def monitor_button(button, controls):
|
||||
"""Monitor button that reverses rainbow direction and changes blink speed.
|
||||
Assume button is active low.
|
||||
"""
|
||||
with keypad.Keys((button,), value_when_pressed=False, pull=True) as key:
|
||||
while True:
|
||||
key_event = key.events.get()
|
||||
if key_event:
|
||||
if key_event.pressed:
|
||||
controls.reverse = True
|
||||
controls.delay = 0.1
|
||||
elif key_event.released:
|
||||
controls.reverse = False
|
||||
controls.delay = 0.5
|
||||
await asyncio.sleep(0)
|
||||
|
||||
|
||||
async def main():
|
||||
animation_controls = AnimationControls()
|
||||
button_task = asyncio.create_task(monitor_button(button_pin, animation_controls))
|
||||
animation_task = asyncio.create_task(rainbow_cycle(animation_controls))
|
||||
blink_task = asyncio.create_task(blink(animation_controls))
|
||||
|
||||
# This will run forever, because no tasks ever finish.
|
||||
await asyncio.gather(button_task, animation_task, blink_task)
|
||||
|
||||
asyncio.run(main())
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
CircuitPython Feather RP2040 RFM95 Packet Receive Demo
|
||||
|
||||
This demo waits for a "button" packet. When the first packet is received, the NeoPixel LED
|
||||
lights up red. The next packet changes it to green. The next packet changes it to blue.
|
||||
Subsequent button packets cycle through the same colors in the same order.
|
||||
|
||||
This example is meant to be paired with the Packet Send Demo code running
|
||||
on a second Feather RP2040 RFM95 board.
|
||||
"""
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import neopixel
|
||||
import adafruit_rfm9x
|
||||
|
||||
# Set up NeoPixel.
|
||||
pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
|
||||
pixel.brightness = 0.5
|
||||
|
||||
# Define the possible NeoPixel colors. You can add as many colors to this list as you like!
|
||||
# Simply follow the format shown below. Make sure you include the comma after the color tuple!
|
||||
color_values = [
|
||||
(255, 0, 0),
|
||||
(0, 255, 0),
|
||||
(0, 0, 255),
|
||||
]
|
||||
|
||||
# Define radio frequency in MHz. Must match your
|
||||
# module. Can be a value like 915.0, 433.0, etc.
|
||||
RADIO_FREQ_MHZ = 915.0
|
||||
|
||||
# Define Chip Select and Reset pins for the radio module.
|
||||
CS = digitalio.DigitalInOut(board.RFM_CS)
|
||||
RESET = digitalio.DigitalInOut(board.RFM_RST)
|
||||
|
||||
# Initialise RFM95 radio
|
||||
rfm95 = adafruit_rfm9x.RFM9x(board.SPI(), CS, RESET, RADIO_FREQ_MHZ)
|
||||
|
||||
color_index = 0
|
||||
# Wait to receive packets.
|
||||
print("Waiting for packets...")
|
||||
while True:
|
||||
# Look for a new packet - wait up to 5 seconds:
|
||||
packet = rfm95.receive(timeout=5.0)
|
||||
# If no packet was received during the timeout then None is returned.
|
||||
if packet is not None:
|
||||
print("Received a packet!")
|
||||
# If the received packet is b'button'...
|
||||
if packet == b'button':
|
||||
# ...cycle the NeoPixel LED color through the color_values list.
|
||||
pixel.fill(color_values[color_index])
|
||||
color_index = (color_index + 1) % len(color_values)
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
CircuitPython Feather RP2040 RFM95 Packet Send Demo
|
||||
|
||||
This demo sends a "button" packet when the Boot button is pressed.
|
||||
|
||||
This example is meant to be paired with the Packet Receive Demo code running
|
||||
on a second Feather RP2040 RFM95 board.
|
||||
"""
|
||||
|
||||
import board
|
||||
import digitalio
|
||||
import keypad
|
||||
import adafruit_rfm9x
|
||||
|
||||
# Set up button using keypad module.
|
||||
button = keypad.Keys((board.BUTTON,), value_when_pressed=False)
|
||||
|
||||
# Define radio frequency in MHz. Must match your
|
||||
# module. Can be a value like 915.0, 433.0, etc.
|
||||
RADIO_FREQ_MHZ = 915.0
|
||||
|
||||
# Define Chip Select and Reset pins for the radio module.
|
||||
CS = digitalio.DigitalInOut(board.RFM_CS)
|
||||
RESET = digitalio.DigitalInOut(board.RFM_RST)
|
||||
|
||||
# Initialise RFM95 radio
|
||||
rfm95 = adafruit_rfm9x.RFM9x(board.SPI(), CS, RESET, RADIO_FREQ_MHZ)
|
||||
|
||||
while True:
|
||||
button_press = button.events.get()
|
||||
if button_press:
|
||||
if button_press.pressed:
|
||||
rfm95.send(bytes("button", "UTF-8"))
|
||||
|
|
@ -8,20 +8,26 @@ import array
|
|||
import math
|
||||
import board
|
||||
import audiobusio
|
||||
import adafruit_apds9960.apds9960
|
||||
import adafruit_bmp280
|
||||
import adafruit_lis3mdl
|
||||
import adafruit_lsm6ds.lsm6ds33
|
||||
import adafruit_sht31d
|
||||
from adafruit_apds9960.apds9960 import APDS9960
|
||||
from adafruit_bmp280 import Adafruit_BMP280_I2C
|
||||
from adafruit_lis3mdl import LIS3MDL
|
||||
from adafruit_sht31d import SHT31D
|
||||
|
||||
i2c = board.I2C() # uses board.SCL and board.SDA
|
||||
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
|
||||
|
||||
apds9960 = adafruit_apds9960.apds9960.APDS9960(i2c)
|
||||
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
|
||||
lis3mdl = adafruit_lis3mdl.LIS3MDL(i2c)
|
||||
lsm6ds33 = adafruit_lsm6ds.lsm6ds33.LSM6DS33(i2c)
|
||||
sht31d = adafruit_sht31d.SHT31D(i2c)
|
||||
# check for LSM6DS33 or LSM6DS3TR-C
|
||||
try:
|
||||
from adafruit_lsm6ds.lsm6ds33 import LSM6DS33 as LSM6DS
|
||||
lsm6ds = LSM6DS(i2c)
|
||||
except RuntimeError:
|
||||
from adafruit_lsm6ds.lsm6ds3 import LSM6DS3 as LSM6DS
|
||||
lsm6ds = LSM6DS(i2c)
|
||||
|
||||
apds9960 = APDS9960(i2c)
|
||||
bmp280 = Adafruit_BMP280_I2C(i2c)
|
||||
lis3mdl = LIS3MDL(i2c)
|
||||
sht31d = SHT31D(i2c)
|
||||
microphone = audiobusio.PDMIn(board.MICROPHONE_CLOCK, board.MICROPHONE_DATA,
|
||||
sample_rate=16000, bit_depth=16)
|
||||
|
||||
|
|
@ -42,14 +48,17 @@ while True:
|
|||
|
||||
print("\nFeather Sense Sensor Demo")
|
||||
print("---------------------------------------------")
|
||||
print("Proximity:", apds9960.proximity)
|
||||
print("Red: {}, Green: {}, Blue: {}, Clear: {}".format(*apds9960.color_data))
|
||||
print("Temperature: {:.1f} C".format(bmp280.temperature))
|
||||
print("Barometric pressure:", bmp280.pressure)
|
||||
print("Altitude: {:.1f} m".format(bmp280.altitude))
|
||||
print("Magnetic: {:.3f} {:.3f} {:.3f} uTesla".format(*lis3mdl.magnetic))
|
||||
print("Acceleration: {:.2f} {:.2f} {:.2f} m/s^2".format(*lsm6ds33.acceleration))
|
||||
print("Gyro: {:.2f} {:.2f} {:.2f} dps".format(*lsm6ds33.gyro))
|
||||
print("Humidity: {:.1f} %".format(sht31d.relative_humidity))
|
||||
print("Sound level:", normalized_rms(samples))
|
||||
print(f"Proximity: {apds9960.proximity}")
|
||||
print(f"Red: {apds9960.color_data[0]}, Green: {apds9960.color_data[1]}, " +
|
||||
f"Blue: {apds9960.color_data[2]}, Clear: {apds9960.color_data[3]}")
|
||||
print(f"Temperature: {bmp280.temperature:.1f} C")
|
||||
print(f"Barometric pressure: {bmp280.pressure}")
|
||||
print(f"Altitude: {bmp280.altitude:.1f} m")
|
||||
print(f"Magnetic: {lis3mdl.magnetic[0]:.3f} {lis3mdl.magnetic[1]:.3f} " +
|
||||
f"{lis3mdl.magnetic[2]:.3f} uTesla")
|
||||
print(f"Acceleration: {lsm6ds.acceleration[0]:.2f} " +
|
||||
f"{lsm6ds.acceleration[1]:.2f} {lsm6ds.acceleration[2]:.2f} m/s^2")
|
||||
print(f"Gyro: {lsm6ds.gyro[0]:.2f} {lsm6ds.gyro[1]:.2f} {lsm6ds.gyro[2]:.2f} dps")
|
||||
print(f"Humidity: {sht31d.relative_humidity:.1f} %")
|
||||
print(f"Sound level: {normalized_rms(samples)}")
|
||||
time.sleep(0.3)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <Adafruit_BMP280.h>
|
||||
#include <Adafruit_LIS3MDL.h>
|
||||
#include <Adafruit_LSM6DS33.h>
|
||||
#include <Adafruit_LSM6DS3TRC.h>
|
||||
#include <Adafruit_SHT31.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <PDM.h>
|
||||
|
|
@ -13,7 +14,8 @@
|
|||
Adafruit_APDS9960 apds9960; // proximity, light, color, gesture
|
||||
Adafruit_BMP280 bmp280; // temperautre, barometric pressure
|
||||
Adafruit_LIS3MDL lis3mdl; // magnetometer
|
||||
Adafruit_LSM6DS33 lsm6ds33; // accelerometer, gyroscope
|
||||
Adafruit_LSM6DS3TRC lsm6ds3trc; // accelerometer, gyroscope
|
||||
Adafruit_LSM6DS33 lsm6ds33;
|
||||
Adafruit_SHT31 sht30; // humidity
|
||||
|
||||
uint8_t proximity;
|
||||
|
|
@ -24,11 +26,15 @@ float accel_x, accel_y, accel_z;
|
|||
float gyro_x, gyro_y, gyro_z;
|
||||
float humidity;
|
||||
int32_t mic;
|
||||
long int accel_array[6];
|
||||
long int check_array[6]={0.00, 0.00, 0.00, 0.00, 0.00, 0.00};
|
||||
|
||||
extern PDMClass PDM;
|
||||
short sampleBuffer[256]; // buffer to read samples into, each sample is 16-bits
|
||||
volatile int samplesRead; // number of samples read
|
||||
|
||||
bool new_rev = true;
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
// while (!Serial) delay(10);
|
||||
|
|
@ -41,6 +47,28 @@ void setup(void) {
|
|||
bmp280.begin();
|
||||
lis3mdl.begin_I2C();
|
||||
lsm6ds33.begin_I2C();
|
||||
// check for readings from LSM6DS33
|
||||
sensors_event_t accel;
|
||||
sensors_event_t gyro;
|
||||
sensors_event_t temp;
|
||||
lsm6ds33.getEvent(&accel, &gyro, &temp);
|
||||
accel_array[0] = accel.acceleration.x;
|
||||
accel_array[1] = accel.acceleration.y;
|
||||
accel_array[2] = accel.acceleration.z;
|
||||
accel_array[3] = gyro.gyro.x;
|
||||
accel_array[4] = gyro.gyro.y;
|
||||
accel_array[5] = gyro.gyro.z;
|
||||
// if all readings are empty, then new rev
|
||||
for (int i =0; i < 5; i++) {
|
||||
if (accel_array[i] != check_array[i]) {
|
||||
new_rev = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// and we need to instantiate the LSM6DS3TRC
|
||||
if (new_rev) {
|
||||
lsm6ds3trc.begin_I2C();
|
||||
}
|
||||
sht30.begin();
|
||||
PDM.onReceive(onPDMdata);
|
||||
PDM.begin(1, 16000);
|
||||
|
|
@ -65,7 +93,12 @@ void loop(void) {
|
|||
sensors_event_t accel;
|
||||
sensors_event_t gyro;
|
||||
sensors_event_t temp;
|
||||
lsm6ds33.getEvent(&accel, &gyro, &temp);
|
||||
if (new_rev) {
|
||||
lsm6ds3trc.getEvent(&accel, &gyro, &temp);
|
||||
}
|
||||
else {
|
||||
lsm6ds33.getEvent(&accel, &gyro, &temp);
|
||||
}
|
||||
accel_x = accel.acceleration.x;
|
||||
accel_y = accel.acceleration.y;
|
||||
accel_z = accel.acceleration.z;
|
||||
|
|
@ -77,7 +110,7 @@ void loop(void) {
|
|||
|
||||
samplesRead = 0;
|
||||
mic = getPDMwave(4000);
|
||||
|
||||
|
||||
Serial.println("\nFeather Sense Sensor Demo");
|
||||
Serial.println("---------------------------------------------");
|
||||
Serial.print("Proximity: ");
|
||||
|
|
@ -157,4 +190,4 @@ void onPDMdata() {
|
|||
|
||||
// 16-bit, 2 bytes per sample
|
||||
samplesRead = bytesAvailable / 2;
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,8 @@
|
|||
"""
|
||||
CircuitPython Adafruit IO Example for LC709203 Sensor
|
||||
"""
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import ssl
|
||||
import alarm
|
||||
|
|
@ -13,11 +15,21 @@ import socketpool
|
|||
import adafruit_requests
|
||||
from adafruit_io.adafruit_io import IO_HTTP
|
||||
from adafruit_lc709203f import LC709203F, PackSize
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi and Adafruit IO credentials are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
if None in [ssid, password, aio_username, aio_key]:
|
||||
raise RuntimeError(
|
||||
"WiFi and Adafruit IO settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
|
||||
)
|
||||
|
||||
# Duration of sleep in seconds. Default is 600 seconds (10 minutes).
|
||||
# Feather will sleep for this duration between sensor readings / sending data to AdafruitIO
|
||||
|
|
@ -58,9 +70,9 @@ def send_io_data(feed, value):
|
|||
# Wi-Fi connections can have issues! This ensures the code will continue to run.
|
||||
try:
|
||||
# Connect to Wi-Fi
|
||||
wifi.radio.connect(secrets["ssid"], secrets["password"])
|
||||
print("Connected to {}!".format(secrets["ssid"]))
|
||||
print("IP:", wifi.radio.ipv4_address)
|
||||
wifi.radio.connect(ssid, password)
|
||||
print(f"Connected to {ssid}!")
|
||||
print(f"IP: {wifi.radio.ipv4_address}")
|
||||
|
||||
pool = socketpool.SocketPool(wifi.radio)
|
||||
requests = adafruit_requests.Session(pool, ssl.create_default_context())
|
||||
|
|
@ -70,12 +82,6 @@ except Exception as e: # pylint: disable=broad-except
|
|||
print(e)
|
||||
go_to_sleep(60)
|
||||
|
||||
# Set your Adafruit IO Username and Key in secrets.py
|
||||
# (visit io.adafruit.com if you need to create an account,
|
||||
# or if you need your Adafruit IO key.)
|
||||
aio_username = secrets["aio_username"]
|
||||
aio_key = secrets["aio_key"]
|
||||
|
||||
# Initialize an Adafruit IO HTTP API object
|
||||
io = IO_HTTP(aio_username, aio_key, requests)
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
"""
|
||||
CircuitPython GitHub Stars viewer
|
||||
"""
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import ssl
|
||||
import wifi
|
||||
|
|
@ -13,12 +15,17 @@ from adafruit_display_text import bitmap_label
|
|||
from adafruit_bitmap_font import bitmap_font
|
||||
import adafruit_requests
|
||||
|
||||
# Get WiFi details secrets.py file
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi secrets are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
# Get WiFi details, ensure these are setup in settings.toml
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
|
||||
if None in [ssid, password]:
|
||||
raise RuntimeError(
|
||||
"WiFi settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"at a minimum."
|
||||
)
|
||||
|
||||
display = board.DISPLAY
|
||||
|
||||
|
|
@ -35,13 +42,13 @@ text_area = bitmap_label.Label(font, text="----", color=0xFFFFFF)
|
|||
text_area.x = 135
|
||||
text_area.y = 90
|
||||
group.append(text_area)
|
||||
display.show(group)
|
||||
display.root_group = group
|
||||
|
||||
# Connect to WiFi
|
||||
print("Connecting to %s"%secrets["ssid"])
|
||||
wifi.radio.connect(secrets["ssid"], secrets["password"])
|
||||
print("Connected to %s!"%secrets["ssid"])
|
||||
print("My IP address is", wifi.radio.ipv4_address)
|
||||
print(f"Connecting to {ssid}")
|
||||
wifi.radio.connect(ssid, password)
|
||||
print(f"Connected to {ssid}!")
|
||||
print(f"My IP address is {wifi.radio.ipv4_address}")
|
||||
|
||||
pool = socketpool.SocketPool(wifi.radio)
|
||||
requests = adafruit_requests.Session(pool, ssl.create_default_context())
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ scale = 3
|
|||
text_area = bitmap_label.Label(terminalio.FONT, text=text, scale=scale)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
board.DISPLAY.show(text_area)
|
||||
board.DISPLAY.root_group = text_area
|
||||
|
||||
while True:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ blinka_img = OnDiskBitmap("images/adafruit_blinka.bmp")
|
|||
tile_grid = TileGrid(bitmap=blinka_img, pixel_shader=blinka_img.pixel_shader)
|
||||
main_group.append(tile_grid)
|
||||
|
||||
board.DISPLAY.show(main_group)
|
||||
board.DISPLAY.root_group = main_group
|
||||
|
||||
tile_grid.x = board.DISPLAY.width // 2 - blinka_img.width // 2
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ sensor = LC709203F(i2c)
|
|||
|
||||
print("IC version:", hex(sensor.ic_version))
|
||||
|
||||
board.DISPLAY.show(main_group)
|
||||
board.DISPLAY.root_group = main_group
|
||||
|
||||
while True:
|
||||
text_area.text = "Battery:\n{:.1f} Volts \n{}%".format(sensor.cell_voltage, sensor.cell_percent)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
// SPDX-FileCopyrightText: 2023 Ladyada for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
This example plays a 'raw' PCM file from memory to I2S
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
#include "startup.h" // audio file in flash
|
||||
|
||||
// Create the I2S port using a PIO state machine
|
||||
I2S i2s(OUTPUT);
|
||||
|
||||
// GPIO pin numbers
|
||||
#define pBCLK A2 // QT Py BFF default BITCLOCK
|
||||
#define pWS A1 // QT Py BFF default LRCLOCK
|
||||
#define pDOUT A0 // QT Py BFF default DATA
|
||||
|
||||
#define USERBUTTON 21 // QT Py RP2040 built in button
|
||||
|
||||
// variable shared between cores
|
||||
volatile bool playaudio = false;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
//while (!Serial) delay(10);
|
||||
Serial.println("I2S playback demo");
|
||||
|
||||
pinMode(USERBUTTON, INPUT_PULLUP);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// on button press tell the other core to play audio clip!
|
||||
if (!digitalRead(USERBUTTON)) {
|
||||
playaudio = true;
|
||||
} else {
|
||||
playaudio = false;
|
||||
}
|
||||
}
|
||||
|
||||
void setup1() {
|
||||
i2s.setBCLK(pBCLK);
|
||||
i2s.setDATA(pDOUT);
|
||||
i2s.setBitsPerSample(16);
|
||||
}
|
||||
|
||||
void loop1() {
|
||||
// the main loop will tell us when it wants us to play!
|
||||
if (playaudio) {
|
||||
play_i2s(startupAudioData, sizeof(startupAudioData), startupSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
void play_i2s(const uint8_t *data, uint32_t len, uint32_t rate) {
|
||||
// start I2S at the sample rate with 16-bits per sample
|
||||
if (!i2s.begin(rate)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
delay(500);
|
||||
i2s.end();
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint32_t i=0; i<len; i++) {
|
||||
uint16_t sample = (uint16_t)data[i] << 6; // our data is 10 bit but we want 16 bit so we add some gain
|
||||
// write the same sample twice, once for left and once for the right channel
|
||||
i2s.write(sample);
|
||||
i2s.write(sample);
|
||||
}
|
||||
i2s.end();
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,74 @@
|
|||
// SPDX-FileCopyrightText: 2016 Sandeep Mistry
|
||||
// SPDX-FileCopyrightText: 2022 Earle F. Philhower, III
|
||||
// SPDX-FileCopyrightText: 2023 Ladyada for Adafruit Industries
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
This example generates a square wave based tone at a specified frequency
|
||||
and sample rate. Then outputs the data using the I2S interface to a
|
||||
MAX08357 I2S Amp Breakout board.
|
||||
|
||||
created 17 November 2016
|
||||
by Sandeep Mistry
|
||||
modified for RP2040 by Earle F. Philhower, III <earlephilhower@yahoo.com>
|
||||
|
||||
|
||||
bool setBCLK(pin_size_t pin);
|
||||
- This assigns two adjacent pins - the pin after this one (one greater)
|
||||
is the WS (word select) signal, which toggles before the sample for
|
||||
each channel is sent
|
||||
|
||||
bool setDATA(pin_size_t pin);
|
||||
- Sets the DOUT pin, can be any valid GPIO pin
|
||||
*/
|
||||
|
||||
#include <I2S.h>
|
||||
|
||||
// Create the I2S port using a PIO state machine
|
||||
I2S i2s(OUTPUT);
|
||||
|
||||
// GPIO pin numbers
|
||||
#define pBCLK A2 // QT Py BFF default BITCLOCK
|
||||
#define pWS A1 // QT Py BFF default LRCLOCK
|
||||
#define pDOUT A0 // QT Py BFF default DATA
|
||||
|
||||
const int frequency = 440; // frequency of square wave in Hz
|
||||
const int amplitude = 500; // amplitude of square wave
|
||||
const int sampleRate = 16000; // 16 KHz is a good quality
|
||||
|
||||
const int halfWavelength = (sampleRate / frequency); // half wavelength of square wave
|
||||
|
||||
int16_t sample = amplitude; // current sample value
|
||||
int count = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(10);
|
||||
Serial.println("I2S simple tone");
|
||||
|
||||
i2s.setBCLK(pBCLK);
|
||||
i2s.setDATA(pDOUT);
|
||||
i2s.setBitsPerSample(16);
|
||||
|
||||
// start I2S at the sample rate with 16-bits per sample
|
||||
if (!i2s.begin(sampleRate)) {
|
||||
Serial.println("Failed to initialize I2S!");
|
||||
while (1); // do nothing
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (count % halfWavelength == 0) {
|
||||
// invert the sample every half wavelength count multiple to generate square wave
|
||||
sample = -1 * sample;
|
||||
}
|
||||
|
||||
// write the same sample twice, once for left and once for the right channel
|
||||
i2s.write(sample);
|
||||
i2s.write(sample);
|
||||
|
||||
// increment the counter for the next sample
|
||||
count++;
|
||||
}
|
||||
28
Adafruit_I2S_BFF/CircuitPython/Tone/code.py
Normal file
28
Adafruit_I2S_BFF/CircuitPython/Tone/code.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S Tone playback example.
|
||||
"""
|
||||
import time
|
||||
import array
|
||||
import math
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
TONE_VOLUME = 0.1 # Increase this to increase the volume of the tone.
|
||||
FREQUENCY = 440 # Set this to the Hz of the tone you want to generate.
|
||||
|
||||
audio = audiobusio.I2SOut(board.A2, board.A1, board.A0)
|
||||
|
||||
length = 8000 // FREQUENCY
|
||||
sine_wave = array.array("h", [0] * length)
|
||||
for i in range(length):
|
||||
sine_wave[i] = int((math.sin(math.pi * 2 * i / length)) * TONE_VOLUME * (2 ** 15 - 1))
|
||||
sine_wave_sample = audiocore.RawSample(sine_wave)
|
||||
|
||||
while True:
|
||||
audio.play(sine_wave_sample, loop=True)
|
||||
time.sleep(1)
|
||||
audio.stop()
|
||||
time.sleep(1)
|
||||
BIN
Adafruit_I2S_BFF/CircuitPython/WAV/booploop.wav
Normal file
BIN
Adafruit_I2S_BFF/CircuitPython/WAV/booploop.wav
Normal file
Binary file not shown.
22
Adafruit_I2S_BFF/CircuitPython/WAV/code.py
Normal file
22
Adafruit_I2S_BFF/CircuitPython/WAV/code.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# SPDX-FileCopyrightText: 2023 Kattni Rembor for Adafruit Industries
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""
|
||||
CircuitPython I2S WAV file playback.
|
||||
"""
|
||||
import audiocore
|
||||
import board
|
||||
import audiobusio
|
||||
|
||||
LOOP = False # Update to True loop WAV playback. False plays once.
|
||||
|
||||
audio = audiobusio.I2SOut(board.A2, board.A1, board.A0)
|
||||
|
||||
with open("booploop.wav", "rb") as wave_file:
|
||||
wav = audiocore.WaveFile(wave_file)
|
||||
|
||||
print("Playing wav file!")
|
||||
audio.play(wav, loop=LOOP)
|
||||
while audio.playing:
|
||||
pass
|
||||
|
||||
print("Done!")
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import board
|
||||
import busio
|
||||
|
|
@ -22,14 +23,22 @@ USE_CELSIUS = False
|
|||
# Interval the sensor publishes to Adafruit IO, in minutes
|
||||
PUBLISH_INTERVAL = 10
|
||||
|
||||
### WiFi ###
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
# Get wifi details and more from a secrets.py file
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi secrets are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
if None in [ssid, password, aio_username, aio_key]:
|
||||
raise RuntimeError(
|
||||
"WiFi and Adafruit IO settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
|
||||
)
|
||||
|
||||
### WiFi ###
|
||||
|
||||
# AirLift FeatherWing
|
||||
esp32_cs = DigitalInOut(board.D13)
|
||||
|
|
@ -38,8 +47,8 @@ esp32_ready = DigitalInOut(board.D11)
|
|||
|
||||
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
|
||||
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
|
||||
status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
|
||||
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
||||
status_pixel = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
|
||||
wifi = adafruit_esp32spi_wifimanager.WiFiManager(esp, ssid, password, status_pixel=status_pixel)
|
||||
|
||||
# Connect to a PM2.5 sensor over UART
|
||||
reset_pin = None
|
||||
|
|
@ -142,7 +151,7 @@ def read_bme(is_celsius=False):
|
|||
|
||||
|
||||
# Create an instance of the Adafruit IO HTTP client
|
||||
io = IO_HTTP(secrets["aio_user"], secrets["aio_key"], wifi)
|
||||
io = IO_HTTP(aio_username, aio_key, wifi)
|
||||
|
||||
# Describes feeds used to hold Adafruit IO data
|
||||
feed_aqi = io.get_feed("air-quality-sensor.aqi")
|
||||
|
|
@ -150,11 +159,11 @@ feed_aqi_category = io.get_feed("air-quality-sensor.category")
|
|||
feed_humidity = io.get_feed("air-quality-sensor.humidity")
|
||||
feed_temperature = io.get_feed("air-quality-sensor.temperature")
|
||||
|
||||
# Set up location metadata from secrets.py file
|
||||
# Set up location metadata from settings.toml file
|
||||
location_metadata = {
|
||||
"lat": secrets["latitude"],
|
||||
"lon": secrets["longitude"],
|
||||
"ele": secrets["elevation"],
|
||||
"lat": getenv("latitude"),
|
||||
"lon": getenv("longitude"),
|
||||
"ele": getenv("elevation"),
|
||||
}
|
||||
|
||||
elapsed_minutes = 0
|
||||
|
|
|
|||
|
|
@ -2,25 +2,31 @@
|
|||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import os
|
||||
import time
|
||||
import board
|
||||
import busio
|
||||
from digitalio import DigitalInOut
|
||||
import neopixel
|
||||
import adafruit_connection_manager
|
||||
from adafruit_esp32spi import adafruit_esp32spi
|
||||
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
|
||||
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
|
||||
|
||||
import adafruit_minimqtt.adafruit_minimqtt as MQTT
|
||||
|
||||
### WiFi ###
|
||||
# Get WiFi details, ensure these are setup in settings.toml
|
||||
ssid = os.getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
|
||||
# Get wifi details and more from a secrets.py file
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi secrets are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
if None in [ssid, password]:
|
||||
raise RuntimeError(
|
||||
"WiFi settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"at a minimum."
|
||||
)
|
||||
|
||||
### WiFi ###
|
||||
|
||||
# If you are using a board with pre-defined ESP32 Pins:
|
||||
esp32_cs = DigitalInOut(board.ESP_CS)
|
||||
|
|
@ -35,19 +41,19 @@ esp32_reset = DigitalInOut(board.ESP_RESET)
|
|||
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
|
||||
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
|
||||
"""Use below for Most Boards"""
|
||||
status_light = neopixel.NeoPixel(
|
||||
status_pixel = neopixel.NeoPixel(
|
||||
board.NEOPIXEL, 1, brightness=0.2
|
||||
) # Uncomment for Most Boards
|
||||
"""Uncomment below for ItsyBitsy M4"""
|
||||
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# Uncomment below for an externally defined RGB LED
|
||||
# import adafruit_rgbled
|
||||
# from adafruit_esp32spi import PWMOut
|
||||
# RED_LED = PWMOut.PWMOut(esp, 26)
|
||||
# GREEN_LED = PWMOut.PWMOut(esp, 27)
|
||||
# BLUE_LED = PWMOut.PWMOut(esp, 25)
|
||||
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
||||
# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.WiFiManager(esp, ssid, password, status_pixel=status_pixel)
|
||||
|
||||
# Set up a pin for controlling the relay
|
||||
power_pin = DigitalInOut(board.D3)
|
||||
|
|
@ -55,7 +61,7 @@ power_pin.switch_to_output()
|
|||
|
||||
### Feeds ###
|
||||
# Set up a feed named Relay for subscribing to the relay feed on Adafruit IO
|
||||
feed_relay = secrets["aio_username"] + "/feeds/relay"
|
||||
feed_relay = os.getenv("AIO_USERNAME") + "/feeds/relay"
|
||||
|
||||
### Code ###
|
||||
|
||||
|
|
@ -101,13 +107,16 @@ print("Connecting to WiFi...")
|
|||
wifi.connect()
|
||||
print("Connected!")
|
||||
|
||||
MQTT.set_socket(socket, esp)
|
||||
pool = adafruit_connection_manager.get_radio_socketpool(esp)
|
||||
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)
|
||||
|
||||
# Set up a MiniMQTT Client
|
||||
client = MQTT.MQTT(
|
||||
broker="io.adafruit.com",
|
||||
username=secrets["aio_username"],
|
||||
password=secrets["aio_key"],
|
||||
username=os.getenv("AIO_USERNAME"),
|
||||
password=os.getenv("AIO_KEY"),
|
||||
socket_pool=pool,
|
||||
ssl_context=ssl_context,
|
||||
)
|
||||
|
||||
# Setup the callback methods above
|
||||
|
|
|
|||
|
|
@ -2,18 +2,34 @@
|
|||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import board
|
||||
import busio
|
||||
from digitalio import DigitalInOut
|
||||
import neopixel
|
||||
import adafruit_bh1750
|
||||
import adafruit_connection_manager
|
||||
from adafruit_esp32spi import adafruit_esp32spi
|
||||
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
|
||||
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
|
||||
|
||||
import adafruit_minimqtt.adafruit_minimqtt as MQTT
|
||||
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
if None in [ssid, password, aio_username, aio_key]:
|
||||
raise RuntimeError(
|
||||
"WiFi and Adafruit IO settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
|
||||
)
|
||||
|
||||
### Sensor Calibration ###
|
||||
# Appliance power LED's light level, in Lux
|
||||
APPLIANCE_ON_LUX = 30.0
|
||||
|
|
@ -22,13 +38,6 @@ SENSOR_READ_TIME = 10.0
|
|||
|
||||
### WiFi ###
|
||||
|
||||
# Get wifi details and more from a secrets.py file
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi secrets are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
|
||||
# If you are using a board with pre-defined ESP32 Pins:
|
||||
esp32_cs = DigitalInOut(board.ESP_CS)
|
||||
esp32_ready = DigitalInOut(board.ESP_BUSY)
|
||||
|
|
@ -42,19 +51,19 @@ esp32_reset = DigitalInOut(board.ESP_RESET)
|
|||
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
|
||||
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
|
||||
"""Use below for Most Boards"""
|
||||
status_light = neopixel.NeoPixel(
|
||||
status_pixel = neopixel.NeoPixel(
|
||||
board.NEOPIXEL, 1, brightness=0.2
|
||||
) # Uncomment for Most Boards
|
||||
"""Uncomment below for ItsyBitsy M4"""
|
||||
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# Uncomment below for an externally defined RGB LED
|
||||
# import adafruit_rgbled
|
||||
# from adafruit_esp32spi import PWMOut
|
||||
# RED_LED = PWMOut.PWMOut(esp, 26)
|
||||
# GREEN_LED = PWMOut.PWMOut(esp, 27)
|
||||
# BLUE_LED = PWMOut.PWMOut(esp, 25)
|
||||
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
||||
# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.WiFiManager(esp, ssid, password, status_pixel=status_pixel)
|
||||
|
||||
# Set up a pin for controlling the relay
|
||||
power_pin = DigitalInOut(board.D3)
|
||||
|
|
@ -67,10 +76,10 @@ sensor = adafruit_bh1750.BH1750(i2c)
|
|||
|
||||
### Feeds ###
|
||||
# Set up a feed named Relay for subscribing to the relay feed on Adafruit IO
|
||||
feed_relay = secrets["aio_username"] + "/feeds/relay"
|
||||
feed_relay = f"{aio_username}/feeds/relay"
|
||||
|
||||
# Set up a feed named status for subscribing to the status feed on Adafruit IO
|
||||
feed_status = secrets["aio_username"] + "/feeds/status"
|
||||
feed_status = f"{aio_username}/feeds/status"
|
||||
|
||||
### Code ###
|
||||
|
||||
|
|
@ -116,13 +125,16 @@ print("Connecting to WiFi...")
|
|||
wifi.connect()
|
||||
print("Connected!")
|
||||
|
||||
MQTT.set_socket(socket, esp)
|
||||
pool = adafruit_connection_manager.get_radio_socketpool(esp)
|
||||
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)
|
||||
|
||||
# Set up a MiniMQTT Client
|
||||
client = MQTT.MQTT(
|
||||
broker="io.adafruit.com",
|
||||
username=secrets["aio_username"],
|
||||
password=secrets["aio_key"],
|
||||
username=aio_username,
|
||||
password=aio_key,
|
||||
socket_pool=pool,
|
||||
ssl_context=ssl_context,
|
||||
)
|
||||
|
||||
# Setup the callback methods above
|
||||
|
|
|
|||
27
Adafruit_IO_Reed_Switch/rpi-pico-w112213141.json
Normal file
27
Adafruit_IO_Reed_Switch/rpi-pico-w112213141.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"exportVersion": "1.0.0",
|
||||
"exportedBy": "tyeth_demo",
|
||||
"exportedAt": "2025-05-02T17:08:03.857Z",
|
||||
"exportedFromDevice": {
|
||||
"board": "rpi-pico-w",
|
||||
"firmwareVersion": "1.0.0-beta.100"
|
||||
},
|
||||
"components": [
|
||||
{
|
||||
"name": "Reed Switch",
|
||||
"pinName": "D13",
|
||||
"type": "reed_switch",
|
||||
"mode": "DIGITAL",
|
||||
"direction": "INPUT",
|
||||
"period": 0,
|
||||
"pull": "UP",
|
||||
"isPin": true,
|
||||
"visualization": {
|
||||
"offLabel": "Open",
|
||||
"offIcon": "fa6:solid:door-open",
|
||||
"onLabel": "Closed",
|
||||
"onIcon": "fa6:regular:door-closed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -2,25 +2,34 @@
|
|||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from os import getenv
|
||||
import time
|
||||
import board
|
||||
import busio
|
||||
from digitalio import DigitalInOut
|
||||
import adafruit_connection_manager
|
||||
from adafruit_esp32spi import adafruit_esp32spi
|
||||
from adafruit_esp32spi import adafruit_esp32spi_wifimanager
|
||||
import adafruit_esp32spi.adafruit_esp32spi_socket as socket
|
||||
import neopixel
|
||||
import adafruit_minimqtt.adafruit_minimqtt as MQTT
|
||||
from adafruit_io.adafruit_io import IO_MQTT
|
||||
|
||||
### WiFi ###
|
||||
# Get WiFi details and Adafruit IO keys, ensure these are setup in settings.toml
|
||||
# (visit io.adafruit.com if you need to create an account, or if you need your Adafruit IO key.)
|
||||
ssid = getenv("CIRCUITPY_WIFI_SSID")
|
||||
password = getenv("CIRCUITPY_WIFI_PASSWORD")
|
||||
aio_username = getenv("ADAFRUIT_AIO_USERNAME")
|
||||
aio_key = getenv("ADAFRUIT_AIO_KEY")
|
||||
|
||||
# Get wifi details and more from a secrets.py file
|
||||
try:
|
||||
from secrets import secrets
|
||||
except ImportError:
|
||||
print("WiFi secrets are kept in secrets.py, please add them there!")
|
||||
raise
|
||||
if None in [ssid, password, aio_username, aio_key]:
|
||||
raise RuntimeError(
|
||||
"WiFi and Adafruit IO settings are kept in settings.toml, "
|
||||
"please add them there. The settings file must contain "
|
||||
"'CIRCUITPY_WIFI_SSID', 'CIRCUITPY_WIFI_PASSWORD', "
|
||||
"'ADAFRUIT_AIO_USERNAME' and 'ADAFRUIT_AIO_KEY' at a minimum."
|
||||
)
|
||||
|
||||
### WiFi ###
|
||||
|
||||
# If you are using a board with pre-defined ESP32 Pins:
|
||||
esp32_cs = DigitalInOut(board.ESP_CS)
|
||||
|
|
@ -35,19 +44,19 @@ esp32_reset = DigitalInOut(board.ESP_RESET)
|
|||
spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
|
||||
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
|
||||
"""Use below for Most Boards"""
|
||||
status_light = neopixel.NeoPixel(
|
||||
status_pixel = neopixel.NeoPixel(
|
||||
board.NEOPIXEL, 1, brightness=0.2
|
||||
) # Uncomment for Most Boards
|
||||
"""Uncomment below for ItsyBitsy M4"""
|
||||
# status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# status_pixel = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
||||
# Uncomment below for an externally defined RGB LED
|
||||
# import adafruit_rgbled
|
||||
# from adafruit_esp32spi import PWMOut
|
||||
# RED_LED = PWMOut.PWMOut(esp, 26)
|
||||
# GREEN_LED = PWMOut.PWMOut(esp, 27)
|
||||
# BLUE_LED = PWMOut.PWMOut(esp, 25)
|
||||
# status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
||||
# status_pixel = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
|
||||
wifi = adafruit_esp32spi_wifimanager.WiFiManager(esp, ssid, password, status_pixel=status_pixel)
|
||||
|
||||
# Set up a pin for controlling the relay
|
||||
power_pin = DigitalInOut(board.D3)
|
||||
|
|
@ -89,11 +98,11 @@ def on_message(client, feed_id, payload):
|
|||
|
||||
def on_relay_msg(client, topic, message):
|
||||
# Method called whenever user/feeds/relay has a new value
|
||||
if message == "morning":
|
||||
print("Morning - turning outlet ON")
|
||||
if message == "1":
|
||||
print("Received 1 - turning outlet ON")
|
||||
power_pin.value = True
|
||||
elif message == "night":
|
||||
print("Night - turning outlet OFF")
|
||||
elif message == "0":
|
||||
print("Received 0 - turning outlet OFF")
|
||||
power_pin.value = False
|
||||
else:
|
||||
print("Unexpected value received on relay feed.")
|
||||
|
|
@ -104,14 +113,16 @@ print("Connecting to WiFi...")
|
|||
wifi.connect()
|
||||
print("Connected!")
|
||||
|
||||
# Initialize MQTT interface with the esp interface
|
||||
MQTT.set_socket(socket, esp)
|
||||
pool = adafruit_connection_manager.get_radio_socketpool(esp)
|
||||
ssl_context = adafruit_connection_manager.get_radio_ssl_context(esp)
|
||||
|
||||
# Initialize a new MQTT Client object
|
||||
mqtt_client = MQTT.MQTT(
|
||||
broker="io.adafruit.com",
|
||||
username=secrets["aio_username"],
|
||||
password=secrets["aio_key"],
|
||||
username=aio_username,
|
||||
password=aio_key,
|
||||
socket_pool=pool,
|
||||
ssl_context=ssl_context,
|
||||
)
|
||||
|
||||
# Initialize an Adafruit IO MQTT Client
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue