mirror of
https://github.com/micropython/micropython.git
synced 2025-12-24 22:00:12 +01:00
Compare commits
709 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c2fc070ec | ||
|
|
56fd33a6dd | ||
|
|
c68c327310 | ||
|
|
1f396c58d9 | ||
|
|
fb5017f9dc | ||
|
|
496a601c3b | ||
|
|
f873a5005a | ||
|
|
5d05993f10 | ||
|
|
8af64bcf2b | ||
|
|
5036b6ad18 | ||
|
|
8e130fcf2b | ||
|
|
8a3e9036eb | ||
|
|
9df6b3a2c2 | ||
|
|
02fd83bcbc | ||
|
|
b539a61490 | ||
|
|
81a99eb388 | ||
|
|
bb6458bf43 | ||
|
|
db99ae00a2 | ||
|
|
06ec96b47b | ||
|
|
cfc94bec9f | ||
|
|
879bc4197a | ||
|
|
5e94f0b43a | ||
|
|
a6cf45864f | ||
|
|
35e63f0007 | ||
|
|
ae845f13de | ||
|
|
c2d885501f | ||
|
|
3944d3511f | ||
|
|
76c81cd5a6 | ||
|
|
2123ced3f4 | ||
|
|
3d830415bc | ||
|
|
7b7c99fec1 | ||
|
|
9215cdc7fd | ||
|
|
b8468d12a1 | ||
|
|
c6923f52f0 | ||
|
|
13d9d50fea | ||
|
|
bd9de5ec90 | ||
|
|
5302c3e8c4 | ||
|
|
a22aa53ef1 | ||
|
|
12144e8fcd | ||
|
|
0f682f1ee1 | ||
|
|
5aa4db0505 | ||
|
|
74c6363b97 | ||
|
|
566d8f1d7e | ||
|
|
c816b89353 | ||
|
|
8c35f3979c | ||
|
|
621c644205 | ||
|
|
9549590fc6 | ||
|
|
ddb9dba2f7 | ||
|
|
70ff7350e7 | ||
|
|
26fd0ac571 | ||
|
|
8ebdbcfb27 | ||
|
|
348caaf940 | ||
|
|
1f0dfe37a1 | ||
|
|
fd283eba64 | ||
|
|
e9b7610748 | ||
|
|
59603a2e89 | ||
|
|
4fb9452bff | ||
|
|
ad2889c141 | ||
|
|
8ad1659f68 | ||
|
|
7781caf8d3 | ||
|
|
c468fe65c5 | ||
|
|
a9ed42b3b4 | ||
|
|
6b6acc5b5d | ||
|
|
d46cd02d95 | ||
|
|
df06e34175 | ||
|
|
83e99f88cb | ||
|
|
613fd0a1ca | ||
|
|
9dd2c92d01 | ||
|
|
c1d1c562f3 | ||
|
|
962d5a987f | ||
|
|
006ffe1561 | ||
|
|
859e4e94f3 | ||
|
|
6ddd9f3e2b | ||
|
|
74f413bc60 | ||
|
|
d86d65f625 | ||
|
|
adae53d522 | ||
|
|
18775d3807 | ||
|
|
f8170db390 | ||
|
|
b0f3ae58e7 | ||
|
|
8811b0af9c | ||
|
|
12c61ddddd | ||
|
|
b3bc2ee1b9 | ||
|
|
473b639845 | ||
|
|
3f3ccef829 | ||
|
|
f41e1f1bb7 | ||
|
|
6514ff6160 | ||
|
|
25d0f7d59d | ||
|
|
22050a3ed0 | ||
|
|
b639ce27c7 | ||
|
|
c10d303e1b | ||
|
|
af554b4ba2 | ||
|
|
31fc81d3b8 | ||
|
|
193c62226c | ||
|
|
8fcfaf6f22 | ||
|
|
978a429aaa | ||
|
|
ba61480df5 | ||
|
|
2534bfdb92 | ||
|
|
348edad888 | ||
|
|
8c3b5526ae | ||
|
|
1f7cec944e | ||
|
|
38358a096d | ||
|
|
37d5aa1377 | ||
|
|
a6aa35af09 | ||
|
|
3c2e40b008 | ||
|
|
0ea2108f1c | ||
|
|
eff85bb1dc | ||
|
|
d54290f6e2 | ||
|
|
0785040593 | ||
|
|
941ddfe559 | ||
|
|
8ed3a9eb9c | ||
|
|
6d8156ae28 | ||
|
|
06deec9d35 | ||
|
|
50ef851bee | ||
|
|
1b45670c69 | ||
|
|
df4e1d1279 | ||
|
|
31300b5144 | ||
|
|
c564169c8f | ||
|
|
dc2c8f0b1a | ||
|
|
556e5dfd35 | ||
|
|
e0f7e001e8 | ||
|
|
648333d2d5 | ||
|
|
480c212009 | ||
|
|
351ec6d4ab | ||
|
|
f3f5e975e4 | ||
|
|
0df2ee0126 | ||
|
|
492bf12499 | ||
|
|
678f3a1e05 | ||
|
|
a119983328 | ||
|
|
88ed518390 | ||
|
|
8b8c32c09b | ||
|
|
6afd651f1e | ||
|
|
6149ce01f8 | ||
|
|
1c6d91d968 | ||
|
|
45ac5a85d5 | ||
|
|
a63542387d | ||
|
|
90b2cfe644 | ||
|
|
51cee4495e | ||
|
|
07615d9f7e | ||
|
|
23df4b08fb | ||
|
|
2bddfd4922 | ||
|
|
237c519ac4 | ||
|
|
650df97c06 | ||
|
|
ef2ffc0e4e | ||
|
|
c888831410 | ||
|
|
29c8c8aecb | ||
|
|
9264d42e2a | ||
|
|
b2b771ca02 | ||
|
|
7a012f4793 | ||
|
|
bababce6de | ||
|
|
6d103b6548 | ||
|
|
104aa26271 | ||
|
|
2b46da234c | ||
|
|
4296a8dc5c | ||
|
|
bd66b09512 | ||
|
|
8db4f363e9 | ||
|
|
7c40b15a3f | ||
|
|
0d10e5310a | ||
|
|
92497bff94 | ||
|
|
955b8526f4 | ||
|
|
71c6f93016 | ||
|
|
bbe5245028 | ||
|
|
3bc9b571bb | ||
|
|
5c8147528e | ||
|
|
d422e56631 | ||
|
|
eb40769613 | ||
|
|
51dca54cd0 | ||
|
|
b372156f74 | ||
|
|
67a6d31955 | ||
|
|
a2d5d84ecc | ||
|
|
624738ca64 | ||
|
|
109990fc32 | ||
|
|
fea40ad468 | ||
|
|
d4f4cb6a24 | ||
|
|
c4e26dd19a | ||
|
|
d46bea9ffa | ||
|
|
7652ab77ef | ||
|
|
495da15611 | ||
|
|
067fb2da14 | ||
|
|
dda1a41205 | ||
|
|
36d328e451 | ||
|
|
fcc9d43c6d | ||
|
|
32d7cf6e44 | ||
|
|
2a51f72ed1 | ||
|
|
f73d78394b | ||
|
|
4fa1731b6e | ||
|
|
cc1ef76f88 | ||
|
|
584406880c | ||
|
|
2494399a42 | ||
|
|
46f0641fba | ||
|
|
1b60a6dc4e | ||
|
|
8dd704b019 | ||
|
|
4494b521ea | ||
|
|
21ab304c41 | ||
|
|
0dc85c9f86 | ||
|
|
098f3e2862 | ||
|
|
270dd29320 | ||
|
|
c618f91e22 | ||
|
|
8aa3cbf153 | ||
|
|
97f88eebb6 | ||
|
|
8dcce92606 | ||
|
|
89e56a80b8 | ||
|
|
3a5a35aaec | ||
|
|
d76ebde85e | ||
|
|
89aa7157d0 | ||
|
|
7e5715a6d5 | ||
|
|
6f3b9933bd | ||
|
|
dde9abad16 | ||
|
|
7d57037906 | ||
|
|
67ece47121 | ||
|
|
50e4fa5e19 | ||
|
|
31480fb91b | ||
|
|
5e247a5192 | ||
|
|
31f5dc065a | ||
|
|
432465b167 | ||
|
|
aed1da913b | ||
|
|
53521152a8 | ||
|
|
8007f84cca | ||
|
|
b830f4c610 | ||
|
|
d49a547064 | ||
|
|
69f26c68c9 | ||
|
|
0b6e28c999 | ||
|
|
e943a407f2 | ||
|
|
d4c3349957 | ||
|
|
f4942db044 | ||
|
|
2ba6677775 | ||
|
|
040373e4c4 | ||
|
|
593ffdd976 | ||
|
|
73ccb3fc5b | ||
|
|
53e3770b15 | ||
|
|
000eae121c | ||
|
|
9a627e8881 | ||
|
|
61b560f63f | ||
|
|
d76c65f599 | ||
|
|
dbbf082786 | ||
|
|
050e645ef2 | ||
|
|
53ac7830cb | ||
|
|
2c883c5ab7 | ||
|
|
00137b8c11 | ||
|
|
5801967496 | ||
|
|
47f9b10b30 | ||
|
|
6c84f1e03a | ||
|
|
f474e956d7 | ||
|
|
b122ed0732 | ||
|
|
c3beb16db3 | ||
|
|
091dcaea2f | ||
|
|
bcd719ea3a | ||
|
|
7d2c685544 | ||
|
|
5c1af60e19 | ||
|
|
d3ab4bc7ca | ||
|
|
4f811d0e4c | ||
|
|
9b0714b24c | ||
|
|
272fad6d9c | ||
|
|
a649d72606 | ||
|
|
2243d68345 | ||
|
|
49bb04ee64 | ||
|
|
0c1de1cdee | ||
|
|
0a400a6333 | ||
|
|
df3b1741b6 | ||
|
|
674bf1bc81 | ||
|
|
d9d408135d | ||
|
|
a9a732af1f | ||
|
|
44ab5c3ef1 | ||
|
|
fef0d9818a | ||
|
|
f30b6f0af5 | ||
|
|
59a4fee516 | ||
|
|
733db525e2 | ||
|
|
f9448ddc2c | ||
|
|
0a2e9650f5 | ||
|
|
0699c6bf9e | ||
|
|
594fa73411 | ||
|
|
ed0c11236f | ||
|
|
6d24dc23b8 | ||
|
|
c2a519bab9 | ||
|
|
7f7e247545 | ||
|
|
6eb17c31a9 | ||
|
|
c33df193bf | ||
|
|
eacbd7aeba | ||
|
|
81ebba7e02 | ||
|
|
959ed931a4 | ||
|
|
19e3c9d53a | ||
|
|
54ea253f56 | ||
|
|
47442d9f52 | ||
|
|
22cbcd55f0 | ||
|
|
3177ef544f | ||
|
|
b67d098841 | ||
|
|
eec8a94f04 | ||
|
|
9314b2df4f | ||
|
|
73bc0c24ab | ||
|
|
e813ea1070 | ||
|
|
a525493e40 | ||
|
|
ac63ca7bc5 | ||
|
|
1a65ff1b72 | ||
|
|
67a327cb9b | ||
|
|
e4f963a351 | ||
|
|
69a1aaf654 | ||
|
|
d083712224 | ||
|
|
53ad681ed1 | ||
|
|
3a37426b29 | ||
|
|
260b839483 | ||
|
|
40f5ecd3a8 | ||
|
|
2f5935269b | ||
|
|
54b89665fc | ||
|
|
7acc252e93 | ||
|
|
6f3fc9bfa1 | ||
|
|
1a327c4fa3 | ||
|
|
f49d63a75c | ||
|
|
9b0a150bd6 | ||
|
|
f8fb4470a0 | ||
|
|
7063210014 | ||
|
|
1cc81ed449 | ||
|
|
c734de490a | ||
|
|
358e5d8bad | ||
|
|
657aef66ff | ||
|
|
6e87aeb841 | ||
|
|
b69f798c92 | ||
|
|
558fd5d228 | ||
|
|
6c3db26ab7 | ||
|
|
d6236e85c2 | ||
|
|
6837dba6b8 | ||
|
|
0c97e4c414 | ||
|
|
a45e280c58 | ||
|
|
f38e8f5217 | ||
|
|
5b1c221785 | ||
|
|
397b705647 | ||
|
|
7e9182f3aa | ||
|
|
b32b0d38fe | ||
|
|
20d9bc2d76 | ||
|
|
05ba2433f6 | ||
|
|
5e919b7ef8 | ||
|
|
9c04299da1 | ||
|
|
5e7fa7c80c | ||
|
|
8a8e775035 | ||
|
|
04d5e644fc | ||
|
|
2c915e1ae6 | ||
|
|
ce8b4e8749 | ||
|
|
2c407bcf20 | ||
|
|
d85439fd19 | ||
|
|
1a0a323ca8 | ||
|
|
4e51a3038c | ||
|
|
96eca22322 | ||
|
|
e6a4d4e23c | ||
|
|
e4cb7c6158 | ||
|
|
2c8356c482 | ||
|
|
f81ea6307c | ||
|
|
de12502d89 | ||
|
|
81fd5685fc | ||
|
|
1b811b946e | ||
|
|
069654f2be | ||
|
|
cee888255b | ||
|
|
28d4b94dce | ||
|
|
69b702276b | ||
|
|
e24674d44e | ||
|
|
69256ac0b1 | ||
|
|
debbaac1bd | ||
|
|
919b70b7ec | ||
|
|
8d2bcaf3cd | ||
|
|
9698a60591 | ||
|
|
fcd6862597 | ||
|
|
ef0c5db2ed | ||
|
|
254a5646c1 | ||
|
|
333a63efaa | ||
|
|
4f2d59e82f | ||
|
|
ec5f8db49d | ||
|
|
c07a03a36d | ||
|
|
aa3fb7b387 | ||
|
|
fd2b71f972 | ||
|
|
a5d07c3aba | ||
|
|
a5d2af7949 | ||
|
|
e5fa163a4c | ||
|
|
a0cb4eda9a | ||
|
|
cef073877b | ||
|
|
cf4b72bf13 | ||
|
|
b475327ffa | ||
|
|
6a051a8e0b | ||
|
|
fb6cc96951 | ||
|
|
fc4c43a72e | ||
|
|
785cf9a61f | ||
|
|
777232c9a5 | ||
|
|
3d4a535208 | ||
|
|
5531437941 | ||
|
|
4b597a1c1a | ||
|
|
98af891610 | ||
|
|
61fa7c8152 | ||
|
|
2e75a17bab | ||
|
|
b1dfdaf6cb | ||
|
|
f50d9477c1 | ||
|
|
d7019d0628 | ||
|
|
9475cc59e6 | ||
|
|
2599672384 | ||
|
|
e1e7657277 | ||
|
|
03b8bb7ec9 | ||
|
|
d88250c06e | ||
|
|
c4506ed869 | ||
|
|
402a743821 | ||
|
|
8fc5e56a6a | ||
|
|
c961889e34 | ||
|
|
6ca17c1922 | ||
|
|
b4070ee8a4 | ||
|
|
2f02302e22 | ||
|
|
193795398d | ||
|
|
71d40f132d | ||
|
|
9edd736ee6 | ||
|
|
e8e116e7fc | ||
|
|
8b08a0d9ed | ||
|
|
61230e007d | ||
|
|
b01a373adb | ||
|
|
cd6194aefc | ||
|
|
374654f2b8 | ||
|
|
fe9bc0c573 | ||
|
|
bbc65d4eda | ||
|
|
fd86bf5917 | ||
|
|
53302f1616 | ||
|
|
651a188299 | ||
|
|
13394a632d | ||
|
|
53ad5edc01 | ||
|
|
87c783b454 | ||
|
|
679fe0abae | ||
|
|
eda8746324 | ||
|
|
935e021250 | ||
|
|
c33a76059f | ||
|
|
3962766be0 | ||
|
|
b62beadae0 | ||
|
|
f71c0699a5 | ||
|
|
9c7e3353e5 | ||
|
|
ba640bde55 | ||
|
|
632d8efa05 | ||
|
|
82b95f625e | ||
|
|
91031a75a1 | ||
|
|
4332d72fd8 | ||
|
|
de0c84ebf1 | ||
|
|
5e75f335e6 | ||
|
|
0cb10b5220 | ||
|
|
159f1aaca8 | ||
|
|
e589cddcd4 | ||
|
|
6e6488530e | ||
|
|
4b5606bc09 | ||
|
|
ee6fcc6f91 | ||
|
|
96a644076d | ||
|
|
8f1854ad2d | ||
|
|
ac671546d1 | ||
|
|
88f60de914 | ||
|
|
2c81b9be28 | ||
|
|
063e6e7d0a | ||
|
|
5d93dfbc2c | ||
|
|
3dbd2ee926 | ||
|
|
4a02a8f74d | ||
|
|
24342dd65e | ||
|
|
d4c8e626f2 | ||
|
|
a5d48b1162 | ||
|
|
78d0dde562 | ||
|
|
0cdbd356fd | ||
|
|
5b9f361824 | ||
|
|
667d64b430 | ||
|
|
dd32f02cc3 | ||
|
|
7059c8c23c | ||
|
|
a1d072df81 | ||
|
|
df1f6783f2 | ||
|
|
494aea3e86 | ||
|
|
5bc9398d9d | ||
|
|
8000d51b68 | ||
|
|
1a0adf49df | ||
|
|
e673714cfe | ||
|
|
58e2ad42ae | ||
|
|
b894551772 | ||
|
|
da161fd9f0 | ||
|
|
12154b1774 | ||
|
|
8d4d6731f5 | ||
|
|
2b302dad51 | ||
|
|
6d5a549067 | ||
|
|
b8133c4c0f | ||
|
|
4a6cac4643 | ||
|
|
99146ea444 | ||
|
|
556a1df6fd | ||
|
|
9d7b871f58 | ||
|
|
2466cb67f8 | ||
|
|
3acaa28b52 | ||
|
|
52e062ef33 | ||
|
|
664f03f466 | ||
|
|
9a58316de2 | ||
|
|
be989be861 | ||
|
|
1ded19d4b3 | ||
|
|
157056ecdf | ||
|
|
ab69ed7dac | ||
|
|
9996adc37d | ||
|
|
cea6cf8a5e | ||
|
|
0d1f8868b6 | ||
|
|
77f85db41e | ||
|
|
06b398489e | ||
|
|
0be6359f39 | ||
|
|
2a1cca20b1 | ||
|
|
e7cd1699df | ||
|
|
dddb98db8b | ||
|
|
99fc0d120a | ||
|
|
00f921ce02 | ||
|
|
031fadd10e | ||
|
|
e5c39a3a9e | ||
|
|
0779409d0d | ||
|
|
ba8f7d5171 | ||
|
|
09ed5bcbbb | ||
|
|
21b74604f9 | ||
|
|
85d3b6165a | ||
|
|
70f32f0f73 | ||
|
|
3d0e3a3d3e | ||
|
|
932f07ccf5 | ||
|
|
4c2cb7e384 | ||
|
|
6e5c31c947 | ||
|
|
a099bfe89c | ||
|
|
e5b047369b | ||
|
|
54fc247f9b | ||
|
|
97375f4576 | ||
|
|
7261f17b9e | ||
|
|
97c2628900 | ||
|
|
9ae51257bd | ||
|
|
5239a8a82b | ||
|
|
a49c16069c | ||
|
|
d5a12a6608 | ||
|
|
1c43a0fbf8 | ||
|
|
7378c50b2f | ||
|
|
9e8396accb | ||
|
|
9b5e05a7c7 | ||
|
|
ad725a6661 | ||
|
|
853fb08d0d | ||
|
|
07554486ee | ||
|
|
6b80ebe32e | ||
|
|
42ef5a1567 | ||
|
|
5b74bba3a3 | ||
|
|
4b6077b3fe | ||
|
|
43d497592f | ||
|
|
fda874e406 | ||
|
|
7379be3673 | ||
|
|
4f64f6bfd3 | ||
|
|
6d2e9e70b3 | ||
|
|
6185dc5f3d | ||
|
|
f1919b7c98 | ||
|
|
c7fb87caff | ||
|
|
f7be80398e | ||
|
|
809fbeefb7 | ||
|
|
dcdf8f2d14 | ||
|
|
bb293e6bcf | ||
|
|
2c72ae5c29 | ||
|
|
f0e2d13fd2 | ||
|
|
ed593780bf | ||
|
|
a0cd118b14 | ||
|
|
f8d42da104 | ||
|
|
3fbbbecec9 | ||
|
|
04a9ac7f38 | ||
|
|
d684f872bd | ||
|
|
05dda0ee9e | ||
|
|
88b0490945 | ||
|
|
4f0080346b | ||
|
|
484a471f9b | ||
|
|
367c084c4b | ||
|
|
0edfb7a115 | ||
|
|
d964873e56 | ||
|
|
ce3beb1672 | ||
|
|
b86c20676e | ||
|
|
db984b73f3 | ||
|
|
1d5d4f49d9 | ||
|
|
419bb26ddc | ||
|
|
d973c1bc12 | ||
|
|
50e0a7b9d4 | ||
|
|
fbb3c190f9 | ||
|
|
14848ffa12 | ||
|
|
52d7685d9a | ||
|
|
d9d4a72679 | ||
|
|
d3a4d39687 | ||
|
|
077448328a | ||
|
|
26f0616e8f | ||
|
|
eb247eacd8 | ||
|
|
342d903a13 | ||
|
|
cdad2b6f4d | ||
|
|
8ab16b6af0 | ||
|
|
c70637bc00 | ||
|
|
98b727c931 | ||
|
|
f22a4f8e0a | ||
|
|
f39bcb304b | ||
|
|
7193086c03 | ||
|
|
4284b3811f | ||
|
|
5d7c408ba8 | ||
|
|
6abafca1aa | ||
|
|
a4c8ef9d16 | ||
|
|
57884996b9 | ||
|
|
b41a14a4b9 | ||
|
|
f70873db23 | ||
|
|
7480ee5892 | ||
|
|
70fb9ee99b | ||
|
|
2382d30318 | ||
|
|
259f1344ca | ||
|
|
ff69a1d27d | ||
|
|
65405247a0 | ||
|
|
3aa0f2eed3 | ||
|
|
453a2a3d7c | ||
|
|
701c4152c1 | ||
|
|
02ea74d8f5 | ||
|
|
1febaf3ac3 | ||
|
|
d083d7d610 | ||
|
|
6f4357c28e | ||
|
|
6d0629bddc | ||
|
|
ecd1272d16 | ||
|
|
3d1d92acfc | ||
|
|
6bb9d3ea3e | ||
|
|
dc320164d8 | ||
|
|
4f72aa86bf | ||
|
|
2740dd85f2 | ||
|
|
e0821830b0 | ||
|
|
09e363316f | ||
|
|
9fb36af9af | ||
|
|
08fed6992f | ||
|
|
6ef65e70af | ||
|
|
eaa96a7610 | ||
|
|
bbe832a0b2 | ||
|
|
6f469209e9 | ||
|
|
57425b648f | ||
|
|
19749db7bf | ||
|
|
9c081b740b | ||
|
|
cd6d189f48 | ||
|
|
8a18084571 | ||
|
|
ac23662550 | ||
|
|
476c15290d | ||
|
|
56f76b873a | ||
|
|
ea23520403 | ||
|
|
57b96a7be2 | ||
|
|
8e1fdf2eb3 | ||
|
|
28adab36c7 | ||
|
|
e9d1a94bf0 | ||
|
|
d6c558c0aa | ||
|
|
add930c4b5 | ||
|
|
12547ce737 | ||
|
|
cc7a4d7db2 | ||
|
|
5148860332 | ||
|
|
495e7cfebc | ||
|
|
f5248a087a | ||
|
|
0d210a0be8 | ||
|
|
fe9620a2bd | ||
|
|
73c9f85b4c | ||
|
|
562bcffd3a | ||
|
|
ed8db2e371 | ||
|
|
53fec1ef48 | ||
|
|
40d8430ee3 | ||
|
|
69d9e7d27d | ||
|
|
dfc35afba1 | ||
|
|
6cee869feb | ||
|
|
ec37239e53 | ||
|
|
4b2938a4b0 | ||
|
|
9598f36a84 | ||
|
|
94e4bd456f | ||
|
|
46fc7a3d75 | ||
|
|
4cd45f48b1 | ||
|
|
46a0ac02c5 | ||
|
|
6b0c88256b | ||
|
|
8cb78e0e53 | ||
|
|
72085a669b | ||
|
|
9fdac9144d | ||
|
|
9d0525182d | ||
|
|
9e0478a902 | ||
|
|
0ee1d0f407 | ||
|
|
e3c66a5a67 | ||
|
|
baf47c84c4 | ||
|
|
1bb15ca427 | ||
|
|
8a43a41b3a | ||
|
|
e9be6a378c | ||
|
|
dc3eb55e6a | ||
|
|
e5cff5b223 | ||
|
|
c38809e26b | ||
|
|
609a9c6b71 | ||
|
|
bf904b238d | ||
|
|
d4315a6caf | ||
|
|
2850e7cd97 | ||
|
|
dc587a3623 | ||
|
|
a2e39a756c | ||
|
|
32b7e93535 | ||
|
|
f791e14750 | ||
|
|
38ac23c942 | ||
|
|
7bb501ef9f | ||
|
|
e372e83b30 | ||
|
|
b33a770596 | ||
|
|
34023eb673 | ||
|
|
0e0ce47e65 | ||
|
|
3770cd2e70 | ||
|
|
f7e5e677df | ||
|
|
3a042fb921 | ||
|
|
a888d5ab91 | ||
|
|
13a4c120ce | ||
|
|
c33ad60a67 | ||
|
|
3846fd56c1 | ||
|
|
5b85a86ce3 | ||
|
|
a2e5e4c3d8 | ||
|
|
3e02b1d19a | ||
|
|
9e78ab4b86 | ||
|
|
814b1ae3a9 | ||
|
|
81407729a5 | ||
|
|
96688de601 | ||
|
|
ab0e36b3da | ||
|
|
350ab0f570 | ||
|
|
103fbaaf27 | ||
|
|
5bf6eba845 | ||
|
|
a63a4761cd | ||
|
|
71206f02c3 | ||
|
|
97a0846af9 | ||
|
|
ff1a96ce2c | ||
|
|
2e2e15cec2 | ||
|
|
5f3e005b67 | ||
|
|
086d98cbde | ||
|
|
87e07ea943 | ||
|
|
e3a29de1dc | ||
|
|
2bd758fe96 | ||
|
|
67e8108345 | ||
|
|
93bb7dffd2 | ||
|
|
9e677114e4 |
@@ -11,7 +11,7 @@ before_script:
|
||||
# - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
|
||||
- sudo dpkg --add-architecture i386
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get update -qq || true
|
||||
- sudo apt-get install -y python3 gcc-multilib gcc-arm-none-eabi pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
|
||||
# For teensy build
|
||||
- sudo apt-get install realpath
|
||||
|
||||
851
ACKNOWLEDGEMENTS
851
ACKNOWLEDGEMENTS
@@ -912,3 +912,854 @@ today. The names appear in order of pledging.
|
||||
1955 Pieter Röhling
|
||||
1957 uomorando, Italy
|
||||
1959 Acacio Cruz
|
||||
|
||||
The MicroPython project raised further funds through a second
|
||||
Kickstarter campaign that was primarily targeted at porting the
|
||||
code to the ESP8266 WiFi chip. The campaign ended on 2nd March
|
||||
2016 and gained the support of 1384 fantastic backers who believed
|
||||
in the project and the principles of Open Source code. Those
|
||||
backers who asked to be named are listed below, with an asterisk
|
||||
indicating that they also supported the first campaign.
|
||||
|
||||
* 1 Gabriel, Seattle
|
||||
* 2 @robberwick
|
||||
* 6 Dave Hylands
|
||||
7 Les, UK
|
||||
8 Ryanteck LTD., UK
|
||||
10 karlsruhe, HU
|
||||
* 11 Turbinenreiter
|
||||
13 Ben Nuttall, UK
|
||||
* 14 Bryan Morrissey, MA, USA
|
||||
* 15 Jogy, Qatar
|
||||
* 16 BOB63,IT
|
||||
19 ReaBoyd
|
||||
* 20 Andrew, MK
|
||||
* 21 chrisq, NO
|
||||
22 Pascal RENOU, France
|
||||
23 Javier G, ES
|
||||
25 Forrest, US
|
||||
26 Filip Korling, Sweden
|
||||
27 roberthh - Rhineland
|
||||
* 28 Herbert Graef, Stuttgart, thanking the MicroPython Team for this great project
|
||||
* 29 johnsonfamily38, UK
|
||||
30 CympleCy
|
||||
31 OJ, PK
|
||||
32 Daniel, SVK
|
||||
33 Shabaz Mohammad
|
||||
* 35 Kenneth Henderick, BE
|
||||
* 37 Daniel Mouritzen, DK
|
||||
39 Torntrousers, UK
|
||||
* 44 Scanner
|
||||
45 Radomir Dopieralski
|
||||
46 Nick, UK
|
||||
* 47 Jon Hylands, Canada
|
||||
* 48 Ben Barwise Clacktronics
|
||||
50 Rob Kent, UK
|
||||
52 Carlos Pereira Atencio
|
||||
54 Andy, UK
|
||||
* 55 WMinarik, Canada
|
||||
57 Hauffe, Germany
|
||||
58 HyperTaz, IT
|
||||
* 61 Michael Kovacs, AT
|
||||
62 Erick Navarro, PE
|
||||
69 Karan,US
|
||||
* 71 Nick B, UK
|
||||
* 72 Anthony Lister, NZ
|
||||
* 73 Bryan Lyon
|
||||
76 Miguel Angel Ajo, ES
|
||||
* 78 Sebastian, Regensburg (GER)
|
||||
* 80 iv3unm
|
||||
81 Thierry BÉNET, FR
|
||||
84 Jannis, Germany
|
||||
86 Nathan Jeffrey
|
||||
88 Cory Benfield, UK
|
||||
90 Carlo, IT
|
||||
* 91 Wojciech Bederski (@wuub)
|
||||
92 Steve Holden, UK
|
||||
93 Tristan Roddis, UK
|
||||
94 Balder, Sweden
|
||||
* 95 Rhys, UK
|
||||
96 Rowan, UK
|
||||
* 97 Gary Martin, Edinburgh
|
||||
* 100 Mikael Eiman
|
||||
* 101 torwag
|
||||
* 102 Craig Barnes, UK
|
||||
103 Andrea Grandi, UK
|
||||
105 Piers, UK
|
||||
* 109 Wayne Keenan
|
||||
110 makuk66
|
||||
111 Hamine,DZ
|
||||
112 Arahavica,JP
|
||||
* 113 Bill Eubanks, USA
|
||||
114 Jonathan, UK
|
||||
115 ghickman
|
||||
* 117 Christian Lange, Germany
|
||||
119 Jonty Wareing
|
||||
121 TheHetman
|
||||
123 Víctor R. Ruiz, Spain
|
||||
* 124 Laurynas Paukste, Norway
|
||||
* 125 Taki
|
||||
126 André Milette, Canada
|
||||
* 127 Ron Cromberge,NL
|
||||
128 IJ, Thailand
|
||||
* 130 IGOR VIZIR
|
||||
132 Bill Saturno
|
||||
134 scibi
|
||||
136 Timbo, AU
|
||||
137 Raphael Vogel, DE
|
||||
* 139 jasonkirk, US
|
||||
141 Linköping, Sweden
|
||||
* 142 Dugres
|
||||
144 DarioS, UK
|
||||
146 NelisW
|
||||
* 148 _Mark_
|
||||
* 149 Folke Berglund, Sweden
|
||||
150 Deniz Dag/Belgium
|
||||
152 Jacques Thomas
|
||||
153 Dag Henrik, Norway
|
||||
* 154 Alexander Steppke
|
||||
158 stavros.io
|
||||
* 161 Seong-Woo Kim, KR
|
||||
162 Aaron H, Seattle
|
||||
164 Iwan, CZ
|
||||
165 Jenning, DE
|
||||
167 Oliver Z, Germany
|
||||
* 168 Chris Mason, Australia
|
||||
169 Fabio P. Italy
|
||||
171 Jonathan, Ireland
|
||||
173 Philipp B., DE
|
||||
174 Mancho, IT
|
||||
175 Mikkel Sørensen, DK
|
||||
176 Raphael Lullis
|
||||
* 177 Tim, China
|
||||
179 JasperS, NL
|
||||
180 Scott, AU
|
||||
181 Roland Kay, UK
|
||||
182 Adam Baxter
|
||||
184 Hugo Herter
|
||||
185 Simon AM, Malta
|
||||
186 Leif Denby
|
||||
190 Maxious
|
||||
* 192 Guido, GER
|
||||
* 193 Pierre Rousseau, Canada
|
||||
195 Pete Hinch
|
||||
* 198 KoalaBear,USA. TRUMPED 2016!
|
||||
* 200 Pimoroni, UK
|
||||
201 jpwsutton, UK
|
||||
203 Felix, Sweden
|
||||
204 Dmitri Don, Tallinn Estonia
|
||||
205 PeteDemiSwede, UK
|
||||
* 207 Serge GUILLAUME
|
||||
208 Gurtubay, ES
|
||||
209 Geir-Olav, NO
|
||||
210 RayDeo, Germany
|
||||
215 DIYAbility
|
||||
216 Josef Dunbar, USA
|
||||
* 217 Enrico, BE/IT
|
||||
219 Damian Moore, UK
|
||||
220 Wayne and Layne, LLC
|
||||
221 The Old Crow, USA
|
||||
224 Hackscribble, UK
|
||||
* 225 Alex March, UK
|
||||
226 @rdslw
|
||||
227 Mike, Canada
|
||||
* 228 Adrian Smith
|
||||
229 Dinu Gherman, Germany
|
||||
230 Tinamous.com
|
||||
* 231 Nikesh, US
|
||||
* 232 chrisallick.com
|
||||
234 Daniel Von Fange
|
||||
* 235 Michal Muhlpachr, CZ
|
||||
* 236 Petr Viktorin
|
||||
237 Ryan Aldredge
|
||||
238 Patrik Wallström, SE
|
||||
* 239 MobiusNexus
|
||||
240 Stray, US
|
||||
* 241 BOFG, no
|
||||
244 Issac Kelly
|
||||
* 247 David Prime
|
||||
249 James Marsh, UK
|
||||
* 250 BezouwenR
|
||||
252 Avinash Magdum, India
|
||||
253 Greg Abbas, Menlo Park CA
|
||||
254 Jorge, ES
|
||||
256 JohanP, swe
|
||||
* 258 Ben Doan
|
||||
259 Jan van Haarst, NL
|
||||
* 263 JoshT, Los Angeles
|
||||
264 cstuder, Switzerland
|
||||
266 Jon Armani
|
||||
* 270 Liam Welsh
|
||||
271 Jason Peacock
|
||||
272 Alejandro Lopez
|
||||
275 Dan O'Donovan, UK
|
||||
276 N1TWC
|
||||
277 Roland Tanglao, Vancouver
|
||||
278 Twpsyn
|
||||
280 Robert, ME-US
|
||||
* 282 Thomas, UK
|
||||
283 Jeff Schroeder, USA
|
||||
284 Paulus Schoutsen
|
||||
* 287 Neon22, NZ
|
||||
290 kbmeister
|
||||
291 Gary Hahn
|
||||
292 Dave Matsumoto, USA
|
||||
296 Sam Lee, SG
|
||||
304 Poul Borg, Denmark
|
||||
307 MightyPork
|
||||
308 Dale
|
||||
* 312 Anton Kraft, Germany
|
||||
315 Kism3t, UK
|
||||
317 NateM
|
||||
* 318 N&T, Calvijn Meerpaal, NL
|
||||
322 Andreas Monitzer
|
||||
323 Rikard, SE
|
||||
328 Olaf, DE
|
||||
* 329 John Boudreaux
|
||||
330 DOCE, Germany
|
||||
331 feilipu
|
||||
332 Stefan Schwetschke
|
||||
333 Wayneji, NZ
|
||||
337 Alain de Lamirande, Canada
|
||||
338 Hori, TW
|
||||
340 Azmodie, UK
|
||||
341 Lygon, UK
|
||||
* 342 JRM in STL, USA
|
||||
344 R Colistete-Jr., BR
|
||||
* 345 ChristianG, DE
|
||||
347 Nis Sarup, DK.
|
||||
350 Nickedynick
|
||||
351 Dazza, Oz
|
||||
352 lispmeister, NL
|
||||
355 Tomas Lubkowitz, SE
|
||||
357 Mark, UK
|
||||
* 358 Team ME
|
||||
363 Papahabla
|
||||
364 Greg Chevalley
|
||||
365 Maic Striepe, Germany
|
||||
369 Ian McMahon
|
||||
371 A. DARGA, Fr
|
||||
372 Ernesto Maranesi, BR
|
||||
373 Steve Lyon
|
||||
374 James Cloos
|
||||
375 Bas Zeppenfeldt, The Netherlands
|
||||
378 Pycom Ltd
|
||||
380 Wade Christensen, USA
|
||||
382 Justin Wing Chung Hui, UK
|
||||
383 C Paulson
|
||||
384 Ian Tickle
|
||||
386 Danny, Seattle
|
||||
388 Erik Moe, Chicago, IL
|
||||
* 389 Eric B. Wertz, USA
|
||||
390 Michael. CH
|
||||
391 Christopher Baughman
|
||||
392 James Churchill
|
||||
393 Rob, DC
|
||||
395 Whee Min, Singapore
|
||||
* 396 Jason Doege, TX
|
||||
401 MrFish
|
||||
403 Thejesh GN
|
||||
404 Markus, Sweden
|
||||
405 AMR, Spain
|
||||
407 Svet, ES
|
||||
* 408 Thoralt, Germany
|
||||
409 Emil, Sweden
|
||||
410 David Moloney, ireland
|
||||
411 Marco S, DE
|
||||
415 Peter W., Austria
|
||||
417 emendo A/S
|
||||
* 419 Kalestis, Switzerland
|
||||
421 Ondra, CZ
|
||||
422 Elheffe
|
||||
423 thinkl33t, UK
|
||||
424 TonyF
|
||||
425 Herr Robert Linder, PA, USA
|
||||
* 426 Anders Astrom S(E|G)
|
||||
* 428 Jussi Ylanen, CT, USA
|
||||
431 Neil H., USA
|
||||
434 Rod Perez, MX
|
||||
435 Carol, US
|
||||
436 Gina Haeussge, DE
|
||||
438 Weilinger, GER
|
||||
* 439 Ron Ward, Australia
|
||||
441 Rex, UT, USA
|
||||
* 444 Slush, CZ
|
||||
445 Bruce, Florida
|
||||
* 448 Patrick Di Justo
|
||||
449 ScubaBearLA
|
||||
450 Mike Causer, Sydney AU
|
||||
451 Joel Fries, USA
|
||||
* 452 Andrew Bernstein, US
|
||||
454 EAS, Seattle, WA, USA
|
||||
* 456 Christopher J. Morrone, USA
|
||||
* 457 Anthony Gilley, Sweden
|
||||
458 Andre Breiler, DE
|
||||
* 460 Fuffkin, UK
|
||||
* 461 adent, CZ
|
||||
462 Samuel Pickard
|
||||
463 Mirko, Germany
|
||||
* 464 Ramin/US
|
||||
465 Mike, Grenoble
|
||||
466 Rolf, DE
|
||||
* 467 Dave Haynes
|
||||
* 469 Mac Ha, Vietnam
|
||||
* 470 Enno, DE
|
||||
* 473 Smudo, DE
|
||||
* 474 Duncan, Scotland
|
||||
475 Chris, UK
|
||||
476 Peter Groen, NL
|
||||
478 Gertjan Geerling, Nijmegen
|
||||
* 479 Benjamin Eberle
|
||||
* 480 Mechanical Men Sweden
|
||||
* 482 Rémi de Chazelles, FR
|
||||
483 mager, Bremen
|
||||
484 jurekh, NL
|
||||
* 485 Craig Burkhead
|
||||
487 JohanHartman, SouthAfrica
|
||||
* 489 Viktor, NL
|
||||
491 Jean-Denis Carre
|
||||
492 Jesse, Canada
|
||||
493 Alex C. MacDonald, USA
|
||||
* 494 GustavoV, MX
|
||||
495 Sebastian, Berlin
|
||||
497 Bernard, Feluy
|
||||
* 500 Ron H, USA
|
||||
501 Gregg "Cabe" Bond, UK
|
||||
502 Colin, NI
|
||||
504 Robin, USA
|
||||
* 507 pkropf
|
||||
* 510 6LhasaCo Canada
|
||||
511 Tom Sepe, USA
|
||||
513 Andrew McKenna
|
||||
515 tom46037
|
||||
516 G2, USA
|
||||
* 517 Pauline Middelink, NL
|
||||
* 518 Brush Technology, Ltd
|
||||
520 Pierre Meyitang, USA
|
||||
521 Stephanie Maks, Canada
|
||||
526 John McClain
|
||||
* 527 Sigadore, US
|
||||
528 Richard Hudspeth, US
|
||||
530 Martin, Austria
|
||||
531 Stephen Eaton, Australia
|
||||
* 533 RJCE, UK
|
||||
535 Teiste, Finland
|
||||
536 Pio, UK
|
||||
537 DirtyHarry, DE
|
||||
* 540 Dom G. UK
|
||||
* 541 Nial, UK
|
||||
543 Andreas, AUT
|
||||
545 WisdomWolf
|
||||
* 549 MrMx,ES
|
||||
552 Daniel Soto, Landscape.
|
||||
554 Claus Fischer, DK
|
||||
557 Aleksi Määttä
|
||||
560 Justin Wilcott, USA
|
||||
562 LoneTone, UK
|
||||
567 Cameron, US
|
||||
568 Dirck, Germany
|
||||
569 Michael Keirnan
|
||||
571 Harry, CN
|
||||
* 572 Ward Wouts
|
||||
573 Dan Anaya, USA
|
||||
574 Ben Bennett
|
||||
575 nirvana2165, US
|
||||
576 PDG, BZH
|
||||
* 581 Visit, Thailand
|
||||
582 John Carr, UK
|
||||
* 583 Klankschap
|
||||
587 jacky,FR
|
||||
588 JD Marsters
|
||||
591 Ryan Jarvis, US
|
||||
595 Claudio Hediger, CH
|
||||
* 597 Bambam, Sweden
|
||||
598 Timothé, FR
|
||||
* 599 Luís Manuel, Portugal
|
||||
601 Eric, DE
|
||||
602 Olaf, Cambridge, UK
|
||||
* 603 Tim, Dubai
|
||||
604 Tyndell, US
|
||||
606 Ciellt AB, SE
|
||||
607 Ömer Boratav
|
||||
609 Guy Molinari, US
|
||||
614 Freek Dijkstra
|
||||
615 Carlos Camargo CO
|
||||
616 Michael Nemecky, Norway
|
||||
618 Ovidiu G.
|
||||
619 arobg, USA
|
||||
* 621 Geoff Shilling, US
|
||||
623 EliotB, NZ
|
||||
624 slos UK
|
||||
625 Montreal, CA
|
||||
* 626 Peter Korcz
|
||||
627 Kodi
|
||||
628 Jim, Valdosta, USA
|
||||
629 Sander Boele, NL
|
||||
630 Max Lupo
|
||||
631 Daniel.B, Newcastle Australia
|
||||
632 Andrés Suárez García, Vigo (Spain)
|
||||
633 Rens, NL
|
||||
634 Max Petrich, DE
|
||||
635 Fabian Affolter, CH
|
||||
636 Cadair
|
||||
* 637 Mike Karliner
|
||||
638 Daniel T, UK
|
||||
639 Mark Campbell, UK
|
||||
640 James S, Australia
|
||||
641 PBTX!
|
||||
* 642 amaza,SP
|
||||
644 se4mus
|
||||
* 645 Alexander Steffen
|
||||
* 647 Jim Richards Maine, USA
|
||||
649 Doug D, US
|
||||
650 Keaton Walker
|
||||
* 651 Scott Winder, USA
|
||||
653 Jeff Fischer, USA
|
||||
654 Andrej Mosat
|
||||
655 Mohd Faizal Mansor, Malaysia
|
||||
657 Mike "Cutter" Shievitz, US
|
||||
* 658 Daniel Andersson, SE
|
||||
659 Alexander, NL
|
||||
660 François, CH
|
||||
* 661 AndrewS, UK
|
||||
662 Denisae, PT
|
||||
663 KC8KZN
|
||||
664 Angelo, Wales
|
||||
665 BlueberryE, Germany
|
||||
667 fvlmurat
|
||||
668 Adam Wilson
|
||||
675 Ulrich Norbisrath (http://ulno.net)
|
||||
676 Daniel, Portland OR
|
||||
* 677 Andreas Lindquist, SE
|
||||
680 Jason, NL
|
||||
682 lapawa, GER
|
||||
683 John Batty, UK
|
||||
685 Addy, Netherlands
|
||||
686 Marc, CA
|
||||
690 APapantonatos
|
||||
691 gmorell, US
|
||||
* 692 Jamie Mackenzie, Adelaide, SA
|
||||
* 693 Dave Dean, US
|
||||
697 woojay, US
|
||||
698 Webabot, NY
|
||||
* 699 Jason Fehr, Canada
|
||||
700 Hadi (AU)
|
||||
* 701 Abraham Arce
|
||||
* 703 Must Be Art
|
||||
712 Thanks for the great work!/datax-holding/Stuttgart
|
||||
* 714 Thomas Pr., BE
|
||||
715 Black Country Atelier BCA
|
||||
718 Don W, Arlington VA
|
||||
721 Xavier C. (EU)
|
||||
722 Chad P. Lung, U.S.A
|
||||
726 Alexander Lash (@lexlash)
|
||||
727 Sven, MX
|
||||
728 Terence, PL
|
||||
* 730 Mauro De Giorgi, USA
|
||||
735 Jay Ward, Canada
|
||||
736 Fabian Topfstedt, AT
|
||||
739 sjoerdDOTcom
|
||||
740 David, Australia
|
||||
743 Michael Niewiera, Germany
|
||||
745 cbenhagen
|
||||
746 berserck, CH
|
||||
748 Lars Hansson, Sweden
|
||||
750 Landrash
|
||||
751 Richard B., CT USA
|
||||
752 Neil Chandler, UK
|
||||
* 753 John Griessen US
|
||||
* 755 Caminiti, Mexico
|
||||
757 Mikael Trieb, Sweden
|
||||
760 S1GM9, MX
|
||||
761 Dave C, US
|
||||
* 763 Su Zhou, China
|
||||
765 Caitlyn - USA
|
||||
769 Will, NZ
|
||||
770 CJB,UK
|
||||
771 Victor Claessen, NL
|
||||
772 Antal, CH
|
||||
773 Tokyo, Japan
|
||||
* 774 Join Business & Technology AB, Sweden
|
||||
777 Overspeed Innovation
|
||||
* 778 Bruce, Chanute KS
|
||||
779 TOPALIS, RO
|
||||
780 klaas2
|
||||
781 Matthias Schmitz, Berlin
|
||||
783 Jan Studený wishes "Python everywhere"
|
||||
788 Ian, USA
|
||||
789 Mark K, UK
|
||||
791 DerFlob, Germany
|
||||
792 Staffan Johansson, Sweden
|
||||
793 Stefan W., DE
|
||||
795 Mark S. Harris, Small Dog Electronics
|
||||
796 Kittikun, TH
|
||||
* 798 aerialist, Japan
|
||||
799 Sweta
|
||||
* 800 Mark Shuttleworth
|
||||
802 Kim Thostrup
|
||||
803 Andy Fundinger
|
||||
810 Matt Vallevand, Detroit MI
|
||||
813 Jim McDonald
|
||||
816 Rob Dobson
|
||||
817 Rafał Zieliński, PL
|
||||
* 818 Shaun Walker, AUS
|
||||
819 Timothy R, Belgium
|
||||
820 clem
|
||||
825 JuanB, ES
|
||||
826 Randall Gaz, Colorado USA
|
||||
827 Dick van Ginkel, The Netherlands
|
||||
829 Jan-Pieter Van Impe
|
||||
831 David Kirkpatrick, AU
|
||||
832 Ravi Teja, India
|
||||
833 AkosLukacs, HU
|
||||
834 Dave Desson, CAN
|
||||
837 LWQ.CZ, CZ
|
||||
838 Robert W., Issaquah, WA
|
||||
839 Daniel Hrynczenko
|
||||
840 Martin Filtenborg, DK
|
||||
841 InnHuchen, Ger
|
||||
845 Raju Pillai,India
|
||||
847 cfus/DE
|
||||
* 851 Juli H.
|
||||
853 David Monterroso Cabello , SP
|
||||
857 24x8, LLC, US
|
||||
860 Sebastian, DE
|
||||
861 pajusmar
|
||||
864 Ronnie, UK
|
||||
* 867 Travis Travelstead, USA
|
||||
* 870 Woodat, US/UK
|
||||
872 Gary Bake, UK
|
||||
873 Ernesto Martinez
|
||||
* 874 Scottt, USA
|
||||
876 Ronnie Kizzle, LA
|
||||
880 Harish, Singapore
|
||||
882 Wacht, Pittsburgh
|
||||
883 PatrickF, US
|
||||
886 Paolo, IT
|
||||
888 Defragster
|
||||
889 Rachel Rayns, UK
|
||||
* 890 Peak Data LLC
|
||||
891 Mindwarp, AU
|
||||
892 Vincent Smedley, UK
|
||||
* 894 Bailey & Brayden
|
||||
898 Jacek Artymiak, UK
|
||||
900 John Hudson, USA
|
||||
* 901 ReneS, NL
|
||||
* 902 B Stevens
|
||||
903 Cptnslick, US
|
||||
904 janlj@me.com
|
||||
905 São Caetano do Sul, SP, Brazil
|
||||
906 Lenz Hirsch
|
||||
907 SerSher, RU
|
||||
908 Florian, DE
|
||||
909 Mathias Svendsen, DK
|
||||
* 910 Jeremiah Dey-Oh
|
||||
911 Allan Joseph Medwick
|
||||
913 Matt, Australia
|
||||
914 Christian Pedersen
|
||||
* 915 SPIN
|
||||
916 Denis M., Russia
|
||||
917 Ahmed Alboori, Saudi Arabia
|
||||
918 Luciano, Italy
|
||||
919 Ragdehl
|
||||
* 921 Artur, HU
|
||||
922 Greg, NC - USA
|
||||
924 Gurzixo
|
||||
* 927 Gregg, Oregon
|
||||
928 cwschroeder, BY
|
||||
929 W. Bush - NY, USA.
|
||||
932 ddparker
|
||||
933 Enkion
|
||||
* 934 Eric G. Barron
|
||||
936 thomasDOTwtf
|
||||
940 mifous, cucurbitae.eu
|
||||
942 VFL68, FR
|
||||
943 Casey, Hong Kong
|
||||
* 945 Kean Electronics
|
||||
946 Nima, UK
|
||||
947 Klosinski, USA
|
||||
948 PieWiE, NL
|
||||
* 949 Rui Carmo, PT
|
||||
* 950 basbrun.com
|
||||
951 Aashu, UK
|
||||
* 952 vk2nq - Brian
|
||||
954 gojimmypi
|
||||
955 Jack, USA
|
||||
* 957 @SteveBattle
|
||||
* 958 Beshr, Sweden
|
||||
962 PeterR, UK
|
||||
964 Russell Calbert
|
||||
965 LAurent_B, Fr
|
||||
967 Qazi, USA
|
||||
971 Jonas, FR
|
||||
973 PK Shiu
|
||||
* 974 sea_kev
|
||||
976 Radhika, USA
|
||||
977 Chris Gibson, US
|
||||
* 978 Mike, AU
|
||||
* 979 Geeky Pete
|
||||
981 Timmy the wonderdog
|
||||
983 An Ostler it IT
|
||||
984 Frank Ray Robles
|
||||
985 Kurtsik
|
||||
987 Johan, SE
|
||||
988 NJBerland, Norway
|
||||
992 Leon Noel - @leonnoel
|
||||
994 Kjell, SE
|
||||
995 boriskourt
|
||||
997 Bartek B., CANADA
|
||||
999 Thomas Wiradikusuma, Indonesia
|
||||
1000 Trey, NOLA
|
||||
1002 Jori, FI
|
||||
1005 nmmarkin
|
||||
1006 Mattias Fornander
|
||||
1007 Panayot Daskalov, Bulgaria
|
||||
*1009 AndyP, UK
|
||||
1011 TSD
|
||||
1013 Chris, Berlin
|
||||
1017 Gareth Edwards, UK
|
||||
1018 Trixam,DE
|
||||
1019 César from Makespace Madrid, Spain
|
||||
1020 Prajwal, Australia
|
||||
*1024 Fred Dart - FTDI
|
||||
1025 bsx
|
||||
*1026 Regis, FR
|
||||
1027 Adrian Hill
|
||||
1029 Alice, UK
|
||||
1030 Erkan Shakir, BG
|
||||
1031 Alexander, EE
|
||||
1033 Patric, Luxembourg
|
||||
1034 For my beloved mother, Colleen Clancy.
|
||||
1035 NigelB
|
||||
1037 François, Aus/Fr
|
||||
*1039 Thanura Siribaddana, Australia
|
||||
1041 Harald, USA
|
||||
1042 Jeremy Utting, NZ
|
||||
1043 bejuryu, KR
|
||||
*1044 Daniel Wood, UK
|
||||
1046 C. J. Blocker
|
||||
*1047 Rodrigo Benenson, Germany
|
||||
1048 Håvard Gulldahl
|
||||
1049 SeB, Belgium
|
||||
1054 Ryan Miller, Austin TX
|
||||
1055 Gianluca Cancelmi
|
||||
1057 Francesco, IT
|
||||
1058 RockTractor!
|
||||
1060 Bill G., Atlanta GA USA
|
||||
1061 joenotjoe
|
||||
1064 ATrivedi, USA
|
||||
1067 Jim Chandler, UK
|
||||
1068 Aria Sabeti
|
||||
1069 Noah Rosamilia, USA
|
||||
1070 GAKgDavid, CA
|
||||
1072 Markus, Austria
|
||||
*1073 Tarwin, MUC
|
||||
*1077 Balazs Kinszler, HU
|
||||
*1080 pfh
|
||||
*1082 Ovidiu Hossu, SG
|
||||
*1083 mmhanif, NJ
|
||||
*1084 Wincent Balin, DE
|
||||
*1086 Anatoly Verkhovsky
|
||||
*1087 Greg, Plano
|
||||
*1089 Angelo Compagnucci
|
||||
1090 Ryan Shaw (ryannathans), AU
|
||||
1092 Dries007, BE
|
||||
*1093 Dave Snowdon, UK
|
||||
*1094 halfpress
|
||||
*1096 DeuxVis, FR
|
||||
*1097 Your Creative Solutions
|
||||
1099 Emanuele Goldoni, IT
|
||||
*1100 Tendayi Mawushe
|
||||
1101 Rob, Tikitere
|
||||
*1102 SolidStateSoul
|
||||
*1103 Michael, GER
|
||||
*1106 Paul, San Francisco
|
||||
*1107 Oddvar Lovaas
|
||||
*1108 Doc Savage, Man of Bronze
|
||||
1109 Stijn Debrouwere
|
||||
1111 Ark Nieckarz, USA
|
||||
*1112 ECS87.com, USA
|
||||
*1114 Gary P. Wolfe, USA
|
||||
1117 Tom Hodson
|
||||
*1118 @arikb (twitter)
|
||||
1123 Piotr Gryko UK
|
||||
*1125 Cantalaweb, Spain
|
||||
1126 Edward of Clovis
|
||||
1127 Jim G
|
||||
*1128 billbr, Loveland, CO, USA
|
||||
1129 dalanmiller
|
||||
*1130 StephenH, UK
|
||||
*1132 Thomas Sarlandie - @sarfata
|
||||
1133 Doug Rohm, US
|
||||
*1134 Eric Floehr, Ohio, USA
|
||||
*1135 Sven Haiges
|
||||
1136 relix42
|
||||
*1137 Ralf Nyren
|
||||
*1138 nickgb
|
||||
1139 zwack, DE
|
||||
1140 Michal B., PL
|
||||
1141 Matt, Australia
|
||||
1143 slv, Mi2
|
||||
1144 Pawel, CH
|
||||
*1145 James Saffery
|
||||
*1147 nekomatic
|
||||
*1149 @nt1, Earth
|
||||
*1150 Alister Galpin, NZ
|
||||
1151 Jayemel, UK
|
||||
1152 Koalabs
|
||||
1153 James Myatt, UK
|
||||
*1154 DanS, Norway
|
||||
1155 Sandeep, US
|
||||
*1156 Anil Kavipurapu
|
||||
*1158 Frederik Werner, DE
|
||||
1160 Erik J, Canada
|
||||
1164 bluezebra, Ireland
|
||||
1168 Birk, DE
|
||||
1169 Gabi, FR
|
||||
*1173 mliberty, USA
|
||||
1174 Jamie Smith, Scotland
|
||||
1175 Sebastian, Germany
|
||||
*1176 John Cooper, UK
|
||||
1177 Moritz, DE
|
||||
1178 Kevin, DE
|
||||
*1179 Ming Leung, Canada
|
||||
1180 Laird Popkin
|
||||
1181 tasmaniac, GA
|
||||
*1183 RichardW, UK
|
||||
*1187 Thomas Quinlan, London, UK
|
||||
1188 LGnap, BE
|
||||
*1189 bloater, Edinburgh UK
|
||||
1192 pakt, SE
|
||||
1194 Sandsmark, NO
|
||||
*1195 Gert Menke
|
||||
1197 Emsi88, SK
|
||||
1199 GTtronics HK Ltd.
|
||||
1200 Jo, Bergen
|
||||
*1202 MarkS, Australia
|
||||
1203 Igor, HR
|
||||
1204 Lord Nightmare
|
||||
1205 Great Uncle Bulgaria, UK
|
||||
*1206 salomonderossi
|
||||
1208 Master_Ipse, DE
|
||||
1209 Luis G.F, ES
|
||||
1211 Harald, FO
|
||||
*1212 Kimmo, Finland
|
||||
*1213 P. Perreijn, Netherlands
|
||||
1214 jcea, Spain
|
||||
1215 simon holmes à court
|
||||
1217 Bill M, Newcastle
|
||||
*1218 snowball
|
||||
*1221 Georges, CDN
|
||||
1222 JPLa
|
||||
1225 Erik Gullberg, Sweden
|
||||
1226 Matthias Fuchs, IN, Germany
|
||||
1229 Majed, CA
|
||||
1230 Michiel, Reeuwijk
|
||||
1231 Clive, Essex UK
|
||||
1232 Jan Kalina, CZ
|
||||
1234 MBBest, Australia
|
||||
*1235 Reinoud de Lange, NL
|
||||
1237 Jeffrey Park, South Korea
|
||||
1238 David Olson
|
||||
1239 Nathan Battan
|
||||
1240 Marcus, TW
|
||||
1241 randyrrt, USA
|
||||
1242 Holger, Germany
|
||||
1243 Dmitri Chapkine, FRANCE
|
||||
1244 Ceyhun Kapucu, TR
|
||||
1245 Hong Kong
|
||||
*1246 gPozo, US
|
||||
1247 Peter M, Sweden
|
||||
*1249 Duncan, Cambridge
|
||||
*1251 Schaeferling, DE
|
||||
1252 Christian Prior, DE
|
||||
*1256 ovig
|
||||
1257 Kerry Channing, UK
|
||||
1258 Exception42, GER
|
||||
*1259 nchalikias
|
||||
1261 Kittie, US
|
||||
1263 Alex, Norway
|
||||
1264 wats0n, TW
|
||||
*1265 Henner
|
||||
*1266 Mike M, AZ, USA
|
||||
1268 Bobby Ly, USA
|
||||
*1269 Espen STO, Norway
|
||||
1270 arduware.cc
|
||||
1274 Christopher Flynn, NH USA
|
||||
*1275 Bruce Boyes, USA
|
||||
1276 DCH
|
||||
1278 McGinkel, Netherlands
|
||||
1279 Dieter, Wien
|
||||
1280 R. Tummers, NL
|
||||
1283 Pranav Maddula, USA
|
||||
1286 Dusan, SLovakia
|
||||
1290 Stephen Youndt
|
||||
*1291 Lertsenem, FR
|
||||
1292 NuclearTide, London
|
||||
1293 Ben Gift, USA
|
||||
1294 rmg
|
||||
1295 jmaybe, USA
|
||||
1296 Allan G, Georgia
|
||||
1297 Duncan Brassington, UK
|
||||
1300 Hans, NL
|
||||
1301 Valerio "valdez" Paolini, IT
|
||||
1303 Neotreat, DE
|
||||
1306 tomtoump
|
||||
1307 Edward B Cox, England
|
||||
1310 Oliver Steele
|
||||
1311 merps, AUS
|
||||
1313 n8henrie, USA
|
||||
*1314 YGA-KSD n7/ULB, FR-BE
|
||||
1317 Adrian, Romania
|
||||
*1318 Luca "Loop", ITA
|
||||
*1319 Michael Twomey, Ireland
|
||||
1321 Trey Aughenbaugh
|
||||
1322 Marcel Hecko, SK
|
||||
1323 Hugo Neira, CL
|
||||
1326 JH, US
|
||||
*1330 Luthander, SE
|
||||
1331 Rickard Dahlstrand, Sweden
|
||||
1333 Olivier M., France
|
||||
1334 DWVL, UK
|
||||
1335 MRZANE, Sweden
|
||||
1336 Benedikt, DE
|
||||
*1338 Tiegeng, US
|
||||
*1339 arthoo Eindhoven Nederland
|
||||
1340 Magnus Gustavsson, Sweden
|
||||
1341 Jan Bednařík
|
||||
1344 Mike McGary: US
|
||||
1346 mp3tobi
|
||||
*1350 Cyberhippy
|
||||
1351 Sandro, PT
|
||||
1355 Kwabena W. Agyeman
|
||||
1357 Ryan Young
|
||||
*1358 Chiang Mai, Thailand
|
||||
1359 AKLitman, USA
|
||||
1360 JASK Enterprises, Ltd-John
|
||||
*1361 Tom Gidden, UK
|
||||
1362 AdamT, USA
|
||||
1363 Jose de la Campa, BOL
|
||||
1365 Steve Laguna, U.S.A
|
||||
*1368 Walrusklasse, NL
|
||||
1370 Timofei Korostelev, Belarus
|
||||
1374 Janos,HU
|
||||
*1375 Paul Cunnane
|
||||
1377 IanE, UK
|
||||
1378 Hans, NL
|
||||
1379 Jose Angel Jimenez Vadillo, Spain
|
||||
*1380 PaulT, Lancs
|
||||
1383 Lutz; DE
|
||||
1385 AnRkey
|
||||
1387 Fredrik, FIN
|
||||
1388 Matt W (funkyHat)
|
||||
1389 Zeev Rotshtein, Israel
|
||||
1391 joostd, NL
|
||||
1392 Lukasz Blaszczyk, USA
|
||||
*1397 Wei-Ning Huang, TW
|
||||
1398 myu
|
||||
*1399 Thorsten, Germany
|
||||
1401 sm0ihr
|
||||
1403 Xiaotian, Seattle US
|
||||
*1406 -gt-, Czech Republic
|
||||
1407 Mike Y. Diallo, US
|
||||
1409 ubii, US
|
||||
|
||||
30
README.md
30
README.md
@@ -16,16 +16,18 @@ The MicroPython project
|
||||
|
||||
This is the MicroPython project, which aims to put an implementation
|
||||
of Python 3.x on microcontrollers and small embedded systems.
|
||||
You can find the official website at [micropython.org](http://www.micropython.org).
|
||||
|
||||
WARNING: this project is in beta stage and is subject to changes of the
|
||||
code-base, including project-wide name changes and API changes.
|
||||
|
||||
MicroPython implements the entire Python 3.4 syntax (including exceptions,
|
||||
"with", "yield from", etc.). The following core datatypes are provided:
|
||||
str (including basic Unicode support), bytes, bytearray, tuple, list, dict,
|
||||
set, frozenset, array.array, collections.namedtuple, classes and instances.
|
||||
Builtin modules include sys, time, and struct. Note that only subset of
|
||||
Python 3.4 functionality implemented for the data types and modules.
|
||||
"with", "yield from", etc., and additionally "async" keyword from Python 3.5).
|
||||
The following core datatypes are provided: str (including basic Unicode
|
||||
support), bytes, bytearray, tuple, list, dict, set, frozenset, array.array,
|
||||
collections.namedtuple, classes and instances. Builtin modules include sys,
|
||||
time, and struct. Note that only subset of Python 3.4 functionality
|
||||
implemented for the data types and modules.
|
||||
|
||||
See the repository www.github.com/micropython/pyboard for the Micro
|
||||
Python board, the officially supported reference electronic circuit board.
|
||||
@@ -38,6 +40,8 @@ Major components in this repository:
|
||||
with an STM32F405RG (using ST's Cube HAL drivers).
|
||||
- minimal/ -- a minimal MicroPython port. Start with this if you want
|
||||
to port MicroPython to another microcontroller.
|
||||
- tests/ -- test framework and test scripts.
|
||||
- docs/ -- user documentation in Sphinx reStructuredText format.
|
||||
|
||||
Additional components:
|
||||
- bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used
|
||||
@@ -47,10 +51,8 @@ Additional components:
|
||||
- pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
|
||||
- cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
|
||||
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
|
||||
- tests/ -- test framework and test scripts.
|
||||
- tools/ -- various tools, including the pyboard.py module.
|
||||
- examples/ -- a few example Python scripts.
|
||||
- docs/ -- official documentation in RST format.
|
||||
|
||||
"make" is used to build the components, or "gmake" on BSD-based systems.
|
||||
You will also need bash and Python (at least 2.7 or 3.3).
|
||||
@@ -64,7 +66,7 @@ as ARM and MIPS. Making full-featured port to another architecture requires
|
||||
writing some assembly code for the exception handling and garbage collection.
|
||||
Alternatively, fallback implementation based on setjmp/longjmp can be used.
|
||||
|
||||
To build (*):
|
||||
To build (see section below for required dependencies):
|
||||
|
||||
$ cd unix
|
||||
$ make
|
||||
@@ -129,7 +131,7 @@ The STM version
|
||||
|
||||
The "stmhal" port requires an ARM compiler, arm-none-eabi-gcc, and associated
|
||||
bin-utils. For those using Arch Linux, you need arm-none-eabi-binutils and
|
||||
arm-none-eabi-gcc packages from the AUR. Otherwise, try here:
|
||||
arm-none-eabi-gcc packages. Otherwise, try here:
|
||||
https://launchpad.net/gcc-arm-embedded
|
||||
|
||||
To build:
|
||||
@@ -145,9 +147,7 @@ Then to flash the code via USB DFU to your device:
|
||||
|
||||
$ make deploy
|
||||
|
||||
You will need the dfu-util program, on Arch Linux it's dfu-util-git in the
|
||||
AUR. If the above does not work it may be because you don't have the
|
||||
correct permissions. Try then:
|
||||
|
||||
$ sudo dfu-util -a 0 -d 0483:df11 -D build-PYBV10/firmware.dfu
|
||||
|
||||
This will use the included `tools/pydfu.py` script. If flashing the firmware
|
||||
does not work it may be because you don't have the correct permissions, and
|
||||
need to use `sudo make deploy`.
|
||||
See the README.md file in the stmhal/ directory for further details.
|
||||
|
||||
@@ -34,9 +34,6 @@ int main(int argc, char **argv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gc_collect(void) {
|
||||
}
|
||||
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define MICROPY_ENABLE_DOC_STRING (0)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
|
||||
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
|
||||
#define MICROPY_PY_ASYNC_AWAIT (0)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#define MICROPY_PY_BUILTINS_ENUMERATE (0)
|
||||
|
||||
@@ -17,7 +17,7 @@ include ../py/mkenv.mk
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
|
||||
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
|
||||
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
|
||||
CFLAGS += -Iboards/$(BOARD)
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
__stack_size__ = 3K; /* interrupts are handled within this stack */
|
||||
__stack_size__ = 2K; /* interrupts are handled within this stack */
|
||||
__min_heap_size__ = 8K;
|
||||
|
||||
MEMORY
|
||||
|
||||
@@ -152,12 +152,13 @@ APP_LIB_SRC_C = $(addprefix lib/,\
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
)
|
||||
|
||||
APP_STM_SRC_C = $(addprefix stmhal/,\
|
||||
bufhelper.c \
|
||||
file.c \
|
||||
builtin_open.c \
|
||||
import.c \
|
||||
input.c \
|
||||
irq.c \
|
||||
@@ -171,6 +172,12 @@ OBJ += $(addprefix $(BUILD)/, $(APP_MODS_SRC_C:.c=.o) $(APP_CC3100_SRC_C:.c=.o)
|
||||
OBJ += $(addprefix $(BUILD)/, $(APP_MAIN_SRC_C:.c=.o) $(APP_LIB_SRC_C:.c=.o) $(APP_STM_SRC_C:.c=.o))
|
||||
OBJ += $(BUILD)/pins.o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(APP_MODS_SRC_C) $(APP_MISC_SRC_C) $(APP_STM_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in
|
||||
# SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
# Add the linker script
|
||||
LINKER_SCRIPT = application.lds
|
||||
LDFLAGS += -T $(LINKER_SCRIPT)
|
||||
@@ -183,31 +190,10 @@ $(BUILD)/drivers/cc3100/src/driver.o: CFLAGS += -fno-strict-aliasing
|
||||
|
||||
# Check if we would like to debug the port code
|
||||
ifeq ($(BTYPE), release)
|
||||
# Optimize everything and define the NDEBUG flag
|
||||
CFLAGS += -Os -DNDEBUG
|
||||
CFLAGS += -DNDEBUG
|
||||
else
|
||||
ifeq ($(BTYPE), debug)
|
||||
# Define the DEBUG flag
|
||||
CFLAGS += -DDEBUG=DEBUG
|
||||
# Optimize the stable sources only
|
||||
$(BUILD)/extmod/%.o: CFLAGS += -Os
|
||||
$(BUILD)/lib/%.o: CFLAGS += -Os
|
||||
$(BUILD)/fatfs/src/%.o: CFLAGS += -Os
|
||||
$(BUILD)/FreeRTOS/Source/%.o: CFLAGS += -Os
|
||||
$(BUILD)/ftp/%.o: CFLAGS += -Os
|
||||
$(BUILD)/hal/%.o: CFLAGS += -Os
|
||||
$(BUILD)/misc/%.o: CFLAGS += -Os
|
||||
$(BUILD)/mods/%.o: CFLAGS += -Os
|
||||
$(BUILD)/py/%.o: CFLAGS += -Os
|
||||
$(BUILD)/simplelink/%.o: CFLAGS += -Os
|
||||
$(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os
|
||||
$(BUILD)/stmhal/%.o: CFLAGS += -Os
|
||||
$(BUILD)/telnet/%.o: CFLAGS += -Os
|
||||
$(BUILD)/util/%.o: CFLAGS += -Os
|
||||
$(BUILD)/pins.o: CFLAGS += -Os
|
||||
$(BUILD)/main.o: CFLAGS += -Os
|
||||
$(BUILD)/mptask.o: CFLAGS += -Os
|
||||
$(BUILD)/servertask.o: CFLAGS += -Os
|
||||
CFLAGS += -DNDEBUG
|
||||
else
|
||||
$(error Invalid BTYPE specified)
|
||||
endif
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC
|
||||
1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM0,,,SD0_CLK,UART1_TX,,,,,TIM0_CC1,,,,
|
||||
2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM1,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC0,I2S0_FS,,,
|
||||
3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC1,,,,
|
||||
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC0,,,,
|
||||
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC1,,,,
|
||||
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC0,,,
|
||||
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC1,,,
|
||||
1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM,,,SD0_CLK,UART1_TX,,,,,TIM0_CC,,,,
|
||||
2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC,I2S0_FS,,,
|
||||
3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC,,,,
|
||||
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC,,,,
|
||||
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC,,,,
|
||||
6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC,,,
|
||||
7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC,,,
|
||||
8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,SPI0_CS0,SD0_CMD,,,,,,,,
|
||||
9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,,
|
||||
10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,,
|
||||
@@ -13,13 +13,13 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
|
||||
12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,,
|
||||
13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,,
|
||||
14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,,
|
||||
15,GP22,GP22,GP22,,,,,TIM2_CC0,,I2S0_FS,,,,,,,,,
|
||||
15,GP22,GP22,GP22,,,,,TIM2_CC,,I2S0_FS,,,,,,,,,
|
||||
16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,I2C0_SCL,,,,,,,
|
||||
17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC0,TIM0_PWM0,I2S0_FS,,,I2C0_SDA,,,,,,,
|
||||
17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC,TIM0_PWM,I2S0_FS,,,I2C0_SDA,,,,,,,
|
||||
18,GP28,GP28,GP28,,,,,,,,,,,,,,,,
|
||||
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM2,,,,,,,,
|
||||
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM,,,,,,,,
|
||||
20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,,
|
||||
21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM0,,,,,,,
|
||||
21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM,,,,,,,
|
||||
22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,,
|
||||
23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,,
|
||||
24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,,
|
||||
@@ -48,19 +48,19 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1
|
||||
47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,,
|
||||
48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,,
|
||||
49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,,
|
||||
50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC0,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,,
|
||||
50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,,
|
||||
51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,,
|
||||
52,RTC_XTAL_N,RTC_XTAL_N,GP32,,I2S0_CLK,,I2S0_DAT0,,UART0_RTS,,SPI0_MOSI,,,,,,,,
|
||||
53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC1,,,SPI0_MISO,,UART0_TX,,,,,,,
|
||||
53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC,,,SPI0_MISO,,UART0_TX,,,,,,,
|
||||
54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,,
|
||||
55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC1,,,,,,,,,
|
||||
55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC,,,,,,,,,
|
||||
56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,,
|
||||
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC0,,,,,,,,,ADC0_CH0
|
||||
57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC,,,,,,,,,ADC0_CH0
|
||||
58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC0_CH1
|
||||
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2
|
||||
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC1,,,,,,,,,ADC0_CH3
|
||||
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC0,,,,,,,,,
|
||||
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC,,,,,,,,,ADC0_CH3
|
||||
61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC,,,,,,,,,
|
||||
62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,I2S0_CLK,,,
|
||||
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC0,,,,
|
||||
64,GP9,GP9,GP9,,,TIM2_PWM1,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC0,,,,
|
||||
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC,,,,
|
||||
64,GP9,GP9,GP9,,,TIM2_PWM,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC,,,,
|
||||
65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,,
|
||||
|
||||
|
@@ -12,7 +12,7 @@ SUPPORTED_AFS = { 'UART': ('TX', 'RX', 'RTS', 'CTS'),
|
||||
'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'),
|
||||
#'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'),
|
||||
'I2C': ('SDA', 'SCL'),
|
||||
'TIM': ('PWM0', 'PWM1', 'CC0', 'CC1'),
|
||||
'TIM': ('PWM'),
|
||||
'SD': ('CLK', 'CMD', 'DAT0'),
|
||||
'ADC': ('CH0', 'CH1', 'CH2', 'CH3')
|
||||
}
|
||||
@@ -44,6 +44,7 @@ class AF:
|
||||
def print(self):
|
||||
print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name))
|
||||
|
||||
|
||||
class Pin:
|
||||
"""Holds the information associated with a pin."""
|
||||
def __init__(self, name, port, gpio_bit, pin_num):
|
||||
|
||||
@@ -27,21 +27,12 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/obj.h"
|
||||
#include "lib/utils/pyhelp.h"
|
||||
|
||||
STATIC const char help_text[] = "Welcome to MicroPython!\n"
|
||||
"For online help please visit http://micropython.org/help/.\n"
|
||||
"For further help on a specific object, type help(obj)\n";
|
||||
|
||||
STATIC void pyb_help_print_info_about_object(mp_obj_t name_o, mp_obj_t value) {
|
||||
printf(" ");
|
||||
mp_obj_print(name_o, PRINT_STR);
|
||||
printf(" -- ");
|
||||
mp_obj_print(value, PRINT_STR);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// print a general help message
|
||||
@@ -49,31 +40,7 @@ STATIC mp_obj_t pyb_help(uint n_args, const mp_obj_t *args) {
|
||||
}
|
||||
else {
|
||||
// try to print something sensible about the given object
|
||||
printf("object ");
|
||||
mp_obj_print(args[0], PRINT_STR);
|
||||
printf(" is of type %s\n", mp_obj_get_type_str(args[0]));
|
||||
|
||||
mp_map_t *map = NULL;
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_module)) {
|
||||
map = mp_obj_dict_get_map(mp_obj_module_get_globals(args[0]));
|
||||
} else {
|
||||
mp_obj_type_t *type;
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_type)) {
|
||||
type = args[0];
|
||||
} else {
|
||||
type = mp_obj_get_type(args[0]);
|
||||
}
|
||||
if (type->locals_dict != MP_OBJ_NULL && MP_OBJ_IS_TYPE(type->locals_dict, &mp_type_dict)) {
|
||||
map = mp_obj_dict_get_map(type->locals_dict);
|
||||
}
|
||||
}
|
||||
if (map != NULL) {
|
||||
for (uint i = 0; i < map->alloc; i++) {
|
||||
if (map->table[i].key != MP_OBJ_NULL) {
|
||||
pyb_help_print_info_about_object(map->table[i].key, map->table[i].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
pyhelp_print_obj(args[0]);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
@@ -196,6 +196,10 @@ void nlr_jump_fail(void *val) {
|
||||
|
||||
void mperror_enable_heartbeat (bool enable) {
|
||||
if (enable) {
|
||||
#ifndef BOOTLOADER
|
||||
// configure the led again
|
||||
pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA);
|
||||
#endif
|
||||
mperror_heart_beat.enabled = true;
|
||||
mperror_heart_beat.do_disable = false;
|
||||
mperror_heartbeat_switch_off();
|
||||
|
||||
@@ -153,7 +153,7 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&mod_network_nic_type_wlan },
|
||||
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_server), (mp_obj_t)&network_server_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Server), (mp_obj_t)&network_server_type },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -177,7 +177,7 @@ STATIC MP_DEFINE_CONST_DICT(network_server_locals_dict, network_server_locals_di
|
||||
|
||||
STATIC const mp_obj_type_t network_server_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_server,
|
||||
.name = MP_QSTR_Server,
|
||||
.make_new = network_server_make_new,
|
||||
.locals_dict = (mp_obj_t)&network_server_locals_dict,
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "moduos.h"
|
||||
#include "diskio.h"
|
||||
#include "sflash_diskio.h"
|
||||
#include "file.h"
|
||||
#include "extmod/vfs_fat_file.h"
|
||||
#include "random.h"
|
||||
#include "mpexception.h"
|
||||
#include "version.h"
|
||||
|
||||
@@ -106,8 +106,10 @@ void modusocket_enter_sleep (void) {
|
||||
}
|
||||
}
|
||||
|
||||
// wait for any of the sockets to become ready...
|
||||
sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
|
||||
if (maxfd > 0) {
|
||||
// wait for any of the sockets to become ready...
|
||||
sl_Select(maxfd + 1, &socketset, NULL, NULL, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void modusocket_close_all_user_sockets (void) {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "inc/hw_types.h"
|
||||
#include "inc/hw_ints.h"
|
||||
@@ -149,8 +150,8 @@ STATIC wlan_obj_t wlan_obj = {
|
||||
.ssid = MICROPY_PORT_WLAN_AP_SSID,
|
||||
.key = MICROPY_PORT_WLAN_AP_KEY,
|
||||
.mac = {0},
|
||||
.ssid_o = {0},
|
||||
.bssid = {0},
|
||||
//.ssid_o = {0},
|
||||
//.bssid = {0},
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
.servers_enabled = false,
|
||||
#endif
|
||||
@@ -210,11 +211,11 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
|
||||
{
|
||||
case SL_WLAN_CONNECT_EVENT:
|
||||
{
|
||||
slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
|
||||
//slWlanConnectAsyncResponse_t *pEventData = &pWlanEvent->EventData.STAandP2PModeWlanConnected;
|
||||
// copy the new connection data
|
||||
memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH);
|
||||
memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len);
|
||||
wlan_obj.ssid_o[pEventData->ssid_len] = '\0';
|
||||
//memcpy(wlan_obj.bssid, pEventData->bssid, SL_BSSID_LENGTH);
|
||||
//memcpy(wlan_obj.ssid_o, pEventData->ssid_name, pEventData->ssid_len);
|
||||
//wlan_obj.ssid_o[pEventData->ssid_len] = '\0';
|
||||
SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
// we must reset the servers in case that the last connection
|
||||
@@ -228,15 +229,16 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
|
||||
CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_IP_ACQUIRED);
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
servers_reset();
|
||||
servers_wlan_cycle_power();
|
||||
#endif
|
||||
break;
|
||||
case SL_WLAN_STA_CONNECTED_EVENT:
|
||||
{
|
||||
slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected;
|
||||
//slPeerInfoAsyncResponse_t *pEventData = &pWlanEvent->EventData.APModeStaConnected;
|
||||
// get the mac address and name of the connected device
|
||||
memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH);
|
||||
memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len);
|
||||
wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0';
|
||||
//memcpy(wlan_obj.bssid, pEventData->mac, SL_BSSID_LENGTH);
|
||||
//memcpy(wlan_obj.ssid_o, pEventData->go_peer_device_name, pEventData->go_peer_device_name_len);
|
||||
//wlan_obj.ssid_o[pEventData->go_peer_device_name_len] = '\0';
|
||||
SET_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
// we must reset the servers in case that the last connection
|
||||
@@ -249,6 +251,7 @@ void SimpleLinkWlanEventHandler(SlWlanEvent_t *pWlanEvent) {
|
||||
CLR_STATUS_BIT(wlan_obj.status, STATUS_BIT_CONNECTION);
|
||||
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
|
||||
servers_reset();
|
||||
servers_wlan_cycle_power();
|
||||
#endif
|
||||
break;
|
||||
case SL_WLAN_P2P_DEV_FOUND_EVENT:
|
||||
@@ -547,6 +550,12 @@ void wlan_set_current_time (uint32_t seconds_since_2000) {
|
||||
sl_DevSet(SL_DEVICE_GENERAL_CONFIGURATION, SL_DEVICE_GENERAL_CONFIGURATION_DATE_TIME, sizeof(SlDateTime_t), (_u8 *)(&sl_datetime));
|
||||
}
|
||||
|
||||
void wlan_off_on (void) {
|
||||
// no need to lock the WLAN object on every API call since the servers and the MicroPtyhon
|
||||
// task have the same priority
|
||||
wlan_reenable(wlan_obj.mode);
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// DEFINE STATIC FUNCTIONS
|
||||
//*****************************************************************************
|
||||
@@ -554,8 +563,8 @@ void wlan_set_current_time (uint32_t seconds_since_2000) {
|
||||
STATIC void wlan_clear_data (void) {
|
||||
CLR_STATUS_BIT_ALL(wlan_obj.status);
|
||||
wlan_obj.ip = 0;
|
||||
memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid));
|
||||
memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
|
||||
//memset(wlan_obj.ssid_o, 0, sizeof(wlan_obj.ssid));
|
||||
//memset(wlan_obj.bssid, 0, sizeof(wlan_obj.bssid));
|
||||
}
|
||||
|
||||
STATIC void wlan_reenable (SlWlanMode_t mode) {
|
||||
|
||||
@@ -95,6 +95,7 @@ extern void wlan_get_mac (uint8_t *macAddress);
|
||||
extern void wlan_get_ip (uint32_t *ip);
|
||||
extern bool wlan_is_connected (void);
|
||||
extern void wlan_set_current_time (uint32_t seconds_since_2000);
|
||||
extern void wlan_off_on (void);
|
||||
|
||||
extern int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family);
|
||||
extern int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno);
|
||||
|
||||
@@ -63,7 +63,7 @@ typedef struct _pyb_i2c_obj_t {
|
||||
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
|
||||
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
|
||||
|
||||
#define PYBI2C_TRANSC_TIMEOUT_MS (10)
|
||||
#define PYBI2C_TRANSC_TIMEOUT_MS (20)
|
||||
#define PYBI2C_TRANSAC_WAIT_DELAY_US (10)
|
||||
|
||||
#define PYBI2C_TIMEOUT_TO_COUNT(to_us, baud) (((baud) * to_us) / 16000000)
|
||||
@@ -78,9 +78,13 @@ typedef struct _pyb_i2c_obj_t {
|
||||
DECLARE PRIVATE DATA
|
||||
******************************************************************************/
|
||||
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
|
||||
|
||||
STATIC const mp_obj_t pyb_i2c_def_pin[2] = {&pin_GP13, &pin_GP23};
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
STATIC bool pyb_i2c_write(byte addr, byte *data, uint len, bool stop);
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
@@ -107,13 +111,13 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
|
||||
// Wait until the current byte has been transferred.
|
||||
// Poll on the raw interrupt status.
|
||||
while ((MAP_I2CMasterIntStatusEx(I2CA0_BASE, false) & (I2C_MASTER_INT_DATA | I2C_MASTER_INT_TIMEOUT)) == 0) {
|
||||
// wait for a few microseconds
|
||||
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
|
||||
timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
|
||||
if (timeout < 0) {
|
||||
// the peripheral is not responding, so stop
|
||||
return false;
|
||||
}
|
||||
// wait for a few microseconds
|
||||
UtilsDelay(UTILS_DELAY_US_TO_COUNT(PYBI2C_TRANSAC_WAIT_DELAY_US));
|
||||
timeout -= PYBI2C_TRANSAC_WAIT_DELAY_US;
|
||||
}
|
||||
|
||||
// Check for any errors in the transfer
|
||||
@@ -145,13 +149,22 @@ STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
|
||||
}
|
||||
|
||||
STATIC bool pyb_i2c_scan_device(byte devAddr) {
|
||||
// Set I2C codec slave address
|
||||
bool ret = false;
|
||||
// Set the I2C slave address
|
||||
MAP_I2CMasterSlaveAddrSet(I2CA0_BASE, devAddr, true);
|
||||
// Initiate the transfer.
|
||||
RET_IF_ERR(pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE));
|
||||
// Since this is a hack, send the stop bit anyway
|
||||
if (pyb_i2c_transaction(I2C_MASTER_CMD_SINGLE_RECEIVE)) {
|
||||
ret = true;
|
||||
}
|
||||
// Send the stop bit to cancel the read transaction
|
||||
MAP_I2CMasterControl(I2CA0_BASE, I2C_MASTER_CMD_BURST_SEND_ERROR_STOP);
|
||||
return true;
|
||||
if (!ret) {
|
||||
uint8_t data = 0;
|
||||
if (pyb_i2c_write(devAddr, &data, sizeof(data), true)) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC bool pyb_i2c_mem_addr_write (byte addr, byte *mem_addr, uint mem_addr_len) {
|
||||
@@ -364,8 +377,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_deinit_obj, pyb_i2c_deinit);
|
||||
STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) {
|
||||
pyb_i2c_check_init(&pyb_i2c_obj);
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
for (uint addr = 1; addr <= 127; addr++) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
for (uint addr = 0x08; addr <= 0x77; addr++) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (pyb_i2c_scan_device(addr)) {
|
||||
mp_obj_list_append(list, mp_obj_new_int(addr));
|
||||
break;
|
||||
|
||||
@@ -60,7 +60,6 @@ DECLARE PRIVATE FUNCTIONS
|
||||
STATIC pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name);
|
||||
STATIC pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit);
|
||||
STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);
|
||||
STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);
|
||||
STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type);
|
||||
STATIC void pin_deassign (pin_obj_t* pin);
|
||||
STATIC void pin_obj_configure (const pin_obj_t *self);
|
||||
@@ -199,6 +198,14 @@ uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit)
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
|
||||
int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) {
|
||||
int8_t af = pin_obj_find_af(pin, fn, unit, type);
|
||||
if (af < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
return af;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
@@ -231,14 +238,6 @@ STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, u
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) {
|
||||
int8_t af = pin_obj_find_af(pin, fn, unit, type);
|
||||
if (af < 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
return af;
|
||||
}
|
||||
|
||||
STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) {
|
||||
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict);
|
||||
for (uint i = 0; i < named_map->used - 1; i++) {
|
||||
@@ -248,7 +247,7 @@ STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) {
|
||||
// check if the pin supports the target af
|
||||
int af = pin_obj_find_af(pin, fn, unit, type);
|
||||
if (af > 0 && af == pin->af) {
|
||||
// the pin is assigned to the target af, de-assign it
|
||||
// the pin supports the target af, de-assign it
|
||||
pin_deassign (pin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,10 +72,7 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
PIN_TYPE_TIM_PWM0 = 0,
|
||||
PIN_TYPE_TIM_PWM1,
|
||||
PIN_TYPE_TIM_CC0,
|
||||
PIN_TYPE_TIM_CC1,
|
||||
PIN_TYPE_TIM_PWM = 0,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -139,5 +136,6 @@ pin_obj_t *pin_find(mp_obj_t user_obj);
|
||||
void pin_assign_pins_af (mp_obj_t *pins, uint32_t n_pins, uint32_t pull, uint32_t fn, uint32_t unit);
|
||||
uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type);
|
||||
uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit);
|
||||
int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);;
|
||||
|
||||
#endif // PYBPIN_H_
|
||||
|
||||
@@ -43,7 +43,10 @@
|
||||
#include "interrupt.h"
|
||||
#include "prcm.h"
|
||||
#include "timer.h"
|
||||
#include "pin.h"
|
||||
#include "pybtimer.h"
|
||||
#include "pybpin.h"
|
||||
#include "pins.h"
|
||||
#include "mpirq.h"
|
||||
#include "pybsleep.h"
|
||||
#include "mpexception.h"
|
||||
@@ -55,30 +58,8 @@
|
||||
/// Each timer consists of a counter that counts up at a certain rate. The rate
|
||||
/// at which it counts is the peripheral clock frequency (in Hz) divided by the
|
||||
/// timer prescaler. When the counter reaches the timer period it triggers an
|
||||
/// event, and the counter resets back to zero. By using the callback method,
|
||||
/// event, and the counter resets back to zero. By using the irq method,
|
||||
/// the timer event can call a Python function.
|
||||
///
|
||||
/// Example usage to toggle an LED at a fixed frequency:
|
||||
///
|
||||
/// tim = pyb.Timer(4) # create a timer object using timer 4
|
||||
/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
|
||||
/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
|
||||
/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
|
||||
///
|
||||
/// Further examples:
|
||||
///
|
||||
/// tim1 = pyb.Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
|
||||
/// tim2 = pyb.Timer(1, mode=Timer.PWM) # initialize it in PWM mode
|
||||
/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges
|
||||
/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
|
||||
/// tim_ch.time() # get the current time in usec (can also be set)
|
||||
/// tim_ch.freq(20) # set the frequency (can also get)
|
||||
/// tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
|
||||
/// tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
|
||||
/// tim_ch.event_count() # get the number of captured events
|
||||
/// tim_ch.event_time() # get the the time of the last captured event
|
||||
/// tim_ch.period(2000000) # change the period to 2 seconds
|
||||
///
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE CONSTANTS
|
||||
@@ -87,6 +68,9 @@
|
||||
#define PYBTIMER_POLARITY_POS (0x01)
|
||||
#define PYBTIMER_POLARITY_NEG (0x02)
|
||||
|
||||
#define PYBTIMER_TIMEOUT_TRIGGER (0x01)
|
||||
#define PYBTIMER_MATCH_TRIGGER (0x02)
|
||||
|
||||
#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
|
||||
|
||||
/******************************************************************************
|
||||
@@ -108,8 +92,8 @@ typedef struct _pyb_timer_channel_obj_t {
|
||||
uint32_t frequency;
|
||||
uint32_t period;
|
||||
uint16_t channel;
|
||||
uint16_t duty_cycle;
|
||||
uint8_t polarity;
|
||||
uint8_t duty_cycle;
|
||||
} pyb_timer_channel_obj_t;
|
||||
|
||||
/******************************************************************************
|
||||
@@ -121,12 +105,14 @@ STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_B
|
||||
{.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
|
||||
{.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
|
||||
STATIC const mp_obj_type_t pyb_timer_channel_type;
|
||||
STATIC const mp_obj_t pyb_timer_pwm_pin[8] = {&pin_GP24, MP_OBJ_NULL, &pin_GP25, MP_OBJ_NULL, MP_OBJ_NULL, &pin_GP9, &pin_GP10, &pin_GP11};
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE FUNCTIONS
|
||||
******************************************************************************/
|
||||
STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
STATIC void timer_disable (pyb_timer_obj_t *tim);
|
||||
STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch);
|
||||
STATIC void TIMER0AIntHandler(void);
|
||||
STATIC void TIMER0BIntHandler(void);
|
||||
STATIC void TIMER1AIntHandler(void);
|
||||
@@ -177,6 +163,8 @@ STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
|
||||
pyb_timer_channel_obj_t *channel;
|
||||
if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
|
||||
mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
|
||||
// unregister it with the sleep module
|
||||
pyb_sleep_remove((const mp_obj_t)channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +172,8 @@ STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
|
||||
// remove it in case it already exists
|
||||
pyb_timer_channel_remove(ch);
|
||||
mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
|
||||
// register it with the sleep module
|
||||
pyb_sleep_add((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
|
||||
}
|
||||
|
||||
STATIC void timer_disable (pyb_timer_obj_t *tim) {
|
||||
@@ -191,8 +181,15 @@ STATIC void timer_disable (pyb_timer_obj_t *tim) {
|
||||
MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
|
||||
MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
|
||||
MAP_TimerIntClear(tim->timer, tim->irq_trigger);
|
||||
pyb_timer_channel_obj_t *ch;
|
||||
// disable its channels
|
||||
if ((ch = pyb_timer_channel_find (tim->timer, TIMER_A))) {
|
||||
pyb_sleep_remove(ch);
|
||||
}
|
||||
if ((ch = pyb_timer_channel_find (tim->timer, TIMER_B))) {
|
||||
pyb_sleep_remove(ch);
|
||||
}
|
||||
MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
|
||||
memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
|
||||
}
|
||||
|
||||
// computes prescaler period and match value so timer triggers at freq-Hz
|
||||
@@ -205,20 +202,23 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t
|
||||
if (period_c == 0) {
|
||||
goto error;
|
||||
}
|
||||
prescaler = period_c >> 16;
|
||||
|
||||
prescaler = period_c >> 16; // The prescaler is an extension of the timer counter
|
||||
*period_out = period_c;
|
||||
|
||||
if (prescaler > 0xFF && maxcount == 0xFFFF) {
|
||||
goto error;
|
||||
}
|
||||
// check limit values for the duty cycle
|
||||
if (ch->duty_cycle == 0) {
|
||||
*match_out = period_c - 1;
|
||||
}
|
||||
else {
|
||||
*match_out = period_c - ((period_c * ch->duty_cycle) / 100);
|
||||
}
|
||||
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM && (*match_out > 0xFFFF)) {
|
||||
goto error;
|
||||
} else {
|
||||
if (period_c > 0xFFFF) {
|
||||
uint32_t match = (period_c * 100) / 10000;
|
||||
*match_out = period_c - ((match * ch->duty_cycle) / 100);
|
||||
} else {
|
||||
*match_out = period_c - ((period_c * ch->duty_cycle) / 10000);
|
||||
}
|
||||
}
|
||||
return prescaler;
|
||||
|
||||
@@ -250,17 +250,7 @@ STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
|
||||
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
|
||||
// set the match value (which is simply the duty cycle translated to ticks)
|
||||
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
|
||||
}
|
||||
// configure the event edge type if we are in such mode
|
||||
else if ((ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_COUNT || (ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_TIME) {
|
||||
uint32_t polarity = TIMER_EVENT_BOTH_EDGES;
|
||||
if (ch->polarity == PYBTIMER_POLARITY_POS) {
|
||||
polarity = TIMER_EVENT_POS_EDGE;
|
||||
}
|
||||
else if (ch->polarity == PYBTIMER_POLARITY_NEG) {
|
||||
polarity = TIMER_EVENT_NEG_EDGE;
|
||||
}
|
||||
MAP_TimerControlEvent(ch->timer->timer, ch->channel, polarity);
|
||||
MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -282,37 +272,18 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_
|
||||
// timer mode
|
||||
qstr mode_qst = MP_QSTR_PWM;
|
||||
switch(mode) {
|
||||
case TIMER_CFG_A_ONE_SHOT:
|
||||
case TIMER_CFG_A_ONE_SHOT_UP:
|
||||
mode_qst = MP_QSTR_ONE_SHOT;
|
||||
break;
|
||||
case TIMER_CFG_A_PERIODIC:
|
||||
case TIMER_CFG_A_PERIODIC_UP:
|
||||
mode_qst = MP_QSTR_PERIODIC;
|
||||
break;
|
||||
case TIMER_CFG_A_CAP_COUNT:
|
||||
mode_qst = MP_QSTR_EDGE_COUNT;
|
||||
break;
|
||||
case TIMER_CFG_A_CAP_TIME:
|
||||
mode_qst = MP_QSTR_EDGE_TIME;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mp_printf(print, "<Timer%u, mode=Timer.%q>", (tim->id + 1), mode_qst);
|
||||
mp_printf(print, "Timer(%u, mode=Timer.%q)", tim->id, mode_qst);
|
||||
}
|
||||
|
||||
/// \method init(mode, *, width)
|
||||
/// Initialise the timer. Initialisation must give the desired mode
|
||||
/// and an optional timer width
|
||||
///
|
||||
/// tim.init(mode=Timer.ONE_SHOT, width=32) # one shot mode
|
||||
/// tim.init(mode=Timer.PERIODIC) # configure in free running periodic mode
|
||||
/// split into two 16-bit independent timers
|
||||
///
|
||||
/// Keyword arguments:
|
||||
///
|
||||
/// - `width` - specifies the width of the timer. Default is 32 bit mode. When in 16 bit mode
|
||||
/// the timer is splitted into 2 independent channels.
|
||||
///
|
||||
STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
|
||||
@@ -325,8 +296,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
|
||||
|
||||
// check the mode
|
||||
uint32_t _mode = args[0].u_int;
|
||||
if (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC && _mode != TIMER_CFG_A_CAP_COUNT &&
|
||||
_mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM) {
|
||||
if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -336,7 +306,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co
|
||||
}
|
||||
bool is16bit = (args[1].u_int == 16);
|
||||
|
||||
if (!is16bit && (_mode != TIMER_CFG_A_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC)) {
|
||||
if (!is16bit && _mode == TIMER_CFG_A_PWM) {
|
||||
// 32-bit mode is only available when in free running modes
|
||||
goto error;
|
||||
}
|
||||
@@ -352,16 +322,12 @@ error:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
|
||||
/// \classmethod \constructor(id, ...)
|
||||
/// Construct a new timer object of the given id. If additional
|
||||
/// arguments are given, then the timer is initialised by `init(...)`.
|
||||
/// `id` can be 1 to 4
|
||||
STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
// check arguments
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// create a new Timer object
|
||||
int32_t timer_idx = mp_obj_get_int(args[0]) - 1;
|
||||
int32_t timer_idx = mp_obj_get_int(args[0]);
|
||||
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
|
||||
}
|
||||
@@ -379,15 +345,11 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args,
|
||||
return (mp_obj_t)tim;
|
||||
}
|
||||
|
||||
// \method init()
|
||||
/// initializes the timer
|
||||
STATIC mp_obj_t pyb_timer_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
|
||||
|
||||
// \method deinit()
|
||||
/// disables the timer
|
||||
STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
|
||||
pyb_timer_obj_t *self = self_in;
|
||||
timer_disable(self);
|
||||
@@ -395,24 +357,6 @@ STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
|
||||
|
||||
/// \method channel(channel, *, freq, period, polarity, duty_cycle)
|
||||
/// Initialise the timer channel. Initialization requires at least a frequency param. With no
|
||||
/// extra params given besides the channel id, the channel is returned with the previous configuration
|
||||
/// os 'None', if it hasn't been initialized before.
|
||||
///
|
||||
/// tim1.channel(Timer.A, freq=1000) # set channel A frequency to 1KHz
|
||||
/// tim2.channel(Timer.AB, freq=10) # both channels (because it's a 32 bit timer) combined to create a 10Hz timer
|
||||
///
|
||||
/// when initialiazing the channel of a 32-bit timer, channel ID MUST be = Timer.AB
|
||||
///
|
||||
/// Keyword arguments:
|
||||
///
|
||||
/// - `freq` - specifies the frequency in Hz.
|
||||
/// - `period` - specifies the period in microseconds.
|
||||
/// - `polarity` - in PWM specifies the polarity of the pulse. In capture mode specifies the edge to capture.
|
||||
/// in order to capture on both negative and positive edges, make it = Timer.POSITIVE | Timer.NEGATIVE.
|
||||
/// - `duty_cycle` - sets the duty cycle value
|
||||
///
|
||||
STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
@@ -474,12 +418,21 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
ch->frequency = args[0].u_int;
|
||||
ch->period = args[1].u_int;
|
||||
ch->polarity = args[2].u_int;
|
||||
ch->duty_cycle = MIN(100, MAX(0, args[3].u_int));
|
||||
ch->duty_cycle = MIN(10000, MAX(0, args[3].u_int));
|
||||
|
||||
timer_channel_init(ch);
|
||||
|
||||
// register it with the sleep module
|
||||
pyb_sleep_add ((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
|
||||
// assign the pin
|
||||
if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
|
||||
uint32_t ch_idx = (ch->channel == TIMER_A) ? 0 : 1;
|
||||
// use the default pin if available
|
||||
mp_obj_t pin_o = (mp_obj_t)pyb_timer_pwm_pin[(ch->timer->id * 2) + ch_idx];
|
||||
if (pin_o != MP_OBJ_NULL) {
|
||||
pin_obj_t *pin = pin_find(pin_o);
|
||||
pin_config (pin, pin_find_af_index(pin, PIN_FN_TIM, ch->timer->id, PIN_TYPE_TIM_PWM),
|
||||
0, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA);
|
||||
}
|
||||
}
|
||||
|
||||
// add the timer to the list
|
||||
pyb_timer_channel_add(ch);
|
||||
@@ -500,13 +453,13 @@ STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_A), MP_OBJ_NEW_SMALL_INT(TIMER_A) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_B), MP_OBJ_NEW_SMALL_INT(TIMER_B) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_COUNT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_COUNT) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_TIME), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_TIME) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT_UP) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC_UP) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PWM), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PWM) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_POSITIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_POS) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEGATIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_NEG) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TIMEOUT), MP_OBJ_NEW_SMALL_INT(PYBTIMER_TIMEOUT_TRIGGER) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MATCH), MP_OBJ_NEW_SMALL_INT(PYBTIMER_MATCH_TRIGGER) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
|
||||
|
||||
@@ -528,7 +481,6 @@ STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
|
||||
STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
|
||||
pyb_timer_channel_obj_t *self;
|
||||
uint32_t status;
|
||||
|
||||
if ((self = pyb_timer_channel_find(timer, channel))) {
|
||||
status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
|
||||
MAP_TimerIntClear(self->timer->timer, status);
|
||||
@@ -574,16 +526,14 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
|
||||
// timer channel
|
||||
if (ch->channel == TIMER_A) {
|
||||
ch_id = "A";
|
||||
}
|
||||
else if (ch->channel == TIMER_B) {
|
||||
} else if (ch->channel == TIMER_B) {
|
||||
ch_id = "B";
|
||||
}
|
||||
|
||||
mp_printf(print, "<%q %s, timer=%u, %q=%u", MP_QSTR_TimerChannel,
|
||||
ch_id, (ch->timer->id + 1), MP_QSTR_freq, ch->frequency);
|
||||
mp_printf(print, "timer.channel(Timer.%s, %q=%u", ch_id, MP_QSTR_freq, ch->frequency);
|
||||
|
||||
uint32_t mode = ch->timer->config & 0xFF;
|
||||
if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || mode == TIMER_CFG_A_PWM) {
|
||||
if (mode == TIMER_CFG_A_PWM) {
|
||||
mp_printf(print, ", %q=Timer.", MP_QSTR_polarity);
|
||||
switch (ch->polarity) {
|
||||
case PYBTIMER_POLARITY_POS:
|
||||
@@ -596,15 +546,11 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m
|
||||
mp_printf(print, "BOTH");
|
||||
break;
|
||||
}
|
||||
if (mode == TIMER_CFG_A_PWM) {
|
||||
mp_printf(print, ", %q=%u", MP_QSTR_duty_cycle, ch->duty_cycle);
|
||||
}
|
||||
mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100);
|
||||
}
|
||||
mp_printf(print, ">");
|
||||
mp_printf(print, ")");
|
||||
}
|
||||
|
||||
/// \method freq([value])
|
||||
/// get or set the frequency of the timer channel
|
||||
STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
pyb_timer_channel_obj_t *ch = args[0];
|
||||
if (n_args == 1) {
|
||||
@@ -624,8 +570,6 @@ STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq);
|
||||
|
||||
/// \method period([value])
|
||||
/// get or set the period of the timer channel in microseconds
|
||||
STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
pyb_timer_channel_obj_t *ch = args[0];
|
||||
if (n_args == 1) {
|
||||
@@ -645,74 +589,17 @@ STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args)
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period);
|
||||
|
||||
/// \method time([value])
|
||||
/// get or set the value of the timer channel in microseconds
|
||||
STATIC mp_obj_t pyb_timer_channel_time(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
pyb_timer_channel_obj_t *ch = args[0];
|
||||
uint32_t value;
|
||||
// calculate the period, the prescaler and the match value
|
||||
uint32_t period_c;
|
||||
uint32_t match;
|
||||
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
value = (ch->channel == TIMER_B) ? HWREG(ch->timer->timer + TIMER_O_TBV) : HWREG(ch->timer->timer + TIMER_O_TAV);
|
||||
// return the current timer value in microseconds
|
||||
// substract value to period since we are always operating in count-down mode
|
||||
uint32_t time_t = (1000 * (period_c - value)) / period_c;
|
||||
return mp_obj_new_int((time_t * 1000) / ch->frequency);
|
||||
}
|
||||
else {
|
||||
// set
|
||||
value = (mp_obj_get_int(args[1]) * ((ch->frequency * period_c) / 1000)) / 1000;
|
||||
if ((value > 0xFFFF) && (ch->timer->config & TIMER_CFG_SPLIT_PAIR)) {
|
||||
// this exceeds the maximum value of a 16-bit timer
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||
}
|
||||
// write period minus value since we are always operating in count-down mode
|
||||
TimerValueSet (ch->timer->timer, ch->channel, (period_c - value));
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_time_obj, 1, 2, pyb_timer_channel_time);
|
||||
|
||||
/// \method event_count()
|
||||
/// get the number of events triggered by the configured edge
|
||||
STATIC mp_obj_t pyb_timer_channel_event_count(mp_obj_t self_in) {
|
||||
pyb_timer_channel_obj_t *ch = self_in;
|
||||
return mp_obj_new_int(MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_count_obj, pyb_timer_channel_event_count);
|
||||
|
||||
/// \method event_time()
|
||||
/// get the time at which the last event was triggered
|
||||
STATIC mp_obj_t pyb_timer_channel_event_time(mp_obj_t self_in) {
|
||||
pyb_timer_channel_obj_t *ch = self_in;
|
||||
// calculate the period, the prescaler and the match value
|
||||
uint32_t period_c;
|
||||
uint32_t match;
|
||||
(void)compute_prescaler_period_and_match_value(ch, &period_c, &match);
|
||||
uint32_t value = MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel);
|
||||
// substract value to period since we are always operating in count-down mode
|
||||
uint32_t time_t = (1000 * (period_c - value)) / period_c;
|
||||
return mp_obj_new_int((time_t * 1000) / ch->frequency);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_time_obj, pyb_timer_channel_event_time);
|
||||
|
||||
/// \method duty_cycle()
|
||||
/// get or set the duty cycle when in PWM mode
|
||||
STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
pyb_timer_channel_obj_t *ch = args[0];
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
return mp_obj_new_int(ch->duty_cycle);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// duty cycle must be converted from percentage to ticks
|
||||
// calculate the period, the prescaler and the match value
|
||||
uint32_t period_c;
|
||||
uint32_t match;
|
||||
ch->duty_cycle = MIN(100, MAX(0, mp_obj_get_int(args[1])));
|
||||
ch->duty_cycle = MIN(10000, MAX(0, mp_obj_get_int(args[1])));
|
||||
compute_prescaler_period_and_match_value(ch, &period_c, &match);
|
||||
if (n_args == 3) {
|
||||
// set the new polarity if requested
|
||||
@@ -720,13 +607,12 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a
|
||||
MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
|
||||
}
|
||||
MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
|
||||
MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
|
||||
|
||||
/// \method irq(trigger, priority, handler, wake)
|
||||
/// FIXME triggers!!
|
||||
STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
|
||||
@@ -741,25 +627,28 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg
|
||||
goto invalid_args;
|
||||
}
|
||||
|
||||
// get the trigger
|
||||
uint trigger = mp_obj_get_int(args[0].u_obj);
|
||||
|
||||
// disable the callback first
|
||||
pyb_timer_channel_irq_disable(ch);
|
||||
|
||||
uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
|
||||
uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
|
||||
switch (_config) {
|
||||
case TIMER_CFG_A_ONE_SHOT:
|
||||
case TIMER_CFG_A_PERIODIC:
|
||||
case TIMER_CFG_A_ONE_SHOT_UP:
|
||||
case TIMER_CFG_A_PERIODIC_UP:
|
||||
ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift;
|
||||
break;
|
||||
case TIMER_CFG_A_CAP_COUNT:
|
||||
ch->timer->irq_trigger |= TIMER_CAPA_MATCH << shift;
|
||||
break;
|
||||
case TIMER_CFG_A_CAP_TIME:
|
||||
ch->timer->irq_trigger |= TIMER_CAPA_EVENT << shift;
|
||||
if (trigger != PYBTIMER_TIMEOUT_TRIGGER) {
|
||||
goto invalid_args;
|
||||
}
|
||||
break;
|
||||
case TIMER_CFG_A_PWM:
|
||||
// special case for the PWM match interrupt
|
||||
ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
|
||||
if (trigger != PYBTIMER_MATCH_TRIGGER) {
|
||||
goto invalid_args;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -831,9 +720,6 @@ STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_channel_freq_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_period), (mp_obj_t)&pyb_timer_channel_period_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&pyb_timer_channel_time_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_count), (mp_obj_t)&pyb_timer_channel_event_count_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_event_time), (mp_obj_t)&pyb_timer_channel_event_time_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_duty_cycle), (mp_obj_t)&pyb_timer_channel_duty_cycle_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_timer_channel_irq_obj },
|
||||
};
|
||||
|
||||
@@ -70,10 +70,12 @@
|
||||
#define MICROPY_FATFS_REENTRANT (1)
|
||||
#define MICROPY_FATFS_TIMEOUT (2500)
|
||||
#define MICROPY_FATFS_SYNC_T SemaphoreHandle_t
|
||||
#define MICROPY_FSUSERMOUNT_ADHOC (1)
|
||||
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
#define MICROPY_PY_ASYNC_AWAIT (0)
|
||||
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||
#ifndef DEBUG
|
||||
@@ -112,9 +114,6 @@
|
||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_help_obj;
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_input_obj;
|
||||
extern const struct _mp_obj_fun_builtin_t mp_builtin_open_obj;
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_input), (mp_obj_t)&mp_builtin_input_obj }, \
|
||||
|
||||
@@ -26,370 +26,7 @@
|
||||
*/
|
||||
|
||||
// for machine module
|
||||
Q(umachine)
|
||||
#ifdef DEBUG
|
||||
Q(info)
|
||||
#endif
|
||||
Q(reset)
|
||||
Q(main)
|
||||
Q(sync)
|
||||
Q(rng)
|
||||
Q(freq)
|
||||
Q(unique_id)
|
||||
Q(disable_irq)
|
||||
Q(enable_irq)
|
||||
Q(idle)
|
||||
Q(sleep)
|
||||
Q(deepsleep)
|
||||
Q(reset_cause)
|
||||
Q(wake_reason)
|
||||
Q(IDLE)
|
||||
Q(SLEEP)
|
||||
Q(DEEPSLEEP)
|
||||
Q(POWER_ON)
|
||||
Q(HARD_RESET)
|
||||
Q(WDT_RESET)
|
||||
Q(DEEPSLEEP_RESET)
|
||||
Q(SOFT_RESET)
|
||||
Q(WLAN_WAKE)
|
||||
Q(PIN_WAKE)
|
||||
Q(RTC_WAKE)
|
||||
|
||||
// for wipy module
|
||||
Q(wipy)
|
||||
Q(heartbeat)
|
||||
|
||||
Q(/)
|
||||
// entries for sys.path
|
||||
Q(/flash)
|
||||
Q(/flash/lib)
|
||||
|
||||
// interactive help
|
||||
Q(help)
|
||||
|
||||
// for module weak links
|
||||
Q(struct)
|
||||
Q(binascii)
|
||||
Q(re)
|
||||
Q(json)
|
||||
Q(heapq)
|
||||
//Q(hashlib)
|
||||
|
||||
// for os module
|
||||
Q(os)
|
||||
Q(uos)
|
||||
Q(sysname)
|
||||
Q(nodename)
|
||||
Q(release)
|
||||
Q(version)
|
||||
Q(machine)
|
||||
Q(uname)
|
||||
Q(/)
|
||||
Q(flash)
|
||||
Q(chdir)
|
||||
Q(getcwd)
|
||||
Q(listdir)
|
||||
Q(mkdir)
|
||||
Q(rename)
|
||||
Q(remove)
|
||||
Q(rmdir)
|
||||
Q(unlink)
|
||||
Q(sep)
|
||||
Q(stat)
|
||||
Q(urandom)
|
||||
Q(mkfs)
|
||||
Q(mount)
|
||||
Q(unmount)
|
||||
Q(dupterm)
|
||||
Q(readonly)
|
||||
Q(readblocks)
|
||||
Q(writeblocks)
|
||||
Q(sync)
|
||||
Q(count)
|
||||
|
||||
// for file class
|
||||
Q(seek)
|
||||
Q(tell)
|
||||
Q(input)
|
||||
Q(flush)
|
||||
|
||||
// for Pin class
|
||||
Q(Pin)
|
||||
Q(board)
|
||||
Q(init)
|
||||
Q(value)
|
||||
Q(toggle)
|
||||
Q(id)
|
||||
Q(mode)
|
||||
Q(pull)
|
||||
Q(drive)
|
||||
Q(alt)
|
||||
Q(alt_list)
|
||||
Q(IN)
|
||||
Q(OUT)
|
||||
Q(OPEN_DRAIN)
|
||||
Q(ALT)
|
||||
Q(ALT_OPEN_DRAIN)
|
||||
Q(PULL_UP)
|
||||
Q(PULL_DOWN)
|
||||
Q(LOW_POWER)
|
||||
Q(MED_POWER)
|
||||
Q(HIGH_POWER)
|
||||
Q(IRQ_RISING)
|
||||
Q(IRQ_FALLING)
|
||||
Q(IRQ_LOW_LEVEL)
|
||||
Q(IRQ_HIGH_LEVEL)
|
||||
|
||||
// for UART class
|
||||
Q(UART)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(any)
|
||||
Q(sendbreak)
|
||||
Q(id)
|
||||
Q(baudrate)
|
||||
Q(bits)
|
||||
Q(stop)
|
||||
Q(parity)
|
||||
Q(pins)
|
||||
Q(EVEN)
|
||||
Q(ODD)
|
||||
Q(RX_ANY)
|
||||
|
||||
// for I2C class
|
||||
Q(I2C)
|
||||
Q(id)
|
||||
Q(mode)
|
||||
Q(baudrate)
|
||||
Q(pins)
|
||||
Q(addr)
|
||||
Q(nbytes)
|
||||
Q(buf)
|
||||
Q(stop)
|
||||
Q(memaddr)
|
||||
Q(addrsize)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(scan)
|
||||
Q(readfrom)
|
||||
Q(readfrom_into)
|
||||
Q(writeto)
|
||||
Q(readfrom_mem)
|
||||
Q(readfrom_mem_into)
|
||||
Q(writeto_mem)
|
||||
Q(MASTER)
|
||||
|
||||
// for ADC class
|
||||
Q(ADC)
|
||||
Q(ADCChannel)
|
||||
Q(value)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(channel)
|
||||
Q(id)
|
||||
Q(pin)
|
||||
|
||||
// for SD class
|
||||
Q(SD)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(id)
|
||||
Q(pins)
|
||||
|
||||
// for RTC class
|
||||
Q(RTC)
|
||||
Q(id)
|
||||
Q(init)
|
||||
Q(alarm)
|
||||
Q(alarm_left)
|
||||
Q(alarm_cancel)
|
||||
Q(now)
|
||||
Q(deinit)
|
||||
Q(datetime)
|
||||
Q(repeat)
|
||||
Q(ALARM0)
|
||||
|
||||
// for time class
|
||||
Q(time)
|
||||
Q(utime)
|
||||
Q(localtime)
|
||||
Q(mktime)
|
||||
Q(sleep)
|
||||
Q(sleep_ms)
|
||||
Q(sleep_us)
|
||||
Q(ticks_ms)
|
||||
Q(ticks_us)
|
||||
Q(ticks_cpu)
|
||||
Q(ticks_diff)
|
||||
|
||||
// for select class
|
||||
Q(select)
|
||||
Q(uselect)
|
||||
Q(register)
|
||||
Q(unregister)
|
||||
Q(modify)
|
||||
Q(poll)
|
||||
Q(POLLIN)
|
||||
Q(POLLOUT)
|
||||
Q(POLLERR)
|
||||
Q(POLLHUP)
|
||||
|
||||
// for socket class
|
||||
Q(socket)
|
||||
Q(usocket)
|
||||
Q(getaddrinfo)
|
||||
Q(family)
|
||||
Q(type)
|
||||
Q(send)
|
||||
Q(sendall)
|
||||
Q(sendto)
|
||||
Q(recv)
|
||||
Q(recvfrom)
|
||||
Q(listen)
|
||||
Q(accept)
|
||||
Q(bind)
|
||||
Q(settimeout)
|
||||
Q(setblocking)
|
||||
Q(setsockopt)
|
||||
Q(close)
|
||||
Q(makefile)
|
||||
Q(protocol)
|
||||
Q(error)
|
||||
Q(timeout)
|
||||
Q(AF_INET)
|
||||
Q(SOCK_STREAM)
|
||||
Q(SOCK_DGRAM)
|
||||
Q(IPPROTO_SEC)
|
||||
Q(IPPROTO_TCP)
|
||||
Q(IPPROTO_UDP)
|
||||
|
||||
// for ssl class
|
||||
Q(ssl)
|
||||
Q(ussl)
|
||||
Q(wrap_socket)
|
||||
Q(sock)
|
||||
Q(keyfile)
|
||||
Q(certfile)
|
||||
Q(server_side)
|
||||
Q(cert_reqs)
|
||||
Q(ca_certs)
|
||||
Q(SSLError)
|
||||
Q(CERT_NONE)
|
||||
Q(CERT_OPTIONAL)
|
||||
Q(CERT_REQUIRED)
|
||||
|
||||
// for network class
|
||||
Q(network)
|
||||
Q(server)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(login)
|
||||
Q(timeout)
|
||||
Q(isrunning)
|
||||
|
||||
// for WLAN class
|
||||
Q(WLAN)
|
||||
Q(id)
|
||||
Q(init)
|
||||
Q(mode)
|
||||
Q(auth)
|
||||
Q(ssid)
|
||||
Q(bssid)
|
||||
Q(mac)
|
||||
Q(antenna)
|
||||
Q(scan)
|
||||
Q(connect)
|
||||
Q(isconnected)
|
||||
Q(disconnect)
|
||||
Q(sec)
|
||||
Q(channel)
|
||||
Q(rssi)
|
||||
Q(ifconfig)
|
||||
Q(config)
|
||||
//Q(connections)
|
||||
//Q(urn)
|
||||
Q(STA)
|
||||
Q(AP)
|
||||
Q(OPEN)
|
||||
Q(WEP)
|
||||
Q(WPA)
|
||||
Q(WPA2)
|
||||
Q(INT_ANT)
|
||||
Q(EXT_ANT)
|
||||
Q(ANY_EVENT)
|
||||
|
||||
// for WDT class
|
||||
Q(WDT)
|
||||
Q(feed)
|
||||
Q(timeout)
|
||||
|
||||
// for irq class
|
||||
Q(irq)
|
||||
Q(init)
|
||||
Q(enable)
|
||||
Q(disable)
|
||||
Q(flags)
|
||||
Q(trigger)
|
||||
Q(handler)
|
||||
Q(priority)
|
||||
Q(wake)
|
||||
|
||||
// for SPI class
|
||||
Q(SPI)
|
||||
Q(id)
|
||||
Q(mode)
|
||||
Q(baudrate)
|
||||
Q(bits)
|
||||
Q(polarity)
|
||||
Q(phase)
|
||||
Q(firstbit)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(write)
|
||||
Q(read)
|
||||
Q(readinto)
|
||||
Q(write_readinto)
|
||||
Q(nbytes)
|
||||
Q(buf)
|
||||
Q(MASTER)
|
||||
Q(MSB)
|
||||
|
||||
// for Timer class
|
||||
Q(Timer)
|
||||
Q(TimerChannel)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(freq)
|
||||
Q(period)
|
||||
Q(mode)
|
||||
Q(width)
|
||||
Q(channel)
|
||||
Q(polarity)
|
||||
Q(duty_cycle)
|
||||
Q(time)
|
||||
Q(event_count)
|
||||
Q(event_time)
|
||||
Q(A)
|
||||
Q(B)
|
||||
Q(ONE_SHOT)
|
||||
Q(PERIODIC)
|
||||
Q(EDGE_COUNT)
|
||||
Q(EDGE_TIME)
|
||||
Q(PWM)
|
||||
Q(POSITIVE)
|
||||
Q(NEGATIVE)
|
||||
|
||||
// for uhashlib module
|
||||
//Q(uhashlib)
|
||||
//Q(update)
|
||||
//Q(digest)
|
||||
//Q(md5)
|
||||
//Q(sha1)
|
||||
//Q(sha256)
|
||||
|
||||
// for ubinascii module
|
||||
Q(ubinascii)
|
||||
Q(hexlify)
|
||||
Q(unhexlify)
|
||||
Q(a2b_base64)
|
||||
Q(b2a_base64)
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@
|
||||
#include "pybwdt.h"
|
||||
#include "modusocket.h"
|
||||
#include "mpexception.h"
|
||||
|
||||
#include "modnetwork.h"
|
||||
#include "modwlan.h"
|
||||
|
||||
/******************************************************************************
|
||||
DEFINE PRIVATE TYPES
|
||||
@@ -50,13 +51,13 @@ typedef struct {
|
||||
bool do_disable;
|
||||
bool do_enable;
|
||||
bool do_reset;
|
||||
bool do_wlan_cycle_power;
|
||||
} servers_data_t;
|
||||
|
||||
/******************************************************************************
|
||||
DECLARE PRIVATE DATA
|
||||
******************************************************************************/
|
||||
static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS, .enabled = false, .do_disable = false,
|
||||
.do_enable = false, .do_reset = false};
|
||||
static servers_data_t servers_data = {.timeout = SERVERS_DEF_TIMEOUT_MS};
|
||||
static volatile bool sleep_sockets = false;
|
||||
|
||||
/******************************************************************************
|
||||
@@ -120,10 +121,16 @@ void TASK_Servers (void *pvParameters) {
|
||||
}
|
||||
|
||||
if (sleep_sockets) {
|
||||
sleep_sockets = false;
|
||||
pybwdt_srv_sleeping(true);
|
||||
modusocket_enter_sleep();
|
||||
pybwdt_srv_sleeping(false);
|
||||
mp_hal_delay_ms(SERVERS_CYCLE_TIME_MS * 2);
|
||||
if (servers_data.do_wlan_cycle_power) {
|
||||
servers_data.do_wlan_cycle_power = false;
|
||||
wlan_off_on();
|
||||
}
|
||||
sleep_sockets = false;
|
||||
|
||||
}
|
||||
|
||||
// set the alive flag for the wdt
|
||||
@@ -152,6 +159,10 @@ void servers_reset (void) {
|
||||
servers_data.do_reset = true;
|
||||
}
|
||||
|
||||
void servers_wlan_cycle_power (void) {
|
||||
servers_data.do_wlan_cycle_power = true;
|
||||
}
|
||||
|
||||
bool servers_are_enabled (void) {
|
||||
return servers_data.enabled;
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ extern void TASK_Servers (void *pvParameters);
|
||||
extern void servers_start (void);
|
||||
extern void servers_stop (void);
|
||||
extern void servers_reset (void);
|
||||
extern void servers_wlan_cycle_power (void);
|
||||
extern bool servers_are_enabled (void);
|
||||
extern void servers_close_socket (int16_t *sd);
|
||||
extern void servers_set_login (char *user, char *pass);
|
||||
|
||||
@@ -27,6 +27,6 @@
|
||||
#ifndef VERSION_H_
|
||||
#define VERSION_H_
|
||||
|
||||
#define WIPY_SW_VERSION_NUMBER "1.1.1"
|
||||
#define WIPY_SW_VERSION_NUMBER "1.2.0"
|
||||
|
||||
#endif /* VERSION_H_ */
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
SPHINXOPTS =
|
||||
SPHINXBUILD = sphinx-build
|
||||
PAPER =
|
||||
BUILDDIR = build
|
||||
BUILDDIR = build/$(MICROPY_PORT)
|
||||
|
||||
# User-friendly check for sphinx-build
|
||||
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
|
||||
|
||||
@@ -21,7 +21,7 @@ preferably in a virtualenv:
|
||||
|
||||
In `micropython/docs`, build the docs:
|
||||
|
||||
make MICROPY_PORT=<port_name> BUILDDIR=build/<port_name> html
|
||||
make MICROPY_PORT=<port_name> html
|
||||
|
||||
Where `<port_name>` can be `unix`, `pyboard`, `wipy` or `esp8266`.
|
||||
|
||||
|
||||
30
docs/conf.py
30
docs/conf.py
@@ -26,18 +26,28 @@ from collections import OrderedDict
|
||||
micropy_port = os.getenv('MICROPY_PORT') or 'pyboard'
|
||||
tags.add('port_' + micropy_port)
|
||||
ports = OrderedDict((
|
||||
("unix", "unix"),
|
||||
("pyboard", "the pyboard"),
|
||||
("wipy", "the WiPy"),
|
||||
("esp8266", "esp8266"),
|
||||
('unix', 'unix'),
|
||||
('pyboard', 'the pyboard'),
|
||||
('wipy', 'the WiPy'),
|
||||
('esp8266', 'the ESP8266'),
|
||||
))
|
||||
|
||||
# The members of the html_context dict are available inside topindex.html
|
||||
url_prefix = os.getenv('MICROPY_URL_PREFIX') or '/'
|
||||
micropy_version = os.getenv('MICROPY_VERSION') or 'latest'
|
||||
micropy_all_versions = (os.getenv('MICROPY_ALL_VERSIONS') or 'latest').split(',')
|
||||
url_pattern = '%s/en/%%s/%%s' % (os.getenv('MICROPY_URL_PREFIX') or '/',)
|
||||
html_context = {
|
||||
'port':micropy_port,
|
||||
'port_name':ports[micropy_port],
|
||||
'all_ports':[(n, url_prefix + p) for p, n in ports.items()],
|
||||
'port_version':micropy_version,
|
||||
'all_ports':[
|
||||
(port_id, url_pattern % (micropy_version, port_id))
|
||||
for port_id, port_name in ports.items()
|
||||
],
|
||||
'all_versions':[
|
||||
(ver, url_pattern % (ver, micropy_port))
|
||||
for ver in micropy_all_versions
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -74,16 +84,16 @@ source_suffix = '.rst'
|
||||
|
||||
# General information about the project.
|
||||
project = 'MicroPython'
|
||||
copyright = '2014, Damien P. George'
|
||||
copyright = '2014-2016, Damien P. George and contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.6'
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.6'
|
||||
release = '1.8'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -306,5 +316,3 @@ exclude_patterns.extend([port + '*' for port in ports if port != micropy_port])
|
||||
# Exclude pyb module if the port is the WiPy
|
||||
if micropy_port == 'wipy':
|
||||
exclude_patterns.append('library/pyb*')
|
||||
else: # exclude machine
|
||||
exclude_patterns.append('library/machine*')
|
||||
|
||||
93
docs/esp8266/general.rst
Normal file
93
docs/esp8266/general.rst
Normal file
@@ -0,0 +1,93 @@
|
||||
General information about the ESP8266 port
|
||||
==========================================
|
||||
|
||||
ESP8266 is a popular WiFi-enabled System-on-Chip (SoC) by Espressif Systems.
|
||||
|
||||
Multitude of boards
|
||||
-------------------
|
||||
|
||||
There are multitude of modules and boards from different sources which carry
|
||||
ESP8266 chip. MicroPython tries to provide a generic port which would run on
|
||||
as many boards/modules as possible, but there may be limitations. Adafruit
|
||||
Feather HUZZAH board is taken as a reference board for the port (for example,
|
||||
testing is performed on it). If you have another board, please make sure you
|
||||
have datasheet, schematics and other reference materials for your board
|
||||
handy to look up various aspects of your board functioning.
|
||||
|
||||
To make a generic ESP8266 port and support as many boards as possible,
|
||||
following design and implementation decision were made:
|
||||
|
||||
* GPIO pin numbering is based on ESP8266 chip numbering, not some "logical"
|
||||
numbering of a particular board. Please have manual/pin diagram of your board
|
||||
handy to find correspondce between your board pins and actual ESP8266 pins.
|
||||
We also encourage users of various boards to share this mapping via MicroPython
|
||||
forum, with the idea to collect community-maintained reference materials
|
||||
eventually.
|
||||
* All pins which make sense to support, are supported by MicroPython
|
||||
(for example, we don't expose pins which are used to connect SPI flash
|
||||
are not exposed, as they're unlikely useful for anything else, and
|
||||
operating on them will lead to board lock-up). However, any particular
|
||||
board may expose only subset of pins. Consult your board reference manual.
|
||||
* Some boards may lack external pins/internal connectivity to support
|
||||
ESP8266 deepsleep mode.
|
||||
|
||||
|
||||
Technical specifications and SoC datasheets
|
||||
-------------------------------------------
|
||||
|
||||
The datasheets and other reference material for ESP8266 chip are available
|
||||
from the vendor site: http://bbs.espressif.com/viewtopic.php?f=67&t=225 .
|
||||
The are primary reference for the chip technical specifications, capabilities,
|
||||
operating modes, internal functioning, etc.
|
||||
|
||||
For your convinience, some of technical specifications are provided below:
|
||||
|
||||
* Architecture: Xtensa lx106
|
||||
* CPU frequency: 80MHz overclockable to 160MHz
|
||||
* Total RAM available: 96KB (part of it reserved for system)
|
||||
* BootROM: 64KB
|
||||
* Internal FlashROM: None
|
||||
* External FlashROM: code and data, via SPI Flash. Normal sizes 512KB-4MB.
|
||||
* GPIO: 16 + 1 (GPIOs are multiplexed with other functions, including
|
||||
external FlashROM, UART, deep sleep wake-up, etc.)
|
||||
* UART: One RX/TX UART (no hardware handshaking), one TX-only UART.
|
||||
* SPI: 2 SPI interfaces (one used for FlashROM).
|
||||
* I2C: No native extenal I2C (bitbang implementation available on any pins).
|
||||
* I2S: 1.
|
||||
* Programming: using BootROM bootloader from UART. Due to external FlashROM
|
||||
and always-available BootROM bootloader, ESP8266 is not brickable.
|
||||
|
||||
|
||||
Boot process
|
||||
------------
|
||||
|
||||
On boot, MicroPython EPS8266 port executes ``_boot.py`` script from internal
|
||||
frozen modules. It mounts filesystem in FlashROM, or if it's not available,
|
||||
performs first-time setup of the module and creates the filesystem. This
|
||||
part of boot process is considered fixed, and not available for customization
|
||||
for end users (even if you build from source, please refrain from changes to
|
||||
it; customization of early boot process is available only to advanced users
|
||||
and developers, who can diagnose themselves any issues arising from
|
||||
modifying the standard process).
|
||||
|
||||
Once filesystem is mounted, ``boot.py`` is executed from it. The standard
|
||||
version of this file is created during first-time module set up and by
|
||||
defaults starts up a WebREPL daemon to handle incoming connections. This
|
||||
file is customizable by end users (for example, you may want to disable
|
||||
WebREPL for extra security, or add other services which should be run on
|
||||
module start-up). But keep in mind that incorrect modifications to boot.py
|
||||
may still lead to boot loops or lock ups, requiring to reflash a module
|
||||
from scratch.
|
||||
|
||||
As a final step of boot procedure, ``main.py`` is executed from filesystem,
|
||||
if exists. This file is a hook to start up a user application each time
|
||||
on boot (instead of going to REPL). For small test applications, you may
|
||||
name them directly as ``main.py``, and upload to module, but instead it's
|
||||
recommended to keep your application(s) in separate files, and have just
|
||||
the following in ``main.py``::
|
||||
|
||||
import my_app
|
||||
my_app.main()
|
||||
|
||||
This will allow to keep structure of your application clear, as well as
|
||||
allow to install multiple applications on a board, and switch among them.
|
||||
304
docs/esp8266/quickref.rst
Normal file
304
docs/esp8266/quickref.rst
Normal file
@@ -0,0 +1,304 @@
|
||||
.. _quickref:
|
||||
|
||||
Quick reference for the ESP8266
|
||||
===============================
|
||||
|
||||
.. image:: https://learn.adafruit.com/system/assets/assets/000/028/689/medium640/adafruit_products_pinoutstop.jpg
|
||||
:alt: Adafruit Feather HUZZAH board
|
||||
:width: 640px
|
||||
|
||||
The Adafruit Feather HUZZAH board (image attribution: Adafruit).
|
||||
|
||||
General board control
|
||||
---------------------
|
||||
|
||||
The MicroPython REPL is on UART0 (GPIO1=TX, GPIO3=RX) at baudrate 115200.
|
||||
Tab-completion is useful to find out what methods an object has.
|
||||
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
|
||||
the REPL.
|
||||
|
||||
The ``machine`` module::
|
||||
|
||||
import machine
|
||||
|
||||
machine.freq() # get the current frequency of the CPU
|
||||
machine.freq(160000000) # set the CPU frequency to 160 MHz
|
||||
|
||||
The ``esp`` module::
|
||||
|
||||
import esp
|
||||
|
||||
esp.osdebug(None) # turn off vendor O/S debugging messages
|
||||
esp.osdebug(0) # redirect vendor O/S debugging messages to UART(0)
|
||||
|
||||
Networking
|
||||
----------
|
||||
|
||||
The ``network`` module::
|
||||
|
||||
import network
|
||||
|
||||
wlan = network.WLAN(network.STA_IF) # create station interface
|
||||
wlan.active(True) # activate the interface
|
||||
wlan.scan() # scan for access points
|
||||
wlan.isconnected() # check if the station is connected to an AP
|
||||
wlan.connect('essid', 'password') # connect to an AP
|
||||
wlan.mac() # get the interface's MAC adddress
|
||||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
|
||||
|
||||
ap = network.WLAN(network.AP_IF) # create access-point interface
|
||||
ap.active(True) # activate the interface
|
||||
ap.config(essid='ESP-AP') # set the ESSID of the access point
|
||||
|
||||
A useful function for connecting to your local WiFi network is::
|
||||
|
||||
def do_connect():
|
||||
import network
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
if not wlan.isconnected():
|
||||
print('connecting to network...')
|
||||
wlan.connect('essid', 'password')
|
||||
while not wlan.isconnected():
|
||||
pass
|
||||
print('network config:', wlan.ifconfig())
|
||||
|
||||
Once the network is established the ``socket`` module can be used
|
||||
to create and use TCP/UDP sockets as usual.
|
||||
|
||||
Delay and timing
|
||||
----------------
|
||||
|
||||
Use the ``time`` module::
|
||||
|
||||
import time
|
||||
|
||||
time.sleep(1) # sleep for 1 second
|
||||
time.sleep_ms(500) # sleep for 500 milliseconds
|
||||
time.sleep_us(10) # sleep for 10 microseconds
|
||||
start = time.ticks_ms() # get millisecond counter
|
||||
delta = time.ticks_diff(start, time.ticks_ms()) # compute time difference
|
||||
|
||||
Timers
|
||||
------
|
||||
|
||||
Virtual (RTOS-based) timers are supported. Use the ``machine.Timer`` class
|
||||
with timer ID of -1::
|
||||
|
||||
from machine import Timer
|
||||
|
||||
tim = Timer(-1)
|
||||
tim.init(period=5000, mode=Timer.ONE_SHOT, callback=lambda t:print(1))
|
||||
tim.init(period=2000, mode=Timer.PERIODIC, callback=lambda t:print(2))
|
||||
|
||||
The period is in milliseconds.
|
||||
|
||||
Pins and GPIO
|
||||
-------------
|
||||
|
||||
Use the ``machine.Pin`` class::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
p0 = Pin(0, Pin.OUT) # create output pin on GPIO0
|
||||
p0.high() # set pin to high
|
||||
p0.low() # set pin to low
|
||||
p0.value(1) # set pin to high
|
||||
|
||||
p2 = Pin(2, Pin.IN) # create input pin on GPIO2
|
||||
print(p2.value()) # get value, 0 or 1
|
||||
|
||||
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
|
||||
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
|
||||
|
||||
Available pins are: 0, 1, 2, 3, 4, 5, 12, 13, 14, 15, 16, which correspond
|
||||
to the actual GPIO pin numbers of ESP8266 chip. Note that many end-user
|
||||
boards use their own adhoc pin numbering (marked e.g. D0, D1, ...). As
|
||||
MicroPython supports different boards and modules, physical pin numbering
|
||||
was chosen as the lowest common denominator. For mapping between board
|
||||
logical pins and physical chip pins, consult your board documentation.
|
||||
|
||||
Note that Pin(1) and Pin(3) are REPL UART TX and RX respectively.
|
||||
Also note that Pin(16) is a special pin (used for wakeup from deepsleep
|
||||
mode) and may be not available for use with higher-level classes like
|
||||
``Neopixel``.
|
||||
|
||||
PWM (pulse width modulation)
|
||||
----------------------------
|
||||
|
||||
PWM can be enabled on all pins except Pin(16). There is a single frequency
|
||||
for all channels, with range between 1 and 1000 (measured in Hz). The duty
|
||||
cycle is between 0 and 1023 inclusive.
|
||||
|
||||
Use the ``machine.PWM`` class::
|
||||
|
||||
from machine import Pin, PWM
|
||||
|
||||
pwm0 = PWM(Pin(0)) # create PWM object from a pin
|
||||
pwm0.freq() # get current frequency
|
||||
pwm0.freq(1000) # set frequency
|
||||
pwm0.duty() # get current duty cycle
|
||||
pwm0.duty(200) # set duty cycle
|
||||
pwm0.deinit() # turn off PWM on the pin
|
||||
|
||||
pwm2 = PWM(Pin(2), freq=500, duty=512) # create and configure in one go
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
|
||||
ADC is available on a dedicated pin.
|
||||
Note that input voltages on the ADC pin must be between 0v and 1.0v.
|
||||
|
||||
Use the ``machine.ADC`` class::
|
||||
|
||||
from machine import ADC
|
||||
|
||||
adc = ADC(0) # create ADC object on ADC pin
|
||||
adc.read() # read value, 0-1024
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
|
||||
The SPI driver is implemented in software and works on all pins::
|
||||
|
||||
from machine import Pin, SPI
|
||||
|
||||
# construct an SPI bus on the given pins
|
||||
# polarity is the idle state of SCK
|
||||
# phase=0 means sample on the first edge of SCK, phase=1 means the second
|
||||
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
|
||||
|
||||
spi.init(baudrate=200000) # set the baudrate
|
||||
|
||||
spi.read(10) # read 10 bytes on MISO
|
||||
spi.read(10, 0xff) # read 10 bytes while outputing 0xff on MOSI
|
||||
|
||||
buf = bytearray(50) # create a buffer
|
||||
spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case)
|
||||
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI
|
||||
|
||||
spi.write(b'12345') # write 5 bytes on MOSI
|
||||
|
||||
buf = bytearray(4) # create a buffer
|
||||
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
|
||||
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
||||
The I2C driver is implemented in software and works on all pins::
|
||||
|
||||
from machine import Pin, I2C
|
||||
|
||||
# construct an I2C bus
|
||||
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
|
||||
|
||||
i2c.readfrom(0x3a, 4) # read 4 bytes from slave device with address 0x3a
|
||||
i2c.writeto(0x3a, '12') # write '12' to slave device with address 0x3a
|
||||
|
||||
buf = bytearray(10) # create a buffer with 10 bytes
|
||||
i2c.writeto(0x3a, buf) # write the given buffer to the slave
|
||||
|
||||
i2c.readfrom(0x3a, 4, stop=False) # don't send a stop bit after reading
|
||||
i2c.writeto(0x3a, buf, stop=False) # don't send a stop bit after writing
|
||||
|
||||
Deep-sleep mode
|
||||
---------------
|
||||
|
||||
Connect GPIO16 to the reset pin (RST on HUZZAH). Then the following code
|
||||
can be used to sleep, wake and check the reset cause::
|
||||
|
||||
import machine
|
||||
|
||||
# configure RTC.ALARM0 to be able to wake the device
|
||||
rtc = machine.RTC()
|
||||
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
|
||||
|
||||
# check if the device woke from a deep sleep
|
||||
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
|
||||
print('woke from a deep sleep')
|
||||
|
||||
# set RTC.ALARM0 to fire after 10 seconds (waking the device)
|
||||
rtc.alarm(rtc.ALARM0, 10000)
|
||||
|
||||
# put the device to sleep
|
||||
machine.deepsleep()
|
||||
|
||||
OneWire driver
|
||||
--------------
|
||||
|
||||
The OneWire driver is implemented in software and works on all pins::
|
||||
|
||||
from machine import Pin
|
||||
import onewire
|
||||
|
||||
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
|
||||
ow.scan() # return a list of devices on the bus
|
||||
ow.reset() # reset the bus
|
||||
ow.readbyte() # read a byte
|
||||
ow.read(5) # read 5 bytes
|
||||
ow.writebyte(0x12) # write a byte on the bus
|
||||
ow.write('123') # write bytes on the bus
|
||||
ow.select_rom(b'12345678') # select a specific device by its ROM code
|
||||
|
||||
There is a specific driver for DS18B20 devices::
|
||||
|
||||
import time
|
||||
ds = onewire.DS18B20(ow)
|
||||
roms = ds.scan()
|
||||
ds.convert_temp()
|
||||
time.sleep_ms(750)
|
||||
for rom in roms:
|
||||
print(ds.read_temp(rom))
|
||||
|
||||
Be sure to put a 4.7k pull-up resistor on the data line. Note that
|
||||
the ``convert_temp()`` method must be called each time you want to
|
||||
sample the temperature.
|
||||
|
||||
NeoPixel driver
|
||||
---------------
|
||||
|
||||
Use the ``neopixel`` module::
|
||||
|
||||
from machine import Pin
|
||||
from neopixel import NeoPixel
|
||||
|
||||
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels
|
||||
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels
|
||||
np[0] = (255, 255, 255) # set the first pixel to white
|
||||
np.write() # write data to all pixels
|
||||
r, g, b = np[0] # get first pixel colour
|
||||
|
||||
For low-level driving of a NeoPixel::
|
||||
|
||||
import esp
|
||||
esp.neopixel_write(pin, grb_buf, is800khz)
|
||||
|
||||
WebREPL (web browser interactive prompt)
|
||||
----------------------------------------
|
||||
|
||||
WebREPL (REPL over WebSockets, accessible via a web browser) is an
|
||||
experimental feature available in ESP8266 port. Download web client
|
||||
from https://github.com/micropython/webrepl , and start daemon using::
|
||||
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
|
||||
(Release version will have it started on boot by default.)
|
||||
|
||||
On a first connection, you will be prompted to set password for future
|
||||
sessions to use.
|
||||
|
||||
The supported way to use WebREPL is by connecting to ESP8266 access point,
|
||||
but the daemon is also started on STA interface if it is active, so if your
|
||||
routers is set up and works correctly, you may also use it while connecting
|
||||
to your normal Internet access point (use ESP8266 AP connection method if
|
||||
face any issues).
|
||||
|
||||
WebREPL is an experimental feature and a work in progress, and has known
|
||||
issues. There's also provision to transfer (both upload and download)
|
||||
files over WebREPL connection, but it has unstable status (be ready to
|
||||
reboot a module in case of issues). It still may be a practical way to
|
||||
get script files onto ESP8266, so give it a try using ``webrepl_cli.py``
|
||||
from the repository above. See forum for other community-supported
|
||||
alternatives to transfer files to ESP8266.
|
||||
19
docs/esp8266/tutorial/adc.rst
Normal file
19
docs/esp8266/tutorial/adc.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
Analog to Digital Conversion
|
||||
============================
|
||||
|
||||
The ESP8266 has a single pin (separate to the GPIO pins) which can be used to
|
||||
read analog voltages and convert them to a digital value. You can construct
|
||||
such an ADC pin object using::
|
||||
|
||||
>>> import machine
|
||||
>>> adc = machine.ADC(0)
|
||||
|
||||
Then read its value with::
|
||||
|
||||
>>> adc.read()
|
||||
58
|
||||
|
||||
The values returned from the ``read()`` function are between 0 (for 0.0 volts)
|
||||
and 1024 (for 1.0 volts). Please note that this input can only tolerate a
|
||||
maximum of 1.0 volts and you must use a voltage divider circuit to measure
|
||||
larger voltages.
|
||||
70
docs/esp8266/tutorial/filesystem.rst
Normal file
70
docs/esp8266/tutorial/filesystem.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
The internal filesystem
|
||||
=======================
|
||||
|
||||
If your devices has 1Mbyte or more of storage then it will be set up (upon first
|
||||
boot) to contain a filesystem. This filesystem uses the FAT format and is
|
||||
stored in the flash after the MicroPython firmware.
|
||||
|
||||
Creating and reading files
|
||||
--------------------------
|
||||
|
||||
MicroPython on the ESP8266 supports the standard way of accessing files in
|
||||
Python, using the built-in ``open()`` function.
|
||||
|
||||
To create a file try::
|
||||
|
||||
>>> f = open('data.txt', 'w')
|
||||
>>> f.write('some data')
|
||||
9
|
||||
>>> f.close()
|
||||
|
||||
The "9" is the number of bytes that were written with the ``write()`` method.
|
||||
Then you can read back the contents of this new file using::
|
||||
|
||||
>>> f = open('data.txt')
|
||||
>>> f.read()
|
||||
'some data'
|
||||
>>> f.close()
|
||||
|
||||
Note that the default mode when opening a file is to open it in read-only mode,
|
||||
and as a text file. Specify ``'wb'`` as the second argument to ``open()`` to
|
||||
open for writing in binary mode, and ``'rb'`` to open for reading in binary
|
||||
mode.
|
||||
|
||||
Listing file and more
|
||||
---------------------
|
||||
|
||||
The os module can be used for further control over the filesystem. First
|
||||
import the module::
|
||||
|
||||
>>> import os
|
||||
|
||||
Then try listing the contents of the filesystem::
|
||||
|
||||
>>> os.listdir()
|
||||
['boot.py', 'port_config.py', 'data.txt']
|
||||
|
||||
You can make directories::
|
||||
|
||||
>>> os.mkdir('dir')
|
||||
|
||||
And remove entries::
|
||||
|
||||
>>> os.remove('data.txt')
|
||||
|
||||
Start up scripts
|
||||
----------------
|
||||
|
||||
There are two files that are treated specially by the ESP8266 when it starts up:
|
||||
boot.py and main.py. The boot.py script is executed first (if it exists) and
|
||||
then once it completes the main.py script is executed. You can create these
|
||||
files yourself and populate them with the code that you want to run when the
|
||||
device starts up.
|
||||
|
||||
Accessing the filesystem via WebREPL
|
||||
------------------------------------
|
||||
|
||||
You can access the filesystem over WebREPL using the provided command-line
|
||||
tool. This tool is found at `<https://github.com/micropython/webrepl>`__
|
||||
and is called webrepl_cli.py. Please refer to that program for information
|
||||
on how to use it.
|
||||
32
docs/esp8266/tutorial/index.rst
Normal file
32
docs/esp8266/tutorial/index.rst
Normal file
@@ -0,0 +1,32 @@
|
||||
.. _tutorial-index:
|
||||
|
||||
MicroPython tutorial for ESP8266
|
||||
================================
|
||||
|
||||
This tutorial is intended to get you started using MicroPython on the ESP8266
|
||||
system-on-a-chip. If it is your first time it is recommended to follow the
|
||||
tutorial through in the order below. Otherwise the sections are mostly self
|
||||
contained, so feel free to skip to those that interest you.
|
||||
|
||||
The tutorial does not assume that you know Python, but it also does not attempt
|
||||
to explain any of the details of the Python language. Instead it provides you
|
||||
with commands that are ready to run, and hopes that you will gain a bit of
|
||||
Python knowledge along the way. To learn more about Python itself please refer
|
||||
to `<https://www.python.org>`__.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:numbered:
|
||||
|
||||
intro.rst
|
||||
repl.rst
|
||||
filesystem.rst
|
||||
network_basics.rst
|
||||
network_tcp.rst
|
||||
pins.rst
|
||||
pwm.rst
|
||||
adc.rst
|
||||
powerctrl.rst
|
||||
onewire.rst
|
||||
neopixel.rst
|
||||
nextsteps.rst
|
||||
102
docs/esp8266/tutorial/intro.rst
Normal file
102
docs/esp8266/tutorial/intro.rst
Normal file
@@ -0,0 +1,102 @@
|
||||
Introduction to MicroPython on the ESP8266
|
||||
==========================================
|
||||
|
||||
Using MicroPython is a great way to get the most of your ESP8266 board. And
|
||||
vice versa, the ESP8266 chip is a great platform for using MicroPython. This
|
||||
tutorial will guide you through setting up MicroPython, getting a prompt, using
|
||||
WebREPL, connecting to the network and communicating with the Internet, using
|
||||
the hardware peripherals, and controlling some external components.
|
||||
|
||||
Let's get started!
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
The first thing you need is a board with an ESP8266 chip. The MicroPython
|
||||
software supports the ESP8266 chip itself and any board should work. The main
|
||||
characteristic of a board is how much flash it has, how the GPIO pins are
|
||||
connected to the outside world, and whether it includes a built-in USB-serial
|
||||
convertor to make the UART available to your PC.
|
||||
|
||||
The minimum requirement for flash size is 512k. A board with this amount of
|
||||
flash will not have room for a filesystem, but otherwise is fully functional.
|
||||
If your board has 1Mbyte or more of flash then it will support a filesystem.
|
||||
|
||||
Names of pins will be given in this tutorial using the chip names (eg GPIO0)
|
||||
and it should be straightforward to find which pin this corresponds to on your
|
||||
particular board.
|
||||
|
||||
Powering the board
|
||||
------------------
|
||||
|
||||
If your board has a USB connector on it then most likely it is powered through
|
||||
this when connected to your PC. Otherwise you will need to power it directly.
|
||||
Please refer to the documentation for your board for further details.
|
||||
|
||||
Deploying the firmware
|
||||
----------------------
|
||||
|
||||
The very first thing you need to do is put the MicroPython firmware (compiled
|
||||
code) on your ESP8266 device. There are two main steps to do this: first you
|
||||
need to put your device in boot-loader mode, and second you need to copy across
|
||||
the firmware. The exact procedure for these steps is highly dependent on the
|
||||
particular board and you will need to refer to its documentation for details.
|
||||
|
||||
If you have a board that has a USB connector, a USB-serial convertor, and has
|
||||
the DTR and RTS pins wired in a special way then deploying the firmware should
|
||||
be easy as all steps can be done automatically. Boards that have such features
|
||||
include the Adafruit Feather HUZZAH and NodeMCU boards.
|
||||
|
||||
For best results it is recommended to first erase the entire flash of your
|
||||
device before putting on new MicroPython firmware.
|
||||
|
||||
Currently we only support esptool.py to copy across the firmware. You can find
|
||||
this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
|
||||
using pip::
|
||||
|
||||
pip install esptool
|
||||
|
||||
It requires Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in
|
||||
the command above. Any other
|
||||
flashing program should work, so feel free to try them out, or refer to the
|
||||
documentation for your board to see its recommendations.
|
||||
|
||||
Using esptool.py you can erase the flash with the command::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 erase_flash
|
||||
|
||||
And then deploy the new firmware using::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
You might need to change the "port" setting to something else relevant for your
|
||||
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||
(eg down to 115200). The filename of the firmware should also match the file
|
||||
that you have.
|
||||
|
||||
If you have a NodeMCU board, you may need to use the following command to deploy
|
||||
the firmware (note the "-fm dio" option)::
|
||||
|
||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=8m -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
||||
|
||||
If the above commands run without error then MicroPython should be installed on
|
||||
your board!
|
||||
|
||||
Serial prompt
|
||||
-------------
|
||||
|
||||
Once you have the firmware on the device you can access the REPL (Python prompt)
|
||||
over UART0 (GPIO1=TX, GPIO3=RX), which might be connected to a USB-serial
|
||||
convertor, depending on your board. The baudrate is 115200. The next part of
|
||||
the tutorial will discuss the prompt in more detail.
|
||||
|
||||
WiFi
|
||||
----
|
||||
|
||||
After a fresh install and boot the device configures itself as a WiFi access
|
||||
point (AP) that you can connect to. The ESSID is of the form MicroPython-xxxxxx
|
||||
where the x's are replaced with part of the MAC address of your device (so will
|
||||
be the same everytime, and most likely different for all ESP8266 chips). The
|
||||
password for the WiFi is micropythoN (note the upper-case N). Its IP address
|
||||
will be 192.168.4.1 once you connect to its network. WiFi configuration will
|
||||
be discussed in more detail later in the tutorial.
|
||||
70
docs/esp8266/tutorial/neopixel.rst
Normal file
70
docs/esp8266/tutorial/neopixel.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
Controlling NeoPixels
|
||||
=====================
|
||||
|
||||
NeoPixels, also known as WS2812 LEDs, are full-colour LEDs that are connected in
|
||||
serial, are individually addressable, and can have their red, green and blue
|
||||
components set between 0 and 255. They require precise timing to control them
|
||||
and there is a special neopixel module to do just this.
|
||||
|
||||
To create a NeoPixel object do the following::
|
||||
|
||||
>>> import machine, neopixel
|
||||
>>> np = neopixel.NeoPixel(machine.Pin(4), 8)
|
||||
|
||||
This configures a NeoPixel strip on GPIO4 with 8 pixels. You can adjust the
|
||||
"4" (pin number) and the "8" (number of pixel) to suit your set up.
|
||||
|
||||
To set the colour of pixels use::
|
||||
|
||||
>>> np[0] = (255, 0, 0) # set to red, full brightness
|
||||
>>> np[1] = (0, 128, 0) # set to green, half brightness
|
||||
>>> np[2] = (0, 0, 64) # set to blue, quarter brightness
|
||||
|
||||
Then use the ``write()`` method to output the colours to the LEDs::
|
||||
|
||||
>>> np.write()
|
||||
|
||||
The following demo function makes a fancy show on the LEDs::
|
||||
|
||||
import time
|
||||
|
||||
def demo(np):
|
||||
n = np.n
|
||||
|
||||
# cycle
|
||||
for i in range(4 * n):
|
||||
for j in range(n):
|
||||
np[j] = (0, 0, 0)
|
||||
np[i % n] = (255, 255, 255)
|
||||
np.write()
|
||||
time.sleep_ms(25)
|
||||
|
||||
# bounce
|
||||
for i in range(4 * n):
|
||||
for j in range(n):
|
||||
np[j] = (0, 0, 128)
|
||||
if (i // n) % 2 == 0:
|
||||
np[i % n] = (0, 0, 0)
|
||||
else:
|
||||
np[n - 1 - (i % n)] = (0, 0, 0)
|
||||
np.write()
|
||||
time.sleep_ms(60)
|
||||
|
||||
# fade in/out
|
||||
for i in range(0, 4 * 256, 8):
|
||||
for j in range(n):
|
||||
if (i // 256) % 2 == 0:
|
||||
val = i & 0xff
|
||||
else:
|
||||
val = 255 - (i & 0xff)
|
||||
np[j] = (val, 0, 0)
|
||||
np.write()
|
||||
|
||||
# clear
|
||||
for i in range(n):
|
||||
np[i] = (0, 0, 0)
|
||||
np.write()
|
||||
|
||||
Execute it using::
|
||||
|
||||
>>> demo(np)
|
||||
81
docs/esp8266/tutorial/network_basics.rst
Normal file
81
docs/esp8266/tutorial/network_basics.rst
Normal file
@@ -0,0 +1,81 @@
|
||||
Network basics
|
||||
==============
|
||||
|
||||
The network module is used to configure the WiFi connection. There are two WiFi
|
||||
interfaces, one for the station (when the ESP8266 connects to a router) and one
|
||||
for the access point (for other devices to connect to the ESP8266). Create
|
||||
instances of these objects using::
|
||||
|
||||
>>> import network
|
||||
>>> sta_if = network.WLAN(network.STA_IF)
|
||||
>>> ap_if = network.WLAN(network.AP_IF)
|
||||
|
||||
You can check if the interfaces are active by::
|
||||
|
||||
>>> sta_if.active()
|
||||
False
|
||||
>>> ap_if.active()
|
||||
True
|
||||
|
||||
You can also check the network settings of the interface by::
|
||||
|
||||
>>> ap.ifconfig()
|
||||
('192.168.4.1', '255.255.255.0', '192.168.4.1', '8.8.8.8')
|
||||
|
||||
The returned values are: IP address, netmask, gateway, DNS.
|
||||
|
||||
Configuration of the WiFi
|
||||
-------------------------
|
||||
|
||||
Upon a fresh install the ESP8266 is configured in access point mode, so the
|
||||
AP_IF interface is active and the STA_IF interface is inactive. You can
|
||||
configure the module to connect to your own network using the STA_IF interface.
|
||||
|
||||
First activate the station interface::
|
||||
|
||||
>>> sta_if.active(True)
|
||||
|
||||
Then connect to your WiFi network::
|
||||
|
||||
>>> sta_if.connect('<your ESSID>', '<your password>')
|
||||
|
||||
To check if the connection is established use::
|
||||
|
||||
>>> sta_if.isconnected()
|
||||
|
||||
Once established you can check the IP address::
|
||||
|
||||
>>> sta_if.ifconfig()
|
||||
('192.168.0.2', '255.255.255.0', '192.168.0.1', '8.8.8.8')
|
||||
|
||||
You can then disable the access-point interface if you no longer need it::
|
||||
|
||||
>>> ap_if.active(False)
|
||||
|
||||
Here is a function you can run (or put in your boot.py file) to automatically
|
||||
connect to your WiFi network::
|
||||
|
||||
def do_connect():
|
||||
import network
|
||||
sta_if = network.WLAN(network.STA_IF)
|
||||
if not sta_if.isconnected():
|
||||
print('connecting to network...')
|
||||
sta_if.active(True)
|
||||
sta_if.connect('<essid>', '<password>')
|
||||
while not network.isconnected():
|
||||
pass
|
||||
print('network config:', sta_if.ifconfig())
|
||||
|
||||
Sockets
|
||||
-------
|
||||
|
||||
Once the WiFi is set up the way to access the network is by using sockets.
|
||||
A socket represents an endpoint on a network device, and when two sockets are
|
||||
connected together communication can proceed.
|
||||
Internet protocols are built on top of sockets, such as email (SMTP), the web
|
||||
(HTTP), telnet, ssh, among many others. Each of these protocols is assigned
|
||||
a specific port, which is just an integer. Given an IP address and a port
|
||||
number you can connect to a remote device and start talking with it.
|
||||
|
||||
The next part of the tutorial discusses how to use sockets to do some common
|
||||
and useful network tasks.
|
||||
121
docs/esp8266/tutorial/network_tcp.rst
Normal file
121
docs/esp8266/tutorial/network_tcp.rst
Normal file
@@ -0,0 +1,121 @@
|
||||
Network - TCP sockets
|
||||
=====================
|
||||
|
||||
The building block of most of the internet is the TCP socket. These sockets
|
||||
provide a reliable stream of bytes between the connected network devices.
|
||||
This part of the tutorial will show how to use TCP sockets in a few different
|
||||
cases.
|
||||
|
||||
Star Wars Asciimation
|
||||
---------------------
|
||||
|
||||
The simplest thing to do is to download data from the internet. In this case
|
||||
we will use the Star Wars Asciimation service provided by the blinkenlights.nl
|
||||
website. It uses the telnet protocol on port 23 to stream data to anyone that
|
||||
connects. It's very simple to use because it doesn't require you to
|
||||
authenticate (give a username or password), you can just start downloading data
|
||||
straight away.
|
||||
|
||||
The first thing to do is make sure we have the socket module available::
|
||||
|
||||
>>> import socket
|
||||
|
||||
Then get the IP address of the server::
|
||||
|
||||
>>> addr_info = socket.getaddrinfo("towel.blinkenlights.nl", 23)
|
||||
|
||||
The ``getaddrinfo`` function actually returns a list of addresses, and each
|
||||
address has more information than we need. We want to get just the first valid
|
||||
address, and then just the IP address and port of the server. To do this use::
|
||||
|
||||
>>> addr = addr_info[0][-1]
|
||||
|
||||
If you type ``addr_info`` and ``addr`` at the prompt you will see exactly what
|
||||
information they hold.
|
||||
|
||||
Using the IP address we can make a socket and connect to the server::
|
||||
|
||||
>>> s = socket.socket()
|
||||
>>> s.connect(addr[0][-1])
|
||||
|
||||
Now that we are connected we can download and display the data::
|
||||
|
||||
>>> while True:
|
||||
... data = s.recv(500)
|
||||
... print(str(data, 'utf8'), end='')
|
||||
...
|
||||
|
||||
When this loop executes it should start showing the animation (use ctrl-C to
|
||||
interrupt it).
|
||||
|
||||
You should also be able to run this same code on your PC using normal Python if
|
||||
you want to try it out there.
|
||||
|
||||
HTTP GET request
|
||||
----------------
|
||||
|
||||
The next example shows how to download a webpage. HTTP uses port 80 and you
|
||||
first need to send a "GET" request before you can download anything. As part
|
||||
of the request you need to specify the page to retrieve.
|
||||
|
||||
Let's define a function that can download and print a URL::
|
||||
|
||||
def http_get(url):
|
||||
_, _, host, path = url.split('/', 3)
|
||||
addr = socket.getaddrinfo(host, 80)[0][-1]
|
||||
s = socket.socket()
|
||||
s.connect(addr)
|
||||
s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
|
||||
while True:
|
||||
data = s.recv(100)
|
||||
if data:
|
||||
print(str(data, 'utf8'), end='')
|
||||
else:
|
||||
break
|
||||
|
||||
Make sure that you import the socket module before running this function. Then
|
||||
you can try::
|
||||
|
||||
>>> http_get('http://micropython.org/ks/test.html')
|
||||
|
||||
This should retrieve the webpage and print the HTML to the console.
|
||||
|
||||
Simple HTTP server
|
||||
------------------
|
||||
|
||||
The following code creates an simple HTTP server which serves a single webpage
|
||||
that contains a table with the state of all the GPIO pins::
|
||||
|
||||
import machine
|
||||
pins = [machine.Pin(i, machine.Pin.IN) for i in (0, 2, 4, 5, 12, 13, 14, 15)]
|
||||
|
||||
html = """<!DOCTYPE html>
|
||||
<html>
|
||||
<head> <title>ESP8266 Pins</title> </head>
|
||||
<body> <h1>ESP8266 Pins</h1>
|
||||
<table border="1"> <tr><th>Pin</th><th>Value</th></tr> %s </table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
import socket
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
|
||||
s = socket.socket()
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
|
||||
print('listening on', addr)
|
||||
|
||||
while True:
|
||||
cl, addr = s.accept()
|
||||
print('client connected from', addr)
|
||||
cl_file = cl.makefile('rwb', 0)
|
||||
while True:
|
||||
line = cl_file.readline()
|
||||
if not line or line == b'\r\n':
|
||||
break
|
||||
rows = ['<tr><td>%s</td><td>%d</td></tr>' % (str(p), p.value()) for p in pins]
|
||||
response = html % '\n'.join(rows)
|
||||
cl.send(response)
|
||||
cl.close()
|
||||
12
docs/esp8266/tutorial/nextsteps.rst
Normal file
12
docs/esp8266/tutorial/nextsteps.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
Next steps
|
||||
==========
|
||||
|
||||
That brings us to the end of the tutorial! Hopefully by now you have a good
|
||||
feel for the capabilities of MicroPython on the ESP8266 and understand how to
|
||||
control both the WiFi and IO aspects of the chip.
|
||||
|
||||
There are many features that were not covered in this tutorial. The best way
|
||||
to learn about them is to read the full documentation of the modules, and to
|
||||
experiment!
|
||||
|
||||
Good luck creating your Internet of Things devices!
|
||||
37
docs/esp8266/tutorial/onewire.rst
Normal file
37
docs/esp8266/tutorial/onewire.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Controlling 1-wire devices
|
||||
==========================
|
||||
|
||||
The 1-wire bus is a serial bus that uses just a single wire for communication
|
||||
(in addition to wires for ground and power). The DS18B20 temperature sensor
|
||||
is a very popular 1-wire device, and here we show how to use the onewire module
|
||||
to read from such a device.
|
||||
|
||||
For the following code to work you need to have at least one DS18B20 temperature
|
||||
sensor with its data line connected to GPIO12. You must also power the sensors
|
||||
and connect a 4.7k Ohm resistor between the data pin and the power pin. ::
|
||||
|
||||
import time
|
||||
import machine
|
||||
import onewire
|
||||
|
||||
# the device is on GPIO12
|
||||
dat = machine.Pin(12)
|
||||
|
||||
# create the onewire object
|
||||
ds = onewire.DS18B20(onewire.OneWire(dat))
|
||||
|
||||
# scan for devices on the bus
|
||||
roms = ds.scan()
|
||||
print('found devices:', roms)
|
||||
|
||||
# loop 10 times and print all temperatures
|
||||
for i in range(10):
|
||||
print('temperatures:', end=' ')
|
||||
ds.convert_temp()
|
||||
time.sleep_ms(750)
|
||||
for rom in roms:
|
||||
print(ds.read_temp(rom), end=' ')
|
||||
print()
|
||||
|
||||
Note that you must execute the ``convert_temp()`` function to initiate a
|
||||
temperature reading, then wait at least 750ms before reading the value.
|
||||
75
docs/esp8266/tutorial/pins.rst
Normal file
75
docs/esp8266/tutorial/pins.rst
Normal file
@@ -0,0 +1,75 @@
|
||||
GPIO Pins
|
||||
=========
|
||||
|
||||
The way to connect your board to the external world, and control other
|
||||
components, is through the GPIO pins. Not all pins are available to use,
|
||||
in most cases only pins 0, 2, 4, 5, 12, 13, 14, 15, and 16 can be used.
|
||||
|
||||
The pins are available in the machine module, so make sure you import that
|
||||
first. Then you can create a pin using::
|
||||
|
||||
>>> pin = machine.Pin(0)
|
||||
|
||||
Here, the "0" is the pin that you want to access. Usually you want to
|
||||
configure the pin to be input or output, and you do this when constructing
|
||||
it. To make an input pin use::
|
||||
|
||||
>>> pin = machine.Pin(0, machine.Pin.OUT, machine.Pin.PULL_UP)
|
||||
|
||||
You can either use PULL_UP or None for the input pull-mode. If it's
|
||||
not specified then it defaults to None, which is no pull resistor.
|
||||
You can read the value on the pin using::
|
||||
|
||||
>>> pin.value()
|
||||
0
|
||||
|
||||
The pin on your board may return 0 or 1 here, depending on what it's connected
|
||||
to. To make an output pin use::
|
||||
|
||||
>>> pin = machine.Pin(0, machine.Pin.OUT)
|
||||
|
||||
Then set its value using::
|
||||
|
||||
>>> pin.value(0)
|
||||
>>> pin.value(1)
|
||||
|
||||
Or::
|
||||
|
||||
>>> pin.low()
|
||||
>>> pin.high()
|
||||
|
||||
External interrupts
|
||||
-------------------
|
||||
|
||||
All pins except number 16 can be configured to trigger a hard interrupt if their
|
||||
input changes. You can set code (a callback function) to be executed on the
|
||||
trigger.
|
||||
|
||||
Let's first define a callback function, which must take a single argument,
|
||||
being the pin that triggered the function. We will make the function just print
|
||||
the pin::
|
||||
|
||||
>>> def callback(p):
|
||||
... print('pin change', p)
|
||||
|
||||
Next we will create two pins and configure them as inputs::
|
||||
|
||||
>>> from machine import Pin
|
||||
>>> p0 = Pin(0, Pin.IN)
|
||||
>>> p2 = Pin(2, Pin.IN)
|
||||
|
||||
An finally we need to tell the pins when to trigger, and the function to call
|
||||
when they detect an event::
|
||||
|
||||
>>> p0.irq(trigger=Pin.IRQ_FALLING, handler=callback)
|
||||
>>> p2.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=callback)
|
||||
|
||||
We set pin 0 to trigger only on a falling edge of the input (when it goes from
|
||||
high to low), and set pin 2 to trigger on both a rising and falling edge. After
|
||||
entering this code you can apply high and low voltages to pins 0 and 2 to see
|
||||
the interrupt being executed.
|
||||
|
||||
A hard interrupt will trigger as soon as the event occurs and will interrupt any
|
||||
running code, including Python code. As such your callback functions are
|
||||
limited in what they can do (they cannot allocate memory, for example) and
|
||||
should be as short and simple as possible.
|
||||
61
docs/esp8266/tutorial/powerctrl.rst
Normal file
61
docs/esp8266/tutorial/powerctrl.rst
Normal file
@@ -0,0 +1,61 @@
|
||||
Power control
|
||||
=============
|
||||
|
||||
The ESP8266 provides the ability to change the CPU frequency on the fly, and
|
||||
enter a deep-sleep state. Both can be used to manage power consumption.
|
||||
|
||||
Changing the CPU frequency
|
||||
--------------------------
|
||||
|
||||
The machine module has a function to get and set the CPU frequency. To get the
|
||||
current frequency use::
|
||||
|
||||
>>> import machine
|
||||
>>> machine.freq()
|
||||
80000000
|
||||
|
||||
By default the CPU runs at 80MHz. It can be change to 160MHz if you need more
|
||||
processing power, at the expense of current consumption::
|
||||
|
||||
>>> machine.freq(160000000)
|
||||
>>> machine.freq()
|
||||
160000000
|
||||
|
||||
You can change to the higher frequency just while your code does the heavy
|
||||
processing and then change back when its finished.
|
||||
|
||||
Deep-sleep mode
|
||||
---------------
|
||||
|
||||
The deep-sleep mode will shut down the ESP8266 and all its peripherals,
|
||||
including the WiFi (but not including the real-time-clock, which is used to wake
|
||||
the chip). This drastically reduces current consumption and is a good way to
|
||||
make devices that can run for a while on a battery.
|
||||
|
||||
To be able to use the deep-sleep feature you must connect GPIO16 to the reset
|
||||
pin (RST on the Adafruit Feather HUZZAH board). Then the following code can be
|
||||
used to sleep and wake the device::
|
||||
|
||||
import machine
|
||||
|
||||
# configure RTC.ALARM0 to be able to wake the device
|
||||
rtc = machine.RTC()
|
||||
rtc.irq(trigger=rtc.ALARM0, wake=machine.DEEPSLEEP)
|
||||
|
||||
# set RTC.ALARM0 to fire after 10 seconds (waking the device)
|
||||
rtc.alarm(rtc.ALARM0, 10000)
|
||||
|
||||
# put the device to sleep
|
||||
machine.deepsleep()
|
||||
|
||||
Note that when the chip wakes from a deep-sleep it is completely reset,
|
||||
including all of the memory. The boot scripts will run as usual and you can
|
||||
put code in them to check the reset cause to perhaps do something different if
|
||||
the device just woke from a deep-sleep. For example, to print the reset cause
|
||||
you can use::
|
||||
|
||||
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
|
||||
print('woke from a deep sleep')
|
||||
else:
|
||||
print('power on or hard reset')
|
||||
|
||||
87
docs/esp8266/tutorial/pwm.rst
Normal file
87
docs/esp8266/tutorial/pwm.rst
Normal file
@@ -0,0 +1,87 @@
|
||||
Pulse Width Modulation
|
||||
======================
|
||||
|
||||
Pulse width modulation (PWM) is a way to get an artificial analog output on a
|
||||
digital pin. It achieves this by rapidly toggling the pin from low to high.
|
||||
There are two parameters associated with this: the frequency of the toggling,
|
||||
and the duty cycle. The duty cycle is defined to be how long the pin is high
|
||||
compared with the length of a single period (low plus high time). Maximum
|
||||
duty cycle is when the pin is high all of the time, and minimum is when it is
|
||||
low all of the time.
|
||||
|
||||
On the ESP8266 the pins 0, 2, 4, 5, 12, 13, 14 and 15 all support PWM. The
|
||||
limitation is that they must all be at the same frequency, and the frequency
|
||||
must be between 1Hz and 1kHz.
|
||||
|
||||
To use PWM on a pin you must first create the pin object, for example::
|
||||
|
||||
>>> import machine
|
||||
>>> p12 = machine.Pin(12)
|
||||
|
||||
Then create the PWM object using::
|
||||
|
||||
>>> pwm12 = machine.PWM(p12)
|
||||
|
||||
You can set the frequency and duty cycle using::
|
||||
|
||||
>>> pwm12.freq(500)
|
||||
>>> pwm12.duty(512)
|
||||
|
||||
Note that the duty cycle is between 0 (all off) and 1023 (all on), with 512
|
||||
being a 50% duty. If you print the PWM object then it will tell you its current
|
||||
configuration::
|
||||
|
||||
>>> pwm12
|
||||
PWM(12, freq=500, duty=512)
|
||||
|
||||
You can also call the ``freq()`` and ``duty()`` methods with no arguments to
|
||||
get their current values.
|
||||
|
||||
The pin will continue to be in PWM mode until you deinitialise it using::
|
||||
|
||||
>>> pwm12.deinit()
|
||||
|
||||
Fading an LED
|
||||
-------------
|
||||
|
||||
Let's use the PWM feature to fade an LED. Assuming your board has an LED
|
||||
connected to pin 2 (ESP-12 modules do) we can create an LED-PWM object using::
|
||||
|
||||
>>> led = machine.PWM(machine.Pin(2), freq=1000)
|
||||
|
||||
Notice that we can set the frequency in the PWM constructor.
|
||||
|
||||
For the next part we will use timing and some math, so import these modules::
|
||||
|
||||
>>> import time, math
|
||||
|
||||
Then create a function to pulse the LED::
|
||||
|
||||
>>> def pulse(l, t):
|
||||
... for i in range(20):
|
||||
... l.duty(int(math.sin(i / 10 * math.pi) * 500 + 500))
|
||||
... time.sleep_ms(t)
|
||||
|
||||
You can try this function out using::
|
||||
|
||||
>>> pulse(led, 50)
|
||||
|
||||
For a nice effect you can pulse many times in a row::
|
||||
|
||||
>>> for i in range(10):
|
||||
... pulse(led, 20)
|
||||
|
||||
Remember you can use ctrl-C to interrupt the code.
|
||||
|
||||
Control a hobby servo
|
||||
---------------------
|
||||
|
||||
Hobby servo motors can be controlled using PWM. They require a frequency of
|
||||
50Hz and then a duty between about 40 and 115, with 77 being the centre value.
|
||||
If you connect a servo to the power and ground pins, and then the signal line
|
||||
to pin 12 (other pins will work just as well), you can control the motor using::
|
||||
|
||||
>>> servo = machine.PWM(machine.Pin(12), freq=50)
|
||||
>>> servo.duty(40)
|
||||
>>> servo.duty(115)
|
||||
>>> servo.duty(77)
|
||||
207
docs/esp8266/tutorial/repl.rst
Normal file
207
docs/esp8266/tutorial/repl.rst
Normal file
@@ -0,0 +1,207 @@
|
||||
Getting a MicroPython REPL prompt
|
||||
=================================
|
||||
|
||||
REPL stands for Read Evaluate Print Loop, and is the name given to the
|
||||
interactive MicroPython prompt that you can access on the ESP8266. Using the
|
||||
REPL is by far the easiest way to test out your code and run commands.
|
||||
|
||||
There are two ways to access the REPL: either via a wired connection through the
|
||||
UART serial port, or via WiFi.
|
||||
|
||||
REPL over the serial port
|
||||
-------------------------
|
||||
|
||||
The REPL is always available on the UART0 serial peripheral, which is connected
|
||||
to the pins GPIO1 for TX and GPIO3 for RX. The baudrate of the REPL is 115200.
|
||||
If your board has a USB-serial convertor on it then you should be able to access
|
||||
the REPL directly from your PC. Otherwise you will need to have a way of
|
||||
communicating with the UART.
|
||||
|
||||
To access the prompt over USB-serial you need to use a terminal emulator program.
|
||||
On Windows TeraTerm is a good choice, on Mac you can use the built-in screen
|
||||
program, and Linux has picocom and minicom. Of course, there are many other
|
||||
terminal programs that will work, so pick your favourite!
|
||||
|
||||
For example, on Linux you can try running::
|
||||
|
||||
picocom /dev/ttyUSB0
|
||||
|
||||
Once you have made the connection over the serial port you can test if it is
|
||||
working by hitting enter a few times. You should see the Python REPL prompt,
|
||||
indicated by ``>>>``.
|
||||
|
||||
WebREPL - a prompt over WiFi
|
||||
----------------------------
|
||||
|
||||
WebREPL allows you to use the Python prompt over WiFi, connecting through a
|
||||
browser. The latest versions of Firefox and Chrome are supported.
|
||||
|
||||
For your convinience, WebREPL client is hosted at
|
||||
`<http://micropython.org/webrepl>`__ . Alternatively, you can install it
|
||||
locally from the the GitHub repository
|
||||
`<https://github.com/micropython/webrepl>`__ .
|
||||
|
||||
To use WebREPL connect your computer to the ESP8266's access point
|
||||
(MicroPython-xxxxxx, see the previous section about this). If you have
|
||||
already reconfigured your ESP8266 to connect to a router then you can
|
||||
skip this part.
|
||||
|
||||
Once you are on the same network as the ESP8266 you click the "Connect" button
|
||||
(if you are connecting via a router then you may need to change the IP address,
|
||||
by default the IP address is correct when connected to the ESP8266's access
|
||||
point). If the connection succeeds then you should see a welcome message.
|
||||
|
||||
On the first connection you need to set a password. Make sure that the
|
||||
terminal widget is selected by clicking on it, and then follow prompts to
|
||||
type in your password twice (they should match each other). Then ESP8266
|
||||
will then reboot with the password applied (the WiFi will go down but come
|
||||
back up again). Note that some modules may have troubles rebooting
|
||||
automatically and need reset button press or power cycle (do this if
|
||||
you don't see ESP8266 access point appearing in a minute or so).
|
||||
|
||||
You should then click the "Connect" button again, and enter your password
|
||||
to connect. If you type in the correct password you should get a prompt
|
||||
looking like ``>>>``. You can now start typing Python commands!
|
||||
|
||||
Using the REPL
|
||||
--------------
|
||||
|
||||
Once you have a prompt you can start experimenting! Anything you type at the
|
||||
prompt will be executed after you press the Enter key. MicroPython will run
|
||||
the code that you enter and print the result (if there is one). If there is an
|
||||
error with the text that you enter then an error message is printed.
|
||||
|
||||
Try typing the following at the prompt::
|
||||
|
||||
>>> print('hello esp8266!')
|
||||
hello esp8266!
|
||||
|
||||
Note that you shouldn't type the ``>>>`` arrows, they are there to indicate that
|
||||
you should type the text after it at the prompt. And then the line following is
|
||||
what the device should respond with. In the end, once you have entered the text
|
||||
``print("hello esp8266!")`` and pressed the Enter key, the output on your screen
|
||||
should look exactly like it does above.
|
||||
|
||||
If you already know some python you can now try some basic commands here. For
|
||||
example::
|
||||
|
||||
>>> 1 + 2
|
||||
3
|
||||
>>> 1 / 2
|
||||
0.5
|
||||
>>> 12**34
|
||||
4922235242952026704037113243122008064
|
||||
|
||||
If your board has an LED attached to GPIO2 (the ESP-12 modules do) then you can
|
||||
turn it on and off using the following code::
|
||||
|
||||
>>> import machine
|
||||
>>> pin = machine.Pin(2, machine.Pin.OUT)
|
||||
>>> pin.high()
|
||||
>>> pin.low()
|
||||
|
||||
Note that ``high`` might turn the LED off and ``low`` might turn it on (or vice
|
||||
versa), depending on how the LED is wired on your board.
|
||||
|
||||
Line editing
|
||||
~~~~~~~~~~~~
|
||||
|
||||
You can edit the current line that you are entering using the left and right
|
||||
arrow keys to move the cursor, as well as the delete and backspace keys. Also,
|
||||
pressing Home or ctrl-A moves the cursor to the start of the line, and pressing
|
||||
End or ctrl-E moves to the end of the line.
|
||||
|
||||
Input history
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The REPL remembers a certain number of previous lines of text that you entered
|
||||
(up to 8 on the ESP8266). To recall previous lines use the up and down arrow
|
||||
keys.
|
||||
|
||||
Tab completion
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Pressing the Tab key will do an auto-completion of the current word that you are
|
||||
entering. This can be very useful to find out functions and methods that a
|
||||
module or object has. Try it out by typing "ma" and then pressing Tab. It
|
||||
should complete to "machine" (assuming you imported machine in the above
|
||||
example). Then type "." and press Tab again to see a list of all the functions
|
||||
that the machine module has.
|
||||
|
||||
Line continuation and auto-indent
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Certain things that you type will need "continuing", that is, will need more
|
||||
lines of text to make a proper Python statement. In this case the prompt will
|
||||
change to ``...`` and the cursor will auto-indent the correct amount so you can
|
||||
start typing the next line straight away. Try this by defining the following
|
||||
function::
|
||||
|
||||
>>> def toggle(p):
|
||||
... p.value(not p.value())
|
||||
...
|
||||
...
|
||||
...
|
||||
>>>
|
||||
|
||||
In the above, you needed to press the Enter key three times in a row to finish
|
||||
the compound statement (that's the three lines with just dots on them). The
|
||||
other way to finish a compound statement is to press backspace to get to the
|
||||
start of the line, then press the Enter key. (If you did something wrong and
|
||||
want to escape the continuation mode then press ctrl-C; all lines will be
|
||||
ignored.)
|
||||
|
||||
The function you just defined allows you to toggle a pin. The pin object you
|
||||
created earlier should still exist (recreate it if it doesn't) and you can
|
||||
toggle the LED using::
|
||||
|
||||
>>> toggle(pin)
|
||||
|
||||
Let's now toggle the LED in a loop (if you don't have an LED then you can just
|
||||
print some text instead of calling toggle, to see the effect)::
|
||||
|
||||
>>> import time
|
||||
>>> while True:
|
||||
... toggle(pin)
|
||||
... time.sleep_ms(500)
|
||||
...
|
||||
...
|
||||
...
|
||||
>>>
|
||||
|
||||
This will toggle the LED at 1Hz (half a second on, half a second off). To stop
|
||||
the toggling press ctrl-C, which will raise a KeyboardInterrupt exception and
|
||||
break out of the loop.
|
||||
|
||||
The time module provides some useful functions for making delays and doing
|
||||
timing. Use tab completion to find out what they are and play around with them!
|
||||
|
||||
Paste mode
|
||||
~~~~~~~~~~
|
||||
|
||||
Pressing ctrl-E will enter a special paste mode. This allows you to copy and
|
||||
paste a chunk of text into the REPL. If you press ctrl-E you will see the
|
||||
paste-mode prompt::
|
||||
|
||||
paste mode; Ctrl-C to cancel, Ctrl-D to finish
|
||||
===
|
||||
|
||||
You can then paste (or type) your text in. Note that none of the special keys
|
||||
or commands work in paste mode (eg Tab or backspace), they are just accepted
|
||||
as-is. Press ctrl-D to finish entering the text and execute it.
|
||||
|
||||
Other control commands
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There are four other control commands:
|
||||
|
||||
* Ctrl-A on a blank line will enter raw REPL mode. This is like a permanent
|
||||
paste mode, except that characters are not echoed back.
|
||||
|
||||
* Ctrl-B on a blank like goes to normal REPL mode.
|
||||
|
||||
* Ctrl-C cancels any input, or interrupts the currently running code.
|
||||
|
||||
* Ctrl-D on a blank line will do a soft reset.
|
||||
|
||||
Note that ctrl-A and ctrl-D do not work with WebREPL.
|
||||
@@ -3,6 +3,9 @@ MicroPython documentation contents
|
||||
|
||||
.. toctree::
|
||||
|
||||
esp8266/quickref.rst
|
||||
esp8266/general.rst
|
||||
esp8266/tutorial/index.rst
|
||||
library/index.rst
|
||||
reference/index.rst
|
||||
license.rst
|
||||
|
||||
@@ -3,6 +3,7 @@ MicroPython documentation and references
|
||||
|
||||
.. toctree::
|
||||
|
||||
esp8266/quickref.rst
|
||||
library/index.rst
|
||||
license.rst
|
||||
esp8266_contents.rst
|
||||
|
||||
@@ -10,46 +10,6 @@ The ``esp`` module contains specific functions related to the ESP8266 module.
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: mac([address])
|
||||
|
||||
Get or set the network interface's MAC address.
|
||||
|
||||
If the ``address`` parameter is provided, sets the address to its value. If
|
||||
the function is called wihout parameters, returns the current address.
|
||||
|
||||
.. function:: getaddrinfo((hostname, port, lambda))
|
||||
|
||||
Initiate resolving of the given hostname.
|
||||
|
||||
When the hostname is resolved, the provided ``lambda`` callback will be
|
||||
called with two arguments, first being the hostname being resolved,
|
||||
second a tuple with information about that hostname.
|
||||
|
||||
.. function:: wifi_mode([mode])
|
||||
|
||||
Get or set the wireless network operating mode.
|
||||
|
||||
If the ``mode`` parameter is provided, sets the mode to its value. If
|
||||
the function is called wihout parameters, returns the current mode.
|
||||
|
||||
The possible modes are defined as constants:
|
||||
|
||||
* ``STA_MODE`` -- station mode,
|
||||
* ``AP_MODE`` -- software access point mode,
|
||||
* ``STA_AP_MODE`` -- mixed station and software access point mode.
|
||||
|
||||
.. function:: phy_mode([mode])
|
||||
|
||||
Get or set the network interface mode.
|
||||
|
||||
If the ``mode`` parameter is provided, sets the mode to its value. If
|
||||
the function is called wihout parameters, returns the current mode.
|
||||
|
||||
The possible modes are defined as constants:
|
||||
* ``MODE_11B`` -- IEEE 802.11b,
|
||||
* ``MODE_11G`` -- IEEE 802.11g,
|
||||
* ``MODE_11N`` -- IEEE 802.11n.
|
||||
|
||||
.. function:: sleep_type([sleep_type])
|
||||
|
||||
Get or set the sleep type.
|
||||
@@ -80,10 +40,8 @@ Functions
|
||||
|
||||
Read the device ID of the flash memory.
|
||||
|
||||
Classes
|
||||
-------
|
||||
.. function:: flash_read(byte_offset, length_or_buffer)
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
.. function:: flash_write(byte_offset, bytes)
|
||||
|
||||
esp.socket.rst
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
@@ -1,62 +1,13 @@
|
||||
MicroPython libraries
|
||||
=====================
|
||||
|
||||
Functionality specific to the MicroPython implementation is available in
|
||||
the following library.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
micropython.rst
|
||||
|
||||
Python standard libraries
|
||||
-------------------------
|
||||
|
||||
The following standard Python libraries are built in to MicroPython.
|
||||
|
||||
For additional libraries, please download them from the `micropython-lib repository
|
||||
<https://github.com/micropython/micropython-lib>`_.
|
||||
|
||||
.. only:: port_unix
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
os.rst
|
||||
struct.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
os.rst
|
||||
select.rst
|
||||
struct.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gc.rst
|
||||
os.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
|
||||
Python micro-libraries
|
||||
----------------------
|
||||
Python standard libraries and micro-libraries
|
||||
---------------------------------------------
|
||||
|
||||
The following standard Python libraries have been "micro-ified" to fit in with
|
||||
the philosophy of MicroPython. They provide the core functionality of that
|
||||
@@ -71,19 +22,104 @@ library.
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
|
||||
.. only:: port_pyboard or port_unix
|
||||
.. only:: port_unix
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
ubinascii.rst
|
||||
ucollections.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
uio.rst
|
||||
ujson.rst
|
||||
uos.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ustruct.rst
|
||||
utime.rst
|
||||
uzlib.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
ubinascii.rst
|
||||
ucollections.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
uio.rst
|
||||
ujson.rst
|
||||
uos.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ustruct.rst
|
||||
utime.rst
|
||||
uzlib.rst
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gc.rst
|
||||
select.rst
|
||||
sys.rst
|
||||
ubinascii.rst
|
||||
ujson.rst
|
||||
uos.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ussl.rst
|
||||
utime.rst
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gc.rst
|
||||
math.rst
|
||||
sys.rst
|
||||
ubinascii.rst
|
||||
ucollections.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
uio.rst
|
||||
ujson.rst
|
||||
uos.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ustruct.rst
|
||||
utime.rst
|
||||
uzlib.rst
|
||||
|
||||
|
||||
MicroPython-specific libraries
|
||||
------------------------------
|
||||
|
||||
Functionality specific to the MicroPython implementation is available in
|
||||
the following libraries.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
machine.rst
|
||||
micropython.rst
|
||||
network.rst
|
||||
uctypes.rst
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ubinascii.rst
|
||||
uctypes.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
uzlib.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
@@ -96,18 +132,6 @@ library.
|
||||
:maxdepth: 2
|
||||
|
||||
pyb.rst
|
||||
network.rst
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ubinascii.rst
|
||||
ujson.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ussl.rst
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
@@ -119,8 +143,6 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
machine.rst
|
||||
network.rst
|
||||
wipy.rst
|
||||
|
||||
|
||||
@@ -134,6 +156,4 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
pyb.rst
|
||||
esp.rst
|
||||
network.rst
|
||||
|
||||
@@ -49,12 +49,15 @@ Constructors
|
||||
Construct an I2C object on the given bus. `bus` can only be 0.
|
||||
If the bus is not given, the default one will be selected (0).
|
||||
|
||||
Methods
|
||||
-------
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: i2c.deinit()
|
||||
.. class:: machine.I2C(scl, sda, \*, freq=400000)
|
||||
|
||||
Turn off the I2C bus.
|
||||
Construct and return a new I2C object.
|
||||
See the init method below for a description of the arguments.
|
||||
|
||||
General Methods
|
||||
---------------
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
@@ -66,48 +69,131 @@ Methods
|
||||
- ``baudrate`` is the SCL clock rate
|
||||
- ``pins`` is an optional tuple with the pins to assign to the I2C bus.
|
||||
|
||||
.. method:: i2c.readfrom(addr, nbytes)
|
||||
.. only:: port_esp8266
|
||||
|
||||
Read ``nbytes`` from the slave specified by ``addr``.
|
||||
Returns a ``bytes`` object with the data read.
|
||||
.. method:: i2c.init(scl, sda, \*, freq=400000)
|
||||
|
||||
.. method:: i2c.readfrom_into(addr, buf)
|
||||
Initialise the I2C bus with the given arguments:
|
||||
|
||||
Read into ``buf`` from the slave specified by ``addr``.
|
||||
Returns the number of bytes read.
|
||||
- `scl` is a pin object for the SCL line
|
||||
- `sda` is a pin object for the SDA line
|
||||
- `freq` is the SCL clock rate
|
||||
|
||||
.. method:: i2c.writeto(addr, buf, \*, stop=True)
|
||||
.. method:: i2c.deinit()
|
||||
|
||||
Write ``buf`` to the slave specified by ``addr``. Set ``stop`` to ``False``
|
||||
if the transfer should be continued.
|
||||
Returns the number of bytes written.
|
||||
Turn off the I2C bus.
|
||||
|
||||
.. method:: i2c.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8)
|
||||
|
||||
Read ``nbytes`` from the slave specified by ``addr`` starting from the memory
|
||||
address specified by ``memaddr``.
|
||||
Param ``addrsize`` specifies the address size in bits.
|
||||
Returns a ``bytes`` object with the data read.
|
||||
|
||||
.. method:: i2c.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)
|
||||
|
||||
Read into ``buf`` from the slave specified by ``addr`` starting from the memory
|
||||
address specified by ``memaddr``.
|
||||
Param ``addrsize`` specifies the address size in bits.
|
||||
Returns the number of bytes read.
|
||||
|
||||
.. method:: i2c.writeto_mem(addr, memaddr, buf, \*, addrsize=8)
|
||||
|
||||
Write ``buf`` to the slave specified by ``addr`` starting from the
|
||||
memory address specified by ``memaddr``. Param ``addrsize`` specifies the
|
||||
address size in bits.
|
||||
Set ``stop`` to ``False`` if the transfer should be continued.
|
||||
Returns the number of bytes written.
|
||||
Availability: WiPy.
|
||||
|
||||
.. method:: i2c.scan()
|
||||
|
||||
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
|
||||
Only valid when in master mode.
|
||||
Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of
|
||||
those that respond. A device responds if it pulls the SDA line low after
|
||||
its address (including a read bit) is sent on the bus.
|
||||
|
||||
Note: on WiPy the I2C object must be in master mode for this method to be valid.
|
||||
|
||||
Primitive I2C operations
|
||||
------------------------
|
||||
|
||||
The following methods implement the primitive I2C master bus operations and can
|
||||
be combined to make any I2C transaction. They are provided if you need more
|
||||
control over the bus, otherwise the standard methods (see below) can be used.
|
||||
|
||||
.. method:: i2c.start()
|
||||
|
||||
Send a start bit on the bus (SDA transitions to low while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: i2c.stop()
|
||||
|
||||
Send a stop bit on the bus (SDA transitions to high while SCL is high).
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: i2c.readinto(buf)
|
||||
|
||||
Reads bytes from the bus and stores them into `buf`. The number of bytes
|
||||
read is the length of `buf`. An ACK will be sent on the bus after
|
||||
receiving all but the last byte, and a NACK will be sent following the last
|
||||
byte.
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
.. method:: i2c.write(buf)
|
||||
|
||||
Write all the bytes from `buf` to the bus. Checks that an ACK is received
|
||||
after each byte and raises an OSError if not.
|
||||
|
||||
Availability: ESP8266.
|
||||
|
||||
Standard bus operations
|
||||
-----------------------
|
||||
|
||||
The following methods implement the standard I2C master read and write
|
||||
operations that target a given slave device.
|
||||
|
||||
.. method:: i2c.readfrom(addr, nbytes)
|
||||
|
||||
Read `nbytes` from the slave specified by `addr`.
|
||||
Returns a `bytes` object with the data read.
|
||||
|
||||
.. method:: i2c.readfrom_into(addr, buf)
|
||||
|
||||
Read into `buf` from the slave specified by `addr`.
|
||||
The number of bytes read will be the length of `buf`.
|
||||
|
||||
On WiPy the return value is the number of bytes read. Otherwise the
|
||||
return value is `None`.
|
||||
|
||||
.. method:: i2c.writeto(addr, buf, \*, stop=True)
|
||||
|
||||
Write the bytes from `buf` to the slave specified by `addr`.
|
||||
|
||||
The `stop` argument (only available on WiPy) tells if a stop bit should be
|
||||
sent at the end of the transfer. If `False` the transfer should be
|
||||
continued later on.
|
||||
|
||||
On WiPy the return value is the number of bytes written. Otherwise the
|
||||
return value is `None`.
|
||||
|
||||
Memory operations
|
||||
-----------------
|
||||
|
||||
Some I2C devices act as a memory device (or set of registers) that can be read
|
||||
from and written to. In this case there are two addresses associated with an
|
||||
I2C transaction: the slave address and the memory address. The following
|
||||
methods are convenience functions to communicate with such devices.
|
||||
|
||||
.. method:: i2c.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8)
|
||||
|
||||
Read `nbytes` from the slave specified by `addr` starting from the memory
|
||||
address specified by `memaddr`.
|
||||
The argument `addrsize` specifies the address size in bits (on ESP8266
|
||||
this argument is not recognised and the address size is always 8 bits).
|
||||
Returns a `bytes` object with the data read.
|
||||
|
||||
.. method:: i2c.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8)
|
||||
|
||||
Read into `buf` from the slave specified by `addr` starting from the
|
||||
memory address specified by `memaddr`. The number of bytes read is the
|
||||
length of `buf`.
|
||||
The argument `addrsize` specifies the address size in bits (on ESP8266
|
||||
this argument is not recognised and the address size is always 8 bits).
|
||||
|
||||
On WiPy the return value is the number of bytes read. Otherwise the
|
||||
return value is `None`.
|
||||
|
||||
.. method:: i2c.writeto_mem(addr, memaddr, buf, \*, addrsize=8)
|
||||
|
||||
Write `buf` to the slave specified by `addr` starting from the
|
||||
memory address specified by `memaddr`.
|
||||
The argument `addrsize` specifies the address size in bits (on ESP8266
|
||||
this argument is not recognised and the address size is always 8 bits).
|
||||
|
||||
On WiPy the return value is the number of bytes written. Otherwise the
|
||||
return value is `None`.
|
||||
|
||||
Constants
|
||||
---------
|
||||
@@ -115,3 +201,5 @@ Constants
|
||||
.. data:: I2C.MASTER
|
||||
|
||||
for initialising the bus to master mode
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
@@ -24,7 +24,7 @@ Usage Model:
|
||||
print(pin.id())
|
||||
|
||||
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
|
||||
pin_int.irq(mode=Pin.IRQ_RISING, handler=pincb)
|
||||
pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
|
||||
# the callback can be triggered manually
|
||||
pin_int.irq()()
|
||||
# to disable the callback
|
||||
@@ -39,6 +39,21 @@ Usage Model:
|
||||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
# create an output pin on GPIO0
|
||||
p0 = Pin(0, Pin.OUT)
|
||||
p0.value(0)
|
||||
p0.value(1)
|
||||
|
||||
# create an input pin on GPIO2
|
||||
p2 = Pin(2, Pin.IN, Pin.PULL_UP)
|
||||
print(p2.value())
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
@@ -86,6 +101,25 @@ Methods
|
||||
|
||||
Get the pin id.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: pin.init(mode, pull=None, \*, value)
|
||||
|
||||
Initialise the pin:
|
||||
|
||||
- `mode` can be one of:
|
||||
|
||||
- ``Pin.IN`` - input pin.
|
||||
- ``Pin.OUT`` - output pin in push-pull mode.
|
||||
|
||||
- `pull` can be one of:
|
||||
|
||||
- ``None`` - no pull up or down resistor.
|
||||
- ``Pin.PULL_UP`` - pull up resistor enabled.
|
||||
|
||||
- if `value` is given then it is the output value to set the pin
|
||||
if it is in output mode.
|
||||
|
||||
.. method:: pin.value([value])
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
@@ -95,18 +129,20 @@ Methods
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
|
||||
.. method:: pin([value])
|
||||
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
|
||||
See **pin.value** for more details.
|
||||
|
||||
.. method:: pin.alt_list()
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: pin([value])
|
||||
|
||||
Pin objects are callable. The call method provides a (fast) shortcut to set and get the value of the pin.
|
||||
See **pin.value** for more details.
|
||||
|
||||
.. method:: pin.toggle()
|
||||
|
||||
Toggle the value of the pin.
|
||||
@@ -155,6 +191,23 @@ Methods
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. method:: pin.irq(\*, trigger, handler=None)
|
||||
|
||||
Create a callback to be triggered when the input level at the pin changes.
|
||||
|
||||
- ``trigger`` configures the pin level which can generate an interrupt. Possible values are:
|
||||
|
||||
- ``Pin.IRQ_FALLING`` interrupt on falling edge.
|
||||
- ``Pin.IRQ_RISING`` interrupt on rising edge.
|
||||
|
||||
The values can be OR'ed together to trigger on multiple events.
|
||||
|
||||
- ``handler`` is an optional function to be called when the interrupt triggers.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
@@ -166,44 +219,36 @@ Attributes
|
||||
led = Pin(Pin.board.GP25, mode=Pin.OUT)
|
||||
Pin.board.GP2.alt_list()
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. only:: port_wipy
|
||||
The following constants are used to configure the pin objects. Note that
|
||||
not all constants are available on all ports.
|
||||
|
||||
.. data:: Pin.IN
|
||||
.. data:: IN
|
||||
OUT
|
||||
OPEN_DRAIN
|
||||
ALT
|
||||
ALT_OPEN_DRAIN
|
||||
|
||||
.. data:: Pin.OUT
|
||||
|
||||
.. data:: Pin.OPEN_DRAIN
|
||||
Selects the pin mode.
|
||||
|
||||
.. data:: Pin.ALT
|
||||
.. data:: PULL_UP
|
||||
PULL_DOWN
|
||||
|
||||
.. data:: Pin.ALT_OPEN_DRAIN
|
||||
Selects the whether there is a pull up/down resistor.
|
||||
|
||||
Selects the pin mode.
|
||||
.. data:: LOW_POWER
|
||||
MED_POWER
|
||||
HIGH_POWER
|
||||
|
||||
.. data:: Pin.PULL_UP
|
||||
Selects the pin drive strength.
|
||||
|
||||
.. data:: Pin.PULL_DOWN
|
||||
|
||||
Selectes the wether there's pull up/down resistor.
|
||||
.. data:: IRQ_FALLING
|
||||
IRQ_RISING
|
||||
IRQ_LOW_LEVEL
|
||||
IRQ_HIGH_LEVEL
|
||||
|
||||
.. data:: Pin.LOW_POWER
|
||||
|
||||
.. data:: Pin.MED_POWER
|
||||
|
||||
.. data:: Pin.HIGH_POWER
|
||||
|
||||
Selects the drive strength.
|
||||
|
||||
.. data:: Pin.IRQ_FALLING
|
||||
|
||||
.. data:: Pin.IRQ_RISING
|
||||
|
||||
.. data:: Pin.IRQ_LOW_LEVEL
|
||||
|
||||
.. data:: Pin.IRQ_HIGH_LEVEL
|
||||
|
||||
Selects the IRQ trigger type.
|
||||
Selects the IRQ trigger type.
|
||||
|
||||
@@ -5,55 +5,49 @@ class Timer -- control internal timers
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. note::
|
||||
|
||||
Contrary with the rest of the API, timer IDs start at 1, not a t zero. This is because
|
||||
the ``Timer`` API is still provisional. A new MicroPython wide API will come soon.
|
||||
|
||||
Timers can be used for a great variety of tasks, calling a function periodically,
|
||||
counting events, and generating a PWM signal are among the most common use cases.
|
||||
Each timer consists of 2 16-bit channels and this channels can be tied together to
|
||||
form 1 32-bit timer. The operating mode needs to be configured per timer, but then
|
||||
Each timer consists of two 16-bit channels and this channels can be tied together to
|
||||
form one 32-bit timer. The operating mode needs to be configured per timer, but then
|
||||
the period (or the frequency) can be independently configured on each channel.
|
||||
By using the callback method, the timer event can call a Python function.
|
||||
|
||||
Example usage to toggle an LED at a fixed frequency::
|
||||
|
||||
from machine import Timer
|
||||
tim = Timer(4) # create a timer object using timer 4
|
||||
from machine import Pin
|
||||
led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
|
||||
tim = Timer(3) # create a timer object using timer 3
|
||||
tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
|
||||
tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
|
||||
tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
|
||||
tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz
|
||||
tim_ch.irq(handler=lambda t:led.toggle(), trigger=Timer.TIMEOUT) # toggle a LED on every cycle of the timer
|
||||
|
||||
Example using named function for the callback::
|
||||
|
||||
from machine import Timer
|
||||
tim = Timer(1, mode=Timer.PERIODIC)
|
||||
tim_a = tim.channel(Timer.A, freq=1000)
|
||||
from machine import Pin
|
||||
tim = Timer(1, mode=Timer.PERIODIC, width=32)
|
||||
tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer
|
||||
|
||||
led = Pin('GPIO2', mode=Pin.OUT)
|
||||
led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED
|
||||
|
||||
def tick(timer): # we will receive the timer object when being called
|
||||
print(timer.time()) # show current timer's time value (is microseconds)
|
||||
global led
|
||||
led.toggle() # toggle the LED
|
||||
|
||||
tim_a.callback(handler=tick)
|
||||
tim_a.irq(handler=tick, trigger=Timer.TIMEOUT) # create the interrupt
|
||||
|
||||
Further examples::
|
||||
|
||||
from machine import Timer
|
||||
tim1 = Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
|
||||
tim2 = Timer(1, mode=Timer.PWM) # initialize it in PWM mode
|
||||
tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges
|
||||
tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
|
||||
tim_ch.time() # get the current time in usec (can also be set)
|
||||
tim_ch.freq(20) # set the frequency (can also get)
|
||||
tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
|
||||
tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
|
||||
tim_ch.event_count() # get the number of captured events
|
||||
tim_ch.event_time() # get the the time of the last captured event
|
||||
tim_ch.period(2000000) # change the period to 2 seconds
|
||||
|
||||
tim1 = Timer(1, mode=Timer.ONE_SHOT) # initialize it in one shot mode
|
||||
tim2 = Timer(2, mode=Timer.PWM) # initialize it in PWM mode
|
||||
tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges
|
||||
tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=5000) # start the PWM on channel B with a 50% duty cycle
|
||||
tim2_ch.freq(20) # set the frequency (can also get)
|
||||
tim2_ch.duty_cycle(3010) # set the duty cycle to 30.1% (can also get)
|
||||
tim2_ch.duty_cycle(3020, Timer.NEGATIVE) # set the duty cycle to 30.2% and change the polarity to negative
|
||||
tim2_ch.period(2000000) # change the period to 2 seconds
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -69,9 +63,7 @@ Constructors
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Construct a new timer object of the given id. If additional
|
||||
arguments are given, then the timer is initialised by ``init(...)``.
|
||||
``id`` can be 1 to 4.
|
||||
Construct a new timer object of the given id. ``id`` can take values from 0 to 3.
|
||||
|
||||
|
||||
Methods
|
||||
@@ -94,10 +86,9 @@ Methods
|
||||
period of the channel expires.
|
||||
- ``Timer.PERIODIC`` - The timer runs periodically at the configured
|
||||
frequency of the channel.
|
||||
- ``Timer.EDGE_TIME`` - Meaure the time pin level changes.
|
||||
- ``Timer.EDGE_COUNT`` - Count the number of pin level changes.
|
||||
- ``Timer.PWM`` - Output a PWM signal on a pin.
|
||||
|
||||
- ``width`` must be either 16 or 32 (bits). For really low frequencies <= ~1Hz
|
||||
- ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz
|
||||
(or large periods), 32-bit timers should be used. 32-bit mode is only available
|
||||
for ``ONE_SHOT`` AND ``PERIODIC`` modes.
|
||||
|
||||
@@ -112,7 +103,7 @@ Methods
|
||||
|
||||
If only a channel identifier passed, then a previously initialized channel
|
||||
object is returned (or ``None`` if there is no previous channel).
|
||||
|
||||
|
||||
Othwerwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
The operating mode is is the one configured to the Timer object that was used to
|
||||
@@ -130,12 +121,22 @@ Methods
|
||||
|
||||
Either ``freq`` or ``period`` must be given, never both.
|
||||
|
||||
- ``polarity`` this is applicable for:
|
||||
|
||||
- ``PWM``, defines the polarity of the duty cycle
|
||||
- ``EDGE_TIME`` and ``EDGE_COUNT``, defines the polarity of the pin level change to detect.
|
||||
To detect both rising and falling edges, make ``polarity=Timer.POSITIVE | Timer.NEGATIVE``.
|
||||
- ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0-100)
|
||||
- ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle
|
||||
- ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy
|
||||
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000,
|
||||
where 10000 would represent 100.00, 5050 represents 50.50, and so on.
|
||||
|
||||
.. note::
|
||||
|
||||
When the channel is in PWM mode, the corresponding pin is assigned automatically, therefore
|
||||
there's no need to assign the alternate function of the pin via the ``Pin`` class. The pins which
|
||||
support PWM functionality are the following:
|
||||
|
||||
- ``GP24`` on Timer 0 channel A.
|
||||
- ``GP25`` on Timer 1 channel A.
|
||||
- ``GP9`` on Timer 2 channel B.
|
||||
- ``GP10`` on Timer 3 channel A.
|
||||
- ``GP11`` on Timer 3 channel B.
|
||||
|
||||
class TimerChannel --- setup a channel for a timer
|
||||
==================================================
|
||||
@@ -166,31 +167,49 @@ Methods
|
||||
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
||||
Higher values represent higher priorities.
|
||||
- ``handler`` is an optional function to be called when the interrupt is triggered.
|
||||
- ``trigger`` must be ``Timer.TIMEOUT`` when the operating mode is either ``Timer.PERIODIC`` or
|
||||
``Timer.ONE_SHOT``. In the case that mode is ``Timer.PWM`` then trigger must be equal to
|
||||
``Timer.MATCH``.
|
||||
|
||||
Returns a callback object.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: timerchannel.freq([value])
|
||||
|
||||
|
||||
Get or set the timer channel frequency (in Hz).
|
||||
|
||||
.. method:: timerchannel.period([value])
|
||||
|
||||
Get or set the timer channel period (in microseconds).
|
||||
|
||||
.. method:: timerchannel.time([value])
|
||||
|
||||
Get or set the timer channel current **time** value (in microseconds).
|
||||
|
||||
.. method:: timerchannel.event_count()
|
||||
|
||||
Get the number of edge events counted.
|
||||
|
||||
.. method:: timerchannel.event_time()
|
||||
|
||||
Get the time of ocurrance of the last event.
|
||||
|
||||
.. method:: timerchannel.duty_cycle([value])
|
||||
|
||||
Get or set the duty cycle of the PWM signal (in the range of 0-100).
|
||||
|
||||
Get or set the duty cycle of the PWM signal. It's a percentage (0.00-100.00). Since the WiPy
|
||||
doesn't support floating point numbers the duty cycle must be specified in the range 0-10000,
|
||||
where 10000 would represent 100.00, 5050 represents 50.50, and so on.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: Timer.ONE_SHOT
|
||||
.. data:: Timer.PERIODIC
|
||||
.. data:: Timer.PWM
|
||||
|
||||
Selects the timer operating mode.
|
||||
|
||||
.. data:: Timer.A
|
||||
.. data:: Timer.B
|
||||
|
||||
Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when
|
||||
using a 32-bit timer.
|
||||
|
||||
.. data:: Timer.POSITIVE
|
||||
.. data:: Timer.NEGATIVE
|
||||
|
||||
Timer channel polarity selection (only relevant in PWM mode).
|
||||
|
||||
.. data:: Timer.TIMEOUT
|
||||
.. data:: Timer.MATCH
|
||||
|
||||
Timer channel IRQ triggers.
|
||||
|
||||
@@ -11,83 +11,97 @@ Reset related functions
|
||||
|
||||
.. function:: reset()
|
||||
|
||||
Resets the WiPy in a manner similar to pushing the external RESET
|
||||
Resets the device in a manner similar to pushing the external RESET
|
||||
button.
|
||||
|
||||
.. function:: reset_cause()
|
||||
|
||||
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values.
|
||||
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
.. only:: port_wipy
|
||||
|
||||
.. function:: disable_irq()
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
|
||||
Disable interrupt requests.
|
||||
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
|
||||
respectively. This return value can be passed to enable_irq to restore
|
||||
the IRQ to its original state.
|
||||
.. function:: disable_irq()
|
||||
|
||||
.. function:: enable_irq(state=True)
|
||||
Disable interrupt requests.
|
||||
Returns the previous IRQ state: ``False``/``True`` for disabled/enabled IRQs
|
||||
respectively. This return value can be passed to enable_irq to restore
|
||||
the IRQ to its original state.
|
||||
|
||||
Enable interrupt requests.
|
||||
If ``state`` is ``True`` (the default value) then IRQs are enabled.
|
||||
If ``state`` is ``False`` then IRQs are disabled. The most common use of
|
||||
this function is to pass it the value returned by ``disable_irq`` to
|
||||
exit a critical section.
|
||||
.. function:: enable_irq(state=True)
|
||||
|
||||
Enable interrupt requests.
|
||||
If ``state`` is ``True`` (the default value) then IRQs are enabled.
|
||||
If ``state`` is ``False`` then IRQs are disabled. The most common use of
|
||||
this function is to pass it the value returned by ``disable_irq`` to
|
||||
exit a critical section.
|
||||
|
||||
Power related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: freq()
|
||||
|
||||
Returns a tuple of clock frequencies: ``(sysclk,)``
|
||||
These correspond to:
|
||||
.. only:: not port_wipy
|
||||
|
||||
- sysclk: frequency of the CPU
|
||||
Returns CPU frequency in hertz.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Returns a tuple of clock frequencies: ``(sysclk,)``
|
||||
These correspond to:
|
||||
|
||||
- sysclk: frequency of the CPU
|
||||
|
||||
.. function:: idle()
|
||||
|
||||
Gates the clock to the CPU, useful to reduce power consumption at any time during
|
||||
short or long periods. Peripherals continue working and execution resumes as soon
|
||||
as any interrupt is triggered (including the systick which has a period of 1ms).
|
||||
Current consumption is reduced to ~12mA (in WLAN STA mode)
|
||||
as any interrupt is triggered (on many ports this includes system timer
|
||||
interrupt occuring at regular intervals on the order of millisecond).
|
||||
|
||||
.. function:: sleep()
|
||||
|
||||
Stops the CPU and disables all peripherals except for WLAN. Execution is resumed from
|
||||
the point where the sleep was requested. Wake sources are ``Pin``, ``RTC`` and ``WLAN``.
|
||||
Current consumption is reduced to 950uA (in WLAN STA mode).
|
||||
the point where the sleep was requested. For wake up to actually happen, wake sources
|
||||
should be configured first.
|
||||
|
||||
.. function:: deepsleep()
|
||||
|
||||
Stops the CPU and all peripherals including WLAN. Execution is resumed from main, just
|
||||
as with a reset. The reset cause can be checked to know that we are coming from
|
||||
from ``machine.DEEPSLEEP``. Wake sources are ``Pin`` and ``RTC``. Current consumption
|
||||
is reduced to ~5uA.
|
||||
Stops the CPU and all peripherals (including networking interfaces, if any). Execution
|
||||
is resumed from the main script, just as with a reset. The reset cause can be checked
|
||||
to know that we are coming from ``machine.DEEPSLEEP``. For wake up to actually happen,
|
||||
wake sources should be configured first, like ``Pin`` change or ``RTC`` timeout.
|
||||
|
||||
.. function:: wake_reason()
|
||||
.. only:: port_wipy
|
||||
|
||||
Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values.
|
||||
.. function:: wake_reason()
|
||||
|
||||
Get the wake reason. See :ref:`constants <machine_constants>` for the possible return values.
|
||||
|
||||
Miscellaneous functions
|
||||
-----------------------
|
||||
|
||||
.. function:: main(filename)
|
||||
.. only:: port_wipy
|
||||
|
||||
Set the filename of the main script to run after boot.py is finished. If
|
||||
this function is not called then the default file main.py will be executed.
|
||||
.. function:: main(filename)
|
||||
|
||||
It only makes sense to call this function from within boot.py.
|
||||
Set the filename of the main script to run after boot.py is finished. If
|
||||
this function is not called then the default file main.py will be executed.
|
||||
|
||||
.. function:: rng()
|
||||
It only makes sense to call this function from within boot.py.
|
||||
|
||||
Return a 24-bit software generated random number.
|
||||
.. function:: rng()
|
||||
|
||||
Return a 24-bit software generated random number.
|
||||
|
||||
.. function:: unique_id()
|
||||
|
||||
Returns a string of 6 bytes (48 bits), which is the unique ID of the MCU.
|
||||
This also corresponds to the ``MAC address`` of the WiPy.
|
||||
Returns a byte string with a unique idenifier of a board/SoC. It will vary
|
||||
from a board/SoC instance to another, if underlying hardware allows. Length
|
||||
varies by hardware (so use substring of a full value if you expect a short
|
||||
ID). In some MicroPython ports, ID corresponds to the network MAC address.
|
||||
|
||||
.. _machine_constants:
|
||||
|
||||
|
||||
@@ -30,27 +30,27 @@ For example::
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. _network.server:
|
||||
.. _network.Server:
|
||||
|
||||
class server
|
||||
class Server
|
||||
============
|
||||
|
||||
The server class controls the behaviour and the configuration of the FTP and telnet
|
||||
The ``Server`` class controls the behaviour and the configuration of the FTP and telnet
|
||||
services running on the WiPy. Any changes performed using this class' methods will
|
||||
affect both.
|
||||
|
||||
Example::
|
||||
|
||||
import network
|
||||
s = network.server()
|
||||
s.deinit() # disable the server
|
||||
server = network.Server()
|
||||
server.deinit() # disable the server
|
||||
# enable the server again with new settings
|
||||
s.init(login=('user', 'password'), timeout=600)
|
||||
server.init(login=('user', 'password'), timeout=600)
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: network.server(id, ...)
|
||||
.. class:: network.Server(id, ...)
|
||||
|
||||
Create a server instance, see ``init`` for parameters of initialization.
|
||||
|
||||
@@ -229,26 +229,52 @@ For example::
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
Functions
|
||||
=========
|
||||
|
||||
.. function:: phy_mode([mode])
|
||||
|
||||
Get or set the PHY mode.
|
||||
|
||||
If the ``mode`` parameter is provided, sets the mode to its value. If
|
||||
the function is called wihout parameters, returns the current mode.
|
||||
|
||||
The possible modes are defined as constants:
|
||||
* ``MODE_11B`` -- IEEE 802.11b,
|
||||
* ``MODE_11G`` -- IEEE 802.11g,
|
||||
* ``MODE_11N`` -- IEEE 802.11n.
|
||||
|
||||
class WLAN
|
||||
==========
|
||||
|
||||
This class provides a driver for WiFi network processor in the ESP8266. Example usage::
|
||||
|
||||
import network
|
||||
# setup as a station
|
||||
nic = network.WLAN()
|
||||
# enable station interface and connect to WiFi access point
|
||||
nic = network.WLAN(network.STA_IF)
|
||||
nic.active(True)
|
||||
nic.connect('your-ssid', 'your-password')
|
||||
# now use socket as usual
|
||||
# now use sockets as usual
|
||||
|
||||
Constructors
|
||||
------------
|
||||
.. class:: WLAN()
|
||||
.. class:: WLAN(interface_id)
|
||||
|
||||
Create a WLAN driver object.
|
||||
Create a WLAN network interface object. Supported interfaces are
|
||||
``network.STA_IF`` (station aka client, connects to upstream WiFi access
|
||||
points) and ``network.AP_IF`` (access point, allows other WiFi clients to
|
||||
connect). Availability of the methods below depends on interface type.
|
||||
For example, only STA interface may ``connect()`` to an access point.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: wlan.active([is_active])
|
||||
|
||||
Activate ("up") or deactivate ("down") network interface, if boolean
|
||||
argument is passed. Otherwise, query current state if no argument is
|
||||
provided. Most other methods require active interface.
|
||||
|
||||
.. method:: wlan.connect(ssid, password)
|
||||
|
||||
Connect to the specified wireless network, using the specified password.
|
||||
@@ -257,19 +283,18 @@ For example::
|
||||
|
||||
Disconnect from the currently connected wireless network.
|
||||
|
||||
.. method:: wlan.scan(cb)
|
||||
.. method:: wlan.scan()
|
||||
|
||||
Initiate scanning for the available wireless networks.
|
||||
Scan for the available wireless networks.
|
||||
|
||||
Scanning is only possible if the radio is in station or station+AP mode; if
|
||||
called while in AP only mode, an OSError exception will be raised.
|
||||
|
||||
Once the scanning is complete, the provided callback function ``cb`` will
|
||||
be called once for each network found, and passed a tuple with information
|
||||
about that network:
|
||||
Scanning is only possible on STA interface. Returns list of tuples with
|
||||
the information about WiFi access points:
|
||||
|
||||
(ssid, bssid, channel, RSSI, authmode, hidden)
|
||||
|
||||
`bssid` is hardware address of an access point, in binary form, returned as
|
||||
bytes object. You can use ``ubinascii.hexlify()`` to convert it to ASCII form.
|
||||
|
||||
There are five values for authmode:
|
||||
|
||||
* 0 -- open
|
||||
@@ -283,7 +308,7 @@ For example::
|
||||
* 0 -- visible
|
||||
* 1 -- hidden
|
||||
|
||||
.. method:: status()
|
||||
.. method:: wlan.status()
|
||||
|
||||
Return the current status of the wireless connection.
|
||||
|
||||
@@ -302,6 +327,46 @@ For example::
|
||||
point and has a valid IP address. In AP mode returns ``True`` when a
|
||||
station is connected. Returns ``False`` otherwise.
|
||||
|
||||
.. method:: wlan.ifconfig([(ip, subnet, gateway, dns)])
|
||||
|
||||
Get/set IP-level network interface paremeters: IP address, subnet mask,
|
||||
gateway and DNS server. When called with no arguments, this method returns
|
||||
a 4-tuple with the above information. To set the above values, pass a
|
||||
4-tuple with the required information. For example::
|
||||
|
||||
nic.ifconfig(('192.168.0.4', '255.255.255.0', '192.168.0.1', '8.8.8.8'))
|
||||
|
||||
.. method:: wlan.config('param')
|
||||
.. method:: wlan.config(param=value, ...)
|
||||
|
||||
Get or set general network interface parameters. These methods allow to work
|
||||
with additional parameters beyond standard IP configuration (as dealt with by
|
||||
``wlan.ifconfig()``). These include network-specific and hardware-specific
|
||||
parameters. For setting parameters, keyword argument syntax should be used,
|
||||
multiple parameters can be set at once. For querying, paremeters name should
|
||||
be quoted as a string, and only one paramter can be queries at time::
|
||||
|
||||
# Set WiFi access point name (formally known as ESSID) and WiFi channel
|
||||
ap.config(essid='My AP', channel=11)
|
||||
# Queey params one by one
|
||||
print(ap.config('essid'))
|
||||
print(ap.config('channel'))
|
||||
|
||||
Following are commonly supported parameters (availability of a specific parameter
|
||||
depends on network technology type, driver, and MicroPython port).
|
||||
|
||||
========= ===========
|
||||
Parameter Description
|
||||
========= ===========
|
||||
mac MAC address (bytes)
|
||||
essid WiFi access point name (string)
|
||||
channel WiFi channel (integer)
|
||||
hidden Whether ESSID is hidden (boolean)
|
||||
authmode Authentication mode supported (enumeration, see module constants)
|
||||
password Access password (string)
|
||||
========= ===========
|
||||
|
||||
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ class ADC -- analog to digital conversion
|
||||
val = adc.read_core_vbat() # read MCU VBAT
|
||||
val = adc.read_core_vref() # read MCU VREF
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
@@ -77,6 +78,65 @@ Methods
|
||||
The ADCAll Object
|
||||
-----------------
|
||||
|
||||
Instantiating this changes all ADC pins to analog inputs. It is possible to read the
|
||||
MCU temperature, VREF and VBAT without using ADCAll. The raw data can be accessed on
|
||||
ADC channels 16, 17 and 18 respectively. However appropriate scaling will need to be applied.
|
||||
.. only:: port_pyboard
|
||||
|
||||
Instantiating this changes all ADC pins to analog inputs. The raw MCU temperature,
|
||||
VREF and VBAT data can be accessed on ADC channels 16, 17 and 18 respectively.
|
||||
Appropriate scaling will need to be applied. The temperature sensor on the chip
|
||||
has poor absolute accuracy and is suitable only for detecting temperature changes.
|
||||
|
||||
The ``ADCAll`` ``read_core_vbat()`` and ``read_core_vref()`` methods read
|
||||
the backup battery voltage and the (1.21V nominal) reference voltage using the
|
||||
3.3V supply as a reference. Assuming the ``ADCAll`` object has been Instantiated with
|
||||
``adc = pyb.ADCAll(12)`` the 3.3V supply voltage may be calculated:
|
||||
|
||||
``v33 = 3.3 * 1.21 / adc.read_core_vref()``
|
||||
|
||||
If the 3.3V supply is correct the value of ``adc.read_core_vbat()`` will be
|
||||
valid. If the supply voltage can drop below 3.3V, for example in in battery
|
||||
powered systems with a discharging battery, the regulator will fail to preserve
|
||||
the 3.3V supply resulting in an incorrect reading. To produce a value which will
|
||||
remain valid under these circumstances use the following:
|
||||
|
||||
``vback = adc.read_core_vbat() * 1.21 / adc.read_core_vref()``
|
||||
|
||||
It is possible to access these values without incurring the side effects of ``ADCAll``::
|
||||
|
||||
def adcread(chan): # 16 temp 17 vbat 18 vref
|
||||
assert chan >= 16 and chan <= 18, 'Invalid ADC channel'
|
||||
start = pyb.millis()
|
||||
timeout = 100
|
||||
stm.mem32[stm.RCC + stm.RCC_APB2ENR] |= 0x100 # enable ADC1 clock.0x4100
|
||||
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 # Turn on ADC
|
||||
stm.mem32[stm.ADC1 + stm.ADC_CR1] = 0 # 12 bit
|
||||
if chan == 17:
|
||||
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x200000 # 15 cycles
|
||||
stm.mem32[stm.ADC + 4] = 1 << 23
|
||||
elif chan == 18:
|
||||
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x1000000
|
||||
stm.mem32[stm.ADC + 4] = 0xc00000
|
||||
else:
|
||||
stm.mem32[stm.ADC1 + stm.ADC_SMPR1] = 0x40000
|
||||
stm.mem32[stm.ADC + 4] = 1 << 23
|
||||
stm.mem32[stm.ADC1 + stm.ADC_SQR3] = chan
|
||||
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 1 | (1 << 30) | (1 << 10) # start conversion
|
||||
while not stm.mem32[stm.ADC1 + stm.ADC_SR] & 2: # wait for EOC
|
||||
if pyb.elapsed_millis(start) > timeout:
|
||||
raise OSError('ADC timout')
|
||||
data = stm.mem32[stm.ADC1 + stm.ADC_DR] # clear down EOC
|
||||
stm.mem32[stm.ADC1 + stm.ADC_CR2] = 0 # Turn off ADC
|
||||
return data
|
||||
|
||||
def v33():
|
||||
return 4096 * 1.21 / adcread(17)
|
||||
|
||||
def vbat():
|
||||
return 1.21 * 2 * adcread(18) / adcread(17) # 2:1 divider on Vbat channel
|
||||
|
||||
def vref():
|
||||
return 3.3 * adcread(17) / 4096
|
||||
|
||||
def temperature():
|
||||
return 25 + 400 * (3.3 * adcread(16) / 4096 - 0.76)
|
||||
|
||||
|
||||
@@ -63,16 +63,24 @@ Constructors
|
||||
|
||||
.. class:: pyb.I2C(bus, ...)
|
||||
|
||||
Construct an I2C object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the I2C object is created but not
|
||||
Construct an I2C object on the given bus. ``bus`` can be 1 or 2, 'X' or
|
||||
'Y'. With no additional parameters, the I2C object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the I2C busses are:
|
||||
The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are:
|
||||
|
||||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
|
||||
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)``
|
||||
|
||||
On the Pyboard Lite:
|
||||
|
||||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
|
||||
- ``I2C(3)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PA8, PB8)``
|
||||
|
||||
Calling the constructor with 'X' or 'Y' enables portability between Pyboard
|
||||
types.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
@@ -33,9 +33,9 @@ Constructors
|
||||
|
||||
.. class:: pyb.SPI(bus, ...)
|
||||
|
||||
Construct an SPI object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the SPI object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
Construct an SPI object on the given bus. ``bus`` can be 1 or 2, or
|
||||
'X' or 'Y'. With no additional parameters, the SPI object is created but
|
||||
not initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ using the standard stream methods::
|
||||
|
||||
To check if there is anything to be read, use::
|
||||
|
||||
uart.any() # returns True if any characters waiting
|
||||
uart.any() # returns the number of characters waiting
|
||||
|
||||
|
||||
*Note:* The stream functions ``read``, ``write``, etc. are new in MicroPython v1.3.4.
|
||||
Earlier versions use ``uart.send`` and ``uart.recv``.
|
||||
@@ -57,7 +58,7 @@ Constructors
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
|
||||
The physical pins of the UART busses are:
|
||||
|
||||
- ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)``
|
||||
@@ -66,12 +67,16 @@ Constructors
|
||||
- ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)``
|
||||
- ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)``
|
||||
|
||||
The Pyboard Lite supports UART(1), UART(2) and UART(6) only. Pins are as above except:
|
||||
|
||||
- ``UART(2)`` is on: ``(TX, RX) = (X1, X2) = (PA2, PA3)``
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=None, timeout_char=0, read_buf_len=64)
|
||||
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, flow=0, timeout_char=0, read_buf_len=64)
|
||||
|
||||
Initialise the UART bus with the given parameters:
|
||||
|
||||
@@ -79,7 +84,7 @@ Methods
|
||||
- ``bits`` is the number of bits per character, 7, 8 or 9.
|
||||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``flow`` sets the flow control type. Can be None, ``UART.RTS``, ``UART.CTS``
|
||||
- ``flow`` sets the flow control type. Can be 0, ``UART.RTS``, ``UART.CTS``
|
||||
or ``UART.RTS | UART.CTS``.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||
@@ -103,16 +108,18 @@ Methods
|
||||
|
||||
.. method:: uart.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
Returns the number of bytes waiting (may be 0).
|
||||
|
||||
.. method:: uart.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``.
|
||||
Return value: ``None``. See note below if CTS flow control is used.
|
||||
|
||||
.. method:: uart.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
If ``nbytes`` are available in the buffer, returns immediately, otherwise returns
|
||||
when sufficient characters arrive or the timeout elapses.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
@@ -124,9 +131,9 @@ Methods
|
||||
|
||||
.. method:: uart.readall()
|
||||
|
||||
Read as much data as possible.
|
||||
Read as much data as possible. Returns after the timeout has elapsed.
|
||||
|
||||
Return value: a bytes object or ``None`` on timeout.
|
||||
Return value: a bytes object or ``None`` if timeout prevents any data being read.
|
||||
|
||||
.. method:: uart.readchar()
|
||||
|
||||
@@ -144,9 +151,11 @@ Methods
|
||||
|
||||
.. method:: uart.readline()
|
||||
|
||||
Read a line, ending in a newline character.
|
||||
Read a line, ending in a newline character. If such a line exists, return is
|
||||
immediate. If the timeout elapses, all available data is returned regardless
|
||||
of whether a newline exists.
|
||||
|
||||
Return value: the line read or ``None`` on timeout.
|
||||
Return value: the line read or ``None`` on timeout if no data is available.
|
||||
|
||||
.. method:: uart.write(buf)
|
||||
|
||||
@@ -157,7 +166,8 @@ Methods
|
||||
bytes are used for each character (little endian), and ``buf`` must contain
|
||||
an even number of bytes.
|
||||
|
||||
Return value: number of bytes written or ``None`` on timeout.
|
||||
Return value: number of bytes written. If a timeout occurs and no bytes
|
||||
were written returns ``None``.
|
||||
|
||||
.. method:: uart.sendbreak()
|
||||
|
||||
@@ -173,4 +183,63 @@ Constants
|
||||
.. data:: UART.RTS
|
||||
.. data:: UART.CTS
|
||||
|
||||
to select the flow control type
|
||||
to select the flow control type.
|
||||
|
||||
Flow Control
|
||||
------------
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
On Pyboards V1 and V1.1 ``UART(2)`` and ``UART(3)`` support RTS/CTS hardware flow control
|
||||
using the following pins:
|
||||
|
||||
- ``UART(2)`` is on: ``(TX, RX, nRTS, nCTS) = (X3, X4, X2, X1) = (PA2, PA3, PA1, PA0)``
|
||||
- ``UART(3)`` is on :``(TX, RX, nRTS, nCTS) = (Y9, Y10, Y7, Y6) = (PB10, PB11, PB14, PB13)``
|
||||
|
||||
On the Pyboard Lite only ``UART(2)`` supports flow control on these pins:
|
||||
|
||||
``(TX, RX, nRTS, nCTS) = (X1, X2, X4, X3) = (PA2, PA3, PA1, PA0)``
|
||||
|
||||
In the following paragraphs the term "target" refers to the device connected to
|
||||
the UART.
|
||||
|
||||
When the UART's ``init()`` method is called with ``flow`` set to one or both of
|
||||
``UART.RTS`` and ``UART.CTS`` the relevant flow control pins are configured.
|
||||
``nRTS`` is an active low output, ``nCTS`` is an active low input with pullup
|
||||
enabled. To achieve flow control the Pyboard's ``nCTS`` signal should be connected
|
||||
to the target's ``nRTS`` and the Pyboard's ``nRTS`` to the target's ``nCTS``.
|
||||
|
||||
CTS: target controls Pyboard transmitter
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If CTS flow control is enabled the write behaviour is as follows:
|
||||
|
||||
If the Pyboard's ``uart.write(buf)`` method is called, transmission will stall for
|
||||
any periods when ``nCTS`` is ``False``. This will result in a timeout if the entire
|
||||
buffer was not transmitted in the timeout period. The method returns the number of
|
||||
bytes written, enabling the user to write the remainder of the data if required. In
|
||||
the event of a timeout, a character will remain in the UART pending ``nCTS``. The
|
||||
number of bytes composing this character will be included in the return value.
|
||||
|
||||
If ``uart.writechar()`` is called when ``nCTS`` is ``False`` the method will time
|
||||
out unless the target asserts ``nCTS`` in time. If it times out ``OSError 116``
|
||||
will be raised. The character will be transmitted as soon as the target asserts ``nCTS``.
|
||||
|
||||
RTS: Pyboard controls target's transmitter
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If RTS flow control is enabled, behaviour is as follows:
|
||||
|
||||
If buffered input is used (``read_buf_len`` > 0), incoming characters are buffered.
|
||||
If the buffer becomes full, the next character to arrive will cause ``nRTS`` to go
|
||||
``False``: the target should cease transmission. ``nRTS`` will go ``True`` when
|
||||
characters are read from the buffer.
|
||||
|
||||
Note that the ``any()`` method returns the number of bytes in the buffer. Assume a
|
||||
buffer length of ``N`` bytes. If the buffer becomes full, and another character arrives,
|
||||
``nRTS`` will be set False, and ``any()`` will return the count ``N``. When
|
||||
characters are read the additional character will be placed in the buffer and will
|
||||
be included in the result of a subsequent ``any()`` call.
|
||||
|
||||
If buffered input is not used (``read_buf_len`` == 0) the arrival of a character will
|
||||
cause ``nRTS`` to go ``False`` until the character is read.
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
:mod:`struct` -- pack and unpack primitive data types
|
||||
=====================================================
|
||||
|
||||
.. module:: struct
|
||||
:synopsis: pack and unpack primitive data types
|
||||
|
||||
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
|
||||
information.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: calcsize(fmt)
|
||||
|
||||
Return the number of bytes needed to store the given ``fmt``.
|
||||
|
||||
.. function:: pack(fmt, v1, v2, ...)
|
||||
|
||||
Pack the values ``v1``, ``v2``, ... according to the format string ``fmt``.
|
||||
The return value is a bytes object encoding the values.
|
||||
|
||||
.. function:: unpack(fmt, data)
|
||||
|
||||
Unpack from the ``data`` according to the format string ``fmt``.
|
||||
The return value is a tuple of the unpacked values.
|
||||
@@ -7,14 +7,15 @@
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: exit([retval])
|
||||
.. function:: exit(retval=0)
|
||||
|
||||
Raise a ``SystemExit`` exception. If an argument is given, it is the
|
||||
value given to ``SystemExit``.
|
||||
Terminate current program with a given exit code. Underlyingly, this
|
||||
function raise as ``SystemExit`` exception. If an argument is given, its
|
||||
value given as an argument to ``SystemExit``.
|
||||
|
||||
.. function:: print_exception(exc, [file])
|
||||
.. function:: print_exception(exc, file=sys.stdout)
|
||||
|
||||
Print exception with a traceback to a file-like object ``file`` (or
|
||||
Print exception with a traceback to a file-like object `file` (or
|
||||
``sys.stdout`` by default).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
@@ -27,38 +28,89 @@ Constants
|
||||
|
||||
.. data:: argv
|
||||
|
||||
a mutable list of arguments this program started with
|
||||
A mutable list of arguments the current program was started with.
|
||||
|
||||
.. data:: byteorder
|
||||
|
||||
the byte order of the system ("little" or "big")
|
||||
The byte order of the system ("little" or "big").
|
||||
|
||||
.. data:: implementation
|
||||
|
||||
Object with information about the current Python implementation. For
|
||||
MicroPython, it has following attributes:
|
||||
|
||||
* `name` - string "micropython"
|
||||
* `version` - tuple (major, minor, micro), e.g. (1, 7, 0)
|
||||
|
||||
This object is the recommended way to distinguish MicroPython from other
|
||||
Python implementations (note that it still may not exist in the very
|
||||
minimal ports).
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
CPython mandates more attributes for this object, but the actual useful
|
||||
bare minimum is implemented in MicroPython.
|
||||
|
||||
.. data:: maxsize
|
||||
|
||||
Maximum value which a native integer type can hold on the current platform,
|
||||
or maximum value representable by MicroPython integer type, if it's smaller
|
||||
than platform max value (that is the case for MicroPython ports without
|
||||
long int support).
|
||||
|
||||
This attribute is useful for detecting "bitness" of a platform (32-bit vs
|
||||
64-bit, etc.). It's recommended to not compare this attribute to some
|
||||
value directly, but instead count number of bits in it::
|
||||
|
||||
bits = 0
|
||||
v = sys.maxsize
|
||||
while v:
|
||||
bits += 1
|
||||
v >>= 1
|
||||
if bits > 32:
|
||||
# 64-bit (or more) platform
|
||||
...
|
||||
else:
|
||||
# 32-bit (or less) platform
|
||||
# Note that on 32-bit platform, value of bits may be less than 32
|
||||
# (e.g. 31) due to peculiarities described above, so use "> 16",
|
||||
# "> 32", "> 64" style of comparisons.
|
||||
|
||||
.. data:: modules
|
||||
|
||||
Dictionary of loaded modules. On some ports, it may not include builtin
|
||||
modules.
|
||||
|
||||
.. data:: path
|
||||
|
||||
a mutable list of directories to search for imported modules
|
||||
A mutable list of directories to search for imported modules.
|
||||
|
||||
.. data:: platform
|
||||
|
||||
The platform that MicroPython is running on. This is "pyboard" on the
|
||||
pyboard and provides a robust way of determining if a script is running
|
||||
on the pyboard or not.
|
||||
The platform that MicroPython is running on. For OS/RTOS ports, this is
|
||||
usually an identifier of the OS, e.g. ``"linux"``. For baremetal ports it
|
||||
is an identifier of a board, e.g. "pyboard" for the original MicroPython
|
||||
reference board. It thus can be used to distinguish one board from another.
|
||||
If you need to check whether your program runs on MicroPython (vs other
|
||||
Python implementation), use ``sys.implementation`` instead.
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
standard error (connected to USB VCP, and optional UART object)
|
||||
Standard error stream.
|
||||
|
||||
.. data:: stdin
|
||||
|
||||
standard input (connected to USB VCP, and optional UART object)
|
||||
Standard input stream.
|
||||
|
||||
.. data:: stdout
|
||||
|
||||
standard output (connected to USB VCP, and optional UART object)
|
||||
Standard output stream.
|
||||
|
||||
.. data:: version
|
||||
|
||||
Python language version that this implementation conforms to, as a string
|
||||
Python language version that this implementation conforms to, as a string.
|
||||
|
||||
.. data:: version_info
|
||||
|
||||
Python language version that this implementation conforms to, as a tuple of ints
|
||||
Python language version that this implementation conforms to, as a tuple of ints.
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
:mod:`time` -- time related functions
|
||||
=====================================
|
||||
|
||||
.. module:: time
|
||||
:synopsis: time related functions
|
||||
|
||||
The ``time`` module provides functions for getting the current time and date,
|
||||
and for sleeping.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: localtime([secs])
|
||||
|
||||
Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
|
||||
contains: (year, month, mday, hour, minute, second, weekday, yearday)
|
||||
If secs is not provided or None, then the current time from the RTC is used.
|
||||
year includes the century (for example 2014).
|
||||
|
||||
* month is 1-12
|
||||
* mday is 1-31
|
||||
* hour is 0-23
|
||||
* minute is 0-59
|
||||
* second is 0-59
|
||||
* weekday is 0-6 for Mon-Sun
|
||||
* yearday is 1-366
|
||||
|
||||
.. function:: mktime()
|
||||
|
||||
This is inverse function of localtime. It's argument is a full 8-tuple
|
||||
which expresses a time as per localtime. It returns an integer which is
|
||||
the number of seconds since Jan 1, 2000.
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds. Seconds can be a floating-point number to
|
||||
sleep for a fractional number of seconds.
|
||||
|
||||
.. only:: port_esp8266 or port_wipy
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds.
|
||||
|
||||
.. only:: port_wipy or port_pyboard
|
||||
|
||||
.. function:: sleep_ms(ms)
|
||||
|
||||
Delay for given number of milliseconds, should be positive or 0.
|
||||
|
||||
.. function:: sleep_us(us)
|
||||
|
||||
Delay for given number of microseconds, should be positive or 0
|
||||
|
||||
.. function:: ticks_ms()
|
||||
|
||||
Returns an increasing millisecond counter with arbitrary reference point,
|
||||
that wraps after some (unspecified) value. The value should be treated as
|
||||
opaque, suitable for use only with ticks_diff().
|
||||
|
||||
.. function:: ticks_us()
|
||||
|
||||
Just like ``ticks_ms`` above, but in microseconds.
|
||||
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks).
|
||||
|
||||
.. function:: ticks_diff(old, new)
|
||||
|
||||
Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu().
|
||||
The value returned by these functions may wrap around at any time, so directly
|
||||
subtracting them is not supported. ticks_diff() should be used instead. "old" value should
|
||||
actually precede "new" value in time, or result is undefined. This function should not be
|
||||
used to measure arbitrarily long periods of time (because ticks_*() functions wrap around
|
||||
and usually would have short period). The expected usage pattern is implementing event
|
||||
polling with timeout::
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(start, time.ticks_us()) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since 1/1/2000.
|
||||
@@ -10,11 +10,25 @@ encodings of it in ASCII form (in both directions).
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: hexlify(data)
|
||||
.. function:: hexlify(data, [sep])
|
||||
|
||||
Convert binary data to hexadecimal representation. Return bytes string.
|
||||
Convert binary data to hexadecimal representation. Returns bytes string.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
If additional argument, `sep` is supplied, it is used as a seperator
|
||||
between hexadecimal values.
|
||||
|
||||
.. function:: unhexlify(data)
|
||||
|
||||
Convert hexadecimal data to binary representation. Return bytes string.
|
||||
Convert hexadecimal data to binary representation. Returns bytes string.
|
||||
(i.e. inverse of hexlify)
|
||||
|
||||
.. function:: a2b_base64(data)
|
||||
|
||||
Convert Base64-encoded data to binary representation. Returns bytes string.
|
||||
|
||||
.. function:: b2a_base64(data)
|
||||
|
||||
Encode binary data in Base64 format. Returns string.
|
||||
|
||||
53
docs/library/ucollections.rst
Normal file
53
docs/library/ucollections.rst
Normal file
@@ -0,0 +1,53 @@
|
||||
:mod:`ucollections` -- collection and container types
|
||||
=====================================================
|
||||
|
||||
.. module:: ucollections
|
||||
:synopsis: collection and container types
|
||||
|
||||
This module implements advanced collection and container types to
|
||||
hold/accumulate various objects.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. function:: namedtuple(name, fields)
|
||||
|
||||
This is factory function to create a new namedtuple type with a specific
|
||||
name and set of fields. A namedtyple is a subclass of tuple which allows
|
||||
to access its fields not just by numeric index, but also with an attribute
|
||||
access syntax using symbolic field names. Fields is a sequence of strings
|
||||
specifying field names. For compatibily with CPython it can also be a
|
||||
a string with space-separated field named (but this is less efficient).
|
||||
Example of use::
|
||||
|
||||
from ucollections import namedtuple
|
||||
|
||||
MyTuple = namedtuple("MyTuple", ("id", "name"))
|
||||
t1 = MyTuple(1, "foo")
|
||||
t2 = MyTuple(2, "bar")
|
||||
print(t1.name)
|
||||
assert t2.name == t2[1]
|
||||
|
||||
.. function:: OrderedDict(...)
|
||||
|
||||
``dict`` type subclass which remembers and preserves the order of keys
|
||||
added. When ordered dict is iterated over, keys/items are returned in
|
||||
the order they were added::
|
||||
|
||||
from ucollections import OrderedDict
|
||||
|
||||
# To make benefit of ordered keys, OrderedDict should be initialized
|
||||
# from sequence of (key, value) pairs.
|
||||
d = OrderedDict([("z", 1), ("a", 2)])
|
||||
# More items can be added as usual
|
||||
d["w"] = 5
|
||||
d["b"] = 3
|
||||
for k, v in d.items():
|
||||
print(k, v)
|
||||
|
||||
Output::
|
||||
|
||||
z 1
|
||||
a 2
|
||||
w 5
|
||||
b 3
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
This module implements "foreign data interface" for MicroPython. The idea
|
||||
behind it is similar to CPython's ``ctypes`` modules, but actual API is
|
||||
different, steamlined and optimized for small size.
|
||||
different, streamlined and optimized for small size.
|
||||
|
||||
Defining structure layout
|
||||
-------------------------
|
||||
|
||||
46
docs/library/uio.rst
Normal file
46
docs/library/uio.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
:mod:`uio` -- input/output streams
|
||||
==================================
|
||||
|
||||
.. module:: uio
|
||||
:synopsis: input/output streams
|
||||
|
||||
This module contains additional types of stream (file-like) objects
|
||||
and helper functions.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: open(name, mode='r', **kwargs)
|
||||
|
||||
Open a file. Builtin ``open()`` function is alised to this function.
|
||||
All ports (which provide access to file system) are required to support
|
||||
`mode` parameter, but support for other arguments vary by port.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. class:: FileIO(...)
|
||||
|
||||
This is type of a file open in binary mode, e.g. using ``open(name, "rb")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: TextIOWrapper(...)
|
||||
|
||||
This is type of a file open in text mode, e.g. using ``open(name, "rt")``.
|
||||
You should not instantiate this class directly.
|
||||
|
||||
.. class:: StringIO([string])
|
||||
.. class:: BytesIO([string])
|
||||
|
||||
In-memory file-like objects for input/output. `StringIO` is used for
|
||||
text-mode I/O (similar to a normal file opened with "t" modifier).
|
||||
`BytesIO` is used for binary-mode I/O (similar to a normal file
|
||||
opened with "b" modifier). Initial contents of file-like objects
|
||||
can be specified with `string` parameter (should be normal string
|
||||
for `StringIO` or bytes object for `BytesIO`). All the usual file
|
||||
methods like ``read()``, ``write()``, ``close()`` are available on
|
||||
these objects, and additionally, following method:
|
||||
|
||||
.. method:: getvalue()
|
||||
|
||||
Get the current contents of the underlying buffer which holds data.
|
||||
@@ -1,15 +1,16 @@
|
||||
:mod:`os` -- basic "operating system" services
|
||||
==============================================
|
||||
:mod:`uos` -- basic "operating system" services
|
||||
===============================================
|
||||
|
||||
.. module:: os
|
||||
.. module:: uos
|
||||
:synopsis: basic "operating system" services
|
||||
|
||||
The ``os`` module contains functions for filesystem access and ``urandom``.
|
||||
The ``os`` module contains functions for filesystem access and ``urandom``
|
||||
function.
|
||||
|
||||
Pyboard specifics
|
||||
-----------------
|
||||
Port specifics
|
||||
--------------
|
||||
|
||||
The filesystem on the pyboard has ``/`` as the root directory and the
|
||||
The filesystem has ``/`` as the root directory and the
|
||||
available physical drives are accessible from here. They are currently:
|
||||
|
||||
``/flash`` -- the internal flash filesystem
|
||||
@@ -7,6 +7,18 @@
|
||||
|
||||
This module provides access to the BSD socket interface.
|
||||
|
||||
See corresponding `CPython module <https://docs.python.org/3/library/socket.html>`_ for
|
||||
comparison.
|
||||
|
||||
Socket address format(s)
|
||||
------------------------
|
||||
|
||||
Functions below which expect a network address, accept it in the format of
|
||||
`(ipv4_address, port)`, where `ipv4_address` is a string with dot-notation numeric
|
||||
IPv4 address, e.g. ``"8.8.8.8"``, and port is integer port number in the range
|
||||
1-65535. Note the domain names are not accepted as `ipv4_address`, they should be
|
||||
resolved first using ``socket.getaddrinfo()``.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
@@ -37,13 +49,15 @@ Functions
|
||||
The following example shows how to connect to a given url::
|
||||
|
||||
s = socket.socket()
|
||||
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][4])
|
||||
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
.. only:: port_wipy
|
||||
|
||||
.. data:: socket.error
|
||||
.. data:: socket.timeout
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. data:: socket.error
|
||||
.. data:: socket.timeout
|
||||
|
||||
Constants
|
||||
---------
|
||||
@@ -59,9 +73,10 @@ Constants
|
||||
|
||||
.. data:: socket.IPPROTO_UDP
|
||||
.. data:: socket.IPPROTO_TCP
|
||||
.. data:: socket.IPPROTO_SEC
|
||||
.. only:: port_wipy
|
||||
.. data:: socket.IPPROTO_SEC
|
||||
|
||||
protocol numbers
|
||||
protocol numbers
|
||||
|
||||
class socket
|
||||
============
|
||||
@@ -79,8 +94,7 @@ Methods
|
||||
|
||||
.. method:: socket.bind(address)
|
||||
|
||||
Bind the socket to address. The socket must not already be bound. The format of ``address``
|
||||
is: ``(ipv4 address, port)``
|
||||
Bind the socket to address. The socket must not already be bound.
|
||||
|
||||
.. method:: socket.listen([backlog])
|
||||
|
||||
@@ -98,7 +112,7 @@ Methods
|
||||
|
||||
.. method:: socket.connect(address)
|
||||
|
||||
Connect to a remote socket at address. The format of address is: ``(ipv4 address, port)``
|
||||
Connect to a remote socket at address.
|
||||
|
||||
.. method:: socket.send(bytes)
|
||||
|
||||
@@ -116,8 +130,7 @@ Methods
|
||||
.. method:: socket.sendto(bytes, address)
|
||||
|
||||
Send data to the socket. The socket should not be connected to a remote socket, since the
|
||||
destination socket is specified by address. The ``address`` has the same format as the
|
||||
rest of the methods, see above.
|
||||
destination socket is specified by `address`.
|
||||
|
||||
.. method:: socket.recvfrom(bufsize)
|
||||
|
||||
@@ -158,9 +171,10 @@ Methods
|
||||
The socket must be in blocking mode; it can have a timeout, but the file object’s internal buffer
|
||||
may end up in a inconsistent state if a timeout occurs.
|
||||
|
||||
.. note::
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
**CPython difference:** closing the file object returned by makefile() WILL close the
|
||||
Closing the file object returned by makefile() WILL close the
|
||||
original socket as well.
|
||||
|
||||
.. method:: socket.read(size)
|
||||
|
||||
@@ -21,7 +21,7 @@ Functions
|
||||
import ssl
|
||||
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
|
||||
ss = ssl.wrap_socket(s)
|
||||
ss.connect(socket.getaddrinfo('www.google.com', 443)[0][4])
|
||||
ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1])
|
||||
|
||||
Certificates must be used in order to validate the other side of the connection, and also to
|
||||
authenticate ourselves with the other end. Such certificates must be stored as files using the
|
||||
@@ -44,7 +44,7 @@ Functions
|
||||
import ssl
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
|
||||
ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
|
||||
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][4])
|
||||
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
|
||||
|
||||
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
|
||||
|
||||
|
||||
37
docs/library/ustruct.rst
Normal file
37
docs/library/ustruct.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
:mod:`ustruct` -- pack and unpack primitive data types
|
||||
======================================================
|
||||
|
||||
.. module:: ustruct
|
||||
:synopsis: pack and unpack primitive data types
|
||||
|
||||
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
|
||||
information.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: calcsize(fmt)
|
||||
|
||||
Return the number of bytes needed to store the given `fmt`.
|
||||
|
||||
.. function:: pack(fmt, v1, v2, ...)
|
||||
|
||||
Pack the values `v1`, `v2`, ... according to the format string `fmt`.
|
||||
The return value is a bytes object encoding the values.
|
||||
|
||||
.. function:: pack_into(fmt, buffer, offset, v1, v2, ...)
|
||||
|
||||
Pack the values `v1`, `v2`, ... according to the format string `fmt`
|
||||
into a `buffer` starting at `offset`. `offset` may be negative to count
|
||||
from the end of `buffer`.
|
||||
|
||||
.. function:: unpack(fmt, data)
|
||||
|
||||
Unpack from the `data` according to the format string `fmt`.
|
||||
The return value is a tuple of the unpacked values.
|
||||
|
||||
.. function:: unpack_from(fmt, data, offset=0)
|
||||
|
||||
Unpack from the `data` starting at `offset` according to the format string
|
||||
`fmt`. `offset` may be negative to count from the end of `buffer`. The return
|
||||
value is a tuple of the unpacked values.
|
||||
139
docs/library/utime.rst
Normal file
139
docs/library/utime.rst
Normal file
@@ -0,0 +1,139 @@
|
||||
:mod:`utime` -- time related functions
|
||||
======================================
|
||||
|
||||
.. module:: utime
|
||||
:synopsis: time related functions
|
||||
|
||||
The ``utime`` module provides functions for getting the current time and date,
|
||||
measuring time intervals, and for delays.
|
||||
|
||||
**Time Epoch**: Unix port uses standard for POSIX systems epoch of
|
||||
1970-01-01 00:00:00 UTC. However, embedded ports use epoch of
|
||||
2000-01-01 00:00:00 UTC.
|
||||
|
||||
**Maintaining actual calendar date/time**: This requires a
|
||||
Real Time Clock (RTC). On systems with underlying OS (including some
|
||||
RTOS), an RTC may be implicit. Setting and maintaining actual calendar
|
||||
time is responsibility of OS/RTOS and is done outside of MicroPython,
|
||||
it just uses OS API to query date/time. On baremetal ports however
|
||||
system time depends on ``machine.RTC()`` object. The current calendar time
|
||||
may be set using ``machine.RTC().datetime(tuple)`` function, and maintained
|
||||
by following means:
|
||||
|
||||
* By a backup battery (which may be an additional, optional component for
|
||||
a particular board).
|
||||
* Using networked time protocol (requires setup by a port/user).
|
||||
* Set manually by a user on each power-up (many boards then maintain
|
||||
RTC time across hard resets, though some may require setting it again
|
||||
in such case).
|
||||
|
||||
If actual calendar time is not maintained with a system/MicroPython RTC,
|
||||
functions below which require reference to current absolute time may
|
||||
behave not as expected.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: localtime([secs])
|
||||
|
||||
Convert a time expressed in seconds since the Epoch (see above) into an 8-tuple which
|
||||
contains: (year, month, mday, hour, minute, second, weekday, yearday)
|
||||
If secs is not provided or None, then the current time from the RTC is used.
|
||||
|
||||
* year includes the century (for example 2014).
|
||||
* month is 1-12
|
||||
* mday is 1-31
|
||||
* hour is 0-23
|
||||
* minute is 0-59
|
||||
* second is 0-59
|
||||
* weekday is 0-6 for Mon-Sun
|
||||
* yearday is 1-366
|
||||
|
||||
.. function:: mktime()
|
||||
|
||||
This is inverse function of localtime. It's argument is a full 8-tuple
|
||||
which expresses a time as per localtime. It returns an integer which is
|
||||
the number of seconds since Jan 1, 2000.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_esp8266
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds. Seconds can be a floating-point number to
|
||||
sleep for a fractional number of seconds. Note that other MicroPython ports may
|
||||
not accept floating-point argument, for compatibility with them use ``sleep_ms()``
|
||||
and ``sleep_us()`` functions.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
|
||||
|
||||
.. function:: sleep_ms(ms)
|
||||
|
||||
Delay for given number of milliseconds, should be positive or 0.
|
||||
|
||||
.. function:: sleep_us(us)
|
||||
|
||||
Delay for given number of microseconds, should be positive or 0
|
||||
|
||||
.. function:: ticks_ms()
|
||||
|
||||
Returns an increasing millisecond counter with arbitrary reference point,
|
||||
that wraps after some (unspecified) value. The value should be treated as
|
||||
opaque, suitable for use only with ticks_diff().
|
||||
|
||||
.. function:: ticks_us()
|
||||
|
||||
Just like ``ticks_ms`` above, but in microseconds.
|
||||
|
||||
.. only:: port_wipy or port_pyboard
|
||||
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with higher resolution (usually CPU clocks).
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
|
||||
|
||||
.. function:: ticks_diff(old, new)
|
||||
|
||||
Measure period between consecutive calls to ticks_ms(), ticks_us(), or ticks_cpu().
|
||||
The value returned by these functions may wrap around at any time, so directly
|
||||
subtracting them is not supported. ticks_diff() should be used instead. "old" value should
|
||||
actually precede "new" value in time, or result is undefined. This function should not be
|
||||
used to measure arbitrarily long periods of time (because ticks_*() functions wrap around
|
||||
and usually would have short period). The expected usage pattern is implementing event
|
||||
polling with timeout::
|
||||
|
||||
# Wait for GPIO pin to be asserted, but at most 500us
|
||||
start = time.ticks_us()
|
||||
while pin.value() == 0:
|
||||
if time.ticks_diff(start, time.ticks_us()) > 500:
|
||||
raise TimeoutError
|
||||
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since the Epoch, assuming that underlying
|
||||
RTC is set and maintained as decsribed above. If an RTC is not set, this function returns
|
||||
number of seconds since a port-specific reference point in time (for embedded boards without
|
||||
a battery-backed RTC, usually since power up or reset). If you want to develop portable
|
||||
MicroPython application, you should not rely on this function to provide higher than second
|
||||
precision. If you need higher precision, use ``ticks_ms()`` and ``ticks_us()`` functions,
|
||||
if you need calendar time, ``localtime()`` without an argument is a better choice.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
||||
In CPython, this function returns number of
|
||||
seconds since Unix epoch, 1970-01-01 00:00 UTC, as a floating-point,
|
||||
usually having microsecond precision. With MicroPython, only Unix port
|
||||
uses the same Epoch, and if floating-point precision allows,
|
||||
returns sub-second precision. Embedded hardware usually doesn't have
|
||||
floating-point precision to represent both long time ranges and subsecond
|
||||
precision, so they use integer value with second precision. Some embedded
|
||||
hardware also lacks battery-powered RTC, so returns number of seconds
|
||||
since last power-up or from other relative, hardware-specific point
|
||||
(e.g. reset).
|
||||
@@ -64,8 +64,8 @@ This code uses a few new concepts:
|
||||
Accepting arguments
|
||||
-------------------
|
||||
|
||||
Inline assembler functions can accept up to 3 arguments. If they are
|
||||
used, they must be named ``r0``, ``r1`` and ``r2`` to reflect the registers
|
||||
Inline assembler functions can accept up to 4 arguments. If they are
|
||||
used, they must be named ``r0``, ``r1``, ``r2`` and ``r3`` to reflect the registers
|
||||
and the calling conventions.
|
||||
|
||||
Here is a function that adds its arguments::
|
||||
|
||||
@@ -78,11 +78,23 @@ three arguments, which must (if used) be named ``r0``, ``r1`` and ``r2``. When
|
||||
the code executes the registers will be initialised to those values.
|
||||
|
||||
The data types which can be passed in this way are integers and memory
|
||||
addresses. With current firmware all possible 32 bit values may be passed.
|
||||
Returned integers are restricted in that the top two bits must be identical,
|
||||
limiting the range to -2**30 to 2**30 -1. The limitations on number of arguments
|
||||
and return values can be overcome by means of the ``array`` module which enables
|
||||
any number of values of any type to be accessed.
|
||||
addresses. With current firmware all possible 32 bit values may be passed and
|
||||
returned. If the return value may have the most significant bit set a Python
|
||||
type hint should be employed to enable MicroPython to determine whether the
|
||||
value should be interpreted as a signed or unsigned integer: types are
|
||||
``int`` or ``uint``.
|
||||
|
||||
::
|
||||
|
||||
@micropython.asm_thumb
|
||||
def uadd(r0, r1) -> uint:
|
||||
add(r0, r0, r1)
|
||||
|
||||
``hex(uadd(0x40000000,0x40000000))`` will return 0x80000000, demonstrating the
|
||||
passing and return of integers where bits 30 and 31 differ.
|
||||
|
||||
The limitations on the number of arguments and return values can be overcome by means
|
||||
of the ``array`` module which enables any number of values of any type to be accessed.
|
||||
|
||||
Multiple arguments
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -14,6 +14,7 @@ MicroPython are described in the sections here.
|
||||
|
||||
repl.rst
|
||||
isr_rules.rst
|
||||
speed_python.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
|
||||
332
docs/reference/speed_python.rst
Normal file
332
docs/reference/speed_python.rst
Normal file
@@ -0,0 +1,332 @@
|
||||
Maximising Python Speed
|
||||
=======================
|
||||
|
||||
This tutorial describes ways of improving the performance of MicroPython code.
|
||||
Optimisations involving other languages are covered elsewhere, namely the use
|
||||
of modules written in C and the MicroPython inline ARM Thumb-2 assembler.
|
||||
|
||||
The process of developing high performance code comprises the following stages
|
||||
which should be performed in the order listed.
|
||||
|
||||
* Design for speed.
|
||||
* Code and debug.
|
||||
|
||||
Optimisation steps:
|
||||
|
||||
* Identify the slowest section of code.
|
||||
* Improve the efficiency of the Python code.
|
||||
* Use the native code emitter.
|
||||
* Use the viper code emitter.
|
||||
|
||||
Designing for speed
|
||||
-------------------
|
||||
|
||||
Performance issues should be considered at the outset. This involves taking a view
|
||||
on the sections of code which are most performance critical and devoting particular
|
||||
attention to their design. The process of optimisation begins when the code has
|
||||
been tested: if the design is correct at the outset optimisation will be
|
||||
straightforward and may actually be unnecessary.
|
||||
|
||||
Algorithms
|
||||
~~~~~~~~~~
|
||||
|
||||
The most important aspect of designing any routine for performance is ensuring that
|
||||
the best algorithm is employed. This is a topic for textbooks rather than for a
|
||||
MicroPython guide but spectacular performance gains can sometimes be achieved
|
||||
by adopting algorithms known for their efficiency.
|
||||
|
||||
RAM Allocation
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
To design efficient MicroPython code it is necessary to have an understanding of the
|
||||
way the interpreter allocates RAM. When an object is created or grows in size
|
||||
(for example where an item is appended to a list) the necessary RAM is allocated
|
||||
from a block known as the heap. This takes a significant amount of time;
|
||||
further it will on occasion trigger a process known as garbage collection which
|
||||
can take several milliseconds.
|
||||
|
||||
Consequently the performance of a function or method can be improved if an object is created
|
||||
once only and not permitted to grow in size. This implies that the object persists
|
||||
for the duration of its use: typically it will be instantiated in a class constructor
|
||||
and used in various methods.
|
||||
|
||||
This is covered in further detail :ref:`Controlling garbage collection <gc>` below.
|
||||
|
||||
Buffers
|
||||
~~~~~~~
|
||||
|
||||
An example of the above is the common case where a buffer is required, such as one
|
||||
used for communication with a device. A typical driver will create the buffer in the
|
||||
constructor and use it in its I/O methods which will be called repeatedly.
|
||||
|
||||
The MicroPython libraries typically provide support for pre-allocated buffers. For
|
||||
example, objects which support stream interface (e.g., file or UART) provide ``read()``
|
||||
method which allocate new buffer for read data, but also a ``readinto()`` method
|
||||
to read data into an existing buffer.
|
||||
|
||||
Floating Point
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Some MicroPython ports allocate floating point numbers on heap. Some other ports
|
||||
may lack dedicated floating-point coprocessor, and perform arithmetic operations
|
||||
on them in "software" at considerably lower speed than on integers. Where
|
||||
performance is important, use integer operations and restrict the use of floating
|
||||
point to sections of the code where performance is not paramount. For example,
|
||||
capture ADC readings as integers values to an array in one quick go, and only then
|
||||
convert them to floating-point numbers for signal processing.
|
||||
|
||||
Arrays
|
||||
~~~~~~
|
||||
|
||||
Consider the use of the various types of array classes as an alternative to lists.
|
||||
The ``array`` module supports various element types with 8-bit elements supported
|
||||
by Python's built in ``bytes`` and ``bytearray`` classes. These data structures all store
|
||||
elements in contiguous memory locations. Once again to avoid memory allocation in critical
|
||||
code these should be pre-allocated and passed as arguments or as bound objects.
|
||||
|
||||
When passing slices of objects such as ``bytearray`` instances, Python creates
|
||||
a copy which involves allocation of the size proportional to the size of slice.
|
||||
This can be alleviated using a ``memoryview`` object. ``memoryview`` itself
|
||||
is allocated on heap, but is a small, fixed-size object, regardless of the size
|
||||
of slice it points too.
|
||||
|
||||
.. code:: python
|
||||
|
||||
ba = bytearray(10000) # big array
|
||||
func(ba[30:2000]) # a copy is passed, ~2K new allocation
|
||||
mv = memoryview(ba) # small object is allocated
|
||||
func(mv[30:2000]) # a pointer to memory is passed
|
||||
|
||||
A ``memoryview`` can only be applied to objects supporting the buffer protocol - this
|
||||
includes arrays but not lists. Small caveat is that while memoryview object is live,
|
||||
it also keeps alive the original buffer object. So, a memoryview isn't a universal
|
||||
panacea. For instance, in the example above, if you are done with 10K buffer and
|
||||
just need those bytes 30:2000 from it, it may be better to make a slice, and let
|
||||
the 10K buffer go (be ready for garbage collection), instead of making a
|
||||
long-living memoryview and keeping 10K blocked for GC.
|
||||
|
||||
Nonetheless, ``memoryview`` is indispensable for advanced preallocated buffer
|
||||
management. ``.readinto()`` method discussed above puts data at the beginning
|
||||
of buffer and fills in entire buffer. What if you need to put data in the
|
||||
middle of existing buffer? Just create a memoryview into the needed section
|
||||
of buffer and pass it to ``.readinto()``.
|
||||
|
||||
Identifying the slowest section of code
|
||||
---------------------------------------
|
||||
|
||||
This is a process known as profiling and is covered in textbooks and
|
||||
(for standard Python) supported by various software tools. For the type of
|
||||
smaller embedded application likely to be running on MicroPython platforms
|
||||
the slowest function or method can usually be established by judicious use
|
||||
of the timing ``ticks`` group of functions documented
|
||||
`here <http://docs.micropython.org/en/latest/pyboard/library/time.html>`_.
|
||||
Code execution time can be measured in ms, us, or CPU cycles.
|
||||
|
||||
The following enables any function or method to be timed by adding an
|
||||
``@timed_function`` decorator:
|
||||
|
||||
.. code:: python
|
||||
|
||||
def timed_function(f, *args, **kwargs):
|
||||
myname = str(f).split(' ')[1]
|
||||
def new_func(*args, **kwargs):
|
||||
t = time.ticks_us()
|
||||
result = f(*args, **kwargs)
|
||||
delta = time.ticks_diff(t, time.ticks_us())
|
||||
print('Function {} Time = {:6.3f}ms'.format(myname, delta/1000))
|
||||
return result
|
||||
return new_func
|
||||
|
||||
MicroPython code improvements
|
||||
-----------------------------
|
||||
|
||||
The const() declaration
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
MicroPython provides a ``const()`` declaration. This works in a similar way
|
||||
to ``#define`` in C in that when the code is compiled to bytecode the compiler
|
||||
substitutes the numeric value for the identifier. This avoids a dictionary
|
||||
lookup at runtime. The argument to ``const()`` may be anything which, at
|
||||
compile time, evaluates to an integer e.g. ``0x100`` or ``1 << 8``.
|
||||
|
||||
.. _Caching:
|
||||
|
||||
Caching object references
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Where a function or method repeatedly accesses objects performance is improved
|
||||
by caching the object in a local variable:
|
||||
|
||||
.. code:: python
|
||||
|
||||
class foo(object):
|
||||
def __init__(self):
|
||||
ba = bytearray(100)
|
||||
def bar(self, obj_display):
|
||||
ba_ref = self.ba
|
||||
fb = obj_display.framebuffer
|
||||
# iterative code using these two objects
|
||||
|
||||
This avoids the need repeatedly to look up ``self.ba`` and ``obj_display.framebuffer``
|
||||
in the body of the method ``bar()``.
|
||||
|
||||
.. _gc:
|
||||
|
||||
Controlling garbage collection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When memory allocation is required, MicroPython attempts to locate an adequately
|
||||
sized block on the heap. This may fail, usually because the heap is cluttered
|
||||
with objects which are no longer referenced by code. If a failure occurs, the
|
||||
process known as garbage collection reclaims the memory used by these redundant
|
||||
objects and the allocation is then tried again - a process which can take several
|
||||
milliseconds.
|
||||
|
||||
There are benefits in pre-empting this by periodically issuing ``gc.collect()``.
|
||||
Firstly doing a collection before it is actually required is quicker - typically on the
|
||||
order of 1ms if done frequently. Secondly you can determine the point in code
|
||||
where this time is used rather than have a longer delay occur at random points,
|
||||
possibly in a speed critical section. Finally performing collections regularly
|
||||
can reduce fragmentation in the heap. Severe fragmentation can lead to
|
||||
non-recoverable allocation failures.
|
||||
|
||||
Accessing hardware directly
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This comes into the category of more advanced programming and involves some knowledge
|
||||
of the target MCU. Consider the example of toggling an output pin on the Pyboard. The
|
||||
standard approach would be to write
|
||||
|
||||
.. code:: python
|
||||
|
||||
mypin.value(mypin.value() ^ 1) # mypin was instantiated as an output pin
|
||||
|
||||
This involves the overhead of two calls to the ``Pin`` instance's ``value()``
|
||||
method. This overhead can be eliminated by performing a read/write to the relevant bit
|
||||
of the chip's GPIO port output data register (odr). To facilitate this the ``stm``
|
||||
module provides a set of constants providing the addresses of the relevant registers.
|
||||
A fast toggle of pin ``P4`` (CPU pin ``A14``) - corresponding to the green LED -
|
||||
can be performed as follows:
|
||||
|
||||
.. code:: python
|
||||
|
||||
BIT14 = const(1 << 14)
|
||||
stm.mem16[stm.GPIOA + stm.GPIO_ODR] ^= BIT14
|
||||
|
||||
The Native code emitter
|
||||
-----------------------
|
||||
|
||||
This causes the MicroPython compiler to emit ARM native opcodes rather than
|
||||
bytecode. It covers the bulk of the Python language so most functions will require
|
||||
no adaptation (but see below). It is invoked by means of a function decorator:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@micropython.native
|
||||
def foo(self, arg):
|
||||
buf = self.linebuf # Cached object
|
||||
# code
|
||||
|
||||
There are certain limitations in the current implementation of the native code emitter.
|
||||
|
||||
* Context managers are not supported (the ``with`` statement).
|
||||
* Generators are not supported.
|
||||
* If ``raise`` is used an argument must be supplied.
|
||||
|
||||
The trade-off for the improved performance (roughly twices as fast as bytecode) is an
|
||||
increase in compiled code size.
|
||||
|
||||
The Viper code emitter
|
||||
----------------------
|
||||
|
||||
The optimisations discussed above involve standards-compliant Python code. The
|
||||
Viper code emitter is not fully compliant. It supports special Viper native data types
|
||||
in pursuit of performance. Integer processing is non-compliant because it uses machine
|
||||
words: arithmetic on 32 bit hardware is performed modulo 2**32.
|
||||
|
||||
Like the Native emitter Viper produces machine instructions but further optimisations
|
||||
are performed, substantially increasing performance especially for integer arithmetic and
|
||||
bit manipulations. It is invoked using a decorator:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@micropython.viper
|
||||
def foo(self, arg: int) -> int:
|
||||
# code
|
||||
|
||||
As the above fragment illustrates it is beneficial to use Python type hints to assist the Viper optimiser.
|
||||
Type hints provide information on the data types of arguments and of the return value; these
|
||||
are a standard Python language feature formally defined here `PEP0484 <https://www.python.org/dev/peps/pep-0484/>`_.
|
||||
Viper supports its own set of types namely ``int``, ``uint`` (unsigned integer), ``ptr``, ``ptr8``,
|
||||
``ptr16`` and ``ptr32``. The ``ptrX`` types are discussed below. Currently the ``uint`` type serves
|
||||
a single purpose: as a type hint for a function return value. If such a function returns ``0xffffffff``
|
||||
Python will interpret the result as 2**32 -1 rather than as -1.
|
||||
|
||||
In addition to the restrictions imposed by the native emitter the following constraints apply:
|
||||
|
||||
* Functions may have up to four arguments.
|
||||
* Default argument values are not permitted.
|
||||
* Floating point may be used but is not optimised.
|
||||
|
||||
Viper provides pointer types to assist the optimiser. These comprise
|
||||
|
||||
* ``ptr`` Pointer to an object.
|
||||
* ``ptr8`` Points to a byte.
|
||||
* ``ptr16`` Points to a 16 bit half-word.
|
||||
* ``ptr32`` Points to a 32 bit machine word.
|
||||
|
||||
The concept of a pointer may be unfamiliar to Python programmers. It has similarities
|
||||
to a Python ``memoryview`` object in that it provides direct access to data stored in memory.
|
||||
Items are accessed using subscript notation, but slices are not supported: a pointer can return
|
||||
a single item only. Its purpose is to provide fast random access to data stored in contiguous
|
||||
memory locations - such as data stored in objects which support the buffer protocol, and
|
||||
memory-mapped peripheral registers in a microcontroller. It should be noted that programming
|
||||
using pointers is hazardous: bounds checking is not performed and the compiler does nothing to
|
||||
prevent buffer overrun errors.
|
||||
|
||||
Typical usage is to cache variables:
|
||||
|
||||
.. code:: python
|
||||
|
||||
@micropython.viper
|
||||
def foo(self, arg: int) -> int:
|
||||
buf = ptr8(self.linebuf) # self.linebuf is a bytearray or bytes object
|
||||
for x in range(20, 30):
|
||||
bar = buf[x] # Access a data item through the pointer
|
||||
# code omitted
|
||||
|
||||
In this instance the compiler "knows" that ``buf`` is the address of an array of bytes;
|
||||
it can emit code to rapidly compute the address of ``buf[x]`` at runtime. Where casts are
|
||||
used to convert objects to Viper native types these should be performed at the start of
|
||||
the function rather than in critical timing loops as the cast operation can take several
|
||||
microseconds. The rules for casting are as follows:
|
||||
|
||||
* Casting operators are currently: ``int``, ``bool``, ``uint``, ``ptr``, ``ptr8``, ``ptr16`` and ``ptr32``.
|
||||
* The result of a cast will be a native Viper variable.
|
||||
* Arguments to a cast can be a Python object or a native Viper variable.
|
||||
* If argument is a native Viper variable, then cast is a no-op (i.e. costs nothing at runtime)
|
||||
that just changes the type (e.g. from ``uint`` to ``ptr8``) so that you can then store/load
|
||||
using this pointer.
|
||||
* If the argument is a Python object and the cast is ``int`` or ``uint``, then the Python object
|
||||
must be of integral type and the value of that integral object is returned.
|
||||
* The argument to a bool cast must be integral type (boolean or integer); when used as a return
|
||||
type the viper function will return True or False objects.
|
||||
* If the argument is a Python object and the cast is ``ptr``, ``ptr``, ``ptr16`` or ``ptr32``,
|
||||
then the Python object must either have the buffer protocol with read-write capabilities
|
||||
(in which case a pointer to the start of the buffer is returned) or it must be of integral
|
||||
type (in which case the value of that integral object is returned).
|
||||
|
||||
The following example illustrates the use of a ``ptr16`` cast to toggle pin X1 ``n`` times:
|
||||
|
||||
.. code:: python
|
||||
|
||||
BIT0 = const(1)
|
||||
@micropython.viper
|
||||
def toggle_n(n: int):
|
||||
odr = ptr16(stm.GPIOA + stm.GPIO_ODR)
|
||||
for _ in range(n):
|
||||
odr[0] ^= BIT0
|
||||
|
||||
A detailed technical description of the three code emitters may be found
|
||||
on Kickstarter here `Note 1 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/664832>`_
|
||||
and here `Note 2 <https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/665145>`_
|
||||
39
docs/templates/versions.html
vendored
Normal file
39
docs/templates/versions.html
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
<div class="rst-versions" data-toggle="rst-versions" role="note" aria-label="versions">
|
||||
<span class="rst-current-version" data-toggle="rst-current-version">
|
||||
<span class="fa fa-book"> Ports and Versions</span>
|
||||
{{ port }} ({{ port_version }})
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
<dl>
|
||||
<dt>Ports</dt>
|
||||
{% for slug, url in all_ports %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>Versions</dt>
|
||||
{% for slug, url in all_versions %}
|
||||
<dd><a href="{{ url }}">{{ slug }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
<!--
|
||||
<dl>
|
||||
<dt>Downloads</dt>
|
||||
{% for type, url in downloads %}
|
||||
<dd><a href="{{ url }}">{{ type }}</a></dd>
|
||||
{% endfor %}
|
||||
</dl>
|
||||
-->
|
||||
<hr/>
|
||||
<dl>
|
||||
<dt>External links</dt>
|
||||
<dd>
|
||||
<a href="http://www.micropython.org">micropython.org</a>
|
||||
</dd>
|
||||
<dd>
|
||||
<a href="https://github.com/micropython/micropython">GitHub</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
{% if port == "pyboard" or port == "wipy" %}
|
||||
{% if port in ("pyboard", "wipy", "esp8266") %}
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto(port + "/quickref") }}">Quick reference for {{ port_name }}</a><br/>
|
||||
<span class="linkdescr">pinout for {{ port_name }} and snippets of useful code</span>
|
||||
@@ -41,10 +41,10 @@
|
||||
{% endif %}
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
|
||||
{% if port == "wipy" %}
|
||||
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
|
||||
{% else %}
|
||||
{% if port == "pyboard" %}
|
||||
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/pyb") }}">pyb module</a></span>
|
||||
{% else %}
|
||||
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
|
||||
@@ -170,3 +170,12 @@ There are currently 2 kinds of errors that you might see:
|
||||
2. If the heartbeat LED stays on, then there was a hard fault, you cannot
|
||||
recover from this, the only way out is to press the reset switch.
|
||||
|
||||
Details on sleep modes
|
||||
----------------------
|
||||
|
||||
* ``machine.idle()``: Power consumption: ~12mA (in WLAN STA mode). Wake sources:
|
||||
any hardware interrupt (including systick with period of 1ms), no special
|
||||
configuration required.
|
||||
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
|
||||
and ``WLAN``
|
||||
* ``machine.deepsleep()``: ~5uA. Wake sources are ``Pin`` and ``RTC``.
|
||||
|
||||
@@ -49,10 +49,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. :
|
||||
from machine import Timer
|
||||
from machine import Pin
|
||||
|
||||
tim = Timer(1, mode=Timer.PERIODIC)
|
||||
tim = Timer(0, mode=Timer.PERIODIC)
|
||||
tim_a = tim.channel(Timer.A, freq=1000)
|
||||
tim_a.time() # get the value in microseconds
|
||||
tim_a.freq(1) # 1 Hz
|
||||
tim_a.freq(5) # 5 Hz
|
||||
|
||||
p_out = Pin('GP2', mode=Pin.OUT)
|
||||
tim_a.irq(handler=lambda t: p_out.toggle())
|
||||
@@ -63,16 +63,12 @@ PWM (pulse width modulation)
|
||||
See :ref:`machine.Pin <machine.Pin>` and :ref:`machine.Timer <machine.Timer>`. ::
|
||||
|
||||
from machine import Timer
|
||||
from machine import Pin
|
||||
|
||||
# assign GP25 to alternate function 9 (PWM)
|
||||
p_out = Pin('GP25', mode=Pin.AF, alt=9)
|
||||
|
||||
# timer 2 in PWM mode and width must be 16 buts
|
||||
tim = Timer(2, mode=Timer.PWM, width=16)
|
||||
# timer 1 in PWM mode and width must be 16 buts
|
||||
tim = Timer(1, mode=Timer.PWM, width=16)
|
||||
|
||||
# enable channel A @1KHz with a 50% duty cycle
|
||||
tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=50)
|
||||
# enable channel A @1KHz with a 50.55% duty cycle
|
||||
tim_a = tim.channel(Timer.A, freq=1000, duty_cycle=5055)
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
@@ -201,12 +197,12 @@ See :ref:`network.WLAN <network.WLAN>` and :mod:`machine`. ::
|
||||
Telnet and FTP server
|
||||
---------------------
|
||||
|
||||
See :ref:`network.server <network.server>` ::
|
||||
See :ref:`network.Server <network.Server>` ::
|
||||
|
||||
from network import server
|
||||
from network import Server
|
||||
|
||||
# init with new user, password and seconds timeout
|
||||
server = server.init(login=('user', 'password'), timeout=60)
|
||||
server = Server(login=('user', 'password'), timeout=60)
|
||||
server.timeout(300) # change the timeout
|
||||
server.timeout() # get the timeout
|
||||
server.isrunning() # check wether the server is running or not
|
||||
|
||||
145
drivers/display/ssd1306.py
Normal file
145
drivers/display/ssd1306.py
Normal file
@@ -0,0 +1,145 @@
|
||||
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
|
||||
import time
|
||||
import framebuf
|
||||
|
||||
# register definitions
|
||||
SET_CONTRAST = const(0x81)
|
||||
SET_ENTIRE_ON = const(0xa4)
|
||||
SET_NORM_INV = const(0xa6)
|
||||
SET_DISP = const(0xae)
|
||||
SET_MEM_ADDR = const(0x20)
|
||||
SET_COL_ADDR = const(0x21)
|
||||
SET_PAGE_ADDR = const(0x22)
|
||||
SET_DISP_START_LINE = const(0x40)
|
||||
SET_SEG_REMAP = const(0xa0)
|
||||
SET_MUX_RATIO = const(0xa8)
|
||||
SET_COM_OUT_DIR = const(0xc0)
|
||||
SET_DISP_OFFSET = const(0xd3)
|
||||
SET_COM_PIN_CFG = const(0xda)
|
||||
SET_DISP_CLK_DIV = const(0xd5)
|
||||
SET_PRECHARGE = const(0xd9)
|
||||
SET_VCOM_DESEL = const(0xdb)
|
||||
SET_CHARGE_PUMP = const(0x8d)
|
||||
|
||||
class SSD1306:
|
||||
def __init__(self, height, external_vcc):
|
||||
self.width = 128
|
||||
self.height = height
|
||||
self.external_vcc = external_vcc
|
||||
self.pages = self.height // 8
|
||||
self.buffer = bytearray(self.pages * self.width)
|
||||
self.framebuf = framebuf.FrameBuffer1(self.buffer, self.width, self.height)
|
||||
self.poweron()
|
||||
self.init_display()
|
||||
|
||||
def init_display(self):
|
||||
for cmd in (
|
||||
SET_DISP | 0x00, # off
|
||||
# address setting
|
||||
SET_MEM_ADDR, 0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
|
||||
SET_MUX_RATIO, self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
|
||||
SET_DISP_OFFSET, 0x00,
|
||||
SET_COM_PIN_CFG, 0x02 if self.height == 32 else 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV, 0x80,
|
||||
SET_PRECHARGE, 0x22 if self.external_vcc else 0xf1,
|
||||
SET_VCOM_DESEL, 0x30, # 0.83*Vcc
|
||||
# display
|
||||
SET_CONTRAST, 0xff, # maximum
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
# charge pump
|
||||
SET_CHARGE_PUMP, 0x10 if self.external_vcc else 0x14,
|
||||
SET_DISP | 0x01): # on
|
||||
self.write_cmd(cmd)
|
||||
self.fill(0)
|
||||
self.show()
|
||||
|
||||
def poweroff(self):
|
||||
self.write_cmd(SET_DISP | 0x00)
|
||||
|
||||
def contrast(self, contrast):
|
||||
self.write_cmd(SET_CONTRAST)
|
||||
self.write_cmd(contrast)
|
||||
|
||||
def invert(self, invert):
|
||||
self.write_cmd(SET_NORM_INV | (invert & 1))
|
||||
|
||||
def show(self):
|
||||
self.write_cmd(SET_COL_ADDR)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.width - 1)
|
||||
self.write_cmd(SET_PAGE_ADDR)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.pages - 1)
|
||||
self.write_data(self.buffer)
|
||||
|
||||
def fill(self, col):
|
||||
self.framebuf.fill(col)
|
||||
|
||||
def pixel(self, x, y, col):
|
||||
self.framebuf.pixel(x, y, col)
|
||||
|
||||
def scroll(self, dx, dy):
|
||||
self.framebuf.scroll(dx, dy)
|
||||
|
||||
def text(self, string, x, y, col=1):
|
||||
self.framebuf.text(string, x, y, col)
|
||||
|
||||
class SSD1306_I2C(SSD1306):
|
||||
def __init__(self, height, i2c, addr=0x3c, external_vcc=False):
|
||||
self.i2c = i2c
|
||||
self.addr = addr
|
||||
self.temp = bytearray(2)
|
||||
super().__init__(height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.temp[0] = 0x80 # Co=1, D/C#=0
|
||||
self.temp[1] = cmd
|
||||
self.i2c.writeto(self.addr, self.temp)
|
||||
|
||||
def write_data(self, buf):
|
||||
self.temp[0] = self.addr << 1
|
||||
self.temp[1] = 0x40 # Co=0, D/C#=1
|
||||
self.i2c.start()
|
||||
self.i2c.write(self.temp)
|
||||
self.i2c.write(buf)
|
||||
self.i2c.stop()
|
||||
|
||||
def poweron(self):
|
||||
pass
|
||||
|
||||
# TODO convert this class to use the new hardware API
|
||||
class SSD1306_SPI(SSD1306):
|
||||
def __init__(self, height, spi, dc, res, cs=None, external_vcc=False):
|
||||
rate = 10 * 1024 * 1024
|
||||
spi.init(spi.MASTER, baudrate=rate, polarity=0, phase=0)
|
||||
dc.init(dc.OUT, dc.PULL_NONE, value=0)
|
||||
res.init(res.OUT, dc.PULL_NONE, value=0)
|
||||
if cs is not None:
|
||||
cs.init(cs.OUT, cs.PULL_NONE, value=0)
|
||||
self.spi = spi
|
||||
self.dc = dc
|
||||
self.res = res
|
||||
super().__init__(height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.dc.low()
|
||||
self.spi.send(cmd)
|
||||
|
||||
def write_data(self, buf):
|
||||
self.dc.high()
|
||||
self.spi.send(buf)
|
||||
|
||||
def poweron(self):
|
||||
self.res.high()
|
||||
time.sleep_ms(1)
|
||||
self.res.low()
|
||||
time.sleep_ms(10)
|
||||
self.res.high()
|
||||
time.sleep_ms(10)
|
||||
@@ -25,6 +25,9 @@ class SDCard:
|
||||
#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
|
||||
#R1_ADDRESS_ERROR = const(1 << 5)
|
||||
#R1_PARAMETER_ERROR = const(1 << 6)
|
||||
TOKEN_CMD25 = const(0xfc)
|
||||
TOKEN_STOP_TRAN = const(0xfd)
|
||||
TOKEN_DATA = const(0xfe)
|
||||
|
||||
def __init__(self, spi, cs):
|
||||
self.spi = spi
|
||||
@@ -136,6 +139,18 @@ class SDCard:
|
||||
self.spi.send(0xff)
|
||||
return -1
|
||||
|
||||
def cmd_nodata(self, cmd):
|
||||
self.spi.send(cmd)
|
||||
self.spi.send_recv(0xff) # ignore stuff byte
|
||||
for _ in range(CMD_TIMEOUT):
|
||||
if self.spi.send_recv(0xff)[0] == 0xff:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
return 0 # OK
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
return 1 # timeout
|
||||
|
||||
def readinto(self, buf):
|
||||
self.cs.low()
|
||||
|
||||
@@ -154,11 +169,11 @@ class SDCard:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
|
||||
def write(self, buf):
|
||||
def write(self, token, buf):
|
||||
self.cs.low()
|
||||
|
||||
# send: start of block, data, checksum
|
||||
self.spi.send(0xfe)
|
||||
self.spi.send(token)
|
||||
self.spi.send(buf)
|
||||
self.spi.send(0xff)
|
||||
self.spi.send(0xff)
|
||||
@@ -176,29 +191,62 @@ class SDCard:
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
|
||||
def write_token(self, token):
|
||||
self.cs.low()
|
||||
self.spi.send(token)
|
||||
self.spi.send(0xff)
|
||||
# wait for write to finish
|
||||
while self.spi.send_recv(0xff)[0] == 0:
|
||||
pass
|
||||
|
||||
self.cs.high()
|
||||
self.spi.send(0xff)
|
||||
|
||||
def count(self):
|
||||
return self.sectors
|
||||
|
||||
def readblocks(self, block_num, buf):
|
||||
# TODO support multiple block reads
|
||||
assert len(buf) == 512
|
||||
|
||||
# CMD17: set read address for single block
|
||||
if self.cmd(17, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
|
||||
# receive the data
|
||||
self.readinto(buf)
|
||||
nblocks, err = divmod(len(buf), 512)
|
||||
assert nblocks and not err, 'Buffer length is invalid'
|
||||
if nblocks == 1:
|
||||
# CMD17: set read address for single block
|
||||
if self.cmd(17, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
# receive the data
|
||||
self.readinto(buf)
|
||||
else:
|
||||
# CMD18: set read address for multiple blocks
|
||||
if self.cmd(18, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
offset = 0
|
||||
mv = memoryview(buf)
|
||||
while nblocks:
|
||||
self.readinto(mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
return self.cmd_nodata(12)
|
||||
return 0
|
||||
|
||||
def writeblocks(self, block_num, buf):
|
||||
# TODO support multiple block writes
|
||||
assert len(buf) == 512
|
||||
nblocks, err = divmod(len(buf), 512)
|
||||
assert nblocks and not err, 'Buffer length is invalid'
|
||||
if nblocks == 1:
|
||||
# CMD24: set write address for single block
|
||||
if self.cmd(24, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
|
||||
# CMD24: set write address for single block
|
||||
if self.cmd(24, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
|
||||
# send the data
|
||||
self.write(buf)
|
||||
# send the data
|
||||
self.write(TOKEN_DATA, buf)
|
||||
else:
|
||||
# CMD25: set write address for first block
|
||||
if self.cmd(25, block_num * self.cdv, 0) != 0:
|
||||
return 1
|
||||
# send the data
|
||||
offset = 0
|
||||
mv = memoryview(buf)
|
||||
while nblocks:
|
||||
self.write(TOKEN_CMD25, mv[offset : offset + 512])
|
||||
offset += 512
|
||||
nblocks -= 1
|
||||
self.write_token(TOKEN_STOP_TRAN)
|
||||
return 0
|
||||
|
||||
57
drivers/sdcard/sdtest.py
Normal file
57
drivers/sdcard/sdtest.py
Normal file
@@ -0,0 +1,57 @@
|
||||
# Test for sdcard block protocol
|
||||
# Peter hinch 30th Jan 2016
|
||||
import os, sdcard, pyb
|
||||
|
||||
def sdtest():
|
||||
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X21) # Compatible with PCB
|
||||
pyb.mount(sd, '/fc')
|
||||
print('Filesystem check')
|
||||
print(os.listdir('/fc'))
|
||||
|
||||
line = 'abcdefghijklmnopqrstuvwxyz\n'
|
||||
lines = line * 200 # 5400 chars
|
||||
short = '1234567890\n'
|
||||
|
||||
fn = '/fc/rats.txt'
|
||||
print()
|
||||
print('Multiple block read/write')
|
||||
with open(fn,'w') as f:
|
||||
n = f.write(lines)
|
||||
print(n, 'bytes written')
|
||||
n = f.write(short)
|
||||
print(n, 'bytes written')
|
||||
n = f.write(lines)
|
||||
print(n, 'bytes written')
|
||||
|
||||
with open(fn,'r') as f:
|
||||
result1 = f.read()
|
||||
print(len(result1), 'bytes read')
|
||||
|
||||
fn = '/fc/rats1.txt'
|
||||
print()
|
||||
print('Single block read/write')
|
||||
with open(fn,'w') as f:
|
||||
n = f.write(short) # one block
|
||||
print(n, 'bytes written')
|
||||
|
||||
with open(fn,'r') as f:
|
||||
result2 = f.read()
|
||||
print(len(result2), 'bytes read')
|
||||
|
||||
pyb.mount(None, '/fc')
|
||||
|
||||
print()
|
||||
print('Verifying data read back')
|
||||
success = True
|
||||
if result1 == ''.join((lines, short, lines)):
|
||||
print('Large file Pass')
|
||||
else:
|
||||
print('Large file Fail')
|
||||
success = False
|
||||
if result2 == short:
|
||||
print('Small file Pass')
|
||||
else:
|
||||
print('Small file Fail')
|
||||
success = False
|
||||
print()
|
||||
print('Tests', 'passed' if success else 'failed')
|
||||
@@ -3,14 +3,16 @@ include ../py/mkenv.mk
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
|
||||
|
||||
MICROPY_PY_USSL = 1
|
||||
|
||||
# include py core make definitions
|
||||
include ../py/py.mk
|
||||
|
||||
MAKE_FROZEN = ../tools/make-frozen.py
|
||||
|
||||
SCRIPTDIR = scripts
|
||||
PORT = /dev/ttyACM0
|
||||
BAUD = 115200
|
||||
PORT ?= /dev/ttyACM0
|
||||
BAUD ?= 115200
|
||||
CROSS_COMPILE = xtensa-lx106-elf-
|
||||
ESP_SDK = $(shell $(CC) -print-sysroot)/usr
|
||||
|
||||
@@ -23,18 +25,21 @@ INC += -I../lib/timeutils
|
||||
INC += -I$(BUILD)
|
||||
INC += -I$(ESP_SDK)/include
|
||||
|
||||
UART_OS = 1
|
||||
# UART for "os" messages. 0 is normal UART as used by MicroPython REPL,
|
||||
# 1 is debug UART (tx only).
|
||||
UART_OS = 0
|
||||
|
||||
CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
|
||||
-D__ets__ -DICACHE_FLASH \
|
||||
-fno-inline-functions \
|
||||
-Wl,-EL -mlongcalls -mtext-section-literals \
|
||||
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
|
||||
-DLWIP_OPEN_SRC
|
||||
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
|
||||
$(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA)
|
||||
$(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
LDFLAGS = -nostdlib -T esp8266.ld -Map=$(@:.elf=.map) --cref
|
||||
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip -lpp -lnet80211 -lwpa -lphy -lnet80211
|
||||
LIBS = -L$(ESP_SDK)/lib -lmain -ljson -llwip_open -lpp -lnet80211 -lwpa -lphy -lnet80211 $(LDFLAGS_MOD)
|
||||
|
||||
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
|
||||
@@ -52,31 +57,70 @@ endif
|
||||
SRC_C = \
|
||||
strtoll.c \
|
||||
main.c \
|
||||
help.c \
|
||||
esp_mphal.c \
|
||||
gccollect.c \
|
||||
lexerstr32.c \
|
||||
uart.c \
|
||||
esppwm.c \
|
||||
esponewire.c \
|
||||
espneopixel.c \
|
||||
intr.c \
|
||||
modpyb.c \
|
||||
modpybpin.c \
|
||||
modpybpwm.c \
|
||||
modpybrtc.c \
|
||||
modpybadc.c \
|
||||
modpybuart.c \
|
||||
modpybspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
modutime.c \
|
||||
moduos.c \
|
||||
utils.c \
|
||||
modmachine.c \
|
||||
modonewire.c \
|
||||
ets_alt_task.c \
|
||||
$(BUILD)/frozen.c \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
pybstdio.c \
|
||||
input.c \
|
||||
)
|
||||
|
||||
EXTMOD_SRC_C = $(addprefix extmod/,\
|
||||
modlwip.c \
|
||||
)
|
||||
|
||||
LIB_SRC_C = $(addprefix lib/,\
|
||||
libc/string0.c \
|
||||
libm/math.c \
|
||||
libm/fmodf.c \
|
||||
libm/roundf.c \
|
||||
libm/ef_sqrt.c \
|
||||
libm/kf_rem_pio2.c \
|
||||
libm/kf_sin.c \
|
||||
libm/kf_cos.c \
|
||||
libm/kf_tan.c \
|
||||
libm/ef_rem_pio2.c \
|
||||
libm/sf_sin.c \
|
||||
libm/sf_cos.c \
|
||||
libm/sf_tan.c \
|
||||
libm/sf_frexp.c \
|
||||
libm/sf_modf.c \
|
||||
libm/sf_ldexp.c \
|
||||
libm/asinfacosf.c \
|
||||
libm/atanf.c \
|
||||
libm/atan2f.c \
|
||||
mp-readline/readline.c \
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
)
|
||||
|
||||
SRC_S = \
|
||||
@@ -87,9 +131,15 @@ OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
#OBJ += $(BUILD)/pins_$(BOARD).o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
all: $(BUILD)/firmware-combined.bin
|
||||
|
||||
CONFVARS_FILE = $(BUILD)/confvars
|
||||
@@ -111,16 +161,16 @@ $(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE)
|
||||
|
||||
deploy: $(BUILD)/firmware-combined.bin
|
||||
$(ECHO) "Writing $< to the board"
|
||||
#$(Q)esptool.py --port $(PORT) write_flash 0 $<
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash 0 $(BUILD)/firmware.elf-0x00000.bin 0x10000 $(BUILD)/firmware.elf-0x10000.bin
|
||||
$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $<
|
||||
#$(Q)esptool.py --port $(PORT) --baud $(BAUD) write_flash --flash_size=8m 0 $(BUILD)/firmware.elf-0x00000.bin 0x9000 $(BUILD)/firmware.elf-0x0[1-f]000.bin
|
||||
|
||||
reset:
|
||||
echo -e "\r\nimport pyb; pyb.hard_reset()\r\n" >$(PORT)
|
||||
echo -e "\r\nimport machine; machine.reset()\r\n" >$(PORT)
|
||||
|
||||
$(BUILD)/firmware-combined.bin: $(BUILD)/firmware.elf
|
||||
$(ECHO) "Create $@"
|
||||
$(Q)esptool.py elf2image $^
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x10000.bin $@
|
||||
$(Q)$(PYTHON) makeimg.py $(BUILD)/firmware.elf-0x00000.bin $(BUILD)/firmware.elf-0x0[1-f]000.bin $@
|
||||
|
||||
$(BUILD)/firmware.elf: $(OBJ)
|
||||
$(ECHO) "LINK $@"
|
||||
@@ -154,3 +204,9 @@ $(BUILD)/firmware.elf: $(OBJ)
|
||||
# $(call compile_c)
|
||||
|
||||
include ../py/mkrules.mk
|
||||
|
||||
axtls:
|
||||
cd ../lib/axtls; cp config/upyconfig config/.config
|
||||
cd ../lib/axtls; make oldconfig -B
|
||||
cd ../lib/axtls; make clean
|
||||
cd ../lib/axtls; make all CC="$(CC)" LD="$(LD)" AR="$(AR)" CFLAGS_EXTRA="$(CFLAGS_XTENSA) -Dabort=abort_ -DRT_MAX_PLAIN_LENGTH=1024 -DRT_EXTRA=3072"
|
||||
|
||||
@@ -8,49 +8,79 @@ WARNING: The port is highly experimental and any APIs are subject to change.
|
||||
|
||||
Currently implemented features include:
|
||||
- REPL (Python prompt) over UART0.
|
||||
- 24k heap RAM available for Python code.
|
||||
- Garbage collector, exceptions.
|
||||
- Unicode support.
|
||||
- Builtin modules: gc, array, collections, io, struct, sys, esp, network.
|
||||
- C long-long type used as bignum implementation (gives 64 bit signed ints).
|
||||
- Rudimentary WiFi support in station mode.
|
||||
- Sockets with callbacks.
|
||||
- Basic GPIO support.
|
||||
|
||||
Note that floating-point numbers are not supported.
|
||||
|
||||
On the TODO list:
|
||||
- Full wifi support.
|
||||
- Builtin modules: gc, array, collections, io, struct, sys, esp, network,
|
||||
many more.
|
||||
- Arbitrary-precision long integers and 30-bit precision floats.
|
||||
- WiFi support.
|
||||
- Sockets using modlwip.
|
||||
- GPIO and bit-banging I2C, SPI support.
|
||||
- 1-Wire and WS2812 (aka Neopixel) protocols support.
|
||||
- Internal filesystem using the flash.
|
||||
- ...
|
||||
- WebREPL over WiFi from a browser (clients at https://github.com/micropython/webrepl).
|
||||
|
||||
Work-in-progress documentation is available at
|
||||
http://docs.micropython.org/en/latest/esp8266/ .
|
||||
|
||||
Build instructions
|
||||
------------------
|
||||
|
||||
The tool chain required for the build is the OpenSource ESP SDK, which can be
|
||||
found at <https://github.com/pfalcon/esp-open-sdk>. Clone this repository and
|
||||
run `make` in its directory to build and install the SDK locally.
|
||||
run `make` in its directory to build and install the SDK locally. Make sure
|
||||
to add toolchain bin directory to your PATH. Read esp-open-sdk's README for
|
||||
additional important information on toolchain setup.
|
||||
|
||||
Add the external dependencies to the MicroPython repository checkout:
|
||||
```bash
|
||||
$ git submodule update --init
|
||||
```
|
||||
See the README in the repository root for more information about external
|
||||
dependencies.
|
||||
|
||||
Then, to build MicroPython for the ESP8266, just run:
|
||||
```bash
|
||||
$ cd esp8266
|
||||
$ make axtls
|
||||
$ make
|
||||
```
|
||||
This should produce binary images in the `build/` subdirectory. To flash them
|
||||
to your ESP8266, use:
|
||||
This will produce binary images in the `build/` subdirectory. If you install
|
||||
MicroPython to your module for the first time, or after installing any other
|
||||
firmware, you should erase flash completely:
|
||||
|
||||
```
|
||||
esptool.py --port /dev/ttyXXX erase_flash
|
||||
```
|
||||
|
||||
Erase flash also as a troubleshooting measure, if a module doesn't behave as
|
||||
expected.
|
||||
|
||||
To flash MicroPython image to your ESP8266, use:
|
||||
```bash
|
||||
$ make deploy
|
||||
```
|
||||
This will use the `esptool.py` script to download the images. You must have
|
||||
your ESP module in the bootloader, and connected to a serial port on your PC.
|
||||
your ESP module in the bootloader mode, and connected to a serial port on your PC.
|
||||
The default serial port is `/dev/ttyACM0`. To specify another, use, eg:
|
||||
```bash
|
||||
$ make PORT=/dev/ttyUSB0 deploy
|
||||
```
|
||||
|
||||
The images that are built are:
|
||||
- `firmware.elf-0x00000.bin`: to be flashed at 0x00000
|
||||
- `firmware.elf-0x10000.bin`: to be flashed at 0x10000
|
||||
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
|
||||
|
||||
There is also a combined image, made up of the above 2 binary files with the
|
||||
appropriate padding:
|
||||
- `firmware-combined.bin`: to be flashed at 0x00000
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
While the port is still in alpha, it's known to be generally stable. If you
|
||||
experience strange bootloops, crashes, lockups, here's a list to check against:
|
||||
|
||||
- You didn't erase flash before programming MicroPython firmware.
|
||||
- Firmware can be occasionally flashed incorrectly. Just retry. Recent
|
||||
esptool.py versions have --verify option.
|
||||
- Power supply you use doesn't provide enough power for ESP8266 or isn't
|
||||
stable enough.
|
||||
- A module/flash may be defective (not unheard of for cheap modules).
|
||||
|
||||
Please consult dedicated ESP8266 forums/resources for hardware-related
|
||||
problems.
|
||||
|
||||
66
esp8266/axtls_helpers.c
Normal file
66
esp8266/axtls_helpers.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Paul Sokolovsky
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include "py/mphal.h"
|
||||
#include "py/gc.h"
|
||||
|
||||
// Functions for axTLS
|
||||
|
||||
void *malloc(size_t size) {
|
||||
return gc_alloc(size, false);
|
||||
}
|
||||
void free(void *ptr) {
|
||||
gc_free(ptr);
|
||||
}
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
return m_malloc0(nmemb * size);
|
||||
}
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
return gc_realloc(ptr, size, true);
|
||||
}
|
||||
void abort_(void) {
|
||||
printf("Aborted\n");
|
||||
}
|
||||
|
||||
#define PLATFORM_HTONL(_n) ((uint32_t)( (((_n) & 0xff) << 24) | (((_n) & 0xff00) << 8) | (((_n) >> 8) & 0xff00) | (((_n) >> 24) & 0xff) ))
|
||||
#undef htonl
|
||||
#undef ntohl
|
||||
uint32_t ntohl(uint32_t netlong) {
|
||||
return PLATFORM_HTONL(netlong);
|
||||
}
|
||||
uint32_t htonl(uint32_t netlong) {
|
||||
return PLATFORM_HTONL(netlong);
|
||||
}
|
||||
|
||||
time_t time(time_t *t) {
|
||||
return mp_hal_ticks_ms() / 1000;
|
||||
}
|
||||
|
||||
time_t mktime(void *tm) {
|
||||
return 0;
|
||||
}
|
||||
@@ -50,8 +50,8 @@ PROVIDE ( _UserExceptionVector = 0x40000050 );
|
||||
PROVIDE ( __adddf3 = 0x4000c538 );
|
||||
PROVIDE ( __addsf3 = 0x4000c180 );
|
||||
PROVIDE ( __divdf3 = 0x4000cb94 );
|
||||
PROVIDE ( __divdi3 = 0x4000ce60 );
|
||||
PROVIDE ( __divsi3 = 0x4000dc88 );
|
||||
__divdi3 = 0x4000ce60;
|
||||
__divsi3 = 0x4000dc88;
|
||||
PROVIDE ( __extendsfdf2 = 0x4000cdfc );
|
||||
PROVIDE ( __fixdfsi = 0x4000ccb8 );
|
||||
PROVIDE ( __fixunsdfsi = 0x4000cd00 );
|
||||
@@ -61,16 +61,16 @@ PROVIDE ( __floatsisf = 0x4000e2ac );
|
||||
PROVIDE ( __floatunsidf = 0x4000e2e8 );
|
||||
PROVIDE ( __floatunsisf = 0x4000e2a4 );
|
||||
PROVIDE ( __muldf3 = 0x4000c8f0 );
|
||||
PROVIDE ( __muldi3 = 0x40000650 );
|
||||
__muldi3 = 0x40000650;
|
||||
PROVIDE ( __mulsf3 = 0x4000c3dc );
|
||||
PROVIDE ( __subdf3 = 0x4000c688 );
|
||||
PROVIDE ( __subsf3 = 0x4000c268 );
|
||||
PROVIDE ( __truncdfsf2 = 0x4000cd5c );
|
||||
PROVIDE ( __udivdi3 = 0x4000d310 );
|
||||
PROVIDE ( __udivsi3 = 0x4000e21c );
|
||||
PROVIDE ( __umoddi3 = 0x4000d770 );
|
||||
PROVIDE ( __umodsi3 = 0x4000e268 );
|
||||
PROVIDE ( __umulsidi3 = 0x4000dcf0 );
|
||||
__udivdi3 = 0x4000d310;
|
||||
__udivsi3 = 0x4000e21c;
|
||||
__umoddi3 = 0x4000d770;
|
||||
__umodsi3 = 0x4000e268;
|
||||
__umulsidi3 = 0x4000dcf0;
|
||||
PROVIDE ( _rom_store = 0x4000e388 );
|
||||
PROVIDE ( _rom_store_table = 0x4000e328 );
|
||||
PROVIDE ( _start = 0x4000042c );
|
||||
@@ -132,12 +132,12 @@ PROVIDE ( ets_memcmp = 0x400018d4 );
|
||||
PROVIDE ( ets_memcpy = 0x400018b4 );
|
||||
PROVIDE ( ets_memmove = 0x400018c4 );
|
||||
PROVIDE ( ets_memset = 0x400018a4 );
|
||||
PROVIDE ( ets_post = 0x40000e24 );
|
||||
PROVIDE ( _ets_post = 0x40000e24 );
|
||||
PROVIDE ( ets_printf = 0x400024cc );
|
||||
PROVIDE ( ets_putc = 0x40002be8 );
|
||||
PROVIDE ( ets_rtc_int_register = 0x40002a40 );
|
||||
PROVIDE ( ets_run = 0x40000e04 );
|
||||
PROVIDE ( ets_set_idle_cb = 0x40000dc0 );
|
||||
PROVIDE ( _ets_run = 0x40000e04 );
|
||||
PROVIDE ( _ets_set_idle_cb = 0x40000dc0 );
|
||||
PROVIDE ( ets_set_user_start = 0x40000fbc );
|
||||
PROVIDE ( ets_str2macaddr = 0x40002af8 );
|
||||
PROVIDE ( ets_strcmp = 0x40002aa8 );
|
||||
@@ -146,12 +146,12 @@ PROVIDE ( ets_strlen = 0x40002ac8 );
|
||||
PROVIDE ( ets_strncmp = 0x40002ab8 );
|
||||
PROVIDE ( ets_strncpy = 0x40002a98 );
|
||||
PROVIDE ( ets_strstr = 0x40002ad8 );
|
||||
PROVIDE ( ets_task = 0x40000dd0 );
|
||||
PROVIDE ( _ets_task = 0x40000dd0 );
|
||||
PROVIDE ( ets_timer_arm = 0x40002cc4 );
|
||||
PROVIDE ( ets_timer_disarm = 0x40002d40 );
|
||||
PROVIDE ( ets_timer_done = 0x40002d80 );
|
||||
PROVIDE ( ets_timer_handler_isr = 0x40002da8 );
|
||||
PROVIDE ( ets_timer_init = 0x40002e68 );
|
||||
PROVIDE ( _ets_timer_init = 0x40002e68 );
|
||||
PROVIDE ( ets_timer_setfn = 0x40002c48 );
|
||||
PROVIDE ( ets_uart_printf = 0x40002544 );
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x40002f04 );
|
||||
@@ -343,5 +343,8 @@ PROVIDE ( xthal_window_spill = 0x4000e324 );
|
||||
PROVIDE ( xthal_window_spill_nw = 0x4000e320 );
|
||||
|
||||
PROVIDE ( Te0 = 0x3fffccf0 );
|
||||
PROVIDE ( Td0 = 0x3fffd100 );
|
||||
PROVIDE ( Td4s = 0x3fffd500);
|
||||
PROVIDE ( rcons = 0x3fffd0f0);
|
||||
PROVIDE ( UartDev = 0x3fffde10 );
|
||||
PROVIDE ( flashchip = 0x3fffc714);
|
||||
|
||||
@@ -5,7 +5,7 @@ MEMORY
|
||||
dport0_0_seg : org = 0x3ff00000, len = 0x10
|
||||
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
|
||||
iram1_0_seg : org = 0x40100000, len = 0x8000
|
||||
irom0_0_seg : org = 0x40210000, len = 0x5A000
|
||||
irom0_0_seg : org = 0x40209000, len = 0x80000
|
||||
}
|
||||
|
||||
/* define the top of RAM */
|
||||
@@ -80,26 +80,86 @@ SECTIONS
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
*py/*.o*(.literal* .text*)
|
||||
*pyexec.o(.literal*, .text*)
|
||||
*readline.o(.literal*, .text*)
|
||||
*pybstdio.o(.literal*, .text*)
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
*py/bc.o*(.literal* .text*)
|
||||
*py/binary.o*(.literal* .text*)
|
||||
*py/builtin*.o*(.literal* .text*)
|
||||
*py/compile.o*(.literal* .text*)
|
||||
*py/emit*.o*(.literal* .text*)
|
||||
*py/formatfloat.o*(.literal* .text*)
|
||||
*py/frozenmod.o*(.literal* .text*)
|
||||
*py/gc.o*(.literal* .text*)
|
||||
*py/lexer*.o*(.literal* .text*)
|
||||
*py/malloc*.o*(.literal* .text*)
|
||||
*py/map*.o*(.literal* .text*)
|
||||
*py/mod*.o*(.literal* .text*)
|
||||
*py/mpprint.o*(.literal* .text*)
|
||||
*py/mpstate.o*(.literal* .text*)
|
||||
*py/mpz.o*(.literal* .text*)
|
||||
*py/native*.o*(.literal* .text*)
|
||||
*py/nlr*.o*(.literal* .text*)
|
||||
*py/obj*.o*(.literal* .text*)
|
||||
*py/opmethods.o*(.literal* .text*)
|
||||
*py/parse*.o*(.literal* .text*)
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
*py/smallint.o*(.literal* .text*)
|
||||
*py/stackctrl.o*(.literal* .text*)
|
||||
*py/stream.o*(.literal* .text*)
|
||||
*py/unicode.o*(.literal* .text*)
|
||||
*py/vm.o*(.literal* .text*)
|
||||
*py/vstr.o*(.literal* .text*)
|
||||
*py/warning.o*(.literal* .text*)
|
||||
|
||||
*extmod/*.o*(.literal* .text*)
|
||||
|
||||
*lib/fatfs/*.o*(.literal*, .text*)
|
||||
*/libaxtls.a:(.literal*, .text*)
|
||||
*lib/libm/*.o*(.literal*, .text*)
|
||||
*lib/mp-readline/*.o(.literal*, .text*)
|
||||
*lib/netutils/*.o*(.literal*, .text*)
|
||||
*lib/timeutils/*.o*(.literal*, .text*)
|
||||
*lib/utils/*.o*(.literal*, .text*)
|
||||
|
||||
*stmhal/pybstdio.o(.literal*, .text*)
|
||||
|
||||
*gccollect.o(.literal* .text*)
|
||||
*gchelper.o(.literal* .text*)
|
||||
*lexerstr32.o(.literal* .text*)
|
||||
*utils.o(.literal* .text*)
|
||||
*modpyb.o(.literal*, .text*)
|
||||
*modpybpin.o(.literal*, .text*)
|
||||
*modpybpwm.o(.literal*, .text*)
|
||||
*modpybrtc.o(.literal*, .text*)
|
||||
*modpybadc.o(.literal*, .text*)
|
||||
*modpybuart.o(.literal*, .text*)
|
||||
*modpybi2c.o(.literal*, .text*)
|
||||
*modpybspi.o(.literal*, .text*)
|
||||
*modesp.o(.literal* .text*)
|
||||
*modnetwork.o(.literal* .text*)
|
||||
*moduos.o(.literal* .text*)
|
||||
*modutime.o(.literal* .text*)
|
||||
*modlwip.o(.literal* .text*)
|
||||
*modsocket.o(.literal* .text*)
|
||||
*modonewire.o(.literal* .text*)
|
||||
|
||||
/* we put as much rodata as possible in this section */
|
||||
/* note that only rodata accessed as a machine word is allowed here */
|
||||
*py/qstr.o(.rodata.const_pool)
|
||||
*py/*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*py/*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*py/*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_type_*) /* catches type: mp_obj_type_t */
|
||||
*.o(.rodata.*_locals_dict*) /* catches types: mp_obj_dict_t, mp_map_elem_t */
|
||||
*.o(.rodata.mp_module_*) /* catches types: mp_obj_module_t, mp_obj_dict_t, mp_map_elem_t */
|
||||
*/frozen.o(.rodata.mp_frozen_sizes) /* frozen modules */
|
||||
*/frozen.o(.rodata.mp_frozen_content) /* frozen modules */
|
||||
|
||||
/* for -mforce-l32 */
|
||||
build/*.o(.rodata*)
|
||||
|
||||
_irom0_text_end = ABSOLUTE(.);
|
||||
} >irom0_0_seg :irom0_0_phdr
|
||||
@@ -172,6 +232,7 @@ SECTIONS
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.sdk.version)
|
||||
*(.rodata)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r.*)
|
||||
|
||||
@@ -30,50 +30,81 @@
|
||||
#include "uart.h"
|
||||
#include "esp_mphal.h"
|
||||
#include "user_interface.h"
|
||||
#include "ets_alt_task.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/mpstate.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
|
||||
extern void ets_wdt_disable(void);
|
||||
extern void wdt_feed(void);
|
||||
extern void ets_delay_us();
|
||||
|
||||
STATIC byte input_buf_array[256];
|
||||
ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)};
|
||||
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len);
|
||||
const mp_print_t mp_debug_print = {NULL, mp_hal_debug_tx_strn_cooked};
|
||||
|
||||
void mp_hal_init(void) {
|
||||
ets_wdt_disable(); // it's a pain while developing
|
||||
mp_hal_rtc_init();
|
||||
uart_init(UART_BIT_RATE_115200, UART_BIT_RATE_115200);
|
||||
}
|
||||
|
||||
void mp_hal_feed_watchdog(void) {
|
||||
//ets_wdt_disable(); // it's a pain while developing
|
||||
//WRITE_PERI_REG(0x60000914, 0x73);
|
||||
//wdt_feed(); // might also work
|
||||
}
|
||||
|
||||
void mp_hal_delay_us(uint32_t us) {
|
||||
ets_delay_us(us);
|
||||
uint32_t start = system_get_time();
|
||||
while (system_get_time() - start < us) {
|
||||
ets_event_poll();
|
||||
}
|
||||
}
|
||||
|
||||
int mp_hal_stdin_rx_chr(void) {
|
||||
for (;;) {
|
||||
int c = uart0_rx();
|
||||
int c = ringbuf_get(&input_buf);
|
||||
if (c != -1) {
|
||||
return c;
|
||||
}
|
||||
mp_hal_delay_us(1);
|
||||
mp_hal_feed_watchdog();
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_stdout_tx_str(const char *str) {
|
||||
void mp_hal_stdout_tx_char(char c) {
|
||||
uart_tx_one_char(UART0, c);
|
||||
mp_uos_dupterm_tx_strn(&c, 1);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void mp_hal_debug_str(const char *str) {
|
||||
while (*str) {
|
||||
uart_tx_one_char(UART0, *str++);
|
||||
}
|
||||
uart_flush(UART0);
|
||||
}
|
||||
#endif
|
||||
|
||||
void mp_hal_stdout_tx_str(const char *str) {
|
||||
while (*str) {
|
||||
mp_hal_stdout_tx_char(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
|
||||
while (len--) {
|
||||
uart_tx_one_char(UART0, *str++);
|
||||
mp_hal_stdout_tx_char(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
|
||||
while (len--) {
|
||||
if (*str == '\n') {
|
||||
mp_hal_stdout_tx_char('\r');
|
||||
}
|
||||
mp_hal_stdout_tx_char(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len) {
|
||||
(void)env;
|
||||
while (len--) {
|
||||
if (*str == '\n') {
|
||||
uart_tx_one_char(UART0, '\r');
|
||||
@@ -86,10 +117,142 @@ uint32_t mp_hal_ticks_ms(void) {
|
||||
return system_get_time() / 1000;
|
||||
}
|
||||
|
||||
uint32_t mp_hal_ticks_us(void) {
|
||||
return system_get_time();
|
||||
}
|
||||
|
||||
void mp_hal_delay_ms(uint32_t delay) {
|
||||
mp_hal_delay_us(delay * 1000);
|
||||
}
|
||||
|
||||
void mp_hal_set_interrupt_char(int c) {
|
||||
// TODO
|
||||
if (c != -1) {
|
||||
mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
|
||||
}
|
||||
extern int interrupt_char;
|
||||
interrupt_char = c;
|
||||
}
|
||||
|
||||
void ets_event_poll(void) {
|
||||
ets_loop_iter();
|
||||
if (MP_STATE_VM(mp_pending_exception) != NULL) {
|
||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
||||
nlr_raise(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||
printf("assert:%s:%d:%s: %s\n", file, line, func, expr);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_AssertionError,
|
||||
"C-level assert"));
|
||||
}
|
||||
|
||||
void mp_hal_signal_input(void) {
|
||||
#if MICROPY_REPL_EVENT_DRIVEN
|
||||
system_os_post(UART_TASK_ID, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int call_dupterm_read(void) {
|
||||
if (MP_STATE_PORT(term_obj) == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_obj_t read_m[3];
|
||||
mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
|
||||
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
|
||||
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
|
||||
if (res == mp_const_none) {
|
||||
return -2;
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len == 0) {
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
|
||||
return -1;
|
||||
}
|
||||
nlr_pop();
|
||||
return *(byte*)bufinfo.buf;
|
||||
} else {
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: Exception in read() method, deactivating: ");
|
||||
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATIC void dupterm_task_handler(os_event_t *evt) {
|
||||
static byte lock;
|
||||
if (lock) {
|
||||
return;
|
||||
}
|
||||
lock = 1;
|
||||
while (1) {
|
||||
int c = call_dupterm_read();
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
ringbuf_put(&input_buf, c);
|
||||
}
|
||||
mp_hal_signal_input();
|
||||
lock = 0;
|
||||
}
|
||||
|
||||
STATIC os_event_t dupterm_evt_queue[4];
|
||||
|
||||
void dupterm_task_init() {
|
||||
system_os_task(dupterm_task_handler, DUPTERM_TASK_ID, dupterm_evt_queue, MP_ARRAY_SIZE(dupterm_evt_queue));
|
||||
}
|
||||
|
||||
void mp_hal_signal_dupterm_input(void) {
|
||||
system_os_post(DUPTERM_TASK_ID, 0, 0);
|
||||
}
|
||||
|
||||
void mp_hal_pin_config_od(mp_hal_pin_obj_t pin_id) {
|
||||
const pyb_pin_obj_t *pin = &pyb_pin_obj[pin_id];
|
||||
|
||||
if (pin->phys_port == 16) {
|
||||
// configure GPIO16 as input with output register holding 0
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1)); // out=0
|
||||
return;
|
||||
}
|
||||
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
PIN_FUNC_SELECT(pin->periph, pin->func);
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)),
|
||||
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin->phys_port)))
|
||||
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); // open drain
|
||||
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS,
|
||||
GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << pin->phys_port));
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
}
|
||||
|
||||
// Get pointer to esf_buf bookkeeping structure
|
||||
void *ets_get_esf_buf_ctlblk(void) {
|
||||
// Get literal ptr before start of esf_rx_buf_alloc func
|
||||
extern void *esf_rx_buf_alloc();
|
||||
return ((void**)esf_rx_buf_alloc)[-1];
|
||||
}
|
||||
|
||||
// Get number of esf_buf free buffers of given type, as encoded by index
|
||||
// idx 0 corresponds to buf types 1, 2; 1 - 4; 2 - 5; 3 - 7; 4 - 8
|
||||
// Only following buf types appear to be used:
|
||||
// 1 - tx buffer, 5 - management frame tx buffer; 8 - rx buffer
|
||||
int ets_esf_free_bufs(int idx) {
|
||||
uint32_t *p = ets_get_esf_buf_ctlblk();
|
||||
uint32_t *b = (uint32_t*)p[idx];
|
||||
int cnt = 0;
|
||||
while (b) {
|
||||
b = (uint32_t*)b[0x20 / 4];
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
@@ -27,18 +27,57 @@
|
||||
#ifndef _INCLUDED_MPHAL_H_
|
||||
#define _INCLUDED_MPHAL_H_
|
||||
|
||||
// SDK functions not declared in SDK itself
|
||||
void ets_isr_mask(unsigned);
|
||||
#include "py/ringbuf.h"
|
||||
|
||||
struct _mp_print_t;
|
||||
// Structure for UART-only output via mp_printf()
|
||||
extern const struct _mp_print_t mp_debug_print;
|
||||
|
||||
extern ringbuf_t input_buf;
|
||||
// Call this after putting data to input_buf
|
||||
void mp_hal_signal_input(void);
|
||||
// Call this when data is available in dupterm object
|
||||
void mp_hal_signal_dupterm_input(void);
|
||||
|
||||
void mp_hal_init(void);
|
||||
void mp_hal_feed_watchdog(void);
|
||||
void mp_hal_rtc_init(void);
|
||||
|
||||
uint32_t mp_hal_ticks_us(void);
|
||||
void mp_hal_delay_us(uint32_t);
|
||||
void mp_hal_set_interrupt_char(int c);
|
||||
uint32_t mp_hal_get_cpu_freq(void);
|
||||
|
||||
#define UART_TASK_ID 0
|
||||
#define DUPTERM_TASK_ID 1
|
||||
void uart_task_init();
|
||||
void dupterm_task_init();
|
||||
|
||||
void ets_event_poll(void);
|
||||
#define ETS_POLL_WHILE(cond) { while (cond) ets_event_poll(); }
|
||||
|
||||
// needed for machine.I2C
|
||||
#include "osapi.h"
|
||||
#define mp_hal_delay_us_fast(us) os_delay_us(us)
|
||||
|
||||
// C-level pin HAL
|
||||
#include "etshal.h"
|
||||
#include "gpio.h"
|
||||
#include "esp8266/modpyb.h"
|
||||
#define mp_hal_pin_obj_t uint32_t
|
||||
#define mp_hal_get_pin_obj(o) mp_obj_get_pin(o)
|
||||
void mp_hal_pin_config_od(mp_hal_pin_obj_t pin);
|
||||
#define mp_hal_pin_low(p) do { \
|
||||
if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); } \
|
||||
else { gpio_output_set(0, 1 << (p), 1 << (p), 0); } \
|
||||
} while (0)
|
||||
#define mp_hal_pin_od_high(p) do { \
|
||||
if ((p) == 16) { WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); } \
|
||||
else { gpio_output_set(1 << (p), 0, 1 << (p), 0); } \
|
||||
} while (0)
|
||||
#define mp_hal_pin_read(p) pin_get(p)
|
||||
#define mp_hal_pin_write(p, v) pin_set((p), (v))
|
||||
|
||||
void *ets_get_esf_buf_ctlblk(void);
|
||||
int ets_esf_free_bufs(int idx);
|
||||
|
||||
#endif // _INCLUDED_MPHAL_H_
|
||||
|
||||
64
esp8266/espneopixel.c
Normal file
64
esp8266/espneopixel.c
Normal file
@@ -0,0 +1,64 @@
|
||||
// Original version from https://github.com/adafruit/Adafruit_NeoPixel
|
||||
// Modifications by dpgeorge to support auto-CPU-frequency detection
|
||||
|
||||
// This is a mash-up of the Due show() code + insights from Michael Miller's
|
||||
// ESP8266 work for the NeoPixelBus library: github.com/Makuna/NeoPixelBus
|
||||
// Needs to be a separate .c file to enforce ICACHE_RAM_ATTR execution.
|
||||
|
||||
#include "c_types.h"
|
||||
#include "eagle_soc.h"
|
||||
#include "user_interface.h"
|
||||
#include "espneopixel.h"
|
||||
|
||||
#define NEO_KHZ400 (1)
|
||||
|
||||
static uint32_t _getCycleCount(void) __attribute__((always_inline));
|
||||
static inline uint32_t _getCycleCount(void) {
|
||||
uint32_t ccount;
|
||||
__asm__ __volatile__("rsr %0,ccount":"=a" (ccount));
|
||||
return ccount;
|
||||
}
|
||||
|
||||
void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
|
||||
|
||||
uint8_t *p, *end, pix, mask;
|
||||
uint32_t t, time0, time1, period, c, startTime, pinMask;
|
||||
|
||||
pinMask = 1 << pin;
|
||||
p = pixels;
|
||||
end = p + numBytes;
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
startTime = 0;
|
||||
|
||||
uint32_t fcpu = system_get_cpu_freq() * 1000000;
|
||||
|
||||
#ifdef NEO_KHZ400
|
||||
if(is800KHz) {
|
||||
#endif
|
||||
time0 = fcpu / 2500000; // 0.4us
|
||||
time1 = fcpu / 1250000; // 0.8us
|
||||
period = fcpu / 800000; // 1.25us per bit
|
||||
#ifdef NEO_KHZ400
|
||||
} else { // 400 KHz bitstream
|
||||
time0 = fcpu / 2000000; // 0.5uS
|
||||
time1 = fcpu / 833333; // 1.2us
|
||||
period = fcpu / 400000; // 2.5us per bit
|
||||
}
|
||||
#endif
|
||||
|
||||
for(t = time0;; t = time0) {
|
||||
if(pix & mask) t = time1; // Bit high duration
|
||||
while(((c = _getCycleCount()) - startTime) < period); // Wait for bit start
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high
|
||||
startTime = c; // Save start time
|
||||
while(((c = _getCycleCount()) - startTime) < t); // Wait high duration
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low
|
||||
if(!(mask >>= 1)) { // Next bit/byte
|
||||
if(p >= end) break;
|
||||
pix = *p++;
|
||||
mask = 0x80;
|
||||
}
|
||||
}
|
||||
while((_getCycleCount() - startTime) < period); // Wait for last bit
|
||||
}
|
||||
1
esp8266/espneopixel.h
Normal file
1
esp8266/espneopixel.h
Normal file
@@ -0,0 +1 @@
|
||||
void esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz);
|
||||
99
esp8266/esponewire.c
Normal file
99
esp8266/esponewire.c
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015-2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
#include "esponewire.h"
|
||||
|
||||
#define TIMING_RESET1 (0)
|
||||
#define TIMING_RESET2 (1)
|
||||
#define TIMING_RESET3 (2)
|
||||
#define TIMING_READ1 (3)
|
||||
#define TIMING_READ2 (4)
|
||||
#define TIMING_READ3 (5)
|
||||
#define TIMING_WRITE1 (6)
|
||||
#define TIMING_WRITE2 (7)
|
||||
#define TIMING_WRITE3 (8)
|
||||
|
||||
uint16_t esp_onewire_timings[9] = {480, 40, 420, 5, 5, 40, 10, 50, 10};
|
||||
|
||||
static uint32_t disable_irq(void) {
|
||||
ets_intr_lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void enable_irq(uint32_t i) {
|
||||
ets_intr_unlock();
|
||||
}
|
||||
|
||||
static void mp_hal_delay_us_no_irq(uint32_t us) {
|
||||
uint32_t start = system_get_time();
|
||||
while (system_get_time() - start < us) {
|
||||
}
|
||||
}
|
||||
|
||||
#define DELAY_US mp_hal_delay_us_no_irq
|
||||
|
||||
int esp_onewire_reset(uint pin) {
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(esp_onewire_timings[TIMING_RESET1]);
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(esp_onewire_timings[TIMING_RESET2]);
|
||||
int status = !pin_get(pin);
|
||||
enable_irq(i);
|
||||
DELAY_US(esp_onewire_timings[TIMING_RESET3]);
|
||||
return status;
|
||||
}
|
||||
|
||||
int esp_onewire_readbit(uint pin) {
|
||||
pin_set(pin, 1);
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(esp_onewire_timings[TIMING_READ1]);
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(esp_onewire_timings[TIMING_READ2]);
|
||||
int value = pin_get(pin);
|
||||
enable_irq(i);
|
||||
DELAY_US(esp_onewire_timings[TIMING_READ3]);
|
||||
return value;
|
||||
}
|
||||
|
||||
void esp_onewire_writebit(uint pin, int value) {
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(esp_onewire_timings[TIMING_WRITE1]);
|
||||
if (value) {
|
||||
pin_set(pin, 1);
|
||||
}
|
||||
DELAY_US(esp_onewire_timings[TIMING_WRITE2]);
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(esp_onewire_timings[TIMING_WRITE3]);
|
||||
enable_irq(i);
|
||||
}
|
||||
36
esp8266/esponewire.h
Normal file
36
esp8266/esponewire.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ESP8266_ESPONEWIRE_H__
|
||||
#define __MICROPY_INCLUDED_ESP8266_ESPONEWIRE_H__
|
||||
|
||||
extern uint16_t esp_onewire_timings[9];
|
||||
|
||||
int esp_onewire_reset(uint pin);
|
||||
int esp_onewire_readbit(uint pin);
|
||||
void esp_onewire_writebit(uint pin, int value);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_ESPONEWIRE_H__
|
||||
428
esp8266/esppwm.c
Normal file
428
esp8266/esppwm.c
Normal file
@@ -0,0 +1,428 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013-2014 Espressif Systems (Wuxi)
|
||||
*
|
||||
* FileName: pwm.c
|
||||
*
|
||||
* Description: pwm driver
|
||||
*
|
||||
* Modification history:
|
||||
* 2014/5/1, v1.0 create this file.
|
||||
* 2016/3/2: Modifications by dpgeorge to suit MicroPython
|
||||
*******************************************************************************/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "etshal.h"
|
||||
#include "os_type.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include "esppwm.h"
|
||||
|
||||
#include "py/mpprint.h"
|
||||
#define PWM_DBG(...)
|
||||
//#define PWM_DBG(...) mp_printf(&mp_plat_print, __VA_ARGS__)
|
||||
|
||||
#define ICACHE_RAM_ATTR // __attribute__((section(".text")))
|
||||
|
||||
#define PWM_CHANNEL 8
|
||||
#define PWM_DEPTH 1023
|
||||
#define PWM_FREQ_MAX 1000
|
||||
#define PWM_1S 1000000
|
||||
|
||||
struct pwm_single_param {
|
||||
uint16_t gpio_set;
|
||||
uint16_t gpio_clear;
|
||||
uint32_t h_time;
|
||||
};
|
||||
|
||||
struct pwm_param {
|
||||
uint32_t period;
|
||||
uint16_t freq;
|
||||
uint16_t duty[PWM_CHANNEL];
|
||||
};
|
||||
|
||||
STATIC const uint8_t pin_num[PWM_CHANNEL] = {0, 2, 4, 5, 12, 13, 14, 15};
|
||||
|
||||
STATIC struct pwm_single_param pwm_single_toggle[2][PWM_CHANNEL + 1];
|
||||
STATIC struct pwm_single_param *pwm_single;
|
||||
|
||||
STATIC struct pwm_param pwm;
|
||||
|
||||
STATIC int8_t pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1, -1, -1};
|
||||
|
||||
STATIC uint8_t pwm_channel_toggle[2];
|
||||
STATIC uint8_t *pwm_channel;
|
||||
STATIC uint8_t pwm_toggle = 1;
|
||||
STATIC uint8_t pwm_timer_down = 1;
|
||||
STATIC uint8_t pwm_current_channel = 0;
|
||||
STATIC uint16_t pwm_gpio = 0;
|
||||
STATIC uint8_t pwm_channel_num = 0;
|
||||
|
||||
//XXX: 0xffffffff/(80000000/16)=35A
|
||||
#define US_TO_RTC_TIMER_TICKS(t) \
|
||||
((t) ? \
|
||||
(((t) > 0x35A) ? \
|
||||
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
|
||||
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
|
||||
0)
|
||||
|
||||
//FRC1
|
||||
#define FRC1_ENABLE_TIMER BIT7
|
||||
|
||||
typedef enum {
|
||||
DIVDED_BY_1 = 0,
|
||||
DIVDED_BY_16 = 4,
|
||||
DIVDED_BY_256 = 8,
|
||||
} TIMER_PREDIVED_MODE;
|
||||
|
||||
typedef enum {
|
||||
TM_LEVEL_INT = 1,
|
||||
TM_EDGE_INT = 0,
|
||||
} TIMER_INT_MODE;
|
||||
|
||||
STATIC void ICACHE_FLASH_ATTR
|
||||
pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
for (i = 1; i < n; i++) {
|
||||
if (pwm[i].h_time < pwm[i - 1].h_time) {
|
||||
int8 j = i - 1;
|
||||
struct pwm_single_param tmp;
|
||||
|
||||
memcpy(&tmp, &pwm[i], sizeof(struct pwm_single_param));
|
||||
memcpy(&pwm[i], &pwm[i - 1], sizeof(struct pwm_single_param));
|
||||
|
||||
while (tmp.h_time < pwm[j].h_time) {
|
||||
memcpy(&pwm[j + 1], &pwm[j], sizeof(struct pwm_single_param));
|
||||
j--;
|
||||
if (j < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&pwm[j + 1], &tmp, sizeof(struct pwm_single_param));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC volatile uint8 critical = 0;
|
||||
|
||||
#define LOCK_PWM(c) do { \
|
||||
while( (c)==1 ); \
|
||||
(c) = 1; \
|
||||
} while (0)
|
||||
|
||||
#define UNLOCK_PWM(c) do { \
|
||||
(c) = 0; \
|
||||
} while (0)
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
pwm_start(void)
|
||||
{
|
||||
uint8 i, j;
|
||||
PWM_DBG("--Function pwm_start() is called\n");
|
||||
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
|
||||
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
|
||||
PWM_DBG("pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.period,pwm.duty[0],pwm.duty[1],pwm.duty[2]);
|
||||
|
||||
LOCK_PWM(critical); // enter critical
|
||||
|
||||
struct pwm_single_param *local_single = pwm_single_toggle[pwm_toggle ^ 0x01];
|
||||
uint8 *local_channel = &pwm_channel_toggle[pwm_toggle ^ 0x01];
|
||||
|
||||
// step 1: init PWM_CHANNEL+1 channels param
|
||||
for (i = 0; i < pwm_channel_num; i++) {
|
||||
uint32 us = pwm.period * pwm.duty[i] / PWM_DEPTH;
|
||||
local_single[i].h_time = US_TO_RTC_TIMER_TICKS(us);
|
||||
PWM_DBG("i:%d us:%d ht:%d\n",i,us,local_single[i].h_time);
|
||||
local_single[i].gpio_set = 0;
|
||||
local_single[i].gpio_clear = 1 << pin_num[pwm_out_io_num[i]];
|
||||
}
|
||||
|
||||
local_single[pwm_channel_num].h_time = US_TO_RTC_TIMER_TICKS(pwm.period);
|
||||
local_single[pwm_channel_num].gpio_set = pwm_gpio;
|
||||
local_single[pwm_channel_num].gpio_clear = 0;
|
||||
PWM_DBG("i:%d period:%d ht:%d\n",pwm_channel_num,pwm.period,local_single[pwm_channel_num].h_time);
|
||||
// step 2: sort, small to big
|
||||
pwm_insert_sort(local_single, pwm_channel_num + 1);
|
||||
|
||||
*local_channel = pwm_channel_num + 1;
|
||||
PWM_DBG("1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
|
||||
// step 3: combine same duty channels
|
||||
for (i = pwm_channel_num; i > 0; i--) {
|
||||
if (local_single[i].h_time == local_single[i - 1].h_time) {
|
||||
local_single[i - 1].gpio_set |= local_single[i].gpio_set;
|
||||
local_single[i - 1].gpio_clear |= local_single[i].gpio_clear;
|
||||
|
||||
for (j = i + 1; j < *local_channel; j++) {
|
||||
memcpy(&local_single[j - 1], &local_single[j], sizeof(struct pwm_single_param));
|
||||
}
|
||||
|
||||
(*local_channel)--;
|
||||
}
|
||||
}
|
||||
PWM_DBG("2channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
|
||||
// step 4: cacl delt time
|
||||
for (i = *local_channel - 1; i > 0; i--) {
|
||||
local_single[i].h_time -= local_single[i - 1].h_time;
|
||||
}
|
||||
|
||||
// step 5: last channel needs to clean
|
||||
local_single[*local_channel-1].gpio_clear = 0;
|
||||
|
||||
// step 6: if first channel duty is 0, remove it
|
||||
if (local_single[0].h_time == 0) {
|
||||
local_single[*local_channel - 1].gpio_set &= ~local_single[0].gpio_clear;
|
||||
local_single[*local_channel - 1].gpio_clear |= local_single[0].gpio_clear;
|
||||
|
||||
for (i = 1; i < *local_channel; i++) {
|
||||
memcpy(&local_single[i - 1], &local_single[i], sizeof(struct pwm_single_param));
|
||||
}
|
||||
|
||||
(*local_channel)--;
|
||||
}
|
||||
|
||||
// if timer is down, need to set gpio and start timer
|
||||
if (pwm_timer_down == 1) {
|
||||
pwm_channel = local_channel;
|
||||
pwm_single = local_single;
|
||||
// start
|
||||
gpio_output_set(local_single[0].gpio_set, local_single[0].gpio_clear, pwm_gpio, 0);
|
||||
|
||||
// yeah, if all channels' duty is 0 or 255, don't need to start timer, otherwise start...
|
||||
if (*local_channel != 1) {
|
||||
pwm_timer_down = 0;
|
||||
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, local_single[0].h_time);
|
||||
}
|
||||
}
|
||||
|
||||
if (pwm_toggle == 1) {
|
||||
pwm_toggle = 0;
|
||||
} else {
|
||||
pwm_toggle = 1;
|
||||
}
|
||||
|
||||
UNLOCK_PWM(critical); // leave critical
|
||||
PWM_DBG("3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_set_duty
|
||||
* Description : set each channel's duty params
|
||||
* Parameters : uint8 duty : 0 ~ PWM_DEPTH
|
||||
* uint8 channel : channel index
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
pwm_set_duty(uint16 duty, uint8 channel)
|
||||
{
|
||||
uint8 i;
|
||||
for(i=0;i<pwm_channel_num;i++){
|
||||
if(pwm_out_io_num[i] == channel){
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i==pwm_channel_num) // non found
|
||||
return;
|
||||
|
||||
LOCK_PWM(critical); // enter critical
|
||||
if (duty < 1) {
|
||||
pwm.duty[channel] = 0;
|
||||
} else if (duty >= PWM_DEPTH) {
|
||||
pwm.duty[channel] = PWM_DEPTH;
|
||||
} else {
|
||||
pwm.duty[channel] = duty;
|
||||
}
|
||||
UNLOCK_PWM(critical); // leave critical
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_set_freq
|
||||
* Description : set pwm frequency
|
||||
* Parameters : uint16 freq : 100hz typically
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
pwm_set_freq(uint16 freq, uint8 channel)
|
||||
{
|
||||
LOCK_PWM(critical); // enter critical
|
||||
if (freq > PWM_FREQ_MAX) {
|
||||
pwm.freq = PWM_FREQ_MAX;
|
||||
} else if (freq < 1) {
|
||||
pwm.freq = 1;
|
||||
} else {
|
||||
pwm.freq = freq;
|
||||
}
|
||||
|
||||
pwm.period = PWM_1S / pwm.freq;
|
||||
UNLOCK_PWM(critical); // leave critical
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_get_duty
|
||||
* Description : get duty of each channel
|
||||
* Parameters : uint8 channel : channel index
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
uint16 ICACHE_FLASH_ATTR
|
||||
pwm_get_duty(uint8 channel)
|
||||
{
|
||||
uint8 i;
|
||||
for(i=0;i<pwm_channel_num;i++){
|
||||
if(pwm_out_io_num[i] == channel){
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i==pwm_channel_num) // non found
|
||||
return 0;
|
||||
|
||||
return pwm.duty[channel];
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_get_freq
|
||||
* Description : get pwm frequency
|
||||
* Parameters : NONE
|
||||
* Returns : uint16 : pwm frequency
|
||||
*******************************************************************************/
|
||||
uint16 ICACHE_FLASH_ATTR
|
||||
pwm_get_freq(uint8 channel)
|
||||
{
|
||||
return pwm.freq;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_period_timer
|
||||
* Description : pwm period timer function, output high level,
|
||||
* start each channel's high level timer
|
||||
* Parameters : NONE
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
STATIC void ICACHE_RAM_ATTR
|
||||
pwm_tim1_intr_handler(void *dummy)
|
||||
{
|
||||
(void)dummy;
|
||||
uint8 local_toggle = pwm_toggle; // pwm_toggle may change outside
|
||||
RTC_CLR_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);
|
||||
|
||||
if (pwm_current_channel >= (*pwm_channel - 1)) { // *pwm_channel may change outside
|
||||
pwm_single = pwm_single_toggle[local_toggle];
|
||||
pwm_channel = &pwm_channel_toggle[local_toggle];
|
||||
|
||||
gpio_output_set(pwm_single[*pwm_channel - 1].gpio_set,
|
||||
pwm_single[*pwm_channel - 1].gpio_clear,
|
||||
pwm_gpio,
|
||||
0);
|
||||
|
||||
pwm_current_channel = 0;
|
||||
|
||||
if (*pwm_channel != 1) {
|
||||
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time);
|
||||
} else {
|
||||
pwm_timer_down = 1;
|
||||
}
|
||||
} else {
|
||||
gpio_output_set(pwm_single[pwm_current_channel].gpio_set,
|
||||
pwm_single[pwm_current_channel].gpio_clear,
|
||||
pwm_gpio, 0);
|
||||
|
||||
pwm_current_channel++;
|
||||
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : pwm_init
|
||||
* Description : pwm gpio, params and timer initialization
|
||||
* Parameters : uint16 freq : pwm freq param
|
||||
* uint16 *duty : each channel's duty
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
pwm_init(void)
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
RTC_REG_WRITE(FRC1_CTRL_ADDRESS, //FRC2_AUTO_RELOAD|
|
||||
DIVDED_BY_16
|
||||
| FRC1_ENABLE_TIMER
|
||||
| TM_EDGE_INT);
|
||||
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 0);
|
||||
|
||||
for (i = 0; i < PWM_CHANNEL; i++) {
|
||||
pwm_gpio = 0;
|
||||
pwm.duty[i] = 0;
|
||||
}
|
||||
|
||||
pwm_set_freq(500, 0);
|
||||
pwm_start();
|
||||
|
||||
ETS_FRC_TIMER1_INTR_ATTACH(pwm_tim1_intr_handler, NULL);
|
||||
TM1_EDGE_INT_ENABLE();
|
||||
ETS_FRC1_INTR_ENABLE();
|
||||
}
|
||||
|
||||
int ICACHE_FLASH_ATTR
|
||||
pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func){
|
||||
PWM_DBG("--Function pwm_add() is called. channel:%d\n", channel);
|
||||
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
|
||||
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
|
||||
PWM_DBG("pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.duty[0],pwm.duty[1],pwm.duty[2]);
|
||||
int channel = -1;
|
||||
for (int i = 0; i < PWM_CHANNEL; ++i) {
|
||||
if (pin_num[i] == pin_id) {
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (channel == -1) {
|
||||
return -1;
|
||||
}
|
||||
uint8 i;
|
||||
for(i=0;i<PWM_CHANNEL;i++){
|
||||
if(pwm_out_io_num[i]==channel) // already exist
|
||||
return channel;
|
||||
if(pwm_out_io_num[i] == -1){ // empty exist
|
||||
LOCK_PWM(critical); // enter critical
|
||||
pwm_out_io_num[i] = channel;
|
||||
pwm.duty[i] = 0;
|
||||
pwm_gpio |= (1 << pin_num[channel]);
|
||||
PIN_FUNC_SELECT(pin_mux, pin_func);
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain;
|
||||
pwm_channel_num++;
|
||||
UNLOCK_PWM(critical); // leave critical
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ICACHE_FLASH_ATTR
|
||||
pwm_delete(uint8 channel){
|
||||
PWM_DBG("--Function pwm_delete() is called. channel:%d\n", channel);
|
||||
PWM_DBG("pwm_gpio:%x,pwm_channel_num:%d\n",pwm_gpio,pwm_channel_num);
|
||||
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
|
||||
PWM_DBG("pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.duty[0],pwm.duty[1],pwm.duty[2]);
|
||||
uint8 i,j;
|
||||
for(i=0;i<pwm_channel_num;i++){
|
||||
if(pwm_out_io_num[i]==channel){ // exist
|
||||
LOCK_PWM(critical); // enter critical
|
||||
pwm_out_io_num[i] = -1;
|
||||
pwm_gpio &= ~(1 << pin_num[channel]); //clear the bit
|
||||
for(j=i;j<pwm_channel_num-1;j++){
|
||||
pwm_out_io_num[j] = pwm_out_io_num[j+1];
|
||||
pwm.duty[j] = pwm.duty[j+1];
|
||||
}
|
||||
pwm_out_io_num[pwm_channel_num-1] = -1;
|
||||
pwm.duty[pwm_channel_num-1] = 0;
|
||||
pwm_channel_num--;
|
||||
UNLOCK_PWM(critical); // leave critical
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// non found
|
||||
return true;
|
||||
}
|
||||
17
esp8266/esppwm.h
Normal file
17
esp8266/esppwm.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef __ESPPWM_H__
|
||||
#define __ESPPWM_H__
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void pwm_init(void);
|
||||
void pwm_start(void);
|
||||
|
||||
void pwm_set_duty(uint16_t duty, uint8_t channel);
|
||||
uint16_t pwm_get_duty(uint8_t channel);
|
||||
void pwm_set_freq(uint16_t freq, uint8_t channel);
|
||||
uint16_t pwm_get_freq(uint8_t channel);
|
||||
int pwm_add(uint8_t pin_id, uint32_t pin_mux, uint32_t pin_func);
|
||||
bool pwm_delete(uint8_t channel);
|
||||
|
||||
#endif
|
||||
194
esp8266/ets_alt_task.c
Normal file
194
esp8266/ets_alt_task.c
Normal file
@@ -0,0 +1,194 @@
|
||||
#include <stdio.h>
|
||||
#include "osapi.h"
|
||||
#include "os_type.h"
|
||||
#include "ets_sys.h"
|
||||
#include <esp_sdk_ver.h>
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
// Use standard ets_task or alternative impl
|
||||
#define USE_ETS_TASK 0
|
||||
|
||||
#define MP_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
struct task_entry {
|
||||
os_event_t *queue;
|
||||
os_task_t task;
|
||||
uint8_t qlen;
|
||||
uint8_t prio;
|
||||
int8_t i_get;
|
||||
int8_t i_put;
|
||||
};
|
||||
|
||||
static void (*idle_cb)(void *);
|
||||
static void *idle_arg;
|
||||
|
||||
#if ESP_SDK_VERSION >= 010500
|
||||
# define FIRST_PRIO 0
|
||||
#else
|
||||
# define FIRST_PRIO 0x14
|
||||
#endif
|
||||
#define LAST_PRIO 0x20
|
||||
#define PRIO2ID(prio) ((prio) - FIRST_PRIO)
|
||||
|
||||
volatile struct task_entry emu_tasks[PRIO2ID(LAST_PRIO) + 1];
|
||||
|
||||
static inline int prio2id(uint8_t prio) {
|
||||
int id = PRIO2ID(prio);
|
||||
if (id < 0 || id >= MP_ARRAY_SIZE(emu_tasks)) {
|
||||
printf("task prio out of range: %d\n", prio);
|
||||
while (1);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
void dump_task(int prio, volatile struct task_entry *t) {
|
||||
printf("q for task %d: queue: %p, get ptr: %d, put ptr: %d, qlen: %d\n",
|
||||
prio, t->queue, t->i_get, t->i_put, t->qlen);
|
||||
}
|
||||
|
||||
void dump_tasks(void) {
|
||||
for (int i = 0; i < MP_ARRAY_SIZE(emu_tasks); i++) {
|
||||
if (emu_tasks[i].qlen) {
|
||||
dump_task(i + FIRST_PRIO, &emu_tasks[i]);
|
||||
}
|
||||
}
|
||||
printf("====\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ets_task(os_task_t task, uint8 prio, os_event_t *queue, uint8 qlen) {
|
||||
static unsigned cnt;
|
||||
printf("#%d ets_task(%p, %d, %p, %d)\n", cnt++, task, prio, queue, qlen);
|
||||
#if USE_ETS_TASK
|
||||
return _ets_task(task, prio, queue, qlen);
|
||||
#else
|
||||
int id = prio2id(prio);
|
||||
emu_tasks[id].task = task;
|
||||
emu_tasks[id].queue = queue;
|
||||
emu_tasks[id].qlen = qlen;
|
||||
emu_tasks[id].i_get = 0;
|
||||
emu_tasks[id].i_put = 0;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
|
||||
// static unsigned cnt; printf("#%d ets_post(%d, %x, %x)\n", cnt++, prio, sig, param);
|
||||
#if USE_ETS_TASK
|
||||
return _ets_post(prio, sig, param);
|
||||
#else
|
||||
ets_intr_lock();
|
||||
|
||||
const int id = prio2id(prio);
|
||||
os_event_t *q = emu_tasks[id].queue;
|
||||
if (emu_tasks[id].i_put == -1) {
|
||||
// queue is full
|
||||
printf("ets_post: task %d queue full\n", prio);
|
||||
return false;
|
||||
}
|
||||
q = &q[emu_tasks[id].i_put++];
|
||||
q->sig = sig;
|
||||
q->par = param;
|
||||
if (emu_tasks[id].i_put == emu_tasks[id].qlen) {
|
||||
emu_tasks[id].i_put = 0;
|
||||
}
|
||||
if (emu_tasks[id].i_put == emu_tasks[id].i_get) {
|
||||
// queue got full
|
||||
emu_tasks[id].i_put = -1;
|
||||
}
|
||||
//printf("after ets_post: "); dump_task(prio, &emu_tasks[id]);
|
||||
//dump_tasks();
|
||||
|
||||
ets_intr_unlock();
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ets_loop_iter(void) {
|
||||
//static unsigned cnt;
|
||||
bool progress = false;
|
||||
for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) {
|
||||
system_soft_wdt_feed();
|
||||
ets_intr_lock();
|
||||
//printf("etc_loop_iter: "); dump_task(t - emu_tasks + FIRST_PRIO, t);
|
||||
if (t->i_get != t->i_put) {
|
||||
progress = true;
|
||||
//printf("#%d Calling task %d(%p) (%x, %x)\n", cnt++,
|
||||
// t - emu_tasks + FIRST_PRIO, t->task, t->queue[t->i_get].sig, t->queue[t->i_get].par);
|
||||
int idx = t->i_get;
|
||||
if (t->i_put == -1) {
|
||||
t->i_put = t->i_get;
|
||||
}
|
||||
if (++t->i_get == t->qlen) {
|
||||
t->i_get = 0;
|
||||
}
|
||||
//ets_intr_unlock();
|
||||
t->task(&t->queue[idx]);
|
||||
//ets_intr_lock();
|
||||
//printf("Done calling task %d\n", t - emu_tasks + FIRST_PRIO);
|
||||
}
|
||||
ets_intr_unlock();
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
#if SDK_BELOW_1_1_1
|
||||
void my_timer_isr(void *arg) {
|
||||
// uart0_write_char('+');
|
||||
ets_post(0x1f, 0, 0);
|
||||
}
|
||||
|
||||
// Timer init func is in ROM, and calls ets_task by relative addr directly in ROM
|
||||
// so, we have to re-init task using our handler
|
||||
void ets_timer_init() {
|
||||
printf("ets_timer_init\n");
|
||||
// _ets_timer_init();
|
||||
ets_isr_attach(10, my_timer_isr, NULL);
|
||||
SET_PERI_REG_MASK(0x3FF00004, 4);
|
||||
ETS_INTR_ENABLE(10);
|
||||
ets_task((os_task_t)0x40002E3C, 0x1f, (os_event_t*)0x3FFFDDC0, 4);
|
||||
|
||||
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0);
|
||||
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x28, 0x88);
|
||||
WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + 0x30, 0);
|
||||
printf("Installed timer ISR\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ets_run(void) {
|
||||
#if USE_ETS_TASK
|
||||
#if SDK_BELOW_1_1_1
|
||||
ets_isr_attach(10, my_timer_isr, NULL);
|
||||
#endif
|
||||
_ets_run();
|
||||
#else
|
||||
// ets_timer_init();
|
||||
*(char*)0x3FFFC6FC = 0;
|
||||
ets_intr_lock();
|
||||
printf("ets_alt_task: ets_run\n");
|
||||
#if DEBUG
|
||||
dump_tasks();
|
||||
#endif
|
||||
ets_intr_unlock();
|
||||
while (1) {
|
||||
if (!ets_loop_iter()) {
|
||||
//printf("idle\n");
|
||||
ets_intr_lock();
|
||||
if (idle_cb) {
|
||||
idle_cb(idle_arg);
|
||||
}
|
||||
asm("waiti 0");
|
||||
ets_intr_unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ets_set_idle_cb(void (*handler)(void *), void *arg) {
|
||||
//printf("ets_set_idle_cb(%p, %p)\n", handler, arg);
|
||||
idle_cb = handler;
|
||||
idle_arg = arg;
|
||||
}
|
||||
1
esp8266/ets_alt_task.h
Normal file
1
esp8266/ets_alt_task.h
Normal file
@@ -0,0 +1 @@
|
||||
bool ets_loop_iter(void);
|
||||
@@ -1,9 +1,27 @@
|
||||
#ifndef _INCLUDED_ETSHAL_H_
|
||||
#define _INCLUDED_ETSHAL_H_
|
||||
|
||||
void ets_isr_unmask();
|
||||
#include <os_type.h>
|
||||
|
||||
// see http://esp8266-re.foogod.com/wiki/Random_Number_Generator
|
||||
#define WDEV_HWRNG ((volatile uint32_t*)0x3ff20e44)
|
||||
|
||||
void ets_delay_us();
|
||||
void ets_intr_lock(void);
|
||||
void ets_intr_unlock(void);
|
||||
void ets_isr_mask(uint32_t mask);
|
||||
void ets_isr_unmask(uint32_t mask);
|
||||
void ets_isr_attach(int irq_no, void (*handler)(void *), void *arg);
|
||||
void ets_install_putc1();
|
||||
void ets_isr_attach();
|
||||
void uart_div_modify();
|
||||
void ets_set_idle_cb(void (*handler)(void *), void *arg);
|
||||
|
||||
void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_milli_timer);
|
||||
void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data);
|
||||
void ets_timer_disarm(os_timer_t *tim);
|
||||
|
||||
// These prototypes are for recent SDKs with "malloc tracking"
|
||||
void *pvPortMalloc(unsigned sz, const char *fname, int line);
|
||||
void vPortFree(void *p, const char *fname, int line);
|
||||
|
||||
#endif // _INCLUDED_ETSHAL_H_
|
||||
|
||||
6
esp8266/fatfs_port.c
Normal file
6
esp8266/fatfs_port.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "lib/fatfs/diskio.h"
|
||||
|
||||
DWORD get_fattime(void) {
|
||||
return 0;
|
||||
}
|
||||
@@ -39,10 +39,6 @@ void gc_collect(void) {
|
||||
// start the GC
|
||||
gc_collect_start();
|
||||
|
||||
// We need to scan everything in RAM that can hold a pointer.
|
||||
// The data segment is used, but should not contain pointers, so we just scan the bss.
|
||||
gc_collect_root((void**)&_bss_start, ((uint32_t)&_bss_end - (uint32_t)&_bss_start) / sizeof(uint32_t));
|
||||
|
||||
// get the registers and the sp
|
||||
mp_uint_t regs[8];
|
||||
mp_uint_t sp = gc_helper_get_regs_and_sp(regs);
|
||||
|
||||
70
esp8266/help.c
Normal file
70
esp8266/help.c
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013-2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lib/utils/pyhelp.h"
|
||||
|
||||
STATIC const char *help_text =
|
||||
"Welcome to MicroPython!\n"
|
||||
"\n"
|
||||
"For online docs please visit http://docs.micropython.org/en/latest/esp8266/ .\n"
|
||||
"For diagnostic information to include in bug reports execute 'import port_diag'.\n"
|
||||
"\n"
|
||||
"Basic WiFi configuration:\n"
|
||||
"\n"
|
||||
"import network\n"
|
||||
"sta_if = network.WLAN(network.STA_IF)\n"
|
||||
"sta_if.scan() # Scan for available access points\n"
|
||||
"sta_if.connect(\"<AP_name>\", \"<password>\") # Connect to an AP\n"
|
||||
"sta_if.isconnected() # Check for successful connection\n"
|
||||
"# Change name/password of ESP8266's AP:\n"
|
||||
"ap_if = network.WLAN(network.AP_IF)\n"
|
||||
"ap_if.config(essid=\"<AP_NAME>\", authmode=network.AUTH_WPA_WPA2_PSK, password=\"<password>\")\n"
|
||||
"\n"
|
||||
"Control commands:\n"
|
||||
" CTRL-A -- on a blank line, enter raw REPL mode\n"
|
||||
" CTRL-B -- on a blank line, enter normal REPL mode\n"
|
||||
" CTRL-C -- interrupt a running program\n"
|
||||
" CTRL-D -- on a blank line, do a soft reset of the board\n"
|
||||
" CTRL-E -- on a blank line, enter paste mode\n"
|
||||
"\n"
|
||||
"For further help on a specific object, type help(obj)\n"
|
||||
;
|
||||
|
||||
STATIC mp_obj_t builtin_help(uint n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// print a general help message
|
||||
printf("%s", help_text);
|
||||
|
||||
} else {
|
||||
// try to print something sensible about the given object
|
||||
pyhelp_print_obj(args[0]);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, builtin_help);
|
||||
37
esp8266/intr.c
Normal file
37
esp8266/intr.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "etshal.h"
|
||||
#include "ets_alt_task.h"
|
||||
|
||||
#include "modpyb.h"
|
||||
|
||||
// this is in a separate file so it can go in iRAM
|
||||
void pin_intr_handler_iram(void *arg) {
|
||||
uint32_t status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, status);
|
||||
pin_intr_handler(status);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user