mirror of
https://github.com/micropython/micropython.git
synced 2025-12-25 06:10:13 +01:00
Compare commits
306 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 |
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
|
||||
|
||||
17
README.md
17
README.md
@@ -22,11 +22,12 @@ 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.
|
||||
@@ -39,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
|
||||
@@ -48,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).
|
||||
@@ -65,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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -152,6 +152,7 @@ APP_LIB_SRC_C = $(addprefix lib/,\
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ 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 (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));
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
#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
|
||||
@@ -113,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,367 +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(A)
|
||||
Q(B)
|
||||
Q(ONE_SHOT)
|
||||
Q(PERIODIC)
|
||||
Q(PWM)
|
||||
Q(POSITIVE)
|
||||
Q(NEGATIVE)
|
||||
Q(TIMEOUT)
|
||||
Q(MATCH)
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
17
docs/conf.py
17
docs/conf.py
@@ -26,10 +26,10 @@ from collections import OrderedDict
|
||||
micropy_port = os.getenv('MICROPY_PORT') or 'pyboard'
|
||||
tags.add('port_' + micropy_port)
|
||||
ports = OrderedDict((
|
||||
('unix', ('unix', 'unix')),
|
||||
('pyboard', ('pyboard', 'the pyboard')),
|
||||
('wipy', ('WiPy', 'the WiPy')),
|
||||
('esp8266', ('ESP8266', 'the ESP8266')),
|
||||
('unix', 'unix'),
|
||||
('pyboard', 'the pyboard'),
|
||||
('wipy', 'the WiPy'),
|
||||
('esp8266', 'the ESP8266'),
|
||||
))
|
||||
|
||||
# The members of the html_context dict are available inside topindex.html
|
||||
@@ -38,11 +38,10 @@ 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_short_name':ports[micropy_port][0],
|
||||
'port_name':ports[micropy_port][1],
|
||||
'port_name':ports[micropy_port],
|
||||
'port_version':micropy_version,
|
||||
'all_ports':[
|
||||
(port_name[0], url_pattern % (micropy_version, port_id))
|
||||
(port_id, url_pattern % (micropy_version, port_id))
|
||||
for port_id, port_name in ports.items()
|
||||
],
|
||||
'all_versions':[
|
||||
@@ -92,9 +91,9 @@ copyright = '2014-2016, Damien P. George and contributors'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '1.7'
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.7'
|
||||
release = '1.8'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
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.
|
||||
@@ -202,6 +202,28 @@ The I2C driver is implemented in software and works on all pins::
|
||||
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
|
||||
--------------
|
||||
|
||||
@@ -213,10 +235,10 @@ The OneWire driver is implemented in software and works on all pins::
|
||||
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.read_byte() # read a byte
|
||||
ow.read_bytes(5) # read 5 bytes
|
||||
ow.write_byte(0x12) # write a byte on the bus
|
||||
ow.write_bytes('123') # write bytes on 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::
|
||||
@@ -224,12 +246,14 @@ There is a specific driver for DS18B20 devices::
|
||||
import time
|
||||
ds = onewire.DS18B20(ow)
|
||||
roms = ds.scan()
|
||||
ds.start_measure()
|
||||
ds.convert_temp()
|
||||
time.sleep_ms(750)
|
||||
for rom in roms:
|
||||
print(ds.get_temp(rom))
|
||||
print(ds.read_temp(rom))
|
||||
|
||||
Be sure to put a 4.7k pull-up resistor on the data line.
|
||||
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
|
||||
---------------
|
||||
@@ -245,10 +269,36 @@ Use the ``neopixel`` module::
|
||||
np.write() # write data to all pixels
|
||||
r, g, b = np[0] # get first pixel colour
|
||||
|
||||
import neopixel
|
||||
neopixel.demo(np) # run a demo
|
||||
|
||||
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.
|
||||
@@ -4,6 +4,8 @@ MicroPython documentation contents
|
||||
.. toctree::
|
||||
|
||||
esp8266/quickref.rst
|
||||
esp8266/general.rst
|
||||
esp8266/tutorial/index.rst
|
||||
library/index.rst
|
||||
reference/index.rst
|
||||
license.rst
|
||||
|
||||
@@ -39,3 +39,9 @@ Functions
|
||||
.. function:: flash_id()
|
||||
|
||||
Read the device ID of the flash memory.
|
||||
|
||||
.. function:: flash_read(byte_offset, length_or_buffer)
|
||||
|
||||
.. function:: flash_write(byte_offset, bytes)
|
||||
|
||||
.. function:: flash_erase(sector_no)
|
||||
|
||||
@@ -1,73 +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
|
||||
|
||||
.. only:: port_esp8266
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
gc.rst
|
||||
math.rst
|
||||
struct.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
|
||||
@@ -82,32 +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
|
||||
|
||||
ubinascii.rst
|
||||
uctypes.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
uzlib.rst
|
||||
.. 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
|
||||
.. 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
|
||||
|
||||
ubinascii.rst
|
||||
uctypes.rst
|
||||
uhashlib.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
ure.rst
|
||||
uzlib.rst
|
||||
|
||||
.. only:: port_pyboard
|
||||
|
||||
@@ -120,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
|
||||
|
||||
@@ -143,8 +143,6 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
machine.rst
|
||||
network.rst
|
||||
wipy.rst
|
||||
|
||||
|
||||
@@ -158,6 +156,4 @@ library.
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
network.rst
|
||||
esp.rst
|
||||
machine.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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -18,76 +18,90 @@ Reset related functions
|
||||
|
||||
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 network ``MAC address``.
|
||||
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:
|
||||
|
||||
|
||||
@@ -283,14 +283,6 @@ For example::
|
||||
|
||||
Disconnect from the currently connected wireless network.
|
||||
|
||||
.. method:: wlan.mac([address])
|
||||
|
||||
Get or set the network interface MAC address.
|
||||
|
||||
If the ``address`` parameter is provided, sets the address to its
|
||||
value, which should be bytes object of length 6. If the function
|
||||
is called wihout parameters, returns the current address.
|
||||
|
||||
.. method:: wlan.scan()
|
||||
|
||||
Scan for the available wireless networks.
|
||||
@@ -300,6 +292,9 @@ For example::
|
||||
|
||||
(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
|
||||
@@ -332,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
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
Returns the number of characters waiting (may be 0).
|
||||
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.
|
||||
@@ -12,7 +12,7 @@ Functions
|
||||
|
||||
.. 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
|
||||
@@ -22,13 +22,13 @@ Functions
|
||||
|
||||
.. 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. Return bytes string.
|
||||
Convert Base64-encoded data to binary representation. Returns bytes string.
|
||||
|
||||
.. function:: b2a_base64(data)
|
||||
|
||||
Encode binary data in Base64 format. Return string.
|
||||
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
|
||||
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,7 +1,7 @@
|
||||
: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``
|
||||
@@ -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).
|
||||
@@ -59,20 +59,21 @@ An example of the above is the common case where a buffer is required, such as o
|
||||
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 optional support for pre-allocated buffers.
|
||||
For example the ``uart.readinto()`` method allows two options for its argument, an integer
|
||||
or a buffer. If an integer is supplied it will read up to that number of bytes and
|
||||
return the outcome: this implies that a buffer is created with a corresponding
|
||||
memory allocation. Providing a pre-allocated buffer as the argument avoids this. See
|
||||
the code fragment in :ref:`Caching object references <Caching>` below.
|
||||
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
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
For the most speed critical sections of code it is worth noting that performing
|
||||
any kind of floating point operation involves heap allocation. Where possible use
|
||||
integer operations and restrict the use of floating point to sections of the code
|
||||
where performance is not paramount.
|
||||
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
|
||||
~~~~~~
|
||||
@@ -84,18 +85,31 @@ elements in contiguous memory locations. Once again to avoid memory allocation i
|
||||
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. This can be avoided using a ``memoryview``
|
||||
object:
|
||||
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(100)
|
||||
func(ba[3:10]) # a copy is passed
|
||||
mv = memoryview(ba)
|
||||
func(mv[3:10]) # a pointer to memory is passed
|
||||
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.
|
||||
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
|
||||
---------------------------------------
|
||||
|
||||
2
docs/templates/versions.html
vendored
2
docs/templates/versions.html
vendored
@@ -1,7 +1,7 @@
|
||||
<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_short_name }} ({{ port_version }})
|
||||
{{ port }} ({{ port_version }})
|
||||
<span class="fa fa-caret-down"></span>
|
||||
</span>
|
||||
<div class="rst-other-versions">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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``.
|
||||
|
||||
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)
|
||||
@@ -3,6 +3,8 @@ 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
|
||||
|
||||
@@ -30,14 +32,14 @@ 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 -lssl -llwip_open -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
|
||||
@@ -48,26 +50,28 @@ CFLAGS += -g
|
||||
COPT = -O0
|
||||
else
|
||||
CFLAGS += -fdata-sections -ffunction-sections
|
||||
COPT += -Os -mforce-l32 -DNDEBUG
|
||||
COPT += -Os -DNDEBUG
|
||||
LDFLAGS += --gc-sections
|
||||
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 \
|
||||
modpybi2c.c \
|
||||
modpybspi.c \
|
||||
modesp.c \
|
||||
modnetwork.c \
|
||||
@@ -75,17 +79,18 @@ SRC_C = \
|
||||
moduos.c \
|
||||
modmachine.c \
|
||||
modonewire.c \
|
||||
utils.c \
|
||||
ets_alt_task.c \
|
||||
$(BUILD)/frozen.c \
|
||||
fatfs_port.o \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
pybstdio.c \
|
||||
input.c \
|
||||
)
|
||||
|
||||
EXTMOD_SRC_C = $(addprefix extmod/,\
|
||||
modlwip.o \
|
||||
modlwip.c \
|
||||
)
|
||||
|
||||
LIB_SRC_C = $(addprefix lib/,\
|
||||
@@ -112,6 +117,7 @@ LIB_SRC_C = $(addprefix lib/,\
|
||||
netutils/netutils.c \
|
||||
timeutils/timeutils.c \
|
||||
utils/pyexec.c \
|
||||
utils/pyhelp.c \
|
||||
utils/printf.c \
|
||||
fatfs/ff.c \
|
||||
fatfs/option/ccsbcs.c \
|
||||
@@ -129,6 +135,11 @@ 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
|
||||
@@ -154,7 +165,7 @@ deploy: $(BUILD)/firmware-combined.bin
|
||||
#$(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 $@"
|
||||
@@ -193,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"
|
||||
|
||||
@@ -13,15 +13,12 @@ Currently implemented features include:
|
||||
- Builtin modules: gc, array, collections, io, struct, sys, esp, network,
|
||||
many more.
|
||||
- Arbitrary-precision long integers and 30-bit precision floats.
|
||||
- Basic WiFi support.
|
||||
- WiFi support.
|
||||
- Sockets using modlwip.
|
||||
- GPIO and bit-banging I2C, SPI support.
|
||||
- 1-Wire and WS2812 (aka Neopixel) protocols support.
|
||||
|
||||
On the TODO list:
|
||||
- Full wifi 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/ .
|
||||
@@ -45,6 +42,7 @@ dependencies.
|
||||
Then, to build MicroPython for the ESP8266, just run:
|
||||
```bash
|
||||
$ cd esp8266
|
||||
$ make axtls
|
||||
$ make
|
||||
```
|
||||
This will produce binary images in the `build/` subdirectory. If you install
|
||||
@@ -52,7 +50,7 @@ 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
|
||||
esptool.py --port /dev/ttyXXX erase_flash
|
||||
```
|
||||
|
||||
Erase flash also as a troubleshooting measure, if a module doesn't behave as
|
||||
|
||||
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 );
|
||||
|
||||
@@ -120,6 +120,7 @@ SECTIONS
|
||||
*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*)
|
||||
@@ -146,6 +147,7 @@ SECTIONS
|
||||
*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 */
|
||||
|
||||
@@ -51,12 +51,6 @@ void mp_hal_init(void) {
|
||||
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) {
|
||||
uint32_t start = system_get_time();
|
||||
while (system_get_time() - start < us) {
|
||||
@@ -71,7 +65,6 @@ int mp_hal_stdin_rx_chr(void) {
|
||||
return c;
|
||||
}
|
||||
mp_hal_delay_us(1);
|
||||
mp_hal_feed_watchdog();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,25 +171,27 @@ static int call_dupterm_read(void) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len == 0) {
|
||||
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
|
||||
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 {
|
||||
// Temporarily disable dupterm to avoid infinite recursion
|
||||
mp_obj_t save_term = MP_STATE_PORT(term_obj);
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: ");
|
||||
mp_printf(&mp_plat_print, "dupterm: Exception in read() method, deactivating: ");
|
||||
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
|
||||
MP_STATE_PORT(term_obj) = save_term;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -205,6 +200,7 @@ STATIC void dupterm_task_handler(os_event_t *evt) {
|
||||
ringbuf_put(&input_buf, c);
|
||||
}
|
||||
mp_hal_signal_input();
|
||||
lock = 0;
|
||||
}
|
||||
|
||||
STATIC os_event_t dupterm_evt_queue[4];
|
||||
@@ -216,3 +212,47 @@ void dupterm_task_init() {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,6 @@ void mp_hal_signal_dupterm_input(void);
|
||||
|
||||
void mp_hal_init(void);
|
||||
void mp_hal_rtc_init(void);
|
||||
void mp_hal_feed_watchdog(void);
|
||||
|
||||
uint32_t mp_hal_ticks_us(void);
|
||||
void mp_hal_delay_us(uint32_t);
|
||||
@@ -56,4 +55,29 @@ 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_
|
||||
|
||||
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__
|
||||
@@ -20,4 +20,8 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi
|
||||
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_
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -47,12 +47,16 @@ STATIC void mp_reset(void) {
|
||||
gc_init(heap, heap + sizeof(heap));
|
||||
mp_init();
|
||||
mp_obj_list_init(mp_sys_path, 0);
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
|
||||
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
|
||||
mp_obj_list_init(mp_sys_argv, 0);
|
||||
#if MICROPY_VFS_FAT
|
||||
memset(MP_STATE_PORT(fs_user_mount), 0, sizeof(MP_STATE_PORT(fs_user_mount)));
|
||||
#endif
|
||||
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
|
||||
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
|
||||
pin_init0();
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
pyexec_frozen_module("_boot");
|
||||
pyexec_file("boot.py");
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "netutils.h"
|
||||
#include "queue.h"
|
||||
#include "ets_sys.h"
|
||||
@@ -40,7 +41,7 @@
|
||||
#include "user_interface.h"
|
||||
#include "espconn.h"
|
||||
#include "spi_flash.h"
|
||||
#include "utils.h"
|
||||
#include "mem.h"
|
||||
#include "espneopixel.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
@@ -537,10 +538,11 @@ STATIC mp_obj_t esp_sleep_type(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_sleep_type_obj, 0, 1, esp_sleep_type);
|
||||
|
||||
STATIC mp_obj_t esp_deepsleep(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
system_deep_sleep_set_option(n_args > 1 ? mp_obj_get_int(args[1]) : 0);
|
||||
system_deep_sleep(n_args > 0 ? mp_obj_get_int(args[0]) : 0);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_deepsleep_obj, 0, 1, esp_deepsleep);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_deepsleep_obj, 0, 2, esp_deepsleep);
|
||||
|
||||
STATIC mp_obj_t esp_flash_id() {
|
||||
return mp_obj_new_int(spi_flash_get_id());
|
||||
@@ -608,6 +610,23 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
|
||||
|
||||
STATIC mp_obj_t esp_flash_size(void) {
|
||||
extern char flashchip;
|
||||
// For SDK 1.5.2, either address has shifted and not mirrored in
|
||||
// eagle.rom.addr.v6.ld, or extra initial member was added.
|
||||
SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4);
|
||||
#if 0
|
||||
printf("deviceId: %x\n", flash->deviceId);
|
||||
printf("chip_size: %u\n", flash->chip_size);
|
||||
printf("block_size: %u\n", flash->block_size);
|
||||
printf("sector_size: %u\n", flash->sector_size);
|
||||
printf("page_size: %u\n", flash->page_size);
|
||||
printf("status_mask: %u\n", flash->status_mask);
|
||||
#endif
|
||||
return mp_obj_new_int_from_uint(flash->chip_size);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
|
||||
|
||||
STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
@@ -628,6 +647,22 @@ STATIC mp_obj_t esp_meminfo() {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_meminfo_obj, esp_meminfo);
|
||||
|
||||
STATIC mp_obj_t esp_malloc(mp_obj_t size_in) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)os_malloc(mp_obj_get_int(size_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_malloc_obj, esp_malloc);
|
||||
|
||||
STATIC mp_obj_t esp_free(mp_obj_t addr_in) {
|
||||
os_free((void*)mp_obj_get_int(addr_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_free_obj, esp_free);
|
||||
|
||||
STATIC mp_obj_t esp_esf_free_bufs(mp_obj_t idx_in) {
|
||||
return MP_OBJ_NEW_SMALL_INT(ets_esf_free_bufs(mp_obj_get_int(idx_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_esf_free_bufs_obj, esp_esf_free_bufs);
|
||||
|
||||
STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
|
||||
|
||||
@@ -638,6 +673,7 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_read), (mp_obj_t)&esp_flash_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_write), (mp_obj_t)&esp_flash_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_size), (mp_obj_t)&esp_flash_size_obj },
|
||||
#if MODESP_ESPCONN
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
|
||||
@@ -645,6 +681,10 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_freemem), (mp_obj_t)&esp_freemem_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_meminfo), (mp_obj_t)&esp_meminfo_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj }, // TODO delete/rename/move elsewhere
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_malloc), (mp_obj_t)&esp_malloc_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_free), (mp_obj_t)&esp_free_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_esf_free_bufs), (mp_obj_t)&esp_esf_free_bufs_obj },
|
||||
|
||||
#if MODESP_INCLUDE_CONSTANTS
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_NONE),
|
||||
|
||||
@@ -30,16 +30,22 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "utils.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "etshal.h"
|
||||
#include "ets_alt_task.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE
|
||||
|
||||
//#define MACHINE_WAKE_IDLE (0x01)
|
||||
//#define MACHINE_WAKE_SLEEP (0x02)
|
||||
#define MACHINE_WAKE_DEEPSLEEP (0x04)
|
||||
|
||||
STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
// get
|
||||
@@ -63,12 +69,51 @@ STATIC mp_obj_t machine_reset(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
|
||||
|
||||
STATIC mp_obj_t machine_reset_cause(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(system_get_rst_info()->reason);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
|
||||
|
||||
STATIC mp_obj_t machine_unique_id(void) {
|
||||
uint32_t id = system_get_chip_id();
|
||||
return mp_obj_new_bytes((byte*)&id, sizeof(id));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_unique_id_obj, machine_unique_id);
|
||||
|
||||
STATIC mp_obj_t machine_deepsleep(void) {
|
||||
// default to sleep forever
|
||||
uint32_t sleep_us = 0;
|
||||
|
||||
// see if RTC.ALARM0 should wake the device
|
||||
if (pyb_rtc_alarm0_wake & MACHINE_WAKE_DEEPSLEEP) {
|
||||
uint64_t t = pyb_rtc_get_us_since_2000();
|
||||
if (pyb_rtc_alarm0_expiry <= t) {
|
||||
sleep_us = 1; // alarm already expired so wake immediately
|
||||
} else {
|
||||
uint64_t delta = pyb_rtc_alarm0_expiry - t;
|
||||
if (delta <= 0xffffffff) {
|
||||
// sleep for the desired time
|
||||
sleep_us = delta;
|
||||
} else {
|
||||
// overflow, just set to maximum sleep time
|
||||
sleep_us = 0xffffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// put the device in a deep-sleep state
|
||||
system_deep_sleep_set_option(0); // default power down mode; TODO check this
|
||||
system_deep_sleep(sleep_us);
|
||||
|
||||
for (;;) {
|
||||
// we must not return
|
||||
ets_loop_iter();
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep);
|
||||
|
||||
typedef struct _esp_timer_obj_t {
|
||||
mp_obj_base_t base;
|
||||
os_timer_t timer;
|
||||
@@ -91,7 +136,7 @@ STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args,
|
||||
|
||||
STATIC void esp_timer_cb(void *arg) {
|
||||
esp_timer_obj_t *self = arg;
|
||||
call_function_1_protected(self->callback, self);
|
||||
mp_call_function_1_protected(self->callback, self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
@@ -152,15 +197,26 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&esp_timer_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pyb_pin_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pyb_pwm_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
|
||||
|
||||
// wake abilities
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
|
||||
|
||||
// reset causes
|
||||
{ MP_ROM_QSTR(MP_QSTR_PWR_ON_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "espconn.h"
|
||||
#include "spi_flash.h"
|
||||
#include "ets_alt_task.h"
|
||||
#include "lwip/dns.h"
|
||||
|
||||
#define MODNETWORK_INCLUDE_CONSTANTS (1)
|
||||
|
||||
@@ -189,40 +190,58 @@ STATIC mp_obj_t esp_isconnected(mp_obj_t self_in) {
|
||||
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_isconnected_obj, esp_isconnected);
|
||||
|
||||
STATIC mp_obj_t esp_mac(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t esp_ifconfig(size_t n_args, const mp_obj_t *args) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
uint8_t mac[6];
|
||||
if (n_args == 1) {
|
||||
wifi_get_macaddr(self->if_id, mac);
|
||||
return mp_obj_new_bytes(mac, sizeof(mac));
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
if (bufinfo.len != 6) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid buffer length"));
|
||||
}
|
||||
|
||||
wifi_set_macaddr(self->if_id, bufinfo.buf);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_mac_obj, 1, 2, esp_mac);
|
||||
|
||||
STATIC mp_obj_t esp_ifconfig(mp_obj_t self_in) {
|
||||
wlan_if_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
struct ip_info info;
|
||||
ip_addr_t dns_addr;
|
||||
wifi_get_ip_info(self->if_id, &info);
|
||||
mp_obj_t ifconfig[4] = {
|
||||
if (n_args == 1) {
|
||||
// get
|
||||
dns_addr = dns_getserver(0);
|
||||
mp_obj_t tuple[4] = {
|
||||
netutils_format_ipv4_addr((uint8_t*)&info.ip, NETUTILS_BIG),
|
||||
netutils_format_ipv4_addr((uint8_t*)&info.netmask, NETUTILS_BIG),
|
||||
netutils_format_ipv4_addr((uint8_t*)&info.gw, NETUTILS_BIG),
|
||||
MP_OBJ_NEW_QSTR(MP_QSTR_), // no DNS server
|
||||
};
|
||||
return mp_obj_new_tuple(4, ifconfig);
|
||||
netutils_format_ipv4_addr((uint8_t*)&dns_addr, NETUTILS_BIG),
|
||||
};
|
||||
return mp_obj_new_tuple(4, tuple);
|
||||
} else {
|
||||
// set
|
||||
mp_obj_t *items;
|
||||
bool restart_dhcp_server = false;
|
||||
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
||||
netutils_parse_ipv4_addr(items[0], (void*)&info.ip, NETUTILS_BIG);
|
||||
if (mp_obj_is_integer(items[1])) {
|
||||
// allow numeric netmask, i.e.:
|
||||
// 24 -> 255.255.255.0
|
||||
// 16 -> 255.255.0.0
|
||||
// etc...
|
||||
uint32_t* m = (uint32_t*)&info.netmask;
|
||||
*m = htonl(0xffffffff << (32 - mp_obj_get_int(items[1])));
|
||||
} else {
|
||||
netutils_parse_ipv4_addr(items[1], (void*)&info.netmask, NETUTILS_BIG);
|
||||
}
|
||||
netutils_parse_ipv4_addr(items[2], (void*)&info.gw, NETUTILS_BIG);
|
||||
netutils_parse_ipv4_addr(items[3], (void*)&dns_addr, NETUTILS_BIG);
|
||||
// To set a static IP we have to disable DHCP first
|
||||
if (self->if_id == STATION_IF) {
|
||||
wifi_station_dhcpc_stop();
|
||||
} else {
|
||||
restart_dhcp_server = wifi_softap_dhcps_status();
|
||||
wifi_softap_dhcps_stop();
|
||||
}
|
||||
if (!wifi_set_ip_info(self->if_id, &info)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"wifi_set_ip_info() failed"));
|
||||
}
|
||||
dns_setserver(0, &dns_addr);
|
||||
if (restart_dhcp_server) {
|
||||
wifi_softap_dhcps_start();
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_ifconfig_obj, esp_ifconfig);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_ifconfig_obj, 1, 2, esp_ifconfig);
|
||||
|
||||
STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
if (n_args != 1 && kwargs->used != 0) {
|
||||
@@ -242,13 +261,26 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
error_check(wifi_softap_get_config(&cfg.ap), "can't get AP config");
|
||||
}
|
||||
|
||||
int req_if = -1;
|
||||
|
||||
if (kwargs->used != 0) {
|
||||
|
||||
for (mp_uint_t i = 0; i < kwargs->alloc; i++) {
|
||||
if (MP_MAP_SLOT_IS_FILLED(kwargs, i)) {
|
||||
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
|
||||
switch ((uintptr_t)kwargs->table[i].key) {
|
||||
case QS(MP_QSTR_mac): {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len != 6) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"invalid buffer length"));
|
||||
}
|
||||
wifi_set_macaddr(self->if_id, bufinfo.buf);
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_essid): {
|
||||
req_if = SOFTAP_IF;
|
||||
mp_uint_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(cfg.ap.ssid));
|
||||
@@ -256,6 +288,30 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
cfg.ap.ssid_len = len;
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_hidden): {
|
||||
req_if = SOFTAP_IF;
|
||||
cfg.ap.ssid_hidden = mp_obj_is_true(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_authmode): {
|
||||
req_if = SOFTAP_IF;
|
||||
cfg.ap.authmode = mp_obj_get_int(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_password): {
|
||||
req_if = SOFTAP_IF;
|
||||
mp_uint_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(cfg.ap.password) - 1);
|
||||
memcpy(cfg.ap.password, s, len);
|
||||
cfg.ap.password[len] = 0;
|
||||
break;
|
||||
}
|
||||
case QS(MP_QSTR_channel): {
|
||||
req_if = SOFTAP_IF;
|
||||
cfg.ap.channel = mp_obj_get_int(kwargs->table[i].value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
@@ -263,6 +319,11 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
}
|
||||
}
|
||||
|
||||
// We post-check interface requirements to save on code size
|
||||
if (req_if >= 0) {
|
||||
require_if(args[0], req_if);
|
||||
}
|
||||
|
||||
if (self->if_id == STATION_IF) {
|
||||
error_check(wifi_station_set_config(&cfg.sta), "can't set STA config");
|
||||
} else {
|
||||
@@ -279,13 +340,43 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
"can query only one param"));
|
||||
}
|
||||
|
||||
mp_obj_t val;
|
||||
|
||||
#define QS(x) (uintptr_t)MP_OBJ_NEW_QSTR(x)
|
||||
switch ((uintptr_t)args[1]) {
|
||||
case QS(MP_QSTR_mac): {
|
||||
uint8_t mac[6];
|
||||
wifi_get_macaddr(self->if_id, mac);
|
||||
return mp_obj_new_bytes(mac, sizeof(mac));
|
||||
}
|
||||
case QS(MP_QSTR_essid):
|
||||
return mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len, false);
|
||||
req_if = SOFTAP_IF;
|
||||
val = mp_obj_new_str((char*)cfg.ap.ssid, cfg.ap.ssid_len, false);
|
||||
break;
|
||||
case QS(MP_QSTR_hidden):
|
||||
req_if = SOFTAP_IF;
|
||||
val = mp_obj_new_bool(cfg.ap.ssid_hidden);
|
||||
break;
|
||||
case QS(MP_QSTR_authmode):
|
||||
req_if = SOFTAP_IF;
|
||||
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.authmode);
|
||||
break;
|
||||
case QS(MP_QSTR_channel):
|
||||
req_if = SOFTAP_IF;
|
||||
val = MP_OBJ_NEW_SMALL_INT(cfg.ap.channel);
|
||||
break;
|
||||
default:
|
||||
goto unknown;
|
||||
}
|
||||
#undef QS
|
||||
|
||||
// We post-check interface requirements to save on code size
|
||||
if (req_if >= 0) {
|
||||
require_if(args[0], req_if);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
unknown:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
|
||||
"unknown config param"));
|
||||
@@ -299,7 +390,6 @@ STATIC const mp_map_elem_t wlan_if_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_status), (mp_obj_t)&esp_status_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&esp_scan_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&esp_isconnected_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mac), (mp_obj_t)&esp_mac_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_config), (mp_obj_t)&esp_config_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&esp_ifconfig_obj },
|
||||
};
|
||||
@@ -312,16 +402,6 @@ const mp_obj_type_t wlan_if_type = {
|
||||
.locals_dict = (mp_obj_t)&wlan_if_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t esp_wifi_mode(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
return mp_obj_new_int(wifi_get_opmode());
|
||||
} else {
|
||||
wifi_set_opmode(mp_obj_get_int(args[0]));
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_wifi_mode_obj, 0, 1, esp_wifi_mode);
|
||||
|
||||
STATIC mp_obj_t esp_phy_mode(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 0) {
|
||||
return mp_obj_new_int(wifi_get_phy_mode());
|
||||
@@ -335,7 +415,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_phy_mode_obj, 0, 1, esp_phy_mode)
|
||||
STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WLAN), (mp_obj_t)&get_wlan_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_wifi_mode), (mp_obj_t)&esp_wifi_mode_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_phy_mode), (mp_obj_t)&esp_phy_mode_obj },
|
||||
|
||||
#if MODNETWORK_INCLUDE_CONSTANTS
|
||||
@@ -363,6 +442,17 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
|
||||
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11G) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MODE_11N),
|
||||
MP_OBJ_NEW_SMALL_INT(PHY_MODE_11N) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_OPEN),
|
||||
MP_OBJ_NEW_SMALL_INT(AUTH_OPEN) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WEP),
|
||||
MP_OBJ_NEW_SMALL_INT(AUTH_WEP) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_PSK),
|
||||
MP_OBJ_NEW_SMALL_INT(AUTH_WPA_PSK) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA2_PSK),
|
||||
MP_OBJ_NEW_SMALL_INT(AUTH_WPA2_PSK) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AUTH_WPA_WPA2_PSK),
|
||||
MP_OBJ_NEW_SMALL_INT(AUTH_WPA_WPA2_PSK) },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -27,80 +27,28 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
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
|
||||
|
||||
#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)
|
||||
|
||||
static int timings[] = {480, 40, 420, 5, 5, 40, 10, 50, 10};
|
||||
#include "esponewire.h"
|
||||
|
||||
STATIC mp_obj_t onewire_timings(mp_obj_t timings_in) {
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array_fixed_n(timings_in, 9, &items);
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
timings[i] = mp_obj_get_int(items[i]);
|
||||
esp_onewire_timings[i] = mp_obj_get_int(items[i]);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_timings_obj, onewire_timings);
|
||||
|
||||
STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) {
|
||||
uint pin = mp_obj_get_pin(pin_in);
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(timings[TIMING_RESET1]);
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(timings[TIMING_RESET2]);
|
||||
int status = !pin_get(pin);
|
||||
enable_irq(i);
|
||||
DELAY_US(timings[TIMING_RESET3]);
|
||||
return mp_obj_new_bool(status);
|
||||
return mp_obj_new_bool(esp_onewire_reset(mp_obj_get_pin(pin_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset);
|
||||
|
||||
STATIC int _onewire_readbit(uint pin) {
|
||||
pin_set(pin, 1);
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(timings[TIMING_READ1]);
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(timings[TIMING_READ2]);
|
||||
int value = pin_get(pin);
|
||||
enable_irq(i);
|
||||
DELAY_US(timings[TIMING_READ3]);
|
||||
return value;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) {
|
||||
return MP_OBJ_NEW_SMALL_INT(_onewire_readbit(mp_obj_get_pin(pin_in)));
|
||||
return MP_OBJ_NEW_SMALL_INT(esp_onewire_readbit(mp_obj_get_pin(pin_in)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit);
|
||||
|
||||
@@ -108,25 +56,14 @@ STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) {
|
||||
uint pin = mp_obj_get_pin(pin_in);
|
||||
uint8_t value = 0;
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
value |= _onewire_readbit(pin) << i;
|
||||
value |= esp_onewire_readbit(pin) << i;
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte);
|
||||
|
||||
STATIC void _onewire_writebit(uint pin, int value) {
|
||||
uint32_t i = disable_irq();
|
||||
pin_set(pin, 0);
|
||||
DELAY_US(timings[TIMING_WRITE1]);
|
||||
pin_set(pin, value);
|
||||
DELAY_US(timings[TIMING_WRITE2]);
|
||||
pin_set(pin, 1);
|
||||
DELAY_US(timings[TIMING_WRITE3]);
|
||||
enable_irq(i);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) {
|
||||
_onewire_writebit(mp_obj_get_pin(pin_in), mp_obj_get_int(value_in));
|
||||
esp_onewire_writebit(mp_obj_get_pin(pin_in), mp_obj_get_int(value_in));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit);
|
||||
@@ -135,7 +72,7 @@ STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) {
|
||||
uint pin = mp_obj_get_pin(pin_in);
|
||||
int value = mp_obj_get_int(value_in);
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
_onewire_writebit(pin, value & 1);
|
||||
esp_onewire_writebit(pin, value & 1);
|
||||
value >>= 1;
|
||||
}
|
||||
return mp_const_none;
|
||||
|
||||
@@ -26,14 +26,15 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "gccollect.h"
|
||||
#include "user_interface.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
// The pyb module no longer exists since all functionality now appears
|
||||
// elsewhere, in more standard places (eg time, machine modules). The
|
||||
// only remaining function is pyb.info() which has been moved to the
|
||||
// esp module, pending deletion/renaming/moving elsewher.
|
||||
|
||||
STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// print info about memory
|
||||
{
|
||||
@@ -75,78 +76,4 @@ STATIC mp_obj_t pyb_info(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
|
||||
|
||||
STATIC mp_obj_t pyb_sync(void) {
|
||||
//storage_flush();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_sync_obj, pyb_sync);
|
||||
|
||||
STATIC mp_obj_t pyb_millis(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
|
||||
|
||||
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
|
||||
uint32_t startMillis = mp_obj_get_int(start);
|
||||
uint32_t currMillis = mp_hal_ticks_ms();
|
||||
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
|
||||
|
||||
STATIC mp_obj_t pyb_micros(void) {
|
||||
return MP_OBJ_NEW_SMALL_INT(system_get_time());
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
|
||||
|
||||
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
|
||||
uint32_t startMicros = mp_obj_get_int(start);
|
||||
uint32_t currMicros = system_get_time();
|
||||
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
|
||||
|
||||
STATIC mp_obj_t pyb_delay(mp_obj_t ms_in) {
|
||||
mp_int_t ms = mp_obj_get_int(ms_in);
|
||||
if (ms >= 0) {
|
||||
mp_hal_delay_ms(ms);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_delay_obj, pyb_delay);
|
||||
|
||||
STATIC mp_obj_t pyb_udelay(mp_obj_t usec_in) {
|
||||
mp_int_t usec = mp_obj_get_int(usec_in);
|
||||
if (usec >= 0) {
|
||||
mp_hal_delay_us(usec);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_udelay_obj, pyb_udelay);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_info_obj },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&pyb_udelay_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&pyb_sync_obj },
|
||||
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pyb_pin_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_module_globals, pyb_module_globals_table);
|
||||
|
||||
const mp_obj_module_t pyb_module = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_pyb,
|
||||
.globals = (mp_obj_dict_t*)&pyb_module_globals,
|
||||
};
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_info_obj, 0, 1, pyb_info);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#ifndef __MICROPY_INCLUDED_ESP8266_MODPYB_H__
|
||||
#define __MICROPY_INCLUDED_ESP8266_MODPYB_H__
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
extern const mp_obj_type_t pyb_pin_type;
|
||||
extern const mp_obj_type_t pyb_pwm_type;
|
||||
extern const mp_obj_type_t pyb_adc_type;
|
||||
@@ -6,15 +11,24 @@ extern const mp_obj_type_t pyb_uart_type;
|
||||
extern const mp_obj_type_t pyb_i2c_type;
|
||||
extern const mp_obj_type_t pyb_spi_type;
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);
|
||||
|
||||
typedef struct _pyb_pin_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint16_t pin_id;
|
||||
uint16_t phys_port;
|
||||
uint32_t periph;
|
||||
uint16_t func;
|
||||
uint32_t periph;
|
||||
} pyb_pin_obj_t;
|
||||
|
||||
const pyb_pin_obj_t pyb_pin_obj[16 + 1];
|
||||
|
||||
void pin_init0(void);
|
||||
void pin_intr_handler_iram(void *arg);
|
||||
void pin_intr_handler(uint32_t);
|
||||
|
||||
uint mp_obj_get_pin(mp_obj_t pin_in);
|
||||
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in);
|
||||
int pin_get(uint pin);
|
||||
void pin_set(uint pin, int value);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_MODPYB_H__
|
||||
|
||||
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "etshal.h"
|
||||
#include "osapi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
typedef struct _pyb_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
pyb_pin_obj_t *scl;
|
||||
pyb_pin_obj_t *sda;
|
||||
} pyb_i2c_obj_t;
|
||||
|
||||
// these set the frequency of SCL
|
||||
#define mphal_i2c_wait_a() os_delay_us(2)
|
||||
#define mphal_i2c_wait_b() os_delay_us(1)
|
||||
|
||||
STATIC void mphal_i2c_set_sda(pyb_i2c_obj_t *self, uint8_t sda) {
|
||||
uint32_t port = self->sda->phys_port;
|
||||
sda &= 0x01;
|
||||
gpio_output_set(sda << port, (1 - sda) << port, 1 << port, 0);
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_set_scl(pyb_i2c_obj_t *self, uint8_t scl) {
|
||||
uint32_t port = self->scl->phys_port;
|
||||
scl &= 0x01;
|
||||
gpio_output_set(scl << port, (1 - scl) << port, 1 << port, 0);
|
||||
}
|
||||
|
||||
STATIC int mphal_i2c_get_sda(pyb_i2c_obj_t *self) {
|
||||
return GPIO_INPUT_GET(GPIO_ID_PIN(self->sda->phys_port));
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_start(pyb_i2c_obj_t *self) {
|
||||
mphal_i2c_set_sda(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_sda(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_stop(pyb_i2c_obj_t *self) {
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_sda(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_sda(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_init(pyb_i2c_obj_t *self, uint32_t freq) {
|
||||
pyb_pin_obj_t *scl = self->scl;
|
||||
pyb_pin_obj_t *sda = self->sda;
|
||||
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
//ETS_INTR_LOCK();
|
||||
|
||||
PIN_FUNC_SELECT(sda->periph, sda->func);
|
||||
PIN_FUNC_SELECT(scl->periph, scl->func);
|
||||
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(sda->phys_port)),
|
||||
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(sda->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 << sda->phys_port));
|
||||
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(scl->phys_port)),
|
||||
GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(scl->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 << scl->phys_port));
|
||||
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_set_sda(self, 1);
|
||||
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
//ETS_INTR_UNLOCK();
|
||||
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
// when SCL = 0, toggle SDA to clear up
|
||||
mphal_i2c_set_sda(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_sda(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
// set data_cnt to max value
|
||||
for (uint8_t i = 0; i < 28; i++) {
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
}
|
||||
|
||||
// reset all
|
||||
mphal_i2c_stop(self);
|
||||
}
|
||||
|
||||
STATIC int mphal_i2c_write_byte(pyb_i2c_obj_t *self, uint8_t val) {
|
||||
uint8_t dat;
|
||||
sint8 i;
|
||||
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
for (i = 7; i >= 0; i--) {
|
||||
dat = val >> i;
|
||||
mphal_i2c_set_sda(self, dat);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
if (i == 0) {
|
||||
mphal_i2c_wait_b();
|
||||
}
|
||||
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
}
|
||||
|
||||
mphal_i2c_set_sda(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
int ret = mphal_i2c_get_sda(self);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_write(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
|
||||
mphal_i2c_start(self);
|
||||
if (!mphal_i2c_write_byte(self, addr << 1)) {
|
||||
goto er;
|
||||
}
|
||||
while (len--) {
|
||||
if (!mphal_i2c_write_byte(self, *data++)) {
|
||||
goto er;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
mphal_i2c_stop(self);
|
||||
}
|
||||
return;
|
||||
|
||||
er:
|
||||
mphal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
STATIC int mphal_i2c_read_byte(pyb_i2c_obj_t *self, uint8_t *val) {
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
uint8_t dat = 0;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
dat = (dat << 1) | mphal_i2c_get_sda(self);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
}
|
||||
*val = dat;
|
||||
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_set_scl(self, 1);
|
||||
mphal_i2c_wait_a();
|
||||
mphal_i2c_wait_b();
|
||||
mphal_i2c_set_scl(self, 0);
|
||||
mphal_i2c_wait_a();
|
||||
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
STATIC void mphal_i2c_read(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
|
||||
mphal_i2c_start(self);
|
||||
if (!mphal_i2c_write_byte(self, (addr << 1) | 1)) {
|
||||
goto er;
|
||||
}
|
||||
while (len--) {
|
||||
if (!mphal_i2c_read_byte(self, data++)) {
|
||||
goto er;
|
||||
}
|
||||
}
|
||||
if (stop) {
|
||||
mphal_i2c_stop(self);
|
||||
}
|
||||
return;
|
||||
|
||||
er:
|
||||
mphal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for I2C
|
||||
|
||||
STATIC void pyb_i2c_obj_init_helper(pyb_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_scl, ARG_sda, ARG_freq };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
self->scl = mp_obj_get_pin_obj(args[ARG_scl].u_obj);
|
||||
self->sda = mp_obj_get_pin_obj(args[ARG_sda].u_obj);
|
||||
mphal_i2c_init(self, args[ARG_freq].u_int);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
pyb_i2c_obj_t *self = m_new_obj(pyb_i2c_obj_t);
|
||||
self->base.type = &pyb_i2c_type;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_i2c_obj_init_helper(self, n_args, args, &kw_args);
|
||||
return (mp_obj_t)self;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_i2c_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
pyb_i2c_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_obj_init);
|
||||
|
||||
STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_n, ARG_stop };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
pyb_i2c_obj_t *self = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// do the I2C transfer
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, args[ARG_n].u_int);
|
||||
mphal_i2c_read(self, args[ARG_addr].u_int, (uint8_t*)vstr.buf, vstr.len, args[ARG_stop].u_bool);
|
||||
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 1, pyb_i2c_readfrom);
|
||||
|
||||
STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_buf, ARG_stop };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
|
||||
};
|
||||
pyb_i2c_obj_t *self = pos_args[0];
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get the buffer to write from
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// do the I2C transfer
|
||||
mphal_i2c_write(self, args[ARG_addr].u_int, bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto);
|
||||
|
||||
STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t pyb_i2c_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_I2C,
|
||||
.make_new = pyb_i2c_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&pyb_i2c_locals_dict,
|
||||
};
|
||||
@@ -28,14 +28,23 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "etshal.h"
|
||||
#include "c_types.h"
|
||||
#include "user_interface.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
#define GET_TRIGGER(phys_port) \
|
||||
GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)))
|
||||
#define SET_TRIGGER(phys_port, trig) \
|
||||
(GPIO_REG_WRITE(GPIO_PIN_ADDR(phys_port), \
|
||||
(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \
|
||||
| GPIO_PIN_INT_TYPE_SET(trig))) \
|
||||
|
||||
#define GPIO_MODE_INPUT (0)
|
||||
#define GPIO_MODE_OUTPUT (1)
|
||||
#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
|
||||
@@ -44,26 +53,64 @@
|
||||
// Removed in SDK 1.1.0
|
||||
//#define GPIO_PULL_DOWN (2)
|
||||
|
||||
STATIC const pyb_pin_obj_t pyb_pin_obj[] = {
|
||||
{{&pyb_pin_type}, 0, 0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0},
|
||||
{{&pyb_pin_type}, 1, 1, PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1},
|
||||
{{&pyb_pin_type}, 2, 2, PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2},
|
||||
{{&pyb_pin_type}, 3, 3, PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3},
|
||||
{{&pyb_pin_type}, 4, 4, PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4},
|
||||
{{&pyb_pin_type}, 5, 5, PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5},
|
||||
{{&pyb_pin_type}, 9, 9, PERIPHS_IO_MUX_SD_DATA2_U, FUNC_GPIO9},
|
||||
{{&pyb_pin_type}, 10, 10, PERIPHS_IO_MUX_SD_DATA3_U, FUNC_GPIO10},
|
||||
{{&pyb_pin_type}, 12, 12, PERIPHS_IO_MUX_MTDI_U, FUNC_GPIO12},
|
||||
{{&pyb_pin_type}, 13, 13, PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13},
|
||||
{{&pyb_pin_type}, 14, 14, PERIPHS_IO_MUX_MTMS_U, FUNC_GPIO14},
|
||||
{{&pyb_pin_type}, 15, 15, PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15},
|
||||
typedef struct _pin_irq_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint16_t phys_port;
|
||||
} pin_irq_obj_t;
|
||||
|
||||
const pyb_pin_obj_t pyb_pin_obj[16 + 1] = {
|
||||
{{&pyb_pin_type}, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U},
|
||||
{{&pyb_pin_type}, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U},
|
||||
{{&pyb_pin_type}, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U},
|
||||
{{&pyb_pin_type}, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U},
|
||||
{{&pyb_pin_type}, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U},
|
||||
{{&pyb_pin_type}, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U},
|
||||
{{NULL}, 0, 0, 0},
|
||||
{{NULL}, 0, 0, 0},
|
||||
{{NULL}, 0, 0, 0},
|
||||
{{&pyb_pin_type}, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U},
|
||||
{{&pyb_pin_type}, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U},
|
||||
{{NULL}, 0, 0, 0},
|
||||
{{&pyb_pin_type}, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U},
|
||||
{{&pyb_pin_type}, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U},
|
||||
{{&pyb_pin_type}, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U},
|
||||
{{&pyb_pin_type}, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U},
|
||||
// GPIO16 is special, belongs to different register set, and
|
||||
// otherwise handled specially.
|
||||
{{&pyb_pin_type}, 16, 16, -1, -1},
|
||||
{{&pyb_pin_type}, 16, -1, -1},
|
||||
};
|
||||
|
||||
STATIC uint8_t pin_mode[16 + 1];
|
||||
|
||||
// forward declaration
|
||||
STATIC const pin_irq_obj_t pin_irq_obj[16];
|
||||
|
||||
void pin_init0(void) {
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL);
|
||||
// disable all interrupts
|
||||
memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t));
|
||||
for (int p = 0; p < 16; ++p) {
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p);
|
||||
SET_TRIGGER(p, 0);
|
||||
}
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
}
|
||||
|
||||
void pin_intr_handler(uint32_t status) {
|
||||
gc_lock();
|
||||
status &= 0xffff;
|
||||
for (int p = 0; status; ++p, status >>= 1) {
|
||||
if (status & 1) {
|
||||
mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p];
|
||||
if (handler != MP_OBJ_NULL) {
|
||||
mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
gc_unlock();
|
||||
}
|
||||
|
||||
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
|
||||
if (mp_obj_get_type(pin_in) != &pyb_pin_type) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin"));
|
||||
@@ -130,36 +177,37 @@ STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ki
|
||||
pyb_pin_obj_t *self = self_in;
|
||||
|
||||
// pin name
|
||||
mp_printf(print, "Pin(%u)", self->pin_id);
|
||||
mp_printf(print, "Pin(%u)", self->phys_port);
|
||||
}
|
||||
|
||||
// pin.init(mode, pull=Pin.PULL_NONE, af=-1)
|
||||
// pin.init(mode, pull=None, *, value)
|
||||
STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_mode, ARG_pull, ARG_value };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
|
||||
{ MP_QSTR_pull, MP_ARG_INT, {.u_int = GPIO_PULL_NONE}},
|
||||
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
|
||||
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
|
||||
};
|
||||
|
||||
// parse args
|
||||
struct {
|
||||
mp_arg_val_t mode, pull, value;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get io mode
|
||||
uint mode = args.mode.u_int;
|
||||
uint mode = args[ARG_mode].u_int;
|
||||
|
||||
// get pull mode
|
||||
uint pull = args.pull.u_int;
|
||||
uint pull = GPIO_PULL_NONE;
|
||||
if (args[ARG_pull].u_obj != mp_const_none) {
|
||||
pull = mp_obj_get_int(args[ARG_pull].u_obj);
|
||||
}
|
||||
|
||||
// get initial value
|
||||
int value;
|
||||
if (args.value.u_obj == MP_OBJ_NULL) {
|
||||
if (args[ARG_value].u_obj == MP_OBJ_NULL) {
|
||||
value = -1;
|
||||
} else {
|
||||
value = mp_obj_is_true(args.value.u_obj);
|
||||
value = mp_obj_is_true(args[ARG_value].u_obj);
|
||||
}
|
||||
|
||||
// save the mode
|
||||
@@ -198,16 +246,13 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
|
||||
STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
|
||||
// Run an argument through the mapper and return the result.
|
||||
// get the wanted pin object
|
||||
int wanted_pin = mp_obj_get_int(args[0]);
|
||||
pyb_pin_obj_t *pin = NULL;
|
||||
for (int i = 0; i < MP_ARRAY_SIZE(pyb_pin_obj); i++) {
|
||||
if (pyb_pin_obj[i].pin_id == wanted_pin) {
|
||||
pin = (pyb_pin_obj_t*)&pyb_pin_obj[i];
|
||||
break;
|
||||
}
|
||||
if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) {
|
||||
pin = (pyb_pin_obj_t*)&pyb_pin_obj[wanted_pin];
|
||||
}
|
||||
if (pin == NULL) {
|
||||
if (pin == NULL || pin->base.type == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
|
||||
}
|
||||
|
||||
@@ -263,20 +308,57 @@ STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high);
|
||||
|
||||
// pin.irq(*, trigger, handler=None)
|
||||
STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_trigger, ARG_handler };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
if (self->phys_port >= 16) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities"));
|
||||
}
|
||||
|
||||
if (args[ARG_trigger].u_int != 0) {
|
||||
// configure irq
|
||||
mp_obj_t handler = args[ARG_handler].u_obj;
|
||||
if (handler == mp_const_none) {
|
||||
handler = MP_OBJ_NULL;
|
||||
}
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler;
|
||||
SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int);
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port);
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
}
|
||||
|
||||
// return the irq object
|
||||
return MP_OBJ_FROM_PTR(&pin_irq_obj[self->phys_port]);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_irq_obj, 1, pyb_pin_irq);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = {
|
||||
// instance methods
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_pin_init_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pyb_pin_value_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pyb_pin_low_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pyb_pin_high_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_pin_irq_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OPEN_DRAIN) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_NONE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_UP) },
|
||||
//{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_DOWN) },
|
||||
|
||||
// IRG triggers, can be or'd together
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_POSEDGE) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_NEGEDGE) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_pin_locals_dict, pyb_pin_locals_dict_table);
|
||||
@@ -289,3 +371,59 @@ const mp_obj_type_t pyb_pin_type = {
|
||||
.call = pyb_pin_call,
|
||||
.locals_dict = (mp_obj_t)&pyb_pin_locals_dict,
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
// Pin IRQ object
|
||||
|
||||
STATIC const mp_obj_type_t pin_irq_type;
|
||||
|
||||
STATIC const pin_irq_obj_t pin_irq_obj[16] = {
|
||||
{{&pin_irq_type}, 0},
|
||||
{{&pin_irq_type}, 1},
|
||||
{{&pin_irq_type}, 2},
|
||||
{{&pin_irq_type}, 3},
|
||||
{{&pin_irq_type}, 4},
|
||||
{{&pin_irq_type}, 5},
|
||||
{{&pin_irq_type}, 6},
|
||||
{{&pin_irq_type}, 7},
|
||||
{{&pin_irq_type}, 8},
|
||||
{{&pin_irq_type}, 9},
|
||||
{{&pin_irq_type}, 10},
|
||||
{{&pin_irq_type}, 11},
|
||||
{{&pin_irq_type}, 12},
|
||||
{{&pin_irq_type}, 13},
|
||||
{{&pin_irq_type}, 14},
|
||||
{{&pin_irq_type}, 15},
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
pin_irq_obj_t *self = self_in;
|
||||
mp_arg_check_num(n_args, n_kw, 0, 0, false);
|
||||
pin_intr_handler(1 << self->phys_port);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pin_irq_trigger(size_t n_args, const mp_obj_t *args) {
|
||||
pin_irq_obj_t *self = args[0];
|
||||
uint32_t orig_trig = GET_TRIGGER(self->phys_port);
|
||||
if (n_args == 2) {
|
||||
// set trigger
|
||||
SET_TRIGGER(self->phys_port, mp_obj_get_int(args[1]));
|
||||
}
|
||||
// return original trigger value
|
||||
return MP_OBJ_NEW_SMALL_INT(orig_trig);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_irq_trigger_obj, 1, 2, pin_irq_trigger);
|
||||
|
||||
STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&pin_irq_trigger_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t pin_irq_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_IRQ,
|
||||
.call = pin_irq_call,
|
||||
.locals_dict = (mp_obj_dict_t*)&pin_irq_locals_dict,
|
||||
};
|
||||
|
||||
@@ -47,7 +47,7 @@ STATIC bool pwm_inited = false;
|
||||
|
||||
STATIC void pyb_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "PWM(%u", self->pin->pin_id);
|
||||
mp_printf(print, "PWM(%u", self->pin->phys_port);
|
||||
if (self->active) {
|
||||
mp_printf(print, ", freq=%u, duty=%u",
|
||||
pwm_get_freq(self->channel), pwm_get_duty(self->channel));
|
||||
|
||||
@@ -49,6 +49,10 @@ typedef struct _pyb_rtc_obj_t {
|
||||
// singleton RTC object
|
||||
STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
|
||||
|
||||
// ALARM0 state
|
||||
uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants
|
||||
uint64_t pyb_rtc_alarm0_expiry; // in microseconds
|
||||
|
||||
void mp_hal_rtc_init(void) {
|
||||
uint32_t magic;
|
||||
|
||||
@@ -61,6 +65,10 @@ void mp_hal_rtc_init(void) {
|
||||
system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal));
|
||||
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
|
||||
}
|
||||
|
||||
// reset ALARM0 state
|
||||
pyb_rtc_alarm0_wake = 0;
|
||||
pyb_rtc_alarm0_expiry = 0;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
@@ -177,9 +185,49 @@ STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_memory_obj, 1, 2, pyb_rtc_memory);
|
||||
|
||||
STATIC mp_obj_t pyb_rtc_alarm(mp_obj_t self_in, mp_obj_t alarm_id, mp_obj_t time_in) {
|
||||
(void)self_in; // unused
|
||||
|
||||
// check we want alarm0
|
||||
if (mp_obj_get_int(alarm_id) != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm"));
|
||||
}
|
||||
|
||||
// set expiry time (in microseconds)
|
||||
pyb_rtc_alarm0_expiry = pyb_rtc_get_us_since_2000() + mp_obj_get_int(time_in) * 1000;
|
||||
|
||||
return mp_const_none;
|
||||
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_rtc_alarm_obj, pyb_rtc_alarm);
|
||||
|
||||
STATIC mp_obj_t pyb_rtc_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_trigger, ARG_wake };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_wake, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// check we want alarm0
|
||||
if (args[ARG_trigger].u_int != 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid alarm"));
|
||||
}
|
||||
|
||||
// set the wake value
|
||||
pyb_rtc_alarm0_wake = args[ARG_wake].u_int;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq);
|
||||
|
||||
STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_memory), (mp_obj_t)&pyb_rtc_memory_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_alarm), (mp_obj_t)&pyb_rtc_alarm_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_rtc_irq_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALARM0), MP_OBJ_NEW_SMALL_INT(0) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
extern uint32_t pyb_rtc_alarm0_wake;
|
||||
extern uint64_t pyb_rtc_alarm0_expiry;
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus);
|
||||
|
||||
uint64_t pyb_rtc_get_us_since_2000();
|
||||
|
||||
@@ -35,16 +35,16 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "modpyb.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
typedef struct _pyb_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t baudrate;
|
||||
uint8_t polarity;
|
||||
uint8_t phase;
|
||||
pyb_pin_obj_t *sck;
|
||||
pyb_pin_obj_t *mosi;
|
||||
pyb_pin_obj_t *miso;
|
||||
mp_hal_pin_obj_t sck;
|
||||
mp_hal_pin_obj_t mosi;
|
||||
mp_hal_pin_obj_t miso;
|
||||
} pyb_spi_obj_t;
|
||||
|
||||
STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8_t *src_buf, size_t dest_len, uint8_t *dest_buf) {
|
||||
@@ -59,20 +59,20 @@ STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8
|
||||
}
|
||||
uint8_t data_in = 0;
|
||||
for (int j = 0; j < 8; ++j, data_out <<= 1) {
|
||||
pin_set(self->mosi->phys_port, (data_out >> 7) & 1);
|
||||
mp_hal_pin_write(self->mosi, (data_out >> 7) & 1);
|
||||
if (self->phase == 0) {
|
||||
ets_delay_us(delay_half);
|
||||
pin_set(self->sck->phys_port, 1 - self->polarity);
|
||||
mp_hal_pin_write(self->sck, 1 - self->polarity);
|
||||
} else {
|
||||
pin_set(self->sck->phys_port, 1 - self->polarity);
|
||||
mp_hal_pin_write(self->sck, 1 - self->polarity);
|
||||
ets_delay_us(delay_half);
|
||||
}
|
||||
data_in = (data_in << 1) | pin_get(self->miso->phys_port);
|
||||
data_in = (data_in << 1) | mp_hal_pin_read(self->miso);
|
||||
if (self->phase == 0) {
|
||||
ets_delay_us(delay_half);
|
||||
pin_set(self->sck->phys_port, self->polarity);
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
} else {
|
||||
pin_set(self->sck->phys_port, self->polarity);
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
ets_delay_us(delay_half);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ STATIC void mp_hal_spi_transfer(pyb_spi_obj_t *self, size_t src_len, const uint8
|
||||
STATIC void pyb_spi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_spi_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "SPI(baudrate=%u, polarity=%u, phase=%u, sck=%u, mosi=%u, miso=%u)",
|
||||
self->baudrate, self->polarity, self->phase, self->sck->phys_port, self->mosi->phys_port, self->miso->phys_port);
|
||||
self->baudrate, self->polarity, self->phase, self->sck, self->mosi, self->miso);
|
||||
}
|
||||
|
||||
STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
@@ -116,13 +116,13 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
|
||||
self->phase = args[ARG_phase].u_int;
|
||||
}
|
||||
if (args[ARG_sck].u_obj != MP_OBJ_NULL) {
|
||||
self->sck = mp_obj_get_pin_obj(args[ARG_sck].u_obj);
|
||||
self->sck = mp_hal_get_pin_obj(args[ARG_sck].u_obj);
|
||||
}
|
||||
if (args[ARG_mosi].u_obj != MP_OBJ_NULL) {
|
||||
self->mosi = mp_obj_get_pin_obj(args[ARG_mosi].u_obj);
|
||||
self->mosi = mp_hal_get_pin_obj(args[ARG_mosi].u_obj);
|
||||
}
|
||||
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
|
||||
self->miso = mp_obj_get_pin_obj(args[ARG_miso].u_obj);
|
||||
self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,9 +134,9 @@ STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
||||
self->baudrate = 500000;
|
||||
self->polarity = 0;
|
||||
self->phase = 0;
|
||||
self->sck = NULL;
|
||||
self->mosi = NULL;
|
||||
self->miso = NULL;
|
||||
self->sck = 14;
|
||||
self->mosi = 13;
|
||||
self->miso = 12;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_spi_init_helper(self, n_args, args, &kw_args);
|
||||
|
||||
@@ -36,9 +36,14 @@
|
||||
#include "py/stream.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
// baudrate is currently fixed to this value
|
||||
#define UART_BAUDRATE (115200)
|
||||
|
||||
typedef struct _pyb_uart_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint8_t uart_id;
|
||||
uint16_t timeout; // timeout waiting for first char (in ms)
|
||||
uint16_t timeout_char; // timeout waiting between chars (in ms)
|
||||
} pyb_uart_obj_t;
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -46,24 +51,35 @@ typedef struct _pyb_uart_obj_t {
|
||||
|
||||
STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "UART(%u)", self->uart_id);
|
||||
mp_printf(print, "UART(%u, baudrate=%u, timeout=%u, timeout_char=%u)",
|
||||
self->uart_id, UART_BAUDRATE, self->timeout, self->timeout_char);
|
||||
}
|
||||
|
||||
STATIC void pyb_uart_init_helper(pyb_uart_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
/*
|
||||
enum { ARG_baudrate, ARG_bits, ARG_parity, ARG_stop };
|
||||
enum { ARG_timeout, ARG_timeout_char };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
|
||||
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
|
||||
{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
//{ MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 9600} },
|
||||
//{ MP_QSTR_bits, MP_ARG_INT, {.u_int = 8} },
|
||||
//{ MP_QSTR_parity, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
//{ MP_QSTR_stop, MP_ARG_INT, {.u_int = 1} },
|
||||
//{ MP_QSTR_tx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
//{ MP_QSTR_rx, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
*/
|
||||
// not implemented
|
||||
|
||||
// set timeout
|
||||
self->timeout = args[ARG_timeout].u_int;
|
||||
|
||||
// set timeout_char
|
||||
// make sure it is at least as long as a whole character (13 bits to be safe)
|
||||
self->timeout_char = args[ARG_timeout_char].u_int;
|
||||
uint32_t min_timeout_char = 13000 / UART_BAUDRATE + 1;
|
||||
if (self->timeout_char < min_timeout_char) {
|
||||
self->timeout_char = min_timeout_char;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
@@ -80,12 +96,10 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
|
||||
self->base.type = &pyb_uart_type;
|
||||
self->uart_id = uart_id;
|
||||
|
||||
if (n_args > 1 || n_kw > 0) {
|
||||
// init the peripheral
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
}
|
||||
// init the peripheral
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
pyb_uart_init_helper(self, n_args - 1, args + 1, &kw_args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
@@ -109,7 +123,32 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
|
||||
|
||||
STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
|
||||
mp_not_implemented("reading from UART");
|
||||
pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
if (self->uart_id == 1) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "UART(1) can't read"));
|
||||
}
|
||||
|
||||
// make sure we want at least 1 char
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// wait for first char to become available
|
||||
if (!uart_rx_wait(self->timeout * 1000)) {
|
||||
*errcode = EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
// read the data
|
||||
uint8_t *buf = buf_in;
|
||||
for (;;) {
|
||||
*buf++ = uart_rx_char();
|
||||
if (--size == 0 || !uart_rx_wait(self->timeout_char * 1000)) {
|
||||
// return number of bytes read
|
||||
return buf - (uint8_t*)buf_in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
#include "etshal.h"
|
||||
#include "esp_mphal.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
extern const mp_obj_type_t mp_fat_vfs_type;
|
||||
@@ -88,6 +88,11 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(os_listdir_obj, 0, 1, os_listdir);
|
||||
|
||||
STATIC mp_obj_t os_mkdir(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_mkdir, 1, &path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
|
||||
|
||||
STATIC mp_obj_t os_remove(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_remove, 1, &path_in);
|
||||
}
|
||||
@@ -105,16 +110,25 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
|
||||
|
||||
STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) {
|
||||
(void)obj_in;
|
||||
mp_hal_signal_dupterm_input();
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify);
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&os_dupterm_notify_obj) },
|
||||
#endif
|
||||
#if MICROPY_VFS_FAT
|
||||
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&os_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&os_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
#define MICROPY_MEM_STATS (0)
|
||||
#define MICROPY_DEBUG_PRINTERS (1)
|
||||
#define MICROPY_DEBUG_PRINTER_DEST mp_debug_print
|
||||
#define MICROPY_ENABLE_GC (1)
|
||||
#define MICROPY_STACK_CHECK (1)
|
||||
#define MICROPY_REPL_EVENT_DRIVEN (0)
|
||||
@@ -50,6 +51,11 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
#define MICROPY_PY_LWIP (1)
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
#define MICROPY_PY_MACHINE_I2C (1)
|
||||
#define MICROPY_PY_WEBSOCKET (1)
|
||||
#define MICROPY_PY_WEBREPL (1)
|
||||
#define MICROPY_PY_WEBREPL_DELAY (20)
|
||||
#define MICROPY_PY_FRAMEBUF (1)
|
||||
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
|
||||
#define MICROPY_PY_OS_DUPTERM (1)
|
||||
#define MICROPY_CPYTHON_COMPAT (1)
|
||||
@@ -57,7 +63,7 @@
|
||||
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
|
||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||
#define MICROPY_MODULE_FROZEN (1)
|
||||
#define MICROPY_MODULE_FROZEN_STR (1)
|
||||
#define MICROPY_MODULE_FROZEN_LEXER mp_lexer_new_from_str32
|
||||
|
||||
#define MICROPY_FATFS_ENABLE_LFN (1)
|
||||
@@ -100,12 +106,12 @@ typedef uint32_t sys_prot_t; // for modlwip
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
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 }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||
|
||||
// extra built in modules to add to the list of known ones
|
||||
extern const struct _mp_obj_module_t pyb_module;
|
||||
extern const struct _mp_obj_module_t esp_module;
|
||||
extern const struct _mp_obj_module_t network_module;
|
||||
extern const struct _mp_obj_module_t utime_module;
|
||||
@@ -115,7 +121,6 @@ extern const struct _mp_obj_module_t mp_module_machine;
|
||||
extern const struct _mp_obj_module_t onewire_module;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_lwip), (mp_obj_t)&mp_module_lwip }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&mp_module_lwip }, \
|
||||
@@ -137,6 +142,7 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
const char *readline_hist[8]; \
|
||||
vstr_t *repl_line; \
|
||||
mp_obj_t mp_kbd_exception; \
|
||||
mp_obj_t pin_irq_handler[16]; \
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
#include <alloca.h>
|
||||
@@ -146,6 +152,6 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
#define MICROPY_MPHALPORT_H "esp_mphal.h"
|
||||
#define MICROPY_HW_BOARD_NAME "ESP module"
|
||||
#define MICROPY_HW_MCU_NAME "ESP8266"
|
||||
#define MICROPY_PY_SYS_PLATFORM "ESP8266"
|
||||
#define MICROPY_PY_SYS_PLATFORM "esp8266"
|
||||
|
||||
#define _assert(expr) ((expr) ? (void)0 : __assert_func(__FILE__, __LINE__, __func__, #expr))
|
||||
|
||||
@@ -24,198 +24,8 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// qstrs specific to this port
|
||||
// qstrs specific to this port, only needed if they aren't auto-generated
|
||||
|
||||
Q(help)
|
||||
|
||||
// pyb module
|
||||
Q(pyb)
|
||||
Q(info)
|
||||
Q(freq)
|
||||
Q(millis)
|
||||
Q(elapsed_millis)
|
||||
Q(micros)
|
||||
Q(elapsed_micros)
|
||||
Q(delay)
|
||||
Q(udelay)
|
||||
Q(sync)
|
||||
Q(unique_id)
|
||||
|
||||
// uos module
|
||||
Q(uos)
|
||||
Q(os)
|
||||
Q(uname)
|
||||
Q(sysname)
|
||||
Q(nodename)
|
||||
Q(release)
|
||||
Q(version)
|
||||
Q(machine)
|
||||
|
||||
Q(esp)
|
||||
Q(socket)
|
||||
Q(usocket)
|
||||
Q(connect)
|
||||
Q(disconnect)
|
||||
Q(wifi_mode)
|
||||
Q(phy_mode)
|
||||
Q(osdebug)
|
||||
Q(sleep_type)
|
||||
Q(deepsleep)
|
||||
Q(adc)
|
||||
Q(vdd33)
|
||||
Q(chip_id)
|
||||
Q(flash_id)
|
||||
Q(flash_read)
|
||||
Q(flash_write)
|
||||
Q(flash_erase)
|
||||
Q(sdk_version)
|
||||
Q(freemem)
|
||||
Q(meminfo)
|
||||
Q(getaddrinfo)
|
||||
Q(send)
|
||||
Q(sendto)
|
||||
Q(recv)
|
||||
Q(recvfrom)
|
||||
Q(listen)
|
||||
Q(accept)
|
||||
Q(bind)
|
||||
Q(settimeout)
|
||||
Q(setblocking)
|
||||
Q(setsockopt)
|
||||
Q(close)
|
||||
Q(protocol)
|
||||
Q(getpeername)
|
||||
Q(onconnect)
|
||||
Q(onrecv)
|
||||
Q(onsent)
|
||||
Q(ondisconnect)
|
||||
Q(neopixel_write)
|
||||
Q(MODE_11B)
|
||||
Q(MODE_11G)
|
||||
Q(MODE_11N)
|
||||
Q(SLEEP_NONE)
|
||||
Q(SLEEP_LIGHT)
|
||||
Q(SLEEP_MODEM)
|
||||
Q(STA_MODE)
|
||||
Q(AP_MODE)
|
||||
Q(STA_AP_MODE)
|
||||
|
||||
// network module
|
||||
Q(network)
|
||||
Q(WLAN)
|
||||
Q(active)
|
||||
Q(scan)
|
||||
Q(status)
|
||||
Q(isconnected)
|
||||
Q(mac)
|
||||
Q(config)
|
||||
Q(ifconfig)
|
||||
Q(STA_IF)
|
||||
Q(AP_IF)
|
||||
Q(STAT_IDLE)
|
||||
Q(STAT_CONNECTING)
|
||||
Q(STAT_WRONG_PASSWORD)
|
||||
Q(STAT_NO_AP_FOUND)
|
||||
Q(STAT_CONNECT_FAIL)
|
||||
Q(STAT_GOT_IP)
|
||||
// config keys
|
||||
Q(essid)
|
||||
|
||||
// Pin class
|
||||
Q(Pin)
|
||||
Q(init)
|
||||
Q(mode)
|
||||
Q(pull)
|
||||
Q(value)
|
||||
Q(low)
|
||||
Q(high)
|
||||
Q(IN)
|
||||
Q(OUT)
|
||||
Q(OPEN_DRAIN)
|
||||
Q(PULL_NONE)
|
||||
Q(PULL_UP)
|
||||
Q(PULL_DOWN)
|
||||
|
||||
// PWM class
|
||||
Q(PWM)
|
||||
Q(init)
|
||||
Q(deinit)
|
||||
Q(freq)
|
||||
Q(duty)
|
||||
|
||||
// RTC
|
||||
Q(RTC)
|
||||
Q(datetime)
|
||||
Q(memory)
|
||||
|
||||
// ADC
|
||||
Q(ADC)
|
||||
Q(read)
|
||||
|
||||
// UART
|
||||
Q(UART)
|
||||
Q(init)
|
||||
|
||||
// I2C
|
||||
Q(I2C)
|
||||
Q(init)
|
||||
Q(scl)
|
||||
Q(sda)
|
||||
Q(freq)
|
||||
Q(readfrom)
|
||||
Q(writeto)
|
||||
Q(stop)
|
||||
Q(buf)
|
||||
Q(addr)
|
||||
Q(n)
|
||||
|
||||
// SPI
|
||||
Q(SPI)
|
||||
Q(init)
|
||||
Q(baudrate)
|
||||
Q(phase)
|
||||
Q(polarity)
|
||||
Q(sck)
|
||||
Q(mosi)
|
||||
Q(miso)
|
||||
Q(read)
|
||||
Q(readinto)
|
||||
Q(write)
|
||||
Q(write_readinto)
|
||||
|
||||
// utime
|
||||
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)
|
||||
Q(time)
|
||||
|
||||
// machine
|
||||
Q(reset)
|
||||
Q(Timer)
|
||||
Q(callback)
|
||||
Q(deinit)
|
||||
Q(init)
|
||||
Q(mode)
|
||||
Q(period)
|
||||
Q(ONE_SHOT)
|
||||
Q(PERIODIC)
|
||||
|
||||
// onewire
|
||||
Q(_onewire)
|
||||
Q(onewire)
|
||||
Q(timings)
|
||||
Q(reset)
|
||||
Q(readbit)
|
||||
Q(readbyte)
|
||||
Q(writebit)
|
||||
Q(writebyte)
|
||||
Q(crc8)
|
||||
|
||||
Q(json)
|
||||
// Entries for sys.path
|
||||
Q(/)
|
||||
Q(/lib)
|
||||
|
||||
9
esp8266/scripts/_boot.py
Normal file
9
esp8266/scripts/_boot.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import uos
|
||||
from flashbdev import bdev
|
||||
|
||||
try:
|
||||
if bdev:
|
||||
vfs = uos.VfsFat(bdev, "")
|
||||
except OSError:
|
||||
import inisetup
|
||||
vfs = inisetup.setup()
|
||||
68
esp8266/scripts/flashbdev.py
Normal file
68
esp8266/scripts/flashbdev.py
Normal file
@@ -0,0 +1,68 @@
|
||||
import esp
|
||||
|
||||
class FlashBdev:
|
||||
|
||||
SEC_SIZE = 4096
|
||||
START_SEC = 0x89000 // SEC_SIZE
|
||||
NUM_BLK = 0x73
|
||||
|
||||
def __init__(self, blocks=NUM_BLK):
|
||||
self.blocks = blocks
|
||||
|
||||
def readblocks(self, n, buf):
|
||||
#print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
|
||||
esp.flash_read((n + self.START_SEC) * self.SEC_SIZE, buf)
|
||||
|
||||
def writeblocks(self, n, buf):
|
||||
#print("writeblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
|
||||
#assert len(buf) <= self.SEC_SIZE, len(buf)
|
||||
esp.flash_erase(n + self.START_SEC)
|
||||
esp.flash_write((n + self.START_SEC) * self.SEC_SIZE, buf)
|
||||
|
||||
def ioctl(self, op, arg):
|
||||
#print("ioctl(%d, %r)" % (op, arg))
|
||||
if op == 4: # BP_IOCTL_SEC_COUNT
|
||||
return self.blocks
|
||||
if op == 5: # BP_IOCTL_SEC_SIZE
|
||||
return self.SEC_SIZE
|
||||
|
||||
def set_bl_flash_size(real_size):
|
||||
if real_size == 256*1024:
|
||||
code = 1
|
||||
elif real_size == 512*1024:
|
||||
code = 0
|
||||
elif real_size == 1024*1024:
|
||||
code = 2
|
||||
elif real_size == 2048*1024:
|
||||
code = 3
|
||||
elif real_size == 4096*1024:
|
||||
code = 4
|
||||
else:
|
||||
code = 2
|
||||
buf = bytearray(4096)
|
||||
esp.flash_read(0, buf)
|
||||
buf[3] = (buf[3] & 0xf) | (code << 4)
|
||||
esp.flash_erase(0)
|
||||
esp.flash_write(0, buf)
|
||||
|
||||
# If bootloader size ID doesn't correspond to real Flash size,
|
||||
# fix bootloader value and reboot.
|
||||
size = esp.flash_id() >> 16
|
||||
# Check that it looks like realistic power of 2 for flash sizes
|
||||
# commonly used with esp8266
|
||||
if 22 >= size >= 18:
|
||||
size = 1 << size
|
||||
if size != esp.flash_size():
|
||||
import machine
|
||||
import time
|
||||
print("Bootloader Flash size appear to have been set incorrectly, trying to fix")
|
||||
set_bl_flash_size(size)
|
||||
machine.reset()
|
||||
while 1: time.sleep(1)
|
||||
|
||||
size = esp.flash_size()
|
||||
if size < 1024*1024:
|
||||
bdev = None
|
||||
else:
|
||||
# 16K at the flash end is reserved for SDK params storage
|
||||
bdev = FlashBdev((size - 16384) // FlashBdev.SEC_SIZE - FlashBdev.START_SEC)
|
||||
46
esp8266/scripts/inisetup.py
Normal file
46
esp8266/scripts/inisetup.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import uos
|
||||
import network
|
||||
from flashbdev import bdev
|
||||
|
||||
def wifi():
|
||||
import ubinascii
|
||||
ap_if = network.WLAN(network.AP_IF)
|
||||
essid = b"MicroPython-%s" % ubinascii.hexlify(ap_if.config("mac")[-3:])
|
||||
ap_if.config(essid=essid, authmode=network.AUTH_WPA_WPA2_PSK, password=b"micropythoN")
|
||||
|
||||
def check_bootsec():
|
||||
buf = bytearray(bdev.SEC_SIZE)
|
||||
bdev.readblocks(0, buf)
|
||||
empty = True
|
||||
for b in buf:
|
||||
if b != 0xff:
|
||||
empty = False
|
||||
break
|
||||
if empty:
|
||||
return True
|
||||
fs_corrupted()
|
||||
|
||||
def fs_corrupted():
|
||||
import time
|
||||
while 1:
|
||||
print("""\
|
||||
FAT filesystem appears to be corrupted. If you had important data there, you
|
||||
may want to make a flash snapshot to try to recover it. Otherwise, perform
|
||||
factory reprogramming of MicroPython firmware (completely erase flash, followed
|
||||
by firmware programming).
|
||||
""")
|
||||
time.sleep(3)
|
||||
|
||||
def setup():
|
||||
check_bootsec()
|
||||
print("Performing initial setup")
|
||||
wifi()
|
||||
uos.VfsFat.mkfs(bdev)
|
||||
vfs = uos.VfsFat(bdev, "")
|
||||
with open("/boot.py", "w") as f:
|
||||
f.write("""\
|
||||
# This file is executed on every boot (including wake-boot from deepsleep)
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
""")
|
||||
return vfs
|
||||
@@ -1 +0,0 @@
|
||||
# This script is run on boot
|
||||
24
esp8266/scripts/neopixel.py
Normal file
24
esp8266/scripts/neopixel.py
Normal file
@@ -0,0 +1,24 @@
|
||||
# NeoPixel driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
from esp import neopixel_write
|
||||
|
||||
class NeoPixel:
|
||||
def __init__(self, pin, n):
|
||||
self.pin = pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 3)
|
||||
self.pin.init(pin.OUT, pin.PULL_NONE)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b = val
|
||||
self.buf[index * 3] = g
|
||||
self.buf[index * 3 + 1] = r
|
||||
self.buf[index * 3 + 2] = b
|
||||
|
||||
def __getitem__(self, index):
|
||||
i = index * 3
|
||||
return self.buf[i + 1], self.buf[i], self.buf[i + 2]
|
||||
|
||||
def write(self):
|
||||
neopixel_write(self.pin, self.buf, True)
|
||||
34
esp8266/scripts/ntptime.py
Normal file
34
esp8266/scripts/ntptime.py
Normal file
@@ -0,0 +1,34 @@
|
||||
try:
|
||||
import usocket as socket
|
||||
except:
|
||||
import socket
|
||||
try:
|
||||
import ustruct as struct
|
||||
except:
|
||||
import struct
|
||||
|
||||
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
|
||||
NTP_DELTA = 3155673600
|
||||
|
||||
def time():
|
||||
NTP_QUERY = bytearray(48)
|
||||
NTP_QUERY[0] = 0x1b
|
||||
addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-1]
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.settimeout(1)
|
||||
res = s.sendto(NTP_QUERY, addr)
|
||||
msg = s.recv(48)
|
||||
s.close()
|
||||
val = struct.unpack("!I", msg[40:44])[0]
|
||||
return val - NTP_DELTA
|
||||
|
||||
# There's currently no timezone support in MicroPython, so
|
||||
# utime.localtime() will return UTC time (as if it was .gmtime())
|
||||
def settime():
|
||||
t = time()
|
||||
import machine
|
||||
import utime
|
||||
tm = utime.localtime(t)
|
||||
tm = tm[0:3] + (0,) + tm[3:6] + (0,)
|
||||
machine.RTC().datetime(tm)
|
||||
print(utime.localtime())
|
||||
@@ -1,12 +1,15 @@
|
||||
import time
|
||||
import pyb
|
||||
# 1-Wire driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
import _onewire as _ow
|
||||
|
||||
class OneWireError(Exception):
|
||||
pass
|
||||
|
||||
class OneWire:
|
||||
CMD_SEARCHROM = const(0xf0)
|
||||
CMD_READROM = const(0x33)
|
||||
CMD_MATCHROM = const(0x55)
|
||||
CMD_SKIPROM = const(0xcc)
|
||||
SEARCH_ROM = const(0xf0)
|
||||
MATCH_ROM = const(0x55)
|
||||
SKIP_ROM = const(0xcc)
|
||||
|
||||
def __init__(self, pin):
|
||||
self.pin = pin
|
||||
@@ -15,32 +18,32 @@ class OneWire:
|
||||
def reset(self):
|
||||
return _ow.reset(self.pin)
|
||||
|
||||
def read_bit(self):
|
||||
def readbit(self):
|
||||
return _ow.readbit(self.pin)
|
||||
|
||||
def read_byte(self):
|
||||
def readbyte(self):
|
||||
return _ow.readbyte(self.pin)
|
||||
|
||||
def read_bytes(self, count):
|
||||
def read(self, count):
|
||||
buf = bytearray(count)
|
||||
for i in range(count):
|
||||
buf[i] = _ow.readbyte(self.pin)
|
||||
return buf
|
||||
|
||||
def write_bit(self, value):
|
||||
def writebit(self, value):
|
||||
return _ow.writebit(self.pin, value)
|
||||
|
||||
def write_byte(self, value):
|
||||
def writebyte(self, value):
|
||||
return _ow.writebyte(self.pin, value)
|
||||
|
||||
def write_bytes(self, buf):
|
||||
def write(self, buf):
|
||||
for b in buf:
|
||||
_ow.writebyte(self.pin, b)
|
||||
|
||||
def select_rom(self, rom):
|
||||
self.reset()
|
||||
self.write_byte(CMD_MATCHROM)
|
||||
self.write_bytes(rom)
|
||||
self.writebyte(MATCH_ROM)
|
||||
self.write(rom)
|
||||
|
||||
def scan(self):
|
||||
devices = []
|
||||
@@ -57,7 +60,7 @@ class OneWire:
|
||||
def _search_rom(self, l_rom, diff):
|
||||
if not self.reset():
|
||||
return None, 0
|
||||
self.write_byte(CMD_SEARCHROM)
|
||||
self.writebyte(SEARCH_ROM)
|
||||
if not l_rom:
|
||||
l_rom = bytearray(8)
|
||||
rom = bytearray(8)
|
||||
@@ -66,8 +69,8 @@ class OneWire:
|
||||
for byte in range(8):
|
||||
r_b = 0
|
||||
for bit in range(8):
|
||||
b = self.read_bit()
|
||||
if self.read_bit():
|
||||
b = self.readbit()
|
||||
if self.readbit():
|
||||
if b: # there are no devices or there is an error on the bus
|
||||
return None, 0
|
||||
else:
|
||||
@@ -75,7 +78,7 @@ class OneWire:
|
||||
if diff > i or ((l_rom[byte] & (1 << bit)) and diff != i):
|
||||
b = 1
|
||||
next_diff = i
|
||||
self.write_bit(b)
|
||||
self.writebit(b)
|
||||
if b:
|
||||
r_b |= 1 << bit
|
||||
i -= 1
|
||||
@@ -86,62 +89,39 @@ class OneWire:
|
||||
return _ow.crc8(data)
|
||||
|
||||
class DS18B20:
|
||||
THERM_CMD_CONVERTTEMP = const(0x44)
|
||||
THERM_CMD_RSCRATCHPAD = const(0xbe)
|
||||
CONVERT = const(0x44)
|
||||
RD_SCRATCH = const(0xbe)
|
||||
WR_SCRATCH = const(0x4e)
|
||||
|
||||
def __init__(self, onewire):
|
||||
self.ow = onewire
|
||||
self.roms = []
|
||||
|
||||
def scan(self):
|
||||
self.roms = []
|
||||
for rom in self.ow.scan():
|
||||
if rom[0] == 0x28:
|
||||
self.roms += [rom]
|
||||
return self.roms
|
||||
return [rom for rom in self.ow.scan() if rom[0] == 0x28]
|
||||
|
||||
def start_measure(self):
|
||||
def convert_temp(self):
|
||||
if not self.ow.reset():
|
||||
return False
|
||||
self.ow.write_byte(CMD_SKIPROM)
|
||||
self.ow.write_byte(THERM_CMD_CONVERTTEMP)
|
||||
return True
|
||||
raise OneWireError
|
||||
self.ow.writebyte(SKIP_ROM)
|
||||
self.ow.writebyte(CONVERT)
|
||||
|
||||
def get_temp(self, rom):
|
||||
def read_scratch(self, rom):
|
||||
if not self.ow.reset():
|
||||
return None
|
||||
|
||||
raise OneWireError
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.write_byte(THERM_CMD_RSCRATCHPAD)
|
||||
|
||||
buf = self.ow.read_bytes(9)
|
||||
self.ow.writebyte(RD_SCRATCH)
|
||||
buf = self.ow.read(9)
|
||||
if self.ow.crc8(buf):
|
||||
return None
|
||||
raise OneWireError
|
||||
return buf
|
||||
|
||||
return self._convert_temp(buf)
|
||||
def write_scratch(self, rom, buf):
|
||||
if not self.ow.reset():
|
||||
raise OneWireError
|
||||
self.ow.select_rom(rom)
|
||||
self.ow.writebyte(WR_SCRATCH)
|
||||
self.ow.write(buf)
|
||||
|
||||
def _convert_temp(self, data):
|
||||
temp_lsb = data[0]
|
||||
temp_msb = data[1]
|
||||
return (temp_msb << 8 | temp_lsb) / 16
|
||||
|
||||
# connect 1-wire temp sensors to GPIO12 for this test
|
||||
def test():
|
||||
dat = pyb.Pin(12)
|
||||
ow = OneWire(dat)
|
||||
|
||||
ds = DS18B20(ow)
|
||||
roms = ow.scan()
|
||||
print('found devices:', roms)
|
||||
|
||||
for i in range(4):
|
||||
print('temperatures:', end=' ')
|
||||
ds.start_measure()
|
||||
time.sleep_ms(750)
|
||||
for rom in roms:
|
||||
print(ds.get_temp(rom), end=' ')
|
||||
print()
|
||||
|
||||
#pyb.freq(80000000)
|
||||
#pyb.freq(160000000)
|
||||
test()
|
||||
def read_temp(self, rom):
|
||||
buf = self.read_scratch(rom)
|
||||
return (buf[1] << 8 | buf[0]) / 16
|
||||
19
esp8266/scripts/port_diag.py
Normal file
19
esp8266/scripts/port_diag.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import esp
|
||||
import uctypes
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
ROM = uctypes.bytearray_at(0x40200000, 16)
|
||||
fid = esp.flash_id()
|
||||
|
||||
print("Flash ID: %x (Vendor: %x Device: %x)" % (fid, fid & 0xff, fid & 0xff00 | fid >> 16))
|
||||
|
||||
print("Flash bootloader data:")
|
||||
SZ_MAP = {0: "512KB", 1: "256KB", 2: "1MB", 3: "2MB", 4: "4MB"}
|
||||
FREQ_MAP = {0: "40MHZ", 1: "26MHZ", 2: "20MHz", 0xf: "80MHz"}
|
||||
print("Byte @2: %02x" % ROM[2])
|
||||
print("Byte @3: %02x (Flash size: %s Flash freq: %s)" % (ROM[3], SZ_MAP.get(ROM[3] >> 4, "?"), FREQ_MAP.get(ROM[3] & 0xf)))
|
||||
|
||||
|
||||
main()
|
||||
62
esp8266/scripts/webrepl.py
Normal file
62
esp8266/scripts/webrepl.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# This module should be imported from REPL, not run from command line.
|
||||
import socket
|
||||
import uos
|
||||
import network
|
||||
import websocket
|
||||
import websocket_helper
|
||||
import _webrepl
|
||||
|
||||
listen_s = None
|
||||
client_s = None
|
||||
|
||||
def setup_conn(port, accept_handler):
|
||||
global listen_s, client_s
|
||||
listen_s = socket.socket()
|
||||
listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
ai = socket.getaddrinfo("0.0.0.0", port)
|
||||
addr = ai[0][4]
|
||||
|
||||
listen_s.bind(addr)
|
||||
listen_s.listen(1)
|
||||
listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
|
||||
for i in (network.AP_IF, network.STA_IF):
|
||||
iface = network.WLAN(i)
|
||||
if iface.active():
|
||||
print("WebREPL daemon started on ws://%s:%d" % (iface.ifconfig()[0], port))
|
||||
|
||||
|
||||
def accept_conn(listen_sock):
|
||||
global client_s
|
||||
cl, remote_addr = listen_sock.accept()
|
||||
print("\nWebREPL connection from:", remote_addr)
|
||||
client_s = cl
|
||||
websocket_helper.server_handshake(cl)
|
||||
ws = websocket.websocket(cl, True)
|
||||
ws = _webrepl._webrepl(ws)
|
||||
cl.setblocking(False)
|
||||
# notify REPL on socket incoming data
|
||||
cl.setsockopt(socket.SOL_SOCKET, 20, uos.dupterm_notify)
|
||||
uos.dupterm(ws)
|
||||
|
||||
|
||||
def stop():
|
||||
global listen_s, client_s
|
||||
uos.dupterm(None)
|
||||
if client_s:
|
||||
client_s.close()
|
||||
if listen_s:
|
||||
listen_s.close()
|
||||
|
||||
|
||||
def start(port=8266):
|
||||
stop()
|
||||
try:
|
||||
import port_config
|
||||
_webrepl.password(port_config.WEBREPL_PASS)
|
||||
setup_conn(port, accept_conn)
|
||||
print("Started webrepl in normal mode")
|
||||
except:
|
||||
import webrepl_setup
|
||||
setup_conn(port, webrepl_setup.handle_conn)
|
||||
print("Started webrepl in setup mode")
|
||||
80
esp8266/scripts/webrepl_setup.py
Normal file
80
esp8266/scripts/webrepl_setup.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import sys
|
||||
import socket
|
||||
import time
|
||||
|
||||
from websocket import *
|
||||
import websocket_helper
|
||||
|
||||
|
||||
def setup_server():
|
||||
s = socket.socket()
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8266)
|
||||
addr = ai[0][4]
|
||||
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
return s
|
||||
|
||||
def getpass(stream, prompt):
|
||||
stream.write(prompt)
|
||||
passwd = b""
|
||||
while 1:
|
||||
c = stream.read(1)
|
||||
if c in (b"\r", b"\n"):
|
||||
stream.write("\r\n")
|
||||
return passwd
|
||||
passwd += c
|
||||
# stream.write("*")
|
||||
|
||||
def handle_conn(listen_sock):
|
||||
cl, remote_addr = listen_sock.accept()
|
||||
|
||||
print("""
|
||||
|
||||
First-time WebREPL connection has been received. WebREPL initial setup
|
||||
will now start over this connection. During setup, UART REPL will be
|
||||
non-responsive. After setup finishes, the board will be rebooted. In
|
||||
case of error during setup, current session will continue.
|
||||
|
||||
If you receive this message unexpectedly, it may mean that your WebREPL
|
||||
connection is being hacked (power off board if unsure).
|
||||
""")
|
||||
|
||||
websocket_helper.server_handshake(cl)
|
||||
ws = websocket(cl)
|
||||
|
||||
ws.write("""\
|
||||
Welcome to MicroPython WebREPL!\r
|
||||
\r
|
||||
This is the first time you connect to WebREPL, so please set a password\r
|
||||
to use for the following WebREPL sessions. Once you enter the password\r
|
||||
twice, your board will reboot with WebREPL running in active mode. On\r
|
||||
some boards, you may need to press reset button or reconnect power.\r
|
||||
\r
|
||||
""")
|
||||
|
||||
while 1:
|
||||
passwd1 = getpass(ws, "New password: ")
|
||||
if len(passwd1) < 4:
|
||||
ws.write("Password too short\r\n")
|
||||
continue
|
||||
passwd2 = getpass(ws, "Confirm password: ")
|
||||
if passwd1 == passwd2:
|
||||
break
|
||||
ws.write("Passwords do not match\r\n")
|
||||
|
||||
with open("port_config.py", "w") as f:
|
||||
f.write("WEBREPL_PASS = %r\n" % passwd1.decode("ascii"))
|
||||
|
||||
ws.write("Password successfully set, restarting...\r\n")
|
||||
cl.close()
|
||||
time.sleep(2)
|
||||
import machine
|
||||
machine.reset()
|
||||
|
||||
|
||||
def test():
|
||||
s = setup_server()
|
||||
handle_conn(s)
|
||||
75
esp8266/scripts/websocket_helper.py
Normal file
75
esp8266/scripts/websocket_helper.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import sys
|
||||
try:
|
||||
import ubinascii as binascii
|
||||
except:
|
||||
import binascii
|
||||
try:
|
||||
import uhashlib as hashlib
|
||||
except:
|
||||
import hashlib
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
def server_handshake(sock):
|
||||
clr = sock.makefile("rwb", 0)
|
||||
l = clr.readline()
|
||||
#sys.stdout.write(repr(l))
|
||||
|
||||
webkey = None
|
||||
|
||||
while 1:
|
||||
l = clr.readline()
|
||||
if not l:
|
||||
raise OSError("EOF in headers")
|
||||
if l == b"\r\n":
|
||||
break
|
||||
# sys.stdout.write(l)
|
||||
h, v = [x.strip() for x in l.split(b":", 1)]
|
||||
if DEBUG:
|
||||
print((h, v))
|
||||
if h == b'Sec-WebSocket-Key':
|
||||
webkey = v
|
||||
|
||||
if not webkey:
|
||||
raise OSError("Not a websocket request")
|
||||
|
||||
if DEBUG:
|
||||
print("Sec-WebSocket-Key:", webkey, len(webkey))
|
||||
|
||||
respkey = webkey + b"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
|
||||
respkey = hashlib.sha1(respkey).digest()
|
||||
respkey = binascii.b2a_base64(respkey)[:-1]
|
||||
|
||||
resp = b"""\
|
||||
HTTP/1.1 101 Switching Protocols\r
|
||||
Upgrade: websocket\r
|
||||
Connection: Upgrade\r
|
||||
Sec-WebSocket-Accept: %s\r
|
||||
\r
|
||||
""" % respkey
|
||||
|
||||
if DEBUG:
|
||||
print(resp)
|
||||
sock.send(resp)
|
||||
|
||||
|
||||
# Very simplified client handshake, works for MicroPython's
|
||||
# websocket server implementation, but probably not for other
|
||||
# servers.
|
||||
def client_handshake(sock):
|
||||
cl = sock.makefile("rwb", 0)
|
||||
cl.write(b"""\
|
||||
GET / HTTP/1.1\r
|
||||
Host: echo.websocket.org\r
|
||||
Connection: Upgrade\r
|
||||
Upgrade: websocket\r
|
||||
Sec-WebSocket-Key: foo\r
|
||||
\r
|
||||
""")
|
||||
l = cl.readline()
|
||||
# print(l)
|
||||
while 1:
|
||||
l = cl.readline()
|
||||
if l == b"\r\n":
|
||||
break
|
||||
# sys.stdout.write(l)
|
||||
@@ -1,64 +0,0 @@
|
||||
import time
|
||||
import machine
|
||||
from esp import neopixel_write
|
||||
|
||||
class NeoPixel:
|
||||
def __init__(self, pin, n):
|
||||
self.pin = pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 3)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b = val
|
||||
self.buf[index * 3] = g
|
||||
self.buf[index * 3 + 1] = r
|
||||
self.buf[index * 3 + 2] = b
|
||||
|
||||
def __getitem__(self, index):
|
||||
i = index * 3
|
||||
return self.buf[i], self.buf[i + 1], self.buf[i + 2]
|
||||
|
||||
def write(self):
|
||||
neopixel_write(self.pin, self.buf, True)
|
||||
|
||||
def test():
|
||||
# put a neopixel strip on GPIO4
|
||||
p = machine.Pin(4, machine.Pin.OUT)
|
||||
np = NeoPixel(p, 8)
|
||||
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()
|
||||
|
||||
test()
|
||||
@@ -27,14 +27,6 @@ extern UartDevice UartDev;
|
||||
// the uart to which OS messages go; -1 to disable
|
||||
static int uart_os = UART_OS;
|
||||
|
||||
/* unused
|
||||
// circular buffer for RX buffering
|
||||
#define RX_BUF_SIZE (256)
|
||||
static uint16_t rx_buf_in;
|
||||
static uint16_t rx_buf_out;
|
||||
static uint8_t rx_buf[RX_BUF_SIZE];
|
||||
*/
|
||||
|
||||
#if MICROPY_REPL_EVENT_DRIVEN
|
||||
static os_event_t uart_evt_queue[16];
|
||||
#endif
|
||||
@@ -94,12 +86,6 @@ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) {
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
|
||||
// enable rx_interrupt
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA);
|
||||
|
||||
/* unused
|
||||
// init RX buffer
|
||||
rx_buf_in = 0;
|
||||
rx_buf_out = 0;
|
||||
*/
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
@@ -179,7 +165,6 @@ static void uart0_rx_intr_handler(void *para) {
|
||||
goto read_chars;
|
||||
} else if (UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) {
|
||||
read_chars:
|
||||
#if 1 //MICROPY_REPL_EVENT_DRIVEN is not available here
|
||||
ETS_UART_INTR_DISABLE();
|
||||
|
||||
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
|
||||
@@ -196,31 +181,28 @@ static void uart0_rx_intr_handler(void *para) {
|
||||
// Clear pending FIFO interrupts
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART_REPL), UART_RXFIFO_TOUT_INT_CLR | UART_RXFIFO_FULL_INT_ST);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
#else
|
||||
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
|
||||
uint8 RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xff;
|
||||
uint16_t rx_buf_in_next = (rx_buf_in + 1) % RX_BUF_SIZE;
|
||||
if (rx_buf_in_next != rx_buf_out) {
|
||||
rx_buf[rx_buf_in] = RcvChar;
|
||||
rx_buf_in = rx_buf_in_next;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* unused
|
||||
int uart0_rx(void) {
|
||||
if (rx_buf_out != rx_buf_in) {
|
||||
int chr = rx_buf[rx_buf_out];
|
||||
rx_buf_out = (rx_buf_out + 1) % RX_BUF_SIZE;
|
||||
return chr;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
// Waits at most timeout microseconds for at least 1 char to become ready for reading.
|
||||
// Returns true if something available, false if not.
|
||||
bool uart_rx_wait(uint32_t timeout_us) {
|
||||
uint32_t start = system_get_time();
|
||||
for (;;) {
|
||||
if (input_buf.iget != input_buf.iput) {
|
||||
return true; // have at least 1 char ready for reading
|
||||
}
|
||||
if (system_get_time() - start >= timeout_us) {
|
||||
return false; // timeout
|
||||
}
|
||||
ets_event_poll();
|
||||
}
|
||||
}
|
||||
|
||||
// Returns char from the input buffer, else -1 if buffer is empty.
|
||||
int uart_rx_char(void) {
|
||||
return ringbuf_get(&input_buf);
|
||||
}
|
||||
*/
|
||||
|
||||
int uart_rx_one_char(uint8 uart_no) {
|
||||
if (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
|
||||
|
||||
@@ -91,6 +91,8 @@ typedef struct {
|
||||
|
||||
void uart_init(UartBautRate uart0_br, UartBautRate uart1_br);
|
||||
int uart0_rx(void);
|
||||
bool uart_rx_wait(uint32_t timeout_us);
|
||||
int uart_rx_char(void);
|
||||
void uart_tx_one_char(uint8 uart, uint8 TxChar);
|
||||
void uart_flush(uint8 uart);
|
||||
void uart_os_config(int uart);
|
||||
|
||||
@@ -9,7 +9,7 @@ def main(use_stream=False):
|
||||
|
||||
ai = socket.getaddrinfo("google.com", 80)
|
||||
print("Address infos:", ai)
|
||||
addr = ai[0][4]
|
||||
addr = ai[0][-1]
|
||||
|
||||
print("Connect address:", addr)
|
||||
s.connect(addr)
|
||||
|
||||
@@ -13,7 +13,7 @@ def main(use_stream=True):
|
||||
|
||||
ai = _socket.getaddrinfo("google.com", 443)
|
||||
print("Address infos:", ai)
|
||||
addr = ai[0][4]
|
||||
addr = ai[0][-1]
|
||||
|
||||
print("Connect address:", addr)
|
||||
s.connect(addr)
|
||||
|
||||
@@ -16,7 +16,7 @@ def main(use_stream=False):
|
||||
# Binding to all interfaces - server will be accessible to other hosts!
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8080)
|
||||
print("Bind address info:", ai)
|
||||
addr = ai[0][4]
|
||||
addr = ai[0][-1]
|
||||
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(addr)
|
||||
|
||||
59
examples/network/http_server_ssl.py
Normal file
59
examples/network/http_server_ssl.py
Normal file
@@ -0,0 +1,59 @@
|
||||
try:
|
||||
import usocket as socket
|
||||
except:
|
||||
import socket
|
||||
import ussl as ssl
|
||||
|
||||
|
||||
CONTENT = b"""\
|
||||
HTTP/1.0 200 OK
|
||||
|
||||
Hello #%d from MicroPython!
|
||||
"""
|
||||
|
||||
def main(use_stream=True):
|
||||
s = socket.socket()
|
||||
|
||||
# Binding to all interfaces - server will be accessible to other hosts!
|
||||
ai = socket.getaddrinfo("0.0.0.0", 8443)
|
||||
print("Bind address info:", ai)
|
||||
addr = ai[0][-1]
|
||||
|
||||
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
s.bind(addr)
|
||||
s.listen(5)
|
||||
print("Listening, connect your browser to https://<this_host>:8443/")
|
||||
|
||||
counter = 0
|
||||
while True:
|
||||
res = s.accept()
|
||||
client_s = res[0]
|
||||
client_addr = res[1]
|
||||
print("Client address:", client_addr)
|
||||
print("Client socket:", client_s)
|
||||
client_s = ssl.wrap_socket(client_s, server_side=True)
|
||||
print(client_s)
|
||||
print("Request:")
|
||||
if use_stream:
|
||||
# Both CPython and MicroPython SSLSocket objects support read() and
|
||||
# write() methods.
|
||||
# Browsers are prone to terminate SSL connection abruptly if they
|
||||
# see unknown certificate, etc. We must continue in such case -
|
||||
# next request they issue will likely be more well-behaving and
|
||||
# will succeed.
|
||||
try:
|
||||
req = client_s.read(4096)
|
||||
print(req)
|
||||
if req:
|
||||
client_s.write(CONTENT % counter)
|
||||
except Exception as e:
|
||||
print("Exception serving request:", e)
|
||||
else:
|
||||
print(client_s.recv(4096))
|
||||
client_s.send(CONTENT % counter)
|
||||
client_s.close()
|
||||
counter += 1
|
||||
print()
|
||||
|
||||
|
||||
main()
|
||||
@@ -81,8 +81,7 @@ fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
}
|
||||
|
||||
// create new object
|
||||
fs_user_mount_t *vfs;
|
||||
MP_STATE_PORT(fs_user_mount)[i] = vfs = m_new_obj(fs_user_mount_t);
|
||||
fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t);
|
||||
vfs->str = mnt_str;
|
||||
vfs->len = mnt_len;
|
||||
vfs->flags = FSUSER_FREE_OBJ;
|
||||
@@ -108,6 +107,11 @@ fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
||||
vfs->writeblocks[0] = MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
// Register the vfs object so that it can be found by the FatFS driver using
|
||||
// ff_get_ldnumber. We don't register it any earlier than this point in case there
|
||||
// is an exception, in which case there would remain a partially mounted device.
|
||||
MP_STATE_PORT(fs_user_mount)[i] = vfs;
|
||||
|
||||
// mount the block device (if mkfs, only pre-mount)
|
||||
FRESULT res = f_mount(&vfs->fatfs, vfs->str, !mkfs);
|
||||
// check the result
|
||||
@@ -120,6 +124,7 @@ mkfs:
|
||||
res = f_mkfs(vfs->str, 1, 0);
|
||||
if (res != FR_OK) {
|
||||
mkfs_error:
|
||||
MP_STATE_PORT(fs_user_mount)[i] = NULL;
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't mkfs"));
|
||||
}
|
||||
if (mkfs) {
|
||||
@@ -132,6 +137,7 @@ mkfs_error:
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
MP_STATE_PORT(fs_user_mount)[i] = NULL;
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't mount"));
|
||||
}
|
||||
|
||||
|
||||
464
extmod/machine_i2c.c
Normal file
464
extmod/machine_i2c.c
Normal file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_I2C
|
||||
|
||||
typedef struct _machine_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
uint32_t us_delay;
|
||||
mp_hal_pin_obj_t scl;
|
||||
mp_hal_pin_obj_t sda;
|
||||
} machine_i2c_obj_t;
|
||||
|
||||
STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) {
|
||||
// We need to use an accurate delay to get acceptable I2C
|
||||
// speeds (eg 1us should be not much more than 1us).
|
||||
mp_hal_delay_us_fast(self->us_delay);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_low(self->scl);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_od_high(self->scl);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_low(self->sda);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_od_high(self->sda);
|
||||
}
|
||||
|
||||
STATIC int mp_hal_i2c_sda_read(machine_i2c_obj_t *self) {
|
||||
return mp_hal_pin_read(self->sda);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_start(machine_i2c_obj_t *self) {
|
||||
mp_hal_i2c_sda_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_sda_low(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_stop(machine_i2c_obj_t *self) {
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_sda_low(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_sda_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t freq) {
|
||||
self->us_delay = 500000 / freq;
|
||||
if (self->us_delay == 0) {
|
||||
self->us_delay = 1;
|
||||
}
|
||||
mp_hal_pin_config_od(self->scl);
|
||||
mp_hal_pin_config_od(self->sda);
|
||||
mp_hal_i2c_stop(self);
|
||||
}
|
||||
|
||||
STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
if ((val >> i) & 1) {
|
||||
mp_hal_i2c_sda_release(self);
|
||||
} else {
|
||||
mp_hal_i2c_sda_low(self);
|
||||
}
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
}
|
||||
|
||||
mp_hal_i2c_sda_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
|
||||
int ret = mp_hal_i2c_sda_read(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
|
||||
return !ret;
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
|
||||
mp_hal_i2c_start(self);
|
||||
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
|
||||
goto er;
|
||||
}
|
||||
while (len--) {
|
||||
if (!mp_hal_i2c_write_byte(self, *data++)) {
|
||||
goto er;
|
||||
}
|
||||
}
|
||||
mp_hal_i2c_stop(self);
|
||||
return;
|
||||
|
||||
er:
|
||||
mp_hal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
|
||||
uint8_t data = 0;
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
data = (data << 1) | mp_hal_i2c_sda_read(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
}
|
||||
*val = data;
|
||||
|
||||
// send ack/nack bit
|
||||
if (!nack) {
|
||||
mp_hal_i2c_sda_low(self);
|
||||
}
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_release(self);
|
||||
mp_hal_i2c_delay(self);
|
||||
mp_hal_i2c_scl_low(self);
|
||||
mp_hal_i2c_sda_release(self);
|
||||
|
||||
return 1; // success
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
|
||||
mp_hal_i2c_start(self);
|
||||
if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
|
||||
goto er;
|
||||
}
|
||||
while (len--) {
|
||||
if (!mp_hal_i2c_read_byte(self, data++, len == 0)) {
|
||||
goto er;
|
||||
}
|
||||
}
|
||||
mp_hal_i2c_stop(self);
|
||||
return;
|
||||
|
||||
er:
|
||||
mp_hal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, const uint8_t *src, size_t len) {
|
||||
// start the I2C transaction
|
||||
mp_hal_i2c_start(self);
|
||||
|
||||
// write the slave address and the memory address within the slave
|
||||
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
|
||||
goto er;
|
||||
}
|
||||
if (!mp_hal_i2c_write_byte(self, memaddr)) {
|
||||
goto er;
|
||||
}
|
||||
|
||||
// write the buffer to the I2C memory
|
||||
while (len--) {
|
||||
if (!mp_hal_i2c_write_byte(self, *src++)) {
|
||||
goto er;
|
||||
}
|
||||
}
|
||||
|
||||
// finish the I2C transaction
|
||||
mp_hal_i2c_stop(self);
|
||||
return;
|
||||
|
||||
er:
|
||||
mp_hal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, uint8_t *dest, size_t len) {
|
||||
// start the I2C transaction
|
||||
mp_hal_i2c_start(self);
|
||||
|
||||
// write the slave address and the memory address within the slave
|
||||
if (!mp_hal_i2c_write_byte(self, addr << 1)) {
|
||||
goto er;
|
||||
}
|
||||
if (!mp_hal_i2c_write_byte(self, memaddr)) {
|
||||
goto er;
|
||||
}
|
||||
|
||||
// i2c_read will do a repeated start, and then read the I2C memory
|
||||
mp_hal_i2c_read(self, addr, dest, len);
|
||||
return;
|
||||
|
||||
er:
|
||||
mp_hal_i2c_stop(self);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for I2C
|
||||
|
||||
STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_scl, ARG_sda, ARG_freq };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} },
|
||||
};
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
|
||||
self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
|
||||
mp_hal_i2c_init(self, args[ARG_freq].u_int);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true);
|
||||
machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t);
|
||||
self->base.type = &machine_i2c_type;
|
||||
mp_map_t kw_args;
|
||||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
|
||||
machine_i2c_obj_init_helper(self, n_args, args, &kw_args);
|
||||
return (mp_obj_t)self;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_i2c_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
|
||||
machine_i2c_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
// 7-bit addresses 0b0000xxx and 0b1111xxx are reserved
|
||||
for (int addr = 0x08; addr < 0x78; ++addr) {
|
||||
mp_hal_i2c_start(self);
|
||||
int ack = mp_hal_i2c_write_byte(self, (addr << 1) | 1);
|
||||
if (ack) {
|
||||
mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr));
|
||||
}
|
||||
mp_hal_i2c_stop(self);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_hal_i2c_start(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_hal_i2c_stop(self);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readinto(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// get the buffer to read into
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// do the read
|
||||
uint8_t *dest = bufinfo.buf;
|
||||
while (bufinfo.len--) {
|
||||
if (!mp_hal_i2c_read_byte(self, dest++, bufinfo.len == 0)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_readinto_obj, machine_i2c_readinto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// get the buffer to write from
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// do the write
|
||||
uint8_t *src = bufinfo.buf;
|
||||
while (bufinfo.len--) {
|
||||
if (!mp_hal_i2c_write_byte(self, *src++)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
|
||||
}
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t nbytes_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, mp_obj_get_int(nbytes_in));
|
||||
mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) {
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
||||
mp_hal_i2c_write(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
|
||||
};
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// create the buffer to store data into
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, args[ARG_n].u_int);
|
||||
|
||||
// do the transfer
|
||||
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len);
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
|
||||
};
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get the buffer to store data into
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// do the transfer
|
||||
mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
|
||||
|
||||
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
//{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
|
||||
};
|
||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get the buffer to write the data from
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
// do the transfer
|
||||
mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) },
|
||||
|
||||
// primitive I2C operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_start), MP_ROM_PTR(&machine_i2c_start_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_i2c_stop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&machine_i2c_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&machine_i2c_write_obj) },
|
||||
|
||||
// standard bus operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
|
||||
|
||||
// memory operations
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table);
|
||||
|
||||
const mp_obj_type_t machine_i2c_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_I2C,
|
||||
.make_new = machine_i2c_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_MACHINE_I2C
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user