mirror of
https://github.com/micropython/micropython.git
synced 2025-12-25 22:30:12 +01:00
Compare commits
189 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b39263b11 | ||
|
|
97ce5d1d77 | ||
|
|
7d60a97914 | ||
|
|
3f6ca4b22c | ||
|
|
cafdfb7af3 | ||
|
|
1191ec6a14 | ||
|
|
43c8f545d2 | ||
|
|
ddadbaed06 | ||
|
|
1bc8aa85a4 | ||
|
|
993cc3611a | ||
|
|
d8cc51ea2b | ||
|
|
ed4e5d2583 | ||
|
|
0b9725812e | ||
|
|
e456b2cc94 | ||
|
|
09f764dc04 | ||
|
|
9a1a49ceec | ||
|
|
fdf45a718b | ||
|
|
c4ab8895e8 | ||
|
|
1a05a59116 | ||
|
|
927388e80e | ||
|
|
752e952096 | ||
|
|
4f3fbf09cc | ||
|
|
15eb1ce52d | ||
|
|
33168081f4 | ||
|
|
cff2b7a6e3 | ||
|
|
93a9c2e840 | ||
|
|
4940bee62a | ||
|
|
298c2ae2c7 | ||
|
|
641300dccb | ||
|
|
ee009d713a | ||
|
|
7d4fd8b6db | ||
|
|
225562d915 | ||
|
|
480159ca8b | ||
|
|
2503b59592 | ||
|
|
12401f337e | ||
|
|
f0eea1fdf9 | ||
|
|
ee5e3f6527 | ||
|
|
cac6c9704e | ||
|
|
f12146cbf6 | ||
|
|
602305b211 | ||
|
|
6707fc94ae | ||
|
|
84381fa0fc | ||
|
|
55df14f1a4 | ||
|
|
715ee9d925 | ||
|
|
282d81a40e | ||
|
|
4889b6ff9b | ||
|
|
e66b3042d6 | ||
|
|
6055d411a9 | ||
|
|
cbe544a76d | ||
|
|
2ec0ee082a | ||
|
|
7c004e794c | ||
|
|
751e3b7a82 | ||
|
|
74e6c0337d | ||
|
|
7ebfe09fbd | ||
|
|
45f3416816 | ||
|
|
48a7ef0576 | ||
|
|
4b37e775ea | ||
|
|
a3dc2c6031 | ||
|
|
9a368ae831 | ||
|
|
849eb835f0 | ||
|
|
99b14593a6 | ||
|
|
7e809b4baf | ||
|
|
68e222afdc | ||
|
|
20aa9c8511 | ||
|
|
f5d63bcd23 | ||
|
|
2ea019f3d3 | ||
|
|
37f9761801 | ||
|
|
9d04fec5d9 | ||
|
|
c76acd8c23 | ||
|
|
2b05b60bbc | ||
|
|
4681b86850 | ||
|
|
116eeee6db | ||
|
|
bc2ba6b2e3 | ||
|
|
eaecc4c02e | ||
|
|
ca41dc2750 | ||
|
|
2133924e46 | ||
|
|
202d5acd06 | ||
|
|
3e03d1b87e | ||
|
|
25a42fb6ef | ||
|
|
74fb4e795b | ||
|
|
9b4c013823 | ||
|
|
274952a117 | ||
|
|
3e33aeb0db | ||
|
|
bca4c9e465 | ||
|
|
cb7693bab4 | ||
|
|
9c2217a165 | ||
|
|
9dde6062cc | ||
|
|
6a60fb3cf4 | ||
|
|
53bac8e869 | ||
|
|
1b5abfcaae | ||
|
|
2c573f00b8 | ||
|
|
8a2970e136 | ||
|
|
daa4793578 | ||
|
|
fb742cdc12 | ||
|
|
b580958216 | ||
|
|
5a2a4e9452 | ||
|
|
0ab372585f | ||
|
|
3a29db8e58 | ||
|
|
ccf4e5ab7b | ||
|
|
497660fcda | ||
|
|
f9dc644017 | ||
|
|
3ff16ff52e | ||
|
|
a0a08b4be1 | ||
|
|
6fa60153ea | ||
|
|
7f7c84b10a | ||
|
|
92a342a011 | ||
|
|
418faae8f7 | ||
|
|
1e024de7be | ||
|
|
99b4719357 | ||
|
|
21ec1fd850 | ||
|
|
7327d5f6f7 | ||
|
|
a676a41cb7 | ||
|
|
afce978aca | ||
|
|
ca63c77073 | ||
|
|
7b1bf0c308 | ||
|
|
719f8c044a | ||
|
|
e53fb1bf03 | ||
|
|
2ae6697300 | ||
|
|
772c73fa16 | ||
|
|
ccb00b7724 | ||
|
|
87981fc517 | ||
|
|
5985e41afc | ||
|
|
1e2f829293 | ||
|
|
cc80c4dd59 | ||
|
|
1e388079f9 | ||
|
|
1dc2862a83 | ||
|
|
68a7a92cec | ||
|
|
9a8751b006 | ||
|
|
10503f3534 | ||
|
|
9a92499641 | ||
|
|
a314b842bb | ||
|
|
a896951a9a | ||
|
|
d45e5f8c35 | ||
|
|
47bf6ba61a | ||
|
|
0d6d315ba6 | ||
|
|
0055457b5f | ||
|
|
c9a7430dbe | ||
|
|
bc04dc277e | ||
|
|
3d7f3f00e0 | ||
|
|
80a8d473f6 | ||
|
|
9b4502b7e8 | ||
|
|
ce2d34d74f | ||
|
|
79a38a7a43 | ||
|
|
83a9a723b9 | ||
|
|
7e1f580910 | ||
|
|
4f2ba9fbdc | ||
|
|
5ab98d5c41 | ||
|
|
088127d91c | ||
|
|
e36ff98c80 | ||
|
|
596a3feb8f | ||
|
|
3f56fd64b8 | ||
|
|
d60cb8e180 | ||
|
|
f16bec6bc9 | ||
|
|
b924f649cd | ||
|
|
e89413e9b0 | ||
|
|
6f34e138f1 | ||
|
|
40f0096ee7 | ||
|
|
a1f2245a81 | ||
|
|
6de8dbb488 | ||
|
|
460b086333 | ||
|
|
de5e0ed2e0 | ||
|
|
65402ab1ec | ||
|
|
dc3faea040 | ||
|
|
d59c2e5e45 | ||
|
|
13a1acc7e2 | ||
|
|
c4587e2426 | ||
|
|
87106d025b | ||
|
|
c156e89379 | ||
|
|
9e47c145c7 | ||
|
|
470c429ee1 | ||
|
|
12dd8df375 | ||
|
|
2724bd4a94 | ||
|
|
cea1c621e0 | ||
|
|
bc7ca7ca01 | ||
|
|
13d06a83e1 | ||
|
|
0c86a9471a | ||
|
|
8db61e5b5a | ||
|
|
5ec11f565b | ||
|
|
88153dc56a | ||
|
|
cbbeb786d7 | ||
|
|
df2b1a4758 | ||
|
|
08d3d5d9ab | ||
|
|
770f169e63 | ||
|
|
05d1664981 | ||
|
|
0f846e563c | ||
|
|
7441ba7749 | ||
|
|
adaaf439b0 | ||
|
|
e64032d6fd | ||
|
|
eb54e4d065 |
@@ -12,7 +12,8 @@ before_script:
|
||||
- sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded
|
||||
- sudo dpkg --add-architecture i386
|
||||
- sudo apt-get update -qq || true
|
||||
- sudo apt-get install -y python3 gcc-multilib gcc-arm-none-eabi pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
|
||||
- sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32
|
||||
- sudo apt-get install -y --force-yes gcc-arm-none-eabi
|
||||
# For teensy build
|
||||
- sudo apt-get install realpath
|
||||
# For coverage testing
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
Git commit conventions
|
||||
======================
|
||||
|
||||
Each commit message should start with a directory or full file path
|
||||
prefix, so it was clear which part of codebase a commit affects. If
|
||||
a change affects one file, it's better to use path to a file. If it
|
||||
affects few files in a subdirectory, using subdirectory as a prefix
|
||||
is ok. For longish paths, it's acceptable to drop intermediate
|
||||
components, which still should provide good context of a change.
|
||||
It's also ok to drop file extensions.
|
||||
|
||||
Besides prefix, first line of a commit message should describe a
|
||||
change clearly and to the point, and be a grammatical sentence with
|
||||
final full stop. First line should fit within 78 characters. Examples
|
||||
of good first line of commit messages:
|
||||
|
||||
py/objstr: Add splitlines() method.
|
||||
py: Rename FOO to BAR.
|
||||
docs/machine: Fix typo in reset() description.
|
||||
ports: Switch to use lib/foo instead of duplicated code.
|
||||
|
||||
After the first line, add an empty line and in following lines describe
|
||||
a change in a detail, if needed. Any change beyond 5 lines would likely
|
||||
require such detailed description.
|
||||
|
||||
To get good practical examples of good commits and their messages, browse
|
||||
thry the `git log` of the project.
|
||||
|
||||
Python code conventions
|
||||
=======================
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ Additional components:
|
||||
- tools/ -- various tools, including the pyboard.py module.
|
||||
- examples/ -- a few example Python scripts.
|
||||
|
||||
The subdirectories above may include READMEs with additional info.
|
||||
|
||||
"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).
|
||||
|
||||
@@ -69,6 +71,7 @@ Alternatively, fallback implementation based on setjmp/longjmp can be used.
|
||||
To build (see section below for required dependencies):
|
||||
|
||||
$ cd unix
|
||||
$ make axtls
|
||||
$ make
|
||||
|
||||
Then to give it a try:
|
||||
|
||||
@@ -26,3 +26,15 @@ In `micropython/docs`, build the docs:
|
||||
Where `<port_name>` can be `unix`, `pyboard`, `wipy` or `esp8266`.
|
||||
|
||||
You'll find the index page at `micropython/docs/build/<port_name>/html/index.html`.
|
||||
|
||||
PDF manual generation
|
||||
---------------------
|
||||
|
||||
This can be achieved with:
|
||||
|
||||
make MICROPY_PORT=<port_name> latexpdf
|
||||
|
||||
but require rather complete install of LaTeX with various extensions. On
|
||||
Debiab/Ubuntu, try (500MB+ download):
|
||||
|
||||
apt-get install texlive-latex-recommended texlive-latex-extra
|
||||
|
||||
@@ -93,7 +93,7 @@ copyright = '2014-2016, Damien P. George and contributors'
|
||||
# The short X.Y version.
|
||||
version = '1.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.8'
|
||||
release = '1.8.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@@ -6,8 +6,8 @@ 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
|
||||
There are a multitude of modules and boards from different sources which carry
|
||||
the 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
|
||||
@@ -18,13 +18,13 @@ 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.
|
||||
numbering of a particular board. Please have the manual/pin diagram of your board
|
||||
at hand to find correspondence 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
|
||||
(for example, 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.
|
||||
@@ -37,10 +37,10 @@ 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,
|
||||
They are the primary reference for the chip technical specifications, capabilities,
|
||||
operating modes, internal functioning, etc.
|
||||
|
||||
For your convinience, some of technical specifications are provided below:
|
||||
For your convenience, some of technical specifications are provided below:
|
||||
|
||||
* Architecture: Xtensa lx106
|
||||
* CPU frequency: 80MHz overclockable to 160MHz
|
||||
@@ -64,18 +64,18 @@ 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
|
||||
part of the 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
|
||||
Once the 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
|
||||
default 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
|
||||
a 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.
|
||||
|
||||
@@ -89,5 +89,14 @@ the following in ``main.py``::
|
||||
import my_app
|
||||
my_app.main()
|
||||
|
||||
This will allow to keep structure of your application clear, as well as
|
||||
This will allow to keep the structure of your application clear, as well as
|
||||
allow to install multiple applications on a board, and switch among them.
|
||||
|
||||
|
||||
Real-time clock
|
||||
---------------
|
||||
|
||||
Due to limitations of the ESP8266 chip the internal real-time clock (RTC)
|
||||
will overflow every 7:45h. If a long-term working RTC time is required then
|
||||
``time()`` or ``localtime()`` must be called at least once within 7 hours.
|
||||
MicroPython will then handle the overflow.
|
||||
|
||||
BIN
docs/esp8266/img/adafruit_products_pinoutstop.jpg
Normal file
BIN
docs/esp8266/img/adafruit_products_pinoutstop.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
@@ -3,7 +3,7 @@
|
||||
Quick reference for the ESP8266
|
||||
===============================
|
||||
|
||||
.. image:: https://learn.adafruit.com/system/assets/assets/000/028/689/medium640/adafruit_products_pinoutstop.jpg
|
||||
.. image:: img/adafruit_products_pinoutstop.jpg
|
||||
:alt: Adafruit Feather HUZZAH board
|
||||
:width: 640px
|
||||
|
||||
@@ -43,7 +43,7 @@ The ``network`` module::
|
||||
wlan.scan() # scan for access points
|
||||
wlan.isconnected() # check if the station is connected to an AP
|
||||
wlan.connect('essid', 'password') # connect to an AP
|
||||
wlan.mac() # get the interface's MAC adddress
|
||||
wlan.config('mac') # get the interface's MAC adddress
|
||||
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
|
||||
|
||||
ap = network.WLAN(network.AP_IF) # create access-point interface
|
||||
@@ -199,9 +199,6 @@ The I2C driver is implemented in software and works on all pins::
|
||||
buf = bytearray(10) # create a buffer with 10 bytes
|
||||
i2c.writeto(0x3a, buf) # write the given buffer to the slave
|
||||
|
||||
i2c.readfrom(0x3a, 4, stop=False) # don't send a stop bit after reading
|
||||
i2c.writeto(0x3a, buf, stop=False) # don't send a stop bit after writing
|
||||
|
||||
Deep-sleep mode
|
||||
---------------
|
||||
|
||||
@@ -274,31 +271,55 @@ For low-level driving of a NeoPixel::
|
||||
import esp
|
||||
esp.neopixel_write(pin, grb_buf, is800khz)
|
||||
|
||||
APA102 driver
|
||||
-------------
|
||||
|
||||
Use the ``apa102`` module::
|
||||
|
||||
from machine import Pin
|
||||
from apa102 import APA102
|
||||
|
||||
clock = Pin(14, Pin.OUT) # set GPIO14 to output to drive the clock
|
||||
data = Pin(13, Pin.OUT) # set GPIO13 to output to drive the data
|
||||
apa = APA102(clock, data, 8) # create APA102 driver on the clock and the data pin for 8 pixels
|
||||
apa[0] = (255, 255, 255, 31) # set the first pixel to white with a maximum brightness of 31
|
||||
apa.write() # write data to all pixels
|
||||
r, g, b, brightness = apa[0] # get first pixel colour
|
||||
|
||||
For low-level driving of an APA102::
|
||||
|
||||
import esp
|
||||
esp.apa102_write(clock_pin, data_pin, rgbi_buf)
|
||||
|
||||
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::
|
||||
from https://github.com/micropython/webrepl (hosted version available
|
||||
at http://micropython.org/webrepl), and start the daemon on a device
|
||||
using::
|
||||
|
||||
import webrepl
|
||||
webrepl.start()
|
||||
|
||||
(Release version will have it started on boot by default.)
|
||||
(Release versions 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).
|
||||
router is set up and works correctly, you may also use WebREPL while connected
|
||||
to your normal Internet access point (use the ESP8266 AP connection method
|
||||
if you 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
|
||||
issues.
|
||||
|
||||
There's also provision to transfer (both upload and download)
|
||||
files over WebREPL connection, but it has even more experimental status
|
||||
than the WebREPL terminal mode. It is still 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.
|
||||
from the repository above. See the MicroPython forum for other
|
||||
community-supported alternatives to transfer files to ESP8266.
|
||||
|
||||
@@ -62,7 +62,7 @@ connect to your WiFi network::
|
||||
print('connecting to network...')
|
||||
sta_if.active(True)
|
||||
sta_if.connect('<essid>', '<password>')
|
||||
while not network.isconnected():
|
||||
while not sta_if.isconnected():
|
||||
pass
|
||||
print('network config:', sta_if.ifconfig())
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ 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])
|
||||
>>> s.connect(addr)
|
||||
|
||||
Now that we are connected we can download and display the data::
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
.. module:: cmath
|
||||
:synopsis: mathematical functions for complex numbers
|
||||
|
||||
The ``cmath`` module provides some basic mathematical funtions for
|
||||
The ``cmath`` module provides some basic mathematical functions for
|
||||
working with complex numbers.
|
||||
|
||||
Availability: not available on WiPy and ESP8266. Floating point support
|
||||
required for this module.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
MicroPython libraries
|
||||
=====================
|
||||
|
||||
The following standard Python libraries are built in to MicroPython.
|
||||
This chapter describes modules (function and class libraries) which are built
|
||||
into MicroPython. There are a few categories of modules:
|
||||
|
||||
For additional libraries, please download them from the `micropython-lib repository
|
||||
* Modules which implement a subset of standard Python functionality and are not
|
||||
intended to be extended by the user.
|
||||
* Modules which implement a subset of Python functionality, with a provision
|
||||
for extension by the user (via Python code).
|
||||
* Modules which implement MicroPython extensions to the Python standard libraries.
|
||||
* Modules specific to a particular port and thus not portable.
|
||||
|
||||
Note about the availability of modules and their contents: This documentation
|
||||
in general aspires to describe all modules and functions/classes which are
|
||||
implemented in MicroPython. However, MicroPython is highly configurable, and
|
||||
each port to a particular board/embedded system makes available only a subset
|
||||
of MicroPython libraries. For officially supported ports, there is an effort
|
||||
to either filter out non-applicable items, or mark individual descriptions
|
||||
with "Availability:" clauses describing which ports provide a given feature.
|
||||
With that in mind, please still be warned that some functions/classes
|
||||
in a module (or even the entire module) described in this documentation may be
|
||||
unavailable in a particular build of MicroPython on a particular board. The
|
||||
best place to find general information of the availability/non-availability
|
||||
of a particular feature is the "General Information" section which contains
|
||||
information pertaining to a specific port.
|
||||
|
||||
Beyond the built-in libraries described in this documentation, many more
|
||||
modules from the Python standard library, as well as further MicroPython
|
||||
extensions to it, can be found in the `micropython-lib repository
|
||||
<https://github.com/micropython/micropython-lib>`_.
|
||||
|
||||
Python standard libraries and micro-libraries
|
||||
@@ -101,6 +125,7 @@ library.
|
||||
uos.rst
|
||||
ure.rst
|
||||
usocket.rst
|
||||
ussl.rst
|
||||
ustruct.rst
|
||||
utime.rst
|
||||
uzlib.rst
|
||||
|
||||
@@ -86,13 +86,15 @@ Methods
|
||||
When no pins are given, then the default set of TX and RX pins is taken, and hardware
|
||||
flow control will be disabled. If pins=None, no pin assignment will be made.
|
||||
|
||||
.. method:: uart.deinit()
|
||||
.. only:: not port_esp8266
|
||||
|
||||
Turn off the UART bus.
|
||||
.. method:: uart.deinit()
|
||||
|
||||
.. method:: uart.any()
|
||||
Turn off the UART bus.
|
||||
|
||||
Return the number of characters available for reading.
|
||||
.. method:: uart.any()
|
||||
|
||||
Return the number of characters available for reading.
|
||||
|
||||
.. method:: uart.read([nbytes])
|
||||
|
||||
@@ -127,11 +129,13 @@ Methods
|
||||
|
||||
Return value: number of bytes written or ``None`` on timeout.
|
||||
|
||||
.. method:: uart.sendbreak()
|
||||
.. only:: not port_esp8266
|
||||
|
||||
Send a break condition on the bus. This drives the bus low for a duration
|
||||
of 13 bits.
|
||||
Return value: ``None``.
|
||||
.. method:: uart.sendbreak()
|
||||
|
||||
Send a break condition on the bus. This drives the bus low for a duration
|
||||
of 13 bits.
|
||||
Return value: ``None``.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
@@ -158,14 +162,16 @@ Methods
|
||||
|
||||
Returns an irq object.
|
||||
|
||||
Constants
|
||||
---------
|
||||
.. only:: not port_esp8266
|
||||
|
||||
.. data:: UART.EVEN
|
||||
.. data:: UART.ODD
|
||||
Constants
|
||||
---------
|
||||
|
||||
parity types (anlong with ``None``)
|
||||
.. data:: UART.EVEN
|
||||
.. data:: UART.ODD
|
||||
|
||||
.. data:: UART.RX_ANY
|
||||
parity types (anlong with ``None``)
|
||||
|
||||
IRQ trigger sources
|
||||
.. data:: UART.RX_ANY
|
||||
|
||||
IRQ trigger sources
|
||||
|
||||
@@ -18,25 +18,23 @@ Reset related functions
|
||||
|
||||
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values.
|
||||
|
||||
.. only:: port_wipy
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
.. function:: disable_irq()
|
||||
|
||||
.. function:: disable_irq()
|
||||
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.
|
||||
|
||||
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:: enable_irq(state=True)
|
||||
|
||||
.. 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.
|
||||
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
|
||||
-----------------------
|
||||
@@ -103,6 +101,19 @@ Miscellaneous functions
|
||||
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.
|
||||
|
||||
.. function:: time_pulse_us(pin, pulse_level, timeout_us=1000000)
|
||||
|
||||
Time a pulse on the given `pin`, and return the duration of the pulse in
|
||||
microseconds. The `pulse_level` argument should be 0 to time a low pulse
|
||||
or 1 to time a high pulse.
|
||||
|
||||
The function first waits while the pin input is different to the `pulse_level`
|
||||
parameter, then times the duration that the pin is equal to `pulse_level`.
|
||||
If the pin is already equal to `pulse_level` then timing starts straight away.
|
||||
|
||||
The function will raise an OSError with ETIMEDOUT if either of the waits is
|
||||
longer than the given timeout value (which is in microseconds).
|
||||
|
||||
.. _machine_constants:
|
||||
|
||||
Constants
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
.. module:: math
|
||||
:synopsis: mathematical functions
|
||||
|
||||
The ``math`` module provides some basic mathematical funtions for
|
||||
The ``math`` module provides some basic mathematical functions for
|
||||
working with floating-point numbers.
|
||||
|
||||
*Note:* On the pyboard, floating-point numbers have 32-bit precision.
|
||||
|
||||
Availability: not available on WiPy. Floating point support required
|
||||
for this module.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ Methods
|
||||
|
||||
Reinitialise the DAC. ``bits`` can be 8 or 12.
|
||||
|
||||
.. method:: dac.deinit()
|
||||
|
||||
De-initialise the DAC making its pin available for other uses.
|
||||
|
||||
.. method:: dac.noise(freq)
|
||||
|
||||
Generate a pseudo-random noise signal. A new random sample is written
|
||||
|
||||
@@ -8,56 +8,79 @@ This module provides access to Transport Layer Security (often known as
|
||||
“Secure Sockets Layer”) encryption and peer authentication facilities for
|
||||
network sockets, both client-side and server-side.
|
||||
|
||||
Functions
|
||||
---------
|
||||
.. only:: not port_wipy
|
||||
|
||||
.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
|
||||
Functions
|
||||
---------
|
||||
|
||||
Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
|
||||
``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
|
||||
socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
|
||||
.. function:: ssl.wrap_socket(sock, server_side=False)
|
||||
|
||||
import socket
|
||||
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][-1])
|
||||
Takes a stream `sock` (usually usocket.socket instance of ``SOCK_STREAM`` type),
|
||||
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
|
||||
an SSL context. Returned object has the usual stream interface methods like
|
||||
`read()`, `write()`, etc. In MicroPython, the returned object does not expose
|
||||
socket interface and methods like `recv()`, `send()`. In particular, a
|
||||
server-side SSL socket should be created from a normal socket returned from
|
||||
`accept()` on a non-SSL listening server socket.
|
||||
|
||||
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
|
||||
FTP server, and they must be placed in specific paths with specific names.
|
||||
.. warning::
|
||||
|
||||
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
|
||||
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
|
||||
- The key for our own certificate goes in: **'/flash/cert/private.key'**
|
||||
Currently, this function does NOT validate server certificates, which makes
|
||||
an SSL connection established prone to man-in-the-middle attacks.
|
||||
|
||||
.. note::
|
||||
|
||||
When these files are stored, they are placed inside the internal **hidden** file system
|
||||
(just like firmware updates), and therefore they are never visible.
|
||||
.. only:: port_wipy
|
||||
|
||||
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
|
||||
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_
|
||||
and put it in '/flash/cert/'. Then do::
|
||||
Functions
|
||||
---------
|
||||
|
||||
import socket
|
||||
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][-1])
|
||||
.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
|
||||
|
||||
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
|
||||
Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
|
||||
``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
|
||||
socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
import socket
|
||||
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][-1])
|
||||
|
||||
.. data:: ssl.SSLError
|
||||
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
|
||||
FTP server, and they must be placed in specific paths with specific names.
|
||||
|
||||
Constants
|
||||
---------
|
||||
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
|
||||
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
|
||||
- The key for our own certificate goes in: **'/flash/cert/private.key'**
|
||||
|
||||
.. data:: ssl.CERT_NONE
|
||||
.. data:: ssl.CERT_OPTIONAL
|
||||
.. data:: ssl.CERT_REQUIRED
|
||||
.. note::
|
||||
|
||||
supported values in ``cert_reqs``
|
||||
When these files are stored, they are placed inside the internal **hidden** file system
|
||||
(just like firmware updates), and therefore they are never visible.
|
||||
|
||||
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
|
||||
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_
|
||||
and put it in '/flash/cert/'. Then do::
|
||||
|
||||
import socket
|
||||
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][-1])
|
||||
|
||||
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
.. data:: ssl.SSLError
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: ssl.CERT_NONE
|
||||
.. data:: ssl.CERT_OPTIONAL
|
||||
.. data:: ssl.CERT_REQUIRED
|
||||
|
||||
supported values in ``cert_reqs``
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
|
||||
information.
|
||||
|
||||
Supported size/byte order prefixes: ``@``, ``<``, ``>``, ``!``.
|
||||
|
||||
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
|
||||
``L``, ``q``, ``Q``, ``s``, ``P``, ``f``, ``d`` (the latter 2 depending
|
||||
on the floating-point support).
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
|
||||
@@ -52,7 +52,12 @@ or::
|
||||
|
||||
$ screen /dev/tty.usbmodem* 115200
|
||||
|
||||
When you are finished and want to exit screen, type CTRL-A CTRL-\\.
|
||||
When you are finished and want to exit ``screen``, type CTRL-A CTRL-\\. If your keyboard does not have a \\-key (i.e. you need an obscure combination for \\ like ALT-SHIFT-7) you can remap the ``quit`` command:
|
||||
|
||||
- create ``~/.screenrc``
|
||||
- add ``bind q quit``
|
||||
|
||||
This will allow you to quit ``screen`` by hitting CTRL-A Q.
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
@@ -169,9 +169,9 @@ typedef INT32 time_t;
|
||||
typedef UINT32 clock_t;
|
||||
typedef INT32 suseconds_t;
|
||||
|
||||
typedef struct timeval timeval;
|
||||
typedef struct cc3000_timeval cc3000_timeval;
|
||||
|
||||
struct timeval
|
||||
struct cc3000_timeval
|
||||
{
|
||||
time_t tv_sec; /* seconds */
|
||||
suseconds_t tv_usec; /* microseconds */
|
||||
|
||||
@@ -416,7 +416,7 @@ extern INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrle
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds,
|
||||
fd_set *exceptsds, struct timeval *timeout);
|
||||
fd_set *exceptsds, struct cc3000_timeval *timeout);
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
|
||||
@@ -587,7 +587,7 @@ INT32 CC3000_EXPORT(connect)(INT32 sd, const sockaddr *addr, INT32 addrlen)
|
||||
//*****************************************************************************
|
||||
|
||||
INT16 CC3000_EXPORT(select)(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds,
|
||||
struct timeval *timeout)
|
||||
struct cc3000_timeval *timeout)
|
||||
{
|
||||
UINT8 *ptr, *args;
|
||||
tBsdSelectRecvParams tParams;
|
||||
|
||||
89
drivers/dht/dht.c
Normal file
89
drivers/dht/dht.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "drivers/dht/dht.h"
|
||||
|
||||
STATIC mp_obj_t dht_readinto(mp_obj_t pin_in, mp_obj_t buf_in) {
|
||||
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
|
||||
mp_hal_pin_open_drain(pin);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
if (bufinfo.len < 5) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "buffer too small"));
|
||||
}
|
||||
|
||||
// issue start command
|
||||
mp_hal_pin_od_high(pin);
|
||||
mp_hal_delay_ms(250);
|
||||
mp_hal_pin_od_low(pin);
|
||||
mp_hal_delay_ms(18);
|
||||
|
||||
mp_uint_t irq_state = mp_hal_quiet_timing_enter();
|
||||
|
||||
// release the line so the device can respond
|
||||
mp_hal_pin_od_high(pin);
|
||||
mp_hal_delay_us_fast(10);
|
||||
|
||||
// wait for device to respond
|
||||
mp_uint_t ticks = mp_hal_ticks_us();
|
||||
while (mp_hal_pin_read(pin) != 0) {
|
||||
if ((mp_uint_t)(mp_hal_ticks_us() - ticks) > 100) {
|
||||
goto timeout;
|
||||
}
|
||||
}
|
||||
|
||||
// time pulse, should be 80us
|
||||
ticks = machine_time_pulse_us(pin, 1, 150);
|
||||
if (ticks == (mp_uint_t)-1) {
|
||||
goto timeout;
|
||||
}
|
||||
|
||||
// time 40 pulses for data (either 26us or 70us)
|
||||
uint8_t *buf = bufinfo.buf;
|
||||
for (int i = 0; i < 40; ++i) {
|
||||
ticks = machine_time_pulse_us(pin, 1, 100);
|
||||
if (ticks == (mp_uint_t)-1) {
|
||||
goto timeout;
|
||||
}
|
||||
buf[i / 8] = (buf[i / 8] << 1) | (ticks > 48);
|
||||
}
|
||||
|
||||
mp_hal_quiet_timing_exit(irq_state);
|
||||
return mp_const_none;
|
||||
|
||||
timeout:
|
||||
mp_hal_quiet_timing_exit(irq_state);
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(dht_readinto_obj, dht_readinto);
|
||||
3
drivers/dht/dht.h
Normal file
3
drivers/dht/dht.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "py/obj.h"
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(dht_readinto_obj);
|
||||
@@ -3,6 +3,7 @@
|
||||
import time
|
||||
import framebuf
|
||||
|
||||
|
||||
# register definitions
|
||||
SET_CONTRAST = const(0x81)
|
||||
SET_ENTIRE_ON = const(0xa4)
|
||||
@@ -22,6 +23,7 @@ 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
|
||||
@@ -91,6 +93,7 @@ class SSD1306:
|
||||
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
|
||||
@@ -114,27 +117,34 @@ class SSD1306_I2C(SSD1306):
|
||||
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)
|
||||
def __init__(self, height, spi, dc, res, cs, external_vcc=False):
|
||||
self.rate = 10 * 1024 * 1024
|
||||
dc.init(dc.OUT, value=0)
|
||||
res.init(res.OUT, value=0)
|
||||
cs.init(cs.OUT, value=1)
|
||||
self.spi = spi
|
||||
self.dc = dc
|
||||
self.res = res
|
||||
self.cs = cs
|
||||
super().__init__(height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
self.cs.high()
|
||||
self.dc.low()
|
||||
self.spi.send(cmd)
|
||||
self.cs.low()
|
||||
self.spi.write(bytearray([cmd]))
|
||||
self.cs.high()
|
||||
|
||||
def write_data(self, buf):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
self.cs.high()
|
||||
self.dc.high()
|
||||
self.spi.send(buf)
|
||||
self.cs.low()
|
||||
self.spi.write(buf)
|
||||
self.cs.high()
|
||||
|
||||
def poweron(self):
|
||||
self.res.high()
|
||||
@@ -142,4 +152,3 @@ class SSD1306_SPI(SSD1306):
|
||||
self.res.low()
|
||||
time.sleep_ms(10)
|
||||
self.res.high()
|
||||
time.sleep_ms(10)
|
||||
|
||||
@@ -26,7 +26,7 @@ INC += -I$(BUILD)
|
||||
INC += -I$(ESP_SDK)/include
|
||||
|
||||
# UART for "os" messages. 0 is normal UART as used by MicroPython REPL,
|
||||
# 1 is debug UART (tx only).
|
||||
# 1 is debug UART (tx only), -1 to disable.
|
||||
UART_OS = 0
|
||||
|
||||
CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
|
||||
@@ -65,6 +65,7 @@ SRC_C = \
|
||||
esppwm.c \
|
||||
esponewire.c \
|
||||
espneopixel.c \
|
||||
espapa102.c \
|
||||
intr.c \
|
||||
modpyb.c \
|
||||
modpybpin.c \
|
||||
@@ -123,6 +124,10 @@ LIB_SRC_C = $(addprefix lib/,\
|
||||
fatfs/option/ccsbcs.c \
|
||||
)
|
||||
|
||||
DRIVERS_SRC_C = $(addprefix drivers/,\
|
||||
dht/dht.c \
|
||||
)
|
||||
|
||||
SRC_S = \
|
||||
gchelper.s \
|
||||
|
||||
@@ -133,10 +138,11 @@ OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_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)
|
||||
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
|
||||
@@ -69,6 +69,34 @@ $ make PORT=/dev/ttyUSB0 deploy
|
||||
|
||||
The image produced is `firmware-combined.bin`, to be flashed at 0x00000.
|
||||
|
||||
First start
|
||||
-----------
|
||||
|
||||
__Serial prompt__
|
||||
|
||||
You can access the REPL (Python prompt) over UART (the same as used for
|
||||
programming).
|
||||
- Baudrate: 115200
|
||||
|
||||
__WiFi__
|
||||
|
||||
Initally, the device configures itself as a WiFi access point (AP).
|
||||
- ESSID: MicroPython-xxxxxx (x’s are replaced with part of the MAC address).
|
||||
- Password: micropythoN (note the upper-case N).
|
||||
- IP address of the board: 192.168.4.1.
|
||||
- DHCP-server is activated.
|
||||
|
||||
__WebREPL__
|
||||
|
||||
Python prompt over WiFi, connecting through a browser.
|
||||
- Hosted at http://micropython.org/webrepl.
|
||||
- GitHub repository https://github.com/micropython/webrepl.
|
||||
|
||||
Please follow the instructions there.
|
||||
|
||||
More detailed instructions can be found at
|
||||
http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
|
||||
|
||||
Troubleshooting
|
||||
---------------
|
||||
|
||||
|
||||
@@ -166,21 +166,24 @@ static int call_dupterm_read(void) {
|
||||
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
|
||||
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
|
||||
if (res == mp_const_none) {
|
||||
nlr_pop();
|
||||
return -2;
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
|
||||
if (bufinfo.len == 0) {
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
|
||||
mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
|
||||
nlr_pop();
|
||||
return -1;
|
||||
}
|
||||
nlr_pop();
|
||||
if (*(byte*)bufinfo.buf == interrupt_char) {
|
||||
mp_keyboard_interrupt();
|
||||
return -2;
|
||||
}
|
||||
return *(byte*)bufinfo.buf;
|
||||
} else {
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: Exception in read() method, deactivating: ");
|
||||
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
|
||||
mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -213,7 +216,7 @@ 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) {
|
||||
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin_id) {
|
||||
const pyb_pin_obj_t *pin = &pyb_pin_obj[pin_id];
|
||||
|
||||
if (pin->phys_port == 16) {
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
#define _INCLUDED_MPHAL_H_
|
||||
|
||||
#include "py/ringbuf.h"
|
||||
#include "xtirq.h"
|
||||
|
||||
void mp_keyboard_interrupt(void);
|
||||
extern int interrupt_char;
|
||||
|
||||
struct _mp_print_t;
|
||||
// Structure for UART-only output via mp_printf()
|
||||
@@ -59,14 +63,19 @@ void ets_event_poll(void);
|
||||
#include "osapi.h"
|
||||
#define mp_hal_delay_us_fast(us) os_delay_us(us)
|
||||
|
||||
#define mp_hal_quiet_timing_enter() disable_irq()
|
||||
#define mp_hal_quiet_timing_exit(irq_state) enable_irq(irq_state)
|
||||
|
||||
// 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 { \
|
||||
void mp_hal_pin_input(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_output(mp_hal_pin_obj_t pin);
|
||||
void mp_hal_pin_open_drain(mp_hal_pin_obj_t pin);
|
||||
#define mp_hal_pin_od_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)
|
||||
|
||||
110
esp8266/espapa102.c
Normal file
110
esp8266/espapa102.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Robert Foss, Daniel Busch
|
||||
*
|
||||
* 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 "c_types.h"
|
||||
#include "eagle_soc.h"
|
||||
#include "user_interface.h"
|
||||
#include "espapa102.h"
|
||||
|
||||
#define NOP asm volatile(" nop \n\t")
|
||||
|
||||
static inline void _esp_apa102_send_byte(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t byte) {
|
||||
for (uint32_t i = 0; i < 8; i++) {
|
||||
if (byte & 0x80) {
|
||||
// set data pin high
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask);
|
||||
} else {
|
||||
// set data pin low
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, dataPinMask);
|
||||
}
|
||||
|
||||
// set clock pin high
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask);
|
||||
byte <<= 1;
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
// set clock pin low
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask);
|
||||
NOP;
|
||||
NOP;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _esp_apa102_send_colors(uint32_t clockPinMask, uint32_t dataPinMask, uint8_t *pixels, uint32_t numBytes) {
|
||||
for (uint32_t i = 0; i < numBytes / 4; i++) {
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 3] | 0xE0);
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 2]);
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4 + 1]);
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, pixels[i * 4]);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _esp_apa102_start_frame(uint32_t clockPinMask, uint32_t dataPinMask) {
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _esp_apa102_append_additionial_cycles(uint32_t clockPinMask, uint32_t dataPinMask, uint32_t numBytes) {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, dataPinMask);
|
||||
|
||||
// we need to write some more clock cycles, because each led
|
||||
// delays the data by one edge after inverting the clock
|
||||
for (uint32_t i = 0; i < numBytes / 8 + ((numBytes / 4) % 2); i++) {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, clockPinMask);
|
||||
NOP;
|
||||
NOP;
|
||||
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clockPinMask);
|
||||
NOP;
|
||||
NOP;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _esp_apa102_end_frame(uint32_t clockPinMask, uint32_t dataPinMask) {
|
||||
for (uint32_t i = 0; i < 4; i++) {
|
||||
_esp_apa102_send_byte(clockPinMask, dataPinMask, 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes) {
|
||||
uint32_t clockPinMask, dataPinMask;
|
||||
|
||||
clockPinMask = 1 << clockPin;
|
||||
dataPinMask = 1 << dataPin;
|
||||
|
||||
// start the frame
|
||||
_esp_apa102_start_frame(clockPinMask, dataPinMask);
|
||||
|
||||
// write pixels
|
||||
_esp_apa102_send_colors(clockPinMask, dataPinMask, pixels, numBytes);
|
||||
|
||||
// end the frame
|
||||
_esp_apa102_append_additionial_cycles(clockPinMask, dataPinMask, numBytes);
|
||||
_esp_apa102_end_frame(clockPinMask, dataPinMask);
|
||||
}
|
||||
27
esp8266/espapa102.h
Normal file
27
esp8266/espapa102.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Robert Foss, Daniel Busch
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
void esp_apa102_write(uint8_t clockPin, uint8_t dataPin, uint8_t *pixels, uint32_t numBytes);
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <esp_sdk_ver.h>
|
||||
#include "etshal.h"
|
||||
#include "user_interface.h"
|
||||
#include "ets_alt_task.h"
|
||||
|
||||
// Use standard ets_task or alternative impl
|
||||
#define USE_ETS_TASK 0
|
||||
@@ -107,7 +108,12 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) {
|
||||
#endif
|
||||
}
|
||||
|
||||
int ets_loop_iter_disable = 0;
|
||||
|
||||
bool ets_loop_iter(void) {
|
||||
if (ets_loop_iter_disable) {
|
||||
return false;
|
||||
}
|
||||
//static unsigned cnt;
|
||||
bool progress = false;
|
||||
for (volatile struct task_entry *t = emu_tasks; t < &emu_tasks[MP_ARRAY_SIZE(emu_tasks)]; t++) {
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
extern int ets_loop_iter_disable;
|
||||
bool ets_loop_iter(void);
|
||||
|
||||
@@ -37,7 +37,7 @@ STATIC const char *help_text =
|
||||
"Basic WiFi configuration:\n"
|
||||
"\n"
|
||||
"import network\n"
|
||||
"sta_if = network.WLAN(network.STA_IF)\n"
|
||||
"sta_if = network.WLAN(network.STA_IF); sta_if.active(True)\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"
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include "gccollect.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
STATIC char heap[24 * 1024];
|
||||
STATIC char heap[28 * 1024];
|
||||
|
||||
STATIC void mp_reset(void) {
|
||||
mp_stack_set_top((void*)0x40000000);
|
||||
@@ -58,7 +58,7 @@ STATIC void mp_reset(void) {
|
||||
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
|
||||
pin_init0();
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
pyexec_frozen_module("_boot");
|
||||
pyexec_frozen_module("_boot.py");
|
||||
pyexec_file("boot.py");
|
||||
pyexec_file("main.py");
|
||||
#endif
|
||||
|
||||
@@ -27,13 +27,14 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "drivers/dht/dht.h"
|
||||
#include "netutils.h"
|
||||
#include "queue.h"
|
||||
#include "ets_sys.h"
|
||||
@@ -43,6 +44,7 @@
|
||||
#include "spi_flash.h"
|
||||
#include "mem.h"
|
||||
#include "espneopixel.h"
|
||||
#include "espapa102.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
#define MODESP_ESPCONN (0)
|
||||
@@ -577,7 +579,7 @@ STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t len_or_buf_in) {
|
||||
if (alloc_buf) {
|
||||
m_del(byte, buf, len);
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_read_obj, esp_flash_read);
|
||||
|
||||
@@ -594,7 +596,7 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, const mp_obj_t buf_in) {
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(
|
||||
&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
|
||||
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);
|
||||
|
||||
@@ -606,7 +608,7 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
|
||||
}
|
||||
nlr_raise(mp_obj_new_exception_arg1(
|
||||
&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? ETIMEDOUT : EIO)));
|
||||
MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO)));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);
|
||||
|
||||
@@ -636,6 +638,16 @@ STATIC mp_obj_t esp_neopixel_write_(mp_obj_t pin, mp_obj_t buf, mp_obj_t is800k)
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_neopixel_write_obj, esp_neopixel_write_);
|
||||
|
||||
STATIC mp_obj_t esp_apa102_write_(mp_obj_t clockPin, mp_obj_t dataPin, mp_obj_t buf) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
|
||||
esp_apa102_write(mp_obj_get_pin_obj(clockPin)->phys_port,
|
||||
mp_obj_get_pin_obj(dataPin)->phys_port,
|
||||
(uint8_t*)bufinfo.buf, bufinfo.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_apa102_write_obj, esp_apa102_write_);
|
||||
|
||||
STATIC mp_obj_t esp_freemem() {
|
||||
return MP_OBJ_NEW_SMALL_INT(system_get_free_heap_size());
|
||||
}
|
||||
@@ -679,6 +691,8 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_apa102_write), (mp_obj_t)&esp_apa102_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dht_readinto), (mp_obj_t)&dht_readinto_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
|
||||
|
||||
@@ -30,10 +30,12 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/machine_mem.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
#include "extmod/machine_i2c.h"
|
||||
#include "modpyb.h"
|
||||
#include "modpybrtc.h"
|
||||
|
||||
#include "xtirq.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "etshal.h"
|
||||
@@ -189,6 +191,25 @@ const mp_obj_type_t esp_timer_type = {
|
||||
.locals_dict = (mp_obj_t)&esp_timer_locals_dict,
|
||||
};
|
||||
|
||||
// this bit is unused in the Xtensa PS register
|
||||
#define ETS_LOOP_ITER_BIT (12)
|
||||
|
||||
STATIC mp_obj_t machine_disable_irq(void) {
|
||||
uint32_t state = disable_irq();
|
||||
state = (state & ~(1 << ETS_LOOP_ITER_BIT)) | (ets_loop_iter_disable << ETS_LOOP_ITER_BIT);
|
||||
ets_loop_iter_disable = 1;
|
||||
return mp_obj_new_int(state);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
|
||||
|
||||
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
|
||||
uint32_t state = mp_obj_get_int(state_in);
|
||||
ets_loop_iter_disable = (state >> ETS_LOOP_ITER_BIT) & 1;
|
||||
enable_irq(state & ~(1 << ETS_LOOP_ITER_BIT));
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
|
||||
|
||||
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
|
||||
@@ -201,6 +222,11 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ 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_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_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) },
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/objlist.h"
|
||||
@@ -137,16 +136,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
|
||||
return;
|
||||
}
|
||||
if (si->pbss && status == 0) {
|
||||
struct bss_info *bs;
|
||||
STAILQ_FOREACH(bs, si->pbss, next) {
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
|
||||
t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid));
|
||||
t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
|
||||
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
|
||||
mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
|
||||
// we need to catch any memory errors
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
struct bss_info *bs;
|
||||
STAILQ_FOREACH(bs, si->pbss, next) {
|
||||
mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL);
|
||||
t->items[0] = mp_obj_new_bytes(bs->ssid, strlen((char*)bs->ssid));
|
||||
t->items[1] = mp_obj_new_bytes(bs->bssid, sizeof(bs->bssid));
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(bs->channel);
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(bs->rssi);
|
||||
t->items[4] = MP_OBJ_NEW_SMALL_INT(bs->authmode);
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(bs->is_hidden);
|
||||
mp_obj_list_append(*esp_scan_list, MP_OBJ_FROM_PTR(t));
|
||||
}
|
||||
nlr_pop();
|
||||
} else {
|
||||
mp_obj_print_exception(&mp_plat_print, MP_OBJ_FROM_PTR(nlr.ret_val));
|
||||
// indicate error
|
||||
*esp_scan_list = MP_OBJ_NULL;
|
||||
}
|
||||
} else {
|
||||
// indicate error
|
||||
@@ -156,14 +164,25 @@ STATIC void esp_scan_cb(scaninfo *si, STATUS status) {
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
|
||||
if (wifi_get_opmode() == SOFTAP_MODE) {
|
||||
require_if(self_in, STATION_IF);
|
||||
if ((wifi_get_opmode() & STATION_MODE) == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"scan unsupported in AP mode"));
|
||||
"STA must be active"));
|
||||
}
|
||||
mp_obj_t list = mp_obj_new_list(0, NULL);
|
||||
esp_scan_list = &list;
|
||||
wifi_station_scan(NULL, (scan_done_cb_t)esp_scan_cb);
|
||||
ETS_POLL_WHILE(esp_scan_list != NULL);
|
||||
while (esp_scan_list != NULL) {
|
||||
// our esp_scan_cb is called via ets_loop_iter so it's safe to set the
|
||||
// esp_scan_list variable to NULL without disabling interrupts
|
||||
if (MP_STATE_VM(mp_pending_exception) != NULL) {
|
||||
esp_scan_list = NULL;
|
||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
||||
nlr_raise(obj);
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
if (list == MP_OBJ_NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "scan failed"));
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
#define GET_TRIGGER(phys_port) \
|
||||
@@ -123,6 +124,34 @@ uint mp_obj_get_pin(mp_obj_t pin_in) {
|
||||
return mp_obj_get_pin_obj(pin_in)->phys_port;
|
||||
}
|
||||
|
||||
void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) {
|
||||
pin_mode[pin_id] = GPIO_MODE_INPUT;
|
||||
if (pin_id == 16) {
|
||||
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
|
||||
} else {
|
||||
const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
|
||||
PIN_FUNC_SELECT(self->periph, self->func);
|
||||
PIN_PULLUP_DIS(self->periph);
|
||||
gpio_output_set(0, 0, 0, 1 << self->phys_port);
|
||||
}
|
||||
}
|
||||
|
||||
void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) {
|
||||
pin_mode[pin_id] = GPIO_MODE_OUTPUT;
|
||||
if (pin_id == 16) {
|
||||
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) | 1); // output
|
||||
} else {
|
||||
const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
|
||||
PIN_FUNC_SELECT(self->periph, self->func);
|
||||
PIN_PULLUP_DIS(self->periph);
|
||||
gpio_output_set(0, 0, 1 << self->phys_port, 0);
|
||||
}
|
||||
}
|
||||
|
||||
int pin_get(uint pin) {
|
||||
if (pin == 16) {
|
||||
return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1;
|
||||
|
||||
@@ -53,6 +53,9 @@ STATIC const pyb_rtc_obj_t pyb_rtc_obj = {{&pyb_rtc_type}};
|
||||
uint32_t pyb_rtc_alarm0_wake; // see MACHINE_WAKE_xxx constants
|
||||
uint64_t pyb_rtc_alarm0_expiry; // in microseconds
|
||||
|
||||
// RTC overflow checking
|
||||
STATIC uint32_t rtc_last_ticks;
|
||||
|
||||
void mp_hal_rtc_init(void) {
|
||||
uint32_t magic;
|
||||
|
||||
@@ -64,7 +67,11 @@ void mp_hal_rtc_init(void) {
|
||||
int64_t delta = 0;
|
||||
system_rtc_mem_write(MEM_CAL_ADDR, &cal, sizeof(cal));
|
||||
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
|
||||
uint32_t len = 0;
|
||||
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));
|
||||
}
|
||||
// system_get_rtc_time() is always 0 after reset/deepsleep
|
||||
rtc_last_ticks = system_get_rtc_time();
|
||||
|
||||
// reset ALARM0 state
|
||||
pyb_rtc_alarm0_wake = 0;
|
||||
@@ -79,13 +86,11 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp
|
||||
return (mp_obj_t)&pyb_rtc_obj;
|
||||
}
|
||||
|
||||
STATIC uint64_t pyb_rtc_raw_us(uint64_t cal) {
|
||||
return (system_get_rtc_time() * cal) >> 12;
|
||||
};
|
||||
|
||||
void pyb_rtc_set_us_since_2000(uint64_t nowus) {
|
||||
uint32_t cal = system_rtc_clock_cali_proc();
|
||||
int64_t delta = nowus - pyb_rtc_raw_us(cal);
|
||||
// Save RTC ticks for overflow detection.
|
||||
rtc_last_ticks = system_get_rtc_time();
|
||||
int64_t delta = nowus - (((uint64_t)rtc_last_ticks * cal) >> 12);
|
||||
|
||||
// As the calibration value jitters quite a bit, to make the
|
||||
// clock at least somewhat practially usable, we need to store it
|
||||
@@ -96,11 +101,23 @@ void pyb_rtc_set_us_since_2000(uint64_t nowus) {
|
||||
uint64_t pyb_rtc_get_us_since_2000() {
|
||||
uint32_t cal;
|
||||
int64_t delta;
|
||||
uint32_t rtc_ticks;
|
||||
|
||||
system_rtc_mem_read(MEM_CAL_ADDR, &cal, sizeof(cal));
|
||||
system_rtc_mem_read(MEM_DELTA_ADDR, &delta, sizeof(delta));
|
||||
|
||||
return pyb_rtc_raw_us(cal) + delta;
|
||||
// ESP-SDK system_get_rtc_time() only returns uint32 and therefore
|
||||
// overflow about every 7:45h. Thus, we have to check for
|
||||
// overflow and handle it.
|
||||
rtc_ticks = system_get_rtc_time();
|
||||
if (rtc_ticks < rtc_last_ticks) {
|
||||
// Adjust delta because of RTC overflow.
|
||||
delta += (uint64_t)cal << 20;
|
||||
system_rtc_mem_write(MEM_DELTA_ADDR, &delta, sizeof(delta));
|
||||
}
|
||||
rtc_last_ticks = rtc_ticks;
|
||||
|
||||
return (((uint64_t)rtc_ticks * cal) >> 12) + delta;
|
||||
};
|
||||
|
||||
STATIC mp_obj_t pyb_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
@@ -145,20 +162,17 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_datetime_obj, 1, 2, pyb_rtc_d
|
||||
STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
uint8_t rtcram[MEM_USER_MAXLEN];
|
||||
uint32_t len;
|
||||
uint32_t magic;
|
||||
|
||||
if (n_args == 1) {
|
||||
|
||||
system_rtc_mem_read(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
|
||||
if (magic != MEM_MAGIC) {
|
||||
return mp_const_none;
|
||||
}
|
||||
// read RTC memory
|
||||
|
||||
system_rtc_mem_read(MEM_USER_LEN_ADDR, &len, sizeof(len));
|
||||
system_rtc_mem_read(MEM_USER_DATA_ADDR, rtcram, len + (4 - len % 4));
|
||||
|
||||
return mp_obj_new_bytes(rtcram, len);
|
||||
} else {
|
||||
// write RTC memory
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
@@ -167,8 +181,6 @@ STATIC mp_obj_t pyb_rtc_memory(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
"buffer too long"));
|
||||
}
|
||||
|
||||
magic = MEM_MAGIC;
|
||||
system_rtc_mem_write(MEM_USER_MAGIC_ADDR, &magic, sizeof(magic));
|
||||
len = bufinfo.len;
|
||||
system_rtc_mem_write(MEM_USER_LEN_ADDR, &len, sizeof(len));
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "etshal.h"
|
||||
@@ -124,6 +123,12 @@ STATIC void pyb_spi_init_helper(pyb_spi_obj_t *self, size_t n_args, const mp_obj
|
||||
if (args[ARG_miso].u_obj != MP_OBJ_NULL) {
|
||||
self->miso = mp_hal_get_pin_obj(args[ARG_miso].u_obj);
|
||||
}
|
||||
|
||||
// configure pins
|
||||
mp_hal_pin_write(self->sck, self->polarity);
|
||||
mp_hal_pin_output(self->sck);
|
||||
mp_hal_pin_output(self->mosi);
|
||||
mp_hal_pin_input(self->miso);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "ets_sys.h"
|
||||
#include "uart.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
// baudrate is currently fixed to this value
|
||||
@@ -136,7 +136,7 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
|
||||
|
||||
// wait for first char to become available
|
||||
if (!uart_rx_wait(self->timeout * 1000)) {
|
||||
*errcode = EAGAIN;
|
||||
*errcode = MP_EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t arg, int *errcode) {
|
||||
*errcode = EINVAL;
|
||||
*errcode = MP_EINVAL;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "py/mpconfig.h"
|
||||
#include "py/nlr.h"
|
||||
@@ -33,6 +32,7 @@
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
#include "esp_mphal.h"
|
||||
@@ -74,12 +74,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
|
||||
#if MICROPY_VFS_FAT
|
||||
mp_obj_t vfs_proxy_call(qstr method_name, mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (MP_STATE_PORT(fs_user_mount)[0] == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENODEV)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENODEV)));
|
||||
}
|
||||
|
||||
mp_obj_t meth[n_args + 2];
|
||||
mp_load_method(MP_STATE_PORT(fs_user_mount)[0], method_name, meth);
|
||||
memcpy(meth + 2, args, n_args * sizeof(*args));
|
||||
if (args != NULL) {
|
||||
memcpy(meth + 2, args, n_args * sizeof(*args));
|
||||
}
|
||||
return mp_call_method_n_kw(n_args, 0, meth);
|
||||
}
|
||||
|
||||
@@ -93,10 +95,29 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir);
|
||||
|
||||
STATIC mp_obj_t os_chdir(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_chdir, 1, &path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_chdir_obj, os_chdir);
|
||||
|
||||
STATIC mp_obj_t os_getcwd(void) {
|
||||
return vfs_proxy_call(MP_QSTR_getcwd, 0, NULL);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_getcwd_obj, os_getcwd);
|
||||
|
||||
STATIC mp_obj_t os_remove(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_remove, 1, &path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove);
|
||||
|
||||
STATIC mp_obj_t os_rename(mp_obj_t path_old, mp_obj_t path_new) {
|
||||
mp_obj_t args[2];
|
||||
args[0] = path_old;
|
||||
args[1] = path_new;
|
||||
return vfs_proxy_call(MP_QSTR_rename, 2, args);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t os_urandom(mp_obj_t num) {
|
||||
@@ -117,6 +138,11 @@ STATIC mp_obj_t os_dupterm_notify(mp_obj_t obj_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_dupterm_notify_obj, os_dupterm_notify);
|
||||
|
||||
STATIC mp_obj_t os_stat(mp_obj_t path_in) {
|
||||
return vfs_proxy_call(MP_QSTR_stat, 1, &path_in);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_stat_obj, os_stat);
|
||||
|
||||
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) },
|
||||
@@ -129,7 +155,11 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ 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_chdir), MP_ROM_PTR(&os_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&os_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&os_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&os_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&os_stat_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#define MICROPY_OBJ_REPR (MICROPY_OBJ_REPR_C)
|
||||
#define MICROPY_ALLOC_PATH_MAX (128)
|
||||
#define MICROPY_ALLOC_LEXER_INDENT_INIT (8)
|
||||
#define MICROPY_ALLOC_PARSE_RULE_INIT (48)
|
||||
#define MICROPY_ALLOC_PARSE_RULE_INC (8)
|
||||
#define MICROPY_ALLOC_PARSE_RESULT_INC (8)
|
||||
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
|
||||
#define MICROPY_EMIT_X64 (0)
|
||||
#define MICROPY_EMIT_THUMB (0)
|
||||
#define MICROPY_EMIT_INLINE_THUMB (0)
|
||||
@@ -19,6 +24,7 @@
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (1)
|
||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
|
||||
@@ -32,14 +38,17 @@
|
||||
#define MICROPY_PY_ARRAY (1)
|
||||
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
|
||||
#define MICROPY_PY_COLLECTIONS (1)
|
||||
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
|
||||
#define MICROPY_PY_MATH (1)
|
||||
#define MICROPY_PY_CMATH (0)
|
||||
#define MICROPY_PY_IO (1)
|
||||
#define MICROPY_PY_IO_FILEIO (1)
|
||||
#define MICROPY_PY_STRUCT (1)
|
||||
#define MICROPY_PY_SYS (1)
|
||||
#define MICROPY_PY_SYS_MAXSIZE (1)
|
||||
#define MICROPY_PY_SYS_EXIT (1)
|
||||
#define MICROPY_PY_SYS_STDFILES (1)
|
||||
#define MICROPY_PY_UERRNO (1)
|
||||
#define MICROPY_PY_UBINASCII (1)
|
||||
#define MICROPY_PY_UCTYPES (1)
|
||||
#define MICROPY_PY_UHASHLIB (1)
|
||||
@@ -51,6 +60,7 @@
|
||||
#define MICROPY_PY_UZLIB (1)
|
||||
#define MICROPY_PY_LWIP (1)
|
||||
#define MICROPY_PY_MACHINE (1)
|
||||
#define MICROPY_PY_MACHINE_PULSE (1)
|
||||
#define MICROPY_PY_MACHINE_I2C (1)
|
||||
#define MICROPY_PY_WEBSOCKET (1)
|
||||
#define MICROPY_PY_WEBREPL (1)
|
||||
@@ -105,6 +115,9 @@ typedef uint32_t sys_prot_t; // for modlwip
|
||||
|
||||
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
|
||||
|
||||
#define mp_type_fileio fatfs_type_fileio
|
||||
#define mp_type_textio fatfs_type_textio
|
||||
|
||||
// extra built in names to add to the global namespace
|
||||
#define MICROPY_PORT_BUILTINS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
|
||||
@@ -135,6 +148,7 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
|
||||
|
||||
#define MP_STATE_PORT MP_STATE_VM
|
||||
|
||||
|
||||
28
esp8266/scripts/apa102.py
Normal file
28
esp8266/scripts/apa102.py
Normal file
@@ -0,0 +1,28 @@
|
||||
# APA102 driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Robert Foss, Daniel Busch
|
||||
|
||||
from esp import apa102_write
|
||||
|
||||
class APA102:
|
||||
def __init__(self, clock_pin, data_pin, n):
|
||||
self.clock_pin = clock_pin
|
||||
self.data_pin = data_pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 4)
|
||||
|
||||
self.clock_pin.init(clock_pin.OUT)
|
||||
self.data_pin.init(data_pin.OUT)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b, brightness = val
|
||||
self.buf[index * 4] = r
|
||||
self.buf[index * 4 + 1] = g
|
||||
self.buf[index * 4 + 2] = b
|
||||
self.buf[index * 4 + 3] = brightness
|
||||
|
||||
def __getitem__(self, index):
|
||||
i = index * 4
|
||||
return self.buf[i], self.buf[i + 1], self.buf[i + 2], self.buf[i + 3]
|
||||
|
||||
def write(self):
|
||||
apa102_write(self.clock_pin, self.data_pin, self.buf)
|
||||
32
esp8266/scripts/dht.py
Normal file
32
esp8266/scripts/dht.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# DHT11/DHT22 driver for MicroPython on ESP8266
|
||||
# MIT license; Copyright (c) 2016 Damien P. George
|
||||
|
||||
import esp
|
||||
|
||||
class DHTBase:
|
||||
def __init__(self, pin):
|
||||
self.pin = pin
|
||||
self.buf = bytearray(5)
|
||||
|
||||
def measure(self):
|
||||
buf = self.buf
|
||||
esp.dht_readinto(self.pin, buf)
|
||||
if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xff != buf[4]:
|
||||
raise Exception("checksum error")
|
||||
|
||||
class DHT11(DHTBase):
|
||||
def humidity(self):
|
||||
return self.buf[0]
|
||||
|
||||
def temperature(self):
|
||||
return self.buf[2]
|
||||
|
||||
class DHT22(DHTBase):
|
||||
def humidity(self):
|
||||
return (self.buf[0] << 8 | self.buf[1]) * 0.1
|
||||
|
||||
def temperature(self):
|
||||
t = ((self.buf[2] & 0x7f) << 8 | self.buf[3]) * 0.1
|
||||
if self.buf[2] & 0x80:
|
||||
t = -t
|
||||
return t
|
||||
@@ -40,7 +40,7 @@ def setup():
|
||||
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()
|
||||
#import webrepl
|
||||
#webrepl.start()
|
||||
""")
|
||||
return vfs
|
||||
|
||||
@@ -8,7 +8,7 @@ class NeoPixel:
|
||||
self.pin = pin
|
||||
self.n = n
|
||||
self.buf = bytearray(n * 3)
|
||||
self.pin.init(pin.OUT, pin.PULL_NONE)
|
||||
self.pin.init(pin.OUT)
|
||||
|
||||
def __setitem__(self, index, val):
|
||||
r, g, b = val
|
||||
@@ -20,5 +20,12 @@ class NeoPixel:
|
||||
i = index * 3
|
||||
return self.buf[i + 1], self.buf[i], self.buf[i + 2]
|
||||
|
||||
def fill(self, color):
|
||||
r, g, b = color
|
||||
for i in range(len(self.buf) / 3):
|
||||
self.buf[i * 3] = g
|
||||
self.buf[i * 3 + 1] = r
|
||||
self.buf[i * 3 + 2] = b
|
||||
|
||||
def write(self):
|
||||
neopixel_write(self.pin, self.buf, True)
|
||||
|
||||
@@ -10,10 +10,12 @@ except:
|
||||
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
|
||||
NTP_DELTA = 3155673600
|
||||
|
||||
host = "pool.ntp.org"
|
||||
|
||||
def time():
|
||||
NTP_QUERY = bytearray(48)
|
||||
NTP_QUERY[0] = 0x1b
|
||||
addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-1]
|
||||
addr = socket.getaddrinfo(host, 123)[0][-1]
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.settimeout(1)
|
||||
res = s.sendto(NTP_QUERY, addr)
|
||||
|
||||
@@ -13,7 +13,7 @@ class OneWire:
|
||||
|
||||
def __init__(self, pin):
|
||||
self.pin = pin
|
||||
self.pin.init(pin.OPEN_DRAIN, pin.PULL_NONE)
|
||||
self.pin.init(pin.OPEN_DRAIN)
|
||||
|
||||
def reset(self):
|
||||
return _ow.reset(self.pin)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import esp
|
||||
import uctypes
|
||||
import network
|
||||
import lwip
|
||||
|
||||
|
||||
def main():
|
||||
@@ -7,6 +9,7 @@ def main():
|
||||
ROM = uctypes.bytearray_at(0x40200000, 16)
|
||||
fid = esp.flash_id()
|
||||
|
||||
print("FlashROM:")
|
||||
print("Flash ID: %x (Vendor: %x Device: %x)" % (fid, fid & 0xff, fid & 0xff00 | fid >> 16))
|
||||
|
||||
print("Flash bootloader data:")
|
||||
@@ -15,5 +18,14 @@ def main():
|
||||
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)))
|
||||
|
||||
print("\nNetworking:")
|
||||
print("STA ifconfig:", network.WLAN(network.STA_IF).ifconfig())
|
||||
print("AP ifconfig:", network.WLAN(network.AP_IF).ifconfig())
|
||||
print("Free WiFi driver buffers of type:")
|
||||
for i in range(5):
|
||||
print("%d: %d" % (i, esp.esf_free_bufs(i)))
|
||||
print("lwIP PCBs:")
|
||||
lwip.print_pcbs()
|
||||
|
||||
|
||||
main()
|
||||
|
||||
@@ -10,7 +10,7 @@ listen_s = None
|
||||
client_s = None
|
||||
|
||||
def setup_conn(port, accept_handler):
|
||||
global listen_s, client_s
|
||||
global listen_s
|
||||
listen_s = socket.socket()
|
||||
listen_s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
@@ -19,11 +19,13 @@ def setup_conn(port, accept_handler):
|
||||
|
||||
listen_s.bind(addr)
|
||||
listen_s.listen(1)
|
||||
listen_s.setsockopt(socket.SOL_SOCKET, 20, accept_handler)
|
||||
if accept_handler:
|
||||
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))
|
||||
return listen_s
|
||||
|
||||
|
||||
def accept_conn(listen_sock):
|
||||
@@ -49,14 +51,25 @@ def stop():
|
||||
listen_s.close()
|
||||
|
||||
|
||||
def start(port=8266):
|
||||
def start(port=8266, password=None):
|
||||
stop()
|
||||
try:
|
||||
import port_config
|
||||
_webrepl.password(port_config.WEBREPL_PASS)
|
||||
if password is None:
|
||||
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")
|
||||
else:
|
||||
_webrepl.password(password)
|
||||
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")
|
||||
|
||||
|
||||
def start_foreground(port=8266):
|
||||
stop()
|
||||
s = setup_conn(port, None)
|
||||
accept_conn(s)
|
||||
|
||||
@@ -26,7 +26,7 @@ def getpass(stream, prompt):
|
||||
stream.write("\r\n")
|
||||
return passwd
|
||||
passwd += c
|
||||
# stream.write("*")
|
||||
stream.write("*")
|
||||
|
||||
def handle_conn(listen_sock):
|
||||
cl, remote_addr = listen_sock.accept()
|
||||
@@ -60,6 +60,9 @@ some boards, you may need to press reset button or reconnect power.\r
|
||||
if len(passwd1) < 4:
|
||||
ws.write("Password too short\r\n")
|
||||
continue
|
||||
elif len(passwd1) > 9:
|
||||
ws.write("Password too long\r\n")
|
||||
continue
|
||||
passwd2 = getpass(ws, "Confirm password: ")
|
||||
if passwd1 == passwd2:
|
||||
break
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
#include "user_interface.h"
|
||||
#include "esp_mphal.h"
|
||||
|
||||
// seems that this is missing in the Espressif SDK
|
||||
#define FUNC_U0RXD 0
|
||||
|
||||
#define UART_REPL UART0
|
||||
|
||||
// UartDev is defined and initialized in rom code.
|
||||
@@ -53,7 +56,7 @@ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) {
|
||||
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, NULL);
|
||||
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
|
||||
}
|
||||
|
||||
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));
|
||||
|
||||
60
esp8266/xtirq.h
Normal file
60
esp8266/xtirq.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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_XTIRQ_H__
|
||||
#define __MICROPY_INCLUDED_ESP8266_XTIRQ_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// returns the value of "intlevel" from the PS register
|
||||
static inline uint32_t query_irq(void) {
|
||||
uint32_t ps;
|
||||
__asm__ volatile("rsr %0, ps" : "=a" (ps));
|
||||
return ps & 0xf;
|
||||
}
|
||||
|
||||
// irqs with a priority value lower or equal to "intlevel" will be disabled
|
||||
// "intlevel" should be between 0 and 15 inclusive, and should be an integer
|
||||
static inline uint32_t raise_irq_pri(uint32_t intlevel) {
|
||||
uint32_t old_ps;
|
||||
__asm__ volatile ("rsil %0, %1" : "=a" (old_ps) : "I" (intlevel));
|
||||
return old_ps;
|
||||
}
|
||||
|
||||
// "ps" should be the value returned from raise_irq_pri
|
||||
static inline void restore_irq_pri(uint32_t ps) {
|
||||
__asm__ volatile ("wsr %0, ps; rsync" :: "a" (ps));
|
||||
}
|
||||
|
||||
static inline uint32_t disable_irq(void) {
|
||||
return raise_irq_pri(15);
|
||||
}
|
||||
|
||||
static inline void enable_irq(uint32_t irq_state) {
|
||||
restore_irq_pri(irq_state);
|
||||
}
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_XTIRQ_H__
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "fsusermount.h"
|
||||
#include "extmod/fsusermount.h"
|
||||
|
||||
fs_user_mount_t *fatfs_mount_mkfs(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args, bool mkfs) {
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
|
||||
@@ -48,7 +48,7 @@ STATIC void mp_hal_i2c_delay(machine_i2c_obj_t *self) {
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_scl_low(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_low(self->scl);
|
||||
mp_hal_pin_od_low(self->scl);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
|
||||
@@ -56,7 +56,7 @@ STATIC void mp_hal_i2c_scl_release(machine_i2c_obj_t *self) {
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_sda_low(machine_i2c_obj_t *self) {
|
||||
mp_hal_pin_low(self->sda);
|
||||
mp_hal_pin_od_low(self->sda);
|
||||
}
|
||||
|
||||
STATIC void mp_hal_i2c_sda_release(machine_i2c_obj_t *self) {
|
||||
@@ -91,8 +91,8 @@ STATIC void mp_hal_i2c_init(machine_i2c_obj_t *self, uint32_t 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_pin_open_drain(self->scl);
|
||||
mp_hal_pin_open_drain(self->sda);
|
||||
mp_hal_i2c_stop(self);
|
||||
}
|
||||
|
||||
|
||||
67
extmod/machine_pulse.c
Normal file
67
extmod/machine_pulse.c
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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 "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/machine_pulse.h"
|
||||
|
||||
#if MICROPY_PY_MACHINE_PULSE
|
||||
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us) {
|
||||
mp_uint_t start = mp_hal_ticks_us();
|
||||
while (mp_hal_pin_read(pin) != pulse_level) {
|
||||
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
|
||||
return (mp_uint_t)-1;
|
||||
}
|
||||
}
|
||||
start = mp_hal_ticks_us();
|
||||
while (mp_hal_pin_read(pin) == pulse_level) {
|
||||
if ((mp_uint_t)(mp_hal_ticks_us() - start) >= timeout_us) {
|
||||
return (mp_uint_t)-1;
|
||||
}
|
||||
}
|
||||
return mp_hal_ticks_us() - start;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_time_pulse_us_(size_t n_args, const mp_obj_t *args) {
|
||||
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(args[0]);
|
||||
int level = 0;
|
||||
if (mp_obj_is_true(args[1])) {
|
||||
level = 1;
|
||||
}
|
||||
mp_uint_t timeout_us = 1000000;
|
||||
if (n_args > 2) {
|
||||
timeout_us = mp_obj_get_int(args[2]);
|
||||
}
|
||||
mp_uint_t us = machine_time_pulse_us(pin, level, timeout_us);
|
||||
if (us == (mp_uint_t)-1) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
|
||||
}
|
||||
return mp_obj_new_int(us);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_time_pulse_us_obj, 2, 3, machine_time_pulse_us_);
|
||||
|
||||
#endif
|
||||
37
extmod/machine_pulse.h
Normal file
37
extmod/machine_pulse.h
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.
|
||||
*/
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
|
||||
#define __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
mp_uint_t machine_time_pulse_us(mp_hal_pin_obj_t pin, int pulse_level, mp_uint_t timeout_us);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(machine_time_pulse_us_obj);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_EXTMOD_MACHINE_PULSE_H__
|
||||
@@ -34,6 +34,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_uos_dupterm_obj);
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
|
||||
void mp_uos_deactivate(const char *msg, mp_obj_t exc);
|
||||
#else
|
||||
#define mp_uos_dupterm_tx_strn(s, l)
|
||||
#endif
|
||||
|
||||
128
extmod/modlwip.c
128
extmod/modlwip.c
@@ -26,13 +26,13 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "netutils.h"
|
||||
@@ -172,45 +172,45 @@ STATIC const mp_obj_type_t lwip_slip_type = {
|
||||
// investigate in more detail.
|
||||
#if LWIP_VERSION < 0x01040100
|
||||
static const int error_lookup_table[] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
MP_EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
|
||||
ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -9 Connection reset. */
|
||||
ENOTCONN, /* ERR_CLSD -10 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -11 Not connected. */
|
||||
EIO, /* ERR_ARG -12 Illegal argument. */
|
||||
EADDRINUSE, /* ERR_USE -13 Address in use. */
|
||||
-1, /* ERR_IF -14 Low-level netif error */
|
||||
EALREADY, /* ERR_ISCONN -15 Already connected. */
|
||||
EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
|
||||
MP_ECONNABORTED, /* ERR_ABRT -8 Connection aborted. */
|
||||
MP_ECONNRESET, /* ERR_RST -9 Connection reset. */
|
||||
MP_ENOTCONN, /* ERR_CLSD -10 Connection closed. */
|
||||
MP_ENOTCONN, /* ERR_CONN -11 Not connected. */
|
||||
MP_EIO, /* ERR_ARG -12 Illegal argument. */
|
||||
MP_EADDRINUSE, /* ERR_USE -13 Address in use. */
|
||||
-1, /* ERR_IF -14 Low-level netif error */
|
||||
MP_EALREADY, /* ERR_ISCONN -15 Already connected. */
|
||||
MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
|
||||
};
|
||||
#else
|
||||
static const int error_lookup_table[] = {
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
0, /* ERR_OK 0 No error, everything OK. */
|
||||
MP_ENOMEM, /* ERR_MEM -1 Out of memory error. */
|
||||
MP_ENOBUFS, /* ERR_BUF -2 Buffer error. */
|
||||
MP_EWOULDBLOCK, /* ERR_TIMEOUT -3 Timeout */
|
||||
MP_EHOSTUNREACH, /* ERR_RTE -4 Routing problem. */
|
||||
MP_EINPROGRESS, /* ERR_INPROGRESS -5 Operation in progress */
|
||||
MP_EINVAL, /* ERR_VAL -6 Illegal value. */
|
||||
MP_EWOULDBLOCK, /* ERR_WOULDBLOCK -7 Operation would block. */
|
||||
|
||||
EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||
EALREADY, /* ERR_ISCONN -9 Already connected. */
|
||||
ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
|
||||
ECONNRESET, /* ERR_RST -11 Connection reset. */
|
||||
ENOTCONN, /* ERR_CLSD -12 Connection closed. */
|
||||
ENOTCONN, /* ERR_CONN -13 Not connected. */
|
||||
EIO, /* ERR_ARG -14 Illegal argument. */
|
||||
-1, /* ERR_IF -15 Low-level netif error */
|
||||
EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
|
||||
MP_EADDRINUSE, /* ERR_USE -8 Address in use. */
|
||||
MP_EALREADY, /* ERR_ISCONN -9 Already connected. */
|
||||
MP_ECONNABORTED, /* ERR_ABRT -10 Connection aborted. */
|
||||
MP_ECONNRESET, /* ERR_RST -11 Connection reset. */
|
||||
MP_ENOTCONN, /* ERR_CLSD -12 Connection closed. */
|
||||
MP_ENOTCONN, /* ERR_CONN -13 Not connected. */
|
||||
MP_EIO, /* ERR_ARG -14 Illegal argument. */
|
||||
-1, /* ERR_IF -15 Low-level netif error */
|
||||
MP_EBADF, /* _ERR_BADF -16 Closed socket (null pcb) */
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -311,6 +311,17 @@ STATIC err_t _lwip_tcp_recv_unaccepted(void *arg, struct tcp_pcb *pcb, struct pb
|
||||
return ERR_BUF;
|
||||
}
|
||||
|
||||
// "Poll" (idle) callback to be called ASAP after accept callback
|
||||
// to execute Python callback function, as it can't be executed
|
||||
// from accept callback itself.
|
||||
STATIC err_t _lwip_tcp_accept_finished(void *arg, struct tcp_pcb *pcb)
|
||||
{
|
||||
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
|
||||
tcp_poll(pcb, NULL, 0);
|
||||
exec_user_callback(socket);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// Callback for incoming tcp connections.
|
||||
STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
|
||||
lwip_socket_obj_t *socket = (lwip_socket_obj_t*)arg;
|
||||
@@ -323,7 +334,12 @@ STATIC err_t _lwip_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err) {
|
||||
return ERR_BUF;
|
||||
} else {
|
||||
socket->incoming.connection = newpcb;
|
||||
exec_user_callback(socket);
|
||||
if (socket->callback != MP_OBJ_NULL) {
|
||||
// Schedule accept callback to be called when lwIP is done
|
||||
// with processing this incoming connection on its side and
|
||||
// is idle.
|
||||
tcp_poll(newpcb, _lwip_tcp_accept_finished, 1);
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
@@ -363,7 +379,7 @@ STATIC mp_uint_t lwip_udp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
|
||||
// FIXME: maybe PBUF_ROM?
|
||||
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM);
|
||||
if (p == NULL) {
|
||||
*_errno = ENOMEM;
|
||||
*_errno = MP_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -401,7 +417,7 @@ STATIC mp_uint_t lwip_udp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
|
||||
if (socket->incoming.pbuf != NULL) break;
|
||||
}
|
||||
if (socket->incoming.pbuf == NULL) {
|
||||
*_errno = ETIMEDOUT;
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
@@ -444,7 +460,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
|
||||
if (available == 0) {
|
||||
// Non-blocking socket
|
||||
if (socket->timeout == 0) {
|
||||
*_errno = EAGAIN;
|
||||
*_errno = MP_EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
@@ -457,7 +473,7 @@ STATIC mp_uint_t lwip_tcp_send(lwip_socket_obj_t *socket, const byte *buf, mp_ui
|
||||
// Avoid sending too small packets, so wait until at least 16 bytes available
|
||||
while (socket->state >= STATE_CONNECTED && (available = tcp_sndbuf(socket->pcb.tcp)) < 16) {
|
||||
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
|
||||
*_errno = ETIMEDOUT;
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
poll_sockets();
|
||||
@@ -491,14 +507,14 @@ STATIC mp_uint_t lwip_tcp_receive(lwip_socket_obj_t *socket, byte *buf, mp_uint_
|
||||
if (socket->state == STATE_PEER_CLOSED) {
|
||||
return 0;
|
||||
}
|
||||
*_errno = EAGAIN;
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
while (socket->state == STATE_CONNECTED && socket->incoming.pbuf == NULL) {
|
||||
if (socket->timeout != -1 && mp_hal_ticks_ms() - start > socket->timeout) {
|
||||
*_errno = ETIMEDOUT;
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
poll_sockets();
|
||||
@@ -570,11 +586,11 @@ STATIC mp_obj_t lwip_socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args
|
||||
case MOD_NETWORK_SOCK_STREAM: socket->pcb.tcp = tcp_new(); break;
|
||||
case MOD_NETWORK_SOCK_DGRAM: socket->pcb.udp = udp_new(); break;
|
||||
//case MOD_NETWORK_SOCK_RAW: socket->pcb.raw = raw_new(); break;
|
||||
default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
|
||||
default: nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
|
||||
}
|
||||
|
||||
if (socket->pcb.tcp == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
|
||||
}
|
||||
|
||||
switch (socket->type) {
|
||||
@@ -670,15 +686,15 @@ STATIC mp_obj_t lwip_socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
|
||||
mp_int_t backlog = mp_obj_get_int(backlog_in);
|
||||
|
||||
if (socket->pcb.tcp == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
|
||||
}
|
||||
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
|
||||
}
|
||||
|
||||
struct tcp_pcb *new_pcb = tcp_listen_with_backlog(socket->pcb.tcp, (u8_t)backlog);
|
||||
if (new_pcb == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ENOMEM)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ENOMEM)));
|
||||
}
|
||||
socket->pcb.tcp = new_pcb;
|
||||
tcp_accept(new_pcb, _lwip_tcp_accept);
|
||||
@@ -691,15 +707,15 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
|
||||
lwip_socket_obj_t *socket = self_in;
|
||||
|
||||
if (socket->pcb.tcp == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
|
||||
}
|
||||
if (socket->type != MOD_NETWORK_SOCK_STREAM) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EOPNOTSUPP)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EOPNOTSUPP)));
|
||||
}
|
||||
// I need to do this because "tcp_accepted", later, is a macro.
|
||||
struct tcp_pcb *listener = socket->pcb.tcp;
|
||||
if (listener->state != LISTEN) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINVAL)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINVAL)));
|
||||
}
|
||||
|
||||
// accept incoming connection
|
||||
@@ -710,7 +726,7 @@ STATIC mp_obj_t lwip_socket_accept(mp_obj_t self_in) {
|
||||
if (socket->incoming.connection != NULL) break;
|
||||
}
|
||||
if (socket->incoming.connection == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
|
||||
}
|
||||
} else {
|
||||
while (socket->incoming.connection == NULL) {
|
||||
@@ -757,7 +773,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
lwip_socket_obj_t *socket = self_in;
|
||||
|
||||
if (socket->pcb.tcp == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EBADF)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EBADF)));
|
||||
}
|
||||
|
||||
// get address
|
||||
@@ -772,9 +788,9 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
case MOD_NETWORK_SOCK_STREAM: {
|
||||
if (socket->state != STATE_NEW) {
|
||||
if (socket->state == STATE_CONNECTED) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EALREADY)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EALREADY)));
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EINPROGRESS)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EINPROGRESS)));
|
||||
}
|
||||
}
|
||||
// Register our recieve callback.
|
||||
@@ -794,7 +810,7 @@ STATIC mp_obj_t lwip_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
if (socket->state != STATE_CONNECTING) break;
|
||||
}
|
||||
if (socket->state == STATE_CONNECTING) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(ETIMEDOUT)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ETIMEDOUT)));
|
||||
}
|
||||
} else {
|
||||
while (socket->state == STATE_CONNECTING) {
|
||||
@@ -982,7 +998,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
// most useful behavior is: check whether we will be able to send all of input
|
||||
// data without EAGAIN, and if won't be, raise it without sending any.
|
||||
if (bufinfo.len > tcp_sndbuf(socket->pcb.tcp)) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EAGAIN)));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_EAGAIN)));
|
||||
}
|
||||
}
|
||||
// TODO: In CPython3.5, socket timeout should apply to the
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/binary.h"
|
||||
#include "modubinascii.h"
|
||||
#include "extmod/modubinascii.h"
|
||||
|
||||
|
||||
mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
|
||||
|
||||
@@ -31,9 +31,20 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/objtuple.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
|
||||
void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
|
||||
mp_obj_t term = MP_STATE_PORT(term_obj);
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, msg);
|
||||
if (exc != MP_OBJ_NULL) {
|
||||
mp_obj_print_exception(&mp_plat_print, exc);
|
||||
}
|
||||
mp_stream_close(term);
|
||||
}
|
||||
|
||||
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
|
||||
if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
|
||||
nlr_buf_t nlr;
|
||||
@@ -44,9 +55,7 @@ void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
|
||||
mp_call_method_n_kw(1, 0, write_m);
|
||||
nlr_pop();
|
||||
} else {
|
||||
MP_STATE_PORT(term_obj) = NULL;
|
||||
mp_printf(&mp_plat_print, "dupterm: Exception in write() method, deactivating: ");
|
||||
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
|
||||
mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, bool server_side) {
|
||||
|
||||
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_ssl_socket_t *self = self_in;
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<_SSLSocket %p>", self->ssl_sock);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_ssl_socket_t *o = o_in;
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
while (o->bytes_left == 0) {
|
||||
mp_int_t r = ssl_read(o->ssl_sock, &o->buf);
|
||||
@@ -113,7 +113,7 @@ STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errc
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_ssl_socket_t *o = o_in;
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
mp_int_t r = ssl_write(o->ssl_sock, buf, size);
|
||||
if (r < 0) {
|
||||
*errcode = r;
|
||||
@@ -123,7 +123,7 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
|
||||
mp_obj_ssl_socket_t *self = self_in;
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
ssl_free(self->ssl_sock);
|
||||
ssl_ctx_free(self->ssl_ctx);
|
||||
|
||||
@@ -133,13 +133,13 @@ STATIC mp_obj_t socket_close(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
|
||||
|
||||
STATIC const mp_map_elem_t ussl_socket_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readall), (mp_obj_t)&mp_stream_readall_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
|
||||
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
|
||||
@@ -157,10 +157,10 @@ STATIC const mp_obj_type_t ussl_socket_type = {
|
||||
.getiter = NULL,
|
||||
.iternext = NULL,
|
||||
.stream_p = &ussl_socket_stream_p,
|
||||
.locals_dict = (mp_obj_t)&ussl_socket_locals_dict,
|
||||
.locals_dict = (void*)&ussl_socket_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
// TODO: Implement more args
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
@@ -175,13 +175,13 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args,
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
|
||||
return socket_new(sock, args.server_side.u_bool);
|
||||
return MP_OBJ_FROM_PTR(socket_new(sock, args.server_side.u_bool));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ussl) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_wrap_socket), (mp_obj_t)&mod_ssl_wrap_socket_obj },
|
||||
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
|
||||
@@ -195,6 +195,8 @@ const mp_obj_module_t mp_module_ussl = {
|
||||
|
||||
// These functions might be split to stream_posix.c. They are referenced by
|
||||
// axtls os_port.h .
|
||||
ssize_t mp_stream_posix_write(void *sock_obj, const void *buf, size_t len);
|
||||
ssize_t mp_stream_posix_read(void *sock_obj, void *buf, size_t len);
|
||||
|
||||
int mp_stream_errno;
|
||||
|
||||
|
||||
@@ -250,8 +250,8 @@ STATIC mp_uint_t _webrepl_read(mp_obj_t self_in, void *buf, mp_uint_t size, int
|
||||
|
||||
DEBUG_printf("webrepl: Writing %lu bytes to file\n", buf_sz);
|
||||
int err;
|
||||
mp_uint_t res = mp_stream_writeall(self->cur_file, filebuf, buf_sz, &err);
|
||||
if(res == MP_STREAM_ERROR) {
|
||||
mp_uint_t res = mp_stream_write_exactly(self->cur_file, filebuf, buf_sz, &err);
|
||||
if (err != 0 || res != buf_sz) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
@@ -284,6 +284,13 @@ STATIC mp_uint_t webrepl_write(mp_obj_t self_in, const void *buf, mp_uint_t size
|
||||
return stream_p->write(self->sock, buf, size, errcode);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t webrepl_close(mp_obj_t self_in) {
|
||||
mp_obj_webrepl_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// TODO: This is a place to do cleanup
|
||||
return mp_stream_close(self->sock);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
|
||||
|
||||
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
|
||||
mp_uint_t len;
|
||||
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
|
||||
@@ -297,6 +304,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_set_password_obj, webrepl_set_password)
|
||||
STATIC const mp_map_elem_t webrepl_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&webrepl_close_obj },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(webrepl_locals_dict, webrepl_locals_dict_table);
|
||||
|
||||
|
||||
@@ -240,9 +240,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
|
||||
mp_call_method_n_kw(1, 0, dest);
|
||||
}
|
||||
|
||||
mp_uint_t out_sz = mp_stream_writeall(self->sock, header, hdr_sz, errcode);
|
||||
if (out_sz != MP_STREAM_ERROR) {
|
||||
out_sz = mp_stream_writeall(self->sock, buf, size, errcode);
|
||||
mp_uint_t out_sz = mp_stream_write_exactly(self->sock, header, hdr_sz, errcode);
|
||||
if (*errcode == 0) {
|
||||
out_sz = mp_stream_write_exactly(self->sock, buf, size, errcode);
|
||||
}
|
||||
|
||||
if (self->opts & BLOCKING_WRITE) {
|
||||
@@ -250,6 +250,9 @@ STATIC mp_uint_t websocket_write(mp_obj_t self_in, const void *buf, mp_uint_t si
|
||||
mp_call_method_n_kw(1, 0, dest);
|
||||
}
|
||||
|
||||
if (*errcode != 0) {
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return out_sz;
|
||||
}
|
||||
|
||||
@@ -269,10 +272,19 @@ STATIC mp_uint_t websocket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t websocket_close(mp_obj_t self_in) {
|
||||
mp_obj_websocket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// TODO: Send close signaling to the other side, otherwise it's
|
||||
// abrupt close (connection abort).
|
||||
return mp_stream_close(self->sock);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(websocket_close_obj, websocket_close);
|
||||
|
||||
STATIC const mp_map_elem_t websocket_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&mp_stream_ioctl_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&websocket_close_obj },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(websocket_locals_dict, websocket_locals_dict_table);
|
||||
|
||||
|
||||
165
extmod/vfs_fat.c
165
extmod/vfs_fat.c
@@ -28,12 +28,14 @@
|
||||
#include "py/mpconfig.h"
|
||||
#if MICROPY_VFS_FAT
|
||||
|
||||
#include <string.h>
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "lib/fatfs/diskio.h"
|
||||
#include "extmod/vfs_fat_file.h"
|
||||
#include "fsusermount.h"
|
||||
#include "extmod/fsusermount.h"
|
||||
#include "timeutils.h"
|
||||
|
||||
#define mp_obj_fat_vfs_t fs_user_mount_t
|
||||
|
||||
@@ -79,12 +81,11 @@ STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
const char *path = mp_obj_str_get_str(path_in);
|
||||
// TODO check that path is actually a file before trying to unlink it
|
||||
FRESULT res = f_unlink(path);
|
||||
switch (res) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
default:
|
||||
// TODO: standard errno's
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error removing file '%s'", path));
|
||||
if (res == FR_OK) {
|
||||
return mp_const_none;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove);
|
||||
@@ -94,11 +95,11 @@ STATIC mp_obj_t fat_vfs_rename(mp_obj_t vfs_in, mp_obj_t path_in, mp_obj_t path_
|
||||
const char *old_path = mp_obj_str_get_str(path_in);
|
||||
const char *new_path = mp_obj_str_get_str(path_out);
|
||||
FRESULT res = f_rename(old_path, new_path);
|
||||
switch (res) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error renaming file '%s' to '%s'", old_path, new_path));
|
||||
if (res == FR_OK) {
|
||||
return mp_const_none;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -108,25 +109,149 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
|
||||
(void)vfs_in;
|
||||
const char *path = mp_obj_str_get_str(path_o);
|
||||
FRESULT res = f_mkdir(path);
|
||||
switch (res) {
|
||||
case FR_OK:
|
||||
return mp_const_none;
|
||||
case FR_EXIST:
|
||||
// TODO should be FileExistsError
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "File exists: '%s'", path));
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "Error creating directory '%s'", path));
|
||||
if (res == FR_OK) {
|
||||
return mp_const_none;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
|
||||
|
||||
/// Change current directory.
|
||||
STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
(void)vfs_in;
|
||||
const char *path;
|
||||
path = mp_obj_str_get_str(path_in);
|
||||
|
||||
FRESULT res = f_chdrive(path);
|
||||
|
||||
if (res == FR_OK) {
|
||||
res = f_chdir(path);
|
||||
}
|
||||
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);
|
||||
|
||||
/// Get the current directory.
|
||||
STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
|
||||
(void)vfs_in;
|
||||
char buf[MICROPY_ALLOC_PATH_MAX + 1];
|
||||
FRESULT res = f_getcwd(buf, sizeof buf);
|
||||
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
|
||||
return mp_obj_new_str(buf, strlen(buf), false);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
|
||||
|
||||
// Checks for path equality, ignoring trailing slashes:
|
||||
// path_equal(/, /) -> true
|
||||
// second argument must be in canonical form (meaning no trailing slash, unless it's just /)
|
||||
STATIC bool path_equal(const char *path, const char *path_canonical) {
|
||||
while (*path_canonical != '\0' && *path == *path_canonical) {
|
||||
++path;
|
||||
++path_canonical;
|
||||
}
|
||||
if (*path_canonical != '\0') {
|
||||
return false;
|
||||
}
|
||||
while (*path == '/') {
|
||||
++path;
|
||||
}
|
||||
return *path == '\0';
|
||||
}
|
||||
|
||||
/// \function stat(path)
|
||||
/// Get the status of a file or directory.
|
||||
STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
(void)vfs_in;
|
||||
const char *path = mp_obj_str_get_str(path_in);
|
||||
|
||||
FILINFO fno;
|
||||
#if _USE_LFN
|
||||
fno.lfname = NULL;
|
||||
fno.lfsize = 0;
|
||||
#endif
|
||||
FRESULT res;
|
||||
|
||||
if (path_equal(path, "/")) {
|
||||
// stat root directory
|
||||
fno.fsize = 0;
|
||||
fno.fdate = 0;
|
||||
fno.ftime = 0;
|
||||
fno.fattrib = AM_DIR;
|
||||
} else {
|
||||
res = FR_NO_PATH;
|
||||
for (size_t i = 0; i < MP_ARRAY_SIZE(MP_STATE_PORT(fs_user_mount)); ++i) {
|
||||
fs_user_mount_t *vfs = MP_STATE_PORT(fs_user_mount)[i];
|
||||
if (vfs != NULL && path_equal(path, vfs->str)) {
|
||||
// stat mounted device directory
|
||||
fno.fsize = 0;
|
||||
fno.fdate = 0;
|
||||
fno.ftime = 0;
|
||||
fno.fattrib = AM_DIR;
|
||||
res = FR_OK;
|
||||
}
|
||||
}
|
||||
if (res == FR_NO_PATH) {
|
||||
// stat normal file
|
||||
res = f_stat(path, &fno);
|
||||
}
|
||||
if (res != FR_OK) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
}
|
||||
}
|
||||
|
||||
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
|
||||
mp_int_t mode = 0;
|
||||
if (fno.fattrib & AM_DIR) {
|
||||
mode |= 0x4000; // stat.S_IFDIR
|
||||
} else {
|
||||
mode |= 0x8000; // stat.S_IFREG
|
||||
}
|
||||
mp_int_t seconds = timeutils_seconds_since_2000(
|
||||
1980 + ((fno.fdate >> 9) & 0x7f),
|
||||
(fno.fdate >> 5) & 0x0f,
|
||||
fno.fdate & 0x1f,
|
||||
(fno.ftime >> 11) & 0x1f,
|
||||
(fno.ftime >> 5) & 0x3f,
|
||||
2 * (fno.ftime & 0x1f)
|
||||
);
|
||||
t->items[0] = MP_OBJ_NEW_SMALL_INT(mode); // st_mode
|
||||
t->items[1] = MP_OBJ_NEW_SMALL_INT(0); // st_ino
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // st_dev
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(0); // st_nlink
|
||||
t->items[4] = MP_OBJ_NEW_SMALL_INT(0); // st_uid
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // st_gid
|
||||
t->items[6] = MP_OBJ_NEW_SMALL_INT(fno.fsize); // st_size
|
||||
t->items[7] = MP_OBJ_NEW_SMALL_INT(seconds); // st_atime
|
||||
t->items[8] = MP_OBJ_NEW_SMALL_INT(seconds); // st_mtime
|
||||
t->items[9] = MP_OBJ_NEW_SMALL_INT(seconds); // st_ctime
|
||||
|
||||
return MP_OBJ_FROM_PTR(t);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_stat_obj, fat_vfs_stat);
|
||||
|
||||
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&fat_vfs_getcwd_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&fat_vfs_remove_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&fat_vfs_rename_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&fat_vfs_stat_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(fat_vfs_locals_dict, fat_vfs_locals_dict_table);
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
#include "lib/fatfs/ff.h"
|
||||
#include "lib/fatfs/diskio.h"
|
||||
#include "extmod/vfs_fat_file.h"
|
||||
#include "fsusermount.h"
|
||||
#include "extmod/fsusermount.h"
|
||||
#include "py/lexer.h"
|
||||
|
||||
#if _USE_LFN
|
||||
@@ -54,8 +54,9 @@ mp_obj_t fat_vfs_listdir(const char *path, bool is_str_type) {
|
||||
|
||||
res = f_opendir(&dir, path); /* Open the directory */
|
||||
if (res != FR_OK) {
|
||||
// TODO should be mp_type_FileNotFoundError
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "No such file or directory: '%s'", path));
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError,
|
||||
MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res])));
|
||||
|
||||
}
|
||||
|
||||
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
|
||||
|
||||
39
extmod/virtpin.c
Normal file
39
extmod/virtpin.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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 "extmod/virtpin.h"
|
||||
|
||||
int mp_virtual_pin_read(mp_obj_t pin) {
|
||||
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
|
||||
mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
|
||||
return pin_p->ioctl(pin, MP_PIN_READ, 0, NULL);
|
||||
}
|
||||
|
||||
void mp_virtual_pin_write(mp_obj_t pin, int value) {
|
||||
mp_obj_base_t* s = (mp_obj_base_t*)MP_OBJ_TO_PTR(pin);
|
||||
mp_pin_p_t *pin_p = (mp_pin_p_t*)s->type->stream_p;
|
||||
pin_p->ioctl(pin, MP_PIN_WRITE, value, NULL);
|
||||
}
|
||||
40
extmod/virtpin.h
Normal file
40
extmod/virtpin.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 "py/obj.h"
|
||||
|
||||
#define MP_PIN_READ (1)
|
||||
#define MP_PIN_WRITE (2)
|
||||
#define MP_PIN_INPUT (3)
|
||||
#define MP_PIN_OUTPUT (4)
|
||||
|
||||
// Pin protocol
|
||||
typedef struct _mp_pin_p_t {
|
||||
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
|
||||
} mp_pin_p_t;
|
||||
|
||||
int mp_virtual_pin_read(mp_obj_t pin);
|
||||
void mp_virtual_pin_write(mp_obj_t pin, int value);
|
||||
@@ -158,8 +158,8 @@ mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month,
|
||||
+ (year - 2000) * 31536000;
|
||||
}
|
||||
|
||||
mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
|
||||
mp_uint_t hours, mp_uint_t minutes, mp_uint_t seconds) {
|
||||
mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday,
|
||||
mp_int_t hours, mp_int_t minutes, mp_int_t seconds) {
|
||||
|
||||
// Normalize the tuple. This allows things like:
|
||||
//
|
||||
@@ -204,7 +204,7 @@ mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
|
||||
}
|
||||
mday += timeutils_days_in_month(year, month);
|
||||
}
|
||||
while (mday > timeutils_days_in_month(year, month)) {
|
||||
while ((mp_uint_t)mday > timeutils_days_in_month(year, month)) {
|
||||
mday -= timeutils_days_in_month(year, month);
|
||||
if (++month == 13) {
|
||||
month = 1;
|
||||
|
||||
@@ -49,7 +49,7 @@ void timeutils_seconds_since_2000_to_struct_time(mp_uint_t t,
|
||||
mp_uint_t timeutils_seconds_since_2000(mp_uint_t year, mp_uint_t month,
|
||||
mp_uint_t date, mp_uint_t hour, mp_uint_t minute, mp_uint_t second);
|
||||
|
||||
mp_uint_t timeutils_mktime(mp_uint_t year, mp_uint_t month, mp_uint_t mday,
|
||||
mp_uint_t hours, mp_uint_t minutes, mp_uint_t seconds);
|
||||
mp_uint_t timeutils_mktime(mp_uint_t year, mp_int_t month, mp_int_t mday,
|
||||
mp_int_t hours, mp_int_t minutes, mp_int_t seconds);
|
||||
|
||||
#endif // __MICROPY_INCLUDED_LIB_TIMEUTILS_H__
|
||||
|
||||
@@ -52,7 +52,7 @@ STATIC void stderr_print_strn(void *env, const char *str, mp_uint_t len) {
|
||||
|
||||
STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
|
||||
|
||||
STATIC int compile_and_save(const char *file, const char *output_file) {
|
||||
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) {
|
||||
mp_lexer_t *lex = mp_lexer_new_from_file(file);
|
||||
if (lex == NULL) {
|
||||
printf("could not open file '%s' for reading\n", file);
|
||||
@@ -61,7 +61,12 @@ STATIC int compile_and_save(const char *file, const char *output_file) {
|
||||
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
qstr source_name = lex->source_name;
|
||||
qstr source_name;
|
||||
if (source_file == NULL) {
|
||||
source_name = lex->source_name;
|
||||
} else {
|
||||
source_name = qstr_from_str(source_file);
|
||||
}
|
||||
|
||||
#if MICROPY_PY___FILE__
|
||||
if (input_kind == MP_PARSE_FILE_INPUT) {
|
||||
@@ -97,7 +102,8 @@ STATIC int usage(char **argv) {
|
||||
printf(
|
||||
"usage: %s [<opts>] [-X <implopt>] <input filename>\n"
|
||||
"Options:\n"
|
||||
"-o : output file for compiled bytecode\n"
|
||||
"-o : output file for compiled bytecode (defaults to input with .mpy extension)\n"
|
||||
"-s : source filename to embed in the compiled bytecode (defaults to input file)\n"
|
||||
"-v : verbose (trace various operations); can be multiple\n"
|
||||
"-O[N] : apply bytecode optimizations of level N\n"
|
||||
"\n"
|
||||
@@ -189,6 +195,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
const char *input_file = NULL;
|
||||
const char *output_file = NULL;
|
||||
const char *source_file = NULL;
|
||||
|
||||
// parse main options
|
||||
for (int a = 1; a < argc; a++) {
|
||||
@@ -210,6 +217,12 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
}
|
||||
a += 1;
|
||||
output_file = argv[a];
|
||||
} else if (strcmp(argv[a], "-s") == 0) {
|
||||
if (a + 1 >= argc) {
|
||||
exit(usage(argv));
|
||||
}
|
||||
a += 1;
|
||||
source_file = argv[a];
|
||||
} else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) {
|
||||
char *end;
|
||||
mp_dynamic_compiler.small_int_bits =
|
||||
@@ -243,7 +256,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int ret = compile_and_save(input_file, output_file);
|
||||
int ret = compile_and_save(input_file, output_file, source_file);
|
||||
|
||||
#if MICROPY_PY_MICROPYTHON_MEM_INFO
|
||||
if (mp_verbose_flag) {
|
||||
|
||||
@@ -98,6 +98,7 @@ extern const mp_obj_module_t mp_module_gc;
|
||||
extern const mp_obj_dict_t mp_module_builtins_globals;
|
||||
|
||||
// extmod modules
|
||||
extern const mp_obj_module_t mp_module_uerrno;
|
||||
extern const mp_obj_module_t mp_module_uctypes;
|
||||
extern const mp_obj_module_t mp_module_uzlib;
|
||||
extern const mp_obj_module_t mp_module_ujson;
|
||||
|
||||
@@ -60,22 +60,34 @@ bool mp_obj_is_package(mp_obj_t module) {
|
||||
return dest[0] != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
// Stat either frozen or normal module by a given path
|
||||
// (whatever is available, if at all).
|
||||
STATIC mp_import_stat_t mp_import_stat_any(const char *path) {
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
mp_import_stat_t st = mp_frozen_stat(path);
|
||||
if (st != MP_IMPORT_STAT_NO_EXIST) {
|
||||
return st;
|
||||
}
|
||||
#endif
|
||||
return mp_import_stat(path);
|
||||
}
|
||||
|
||||
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
|
||||
mp_import_stat_t stat = mp_import_stat(vstr_null_terminated_str(path));
|
||||
mp_import_stat_t stat = mp_import_stat_any(vstr_null_terminated_str(path));
|
||||
DEBUG_printf("stat %s: %d\n", vstr_str(path), stat);
|
||||
if (stat == MP_IMPORT_STAT_DIR) {
|
||||
return stat;
|
||||
}
|
||||
|
||||
vstr_add_str(path, ".py");
|
||||
stat = mp_import_stat(vstr_null_terminated_str(path));
|
||||
stat = mp_import_stat_any(vstr_null_terminated_str(path));
|
||||
if (stat == MP_IMPORT_STAT_FILE) {
|
||||
return stat;
|
||||
}
|
||||
|
||||
#if MICROPY_PERSISTENT_CODE_LOAD
|
||||
vstr_ins_byte(path, path->len - 2, 'm');
|
||||
stat = mp_import_stat(vstr_null_terminated_str(path));
|
||||
stat = mp_import_stat_any(vstr_null_terminated_str(path));
|
||||
if (stat == MP_IMPORT_STAT_FILE) {
|
||||
return stat;
|
||||
}
|
||||
@@ -182,10 +194,37 @@ STATIC void do_execute_raw_code(mp_obj_t module_obj, mp_raw_code_t *raw_code) {
|
||||
#endif
|
||||
|
||||
STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||
#if MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER
|
||||
#if MICROPY_MODULE_FROZEN || MICROPY_PERSISTENT_CODE_LOAD || MICROPY_ENABLE_COMPILER
|
||||
char *file_str = vstr_null_terminated_str(file);
|
||||
#endif
|
||||
|
||||
// If we support frozen modules (either as str or mpy) then try to find the
|
||||
// requested filename in the list of frozen module filenames.
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
void *modref;
|
||||
int frozen_type = mp_find_frozen_module(file_str, file->len, &modref);
|
||||
#endif
|
||||
|
||||
// If we support frozen str modules and the compiler is enabled, and we
|
||||
// found the filename in the list of frozen files, then load and execute it.
|
||||
#if MICROPY_MODULE_FROZEN_STR
|
||||
if (frozen_type == MP_FROZEN_STR) {
|
||||
do_load_from_lexer(module_obj, modref, file_str);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we support frozen mpy modules and we found a corresponding file (and
|
||||
// its data) in the list of frozen files, execute it.
|
||||
#if MICROPY_MODULE_FROZEN_MPY
|
||||
if (frozen_type == MP_FROZEN_MPY) {
|
||||
do_execute_raw_code(module_obj, modref);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we support loading .mpy files then check if the file extension is of
|
||||
// the correct format and, if so, load and execute the file.
|
||||
#if MICROPY_PERSISTENT_CODE_LOAD
|
||||
if (file_str[file->len - 3] == 'm') {
|
||||
mp_raw_code_t *raw_code = mp_raw_code_load_file(file_str);
|
||||
@@ -194,15 +233,18 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we can compile scripts then load the file and compile and execute it.
|
||||
#if MICROPY_ENABLE_COMPILER
|
||||
{
|
||||
mp_lexer_t *lex = mp_lexer_new_from_file(file_str);
|
||||
do_load_from_lexer(module_obj, lex, file_str);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
// If we get here then the file was not frozen and we can't compile scripts.
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
|
||||
"script compilation not supported"));
|
||||
#endif
|
||||
}
|
||||
|
||||
STATIC void chop_component(const char *start, const char **end) {
|
||||
@@ -340,33 +382,6 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
DEBUG_printf("Module not yet loaded\n");
|
||||
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
void *frozen_data;
|
||||
int frozen_type = mp_find_frozen_module(mod_str, mod_len, &frozen_data);
|
||||
if (frozen_type != MP_FROZEN_NONE) {
|
||||
module_obj = mp_obj_new_module(module_name_qstr);
|
||||
// if args[3] (fromtuple) has magic value False, set up
|
||||
// this module for command-line "-m" option (set module's
|
||||
// name to __main__ instead of real name).
|
||||
// TODO: Duplicated below too.
|
||||
if (fromtuple == mp_const_false) {
|
||||
mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
|
||||
mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
|
||||
}
|
||||
#if MICROPY_MODULE_FROZEN_STR
|
||||
if (frozen_type == MP_FROZEN_STR) {
|
||||
do_load_from_lexer(module_obj, frozen_data, mod_str);
|
||||
}
|
||||
#endif
|
||||
#if MICROPY_MODULE_FROZEN_MPY
|
||||
if (frozen_type == MP_FROZEN_MPY) {
|
||||
do_execute_raw_code(module_obj, frozen_data);
|
||||
}
|
||||
#endif
|
||||
return module_obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint last = 0;
|
||||
VSTR_FIXED(path, MICROPY_ALLOC_PATH_MAX)
|
||||
module_obj = MP_OBJ_NULL;
|
||||
@@ -445,7 +460,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
|
||||
mp_store_attr(module_obj, MP_QSTR___path__, mp_obj_new_str(vstr_str(&path), vstr_len(&path), false));
|
||||
vstr_add_char(&path, PATH_SEP_CHAR);
|
||||
vstr_add_str(&path, "__init__.py");
|
||||
if (mp_import_stat(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
|
||||
if (mp_import_stat_any(vstr_null_terminated_str(&path)) != MP_IMPORT_STAT_FILE) {
|
||||
vstr_cut_tail_bytes(&path, sizeof("/__init__.py") - 1); // cut off /__init__.py
|
||||
mp_warning("%s is imported as namespace package", vstr_str(&path));
|
||||
} else {
|
||||
|
||||
@@ -2649,7 +2649,7 @@ STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns)
|
||||
}
|
||||
|
||||
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
||||
STATIC compile_function_t compile_function[] = {
|
||||
STATIC const compile_function_t compile_function[] = {
|
||||
#define nc NULL
|
||||
#define c(f) compile_##f
|
||||
#define DEF_RULE(rule, comp, kind, ...) comp,
|
||||
|
||||
@@ -381,7 +381,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) {
|
||||
// here we define mp_raw_code_load_file depending on the port
|
||||
// TODO abstract this away properly
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || (defined(__arm__) && (defined(__unix__)))
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__)))
|
||||
// unix file reader
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -85,6 +85,43 @@ STATIC const mp_raw_code_t *mp_find_frozen_mpy(const char *str, size_t len) {
|
||||
|
||||
#if MICROPY_MODULE_FROZEN
|
||||
|
||||
STATIC mp_import_stat_t mp_frozen_stat_helper(const char *name, const char *str) {
|
||||
size_t len = strlen(str);
|
||||
|
||||
for (int i = 0; *name != 0; i++) {
|
||||
size_t l = strlen(name);
|
||||
if (l >= len && !memcmp(str, name, len)) {
|
||||
if (name[len] == 0) {
|
||||
return MP_IMPORT_STAT_FILE;
|
||||
} else if (name[len] == '/') {
|
||||
return MP_IMPORT_STAT_DIR;
|
||||
}
|
||||
}
|
||||
name += l + 1;
|
||||
}
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
|
||||
mp_import_stat_t mp_frozen_stat(const char *str) {
|
||||
mp_import_stat_t stat;
|
||||
|
||||
#if MICROPY_MODULE_FROZEN_STR
|
||||
stat = mp_frozen_stat_helper(mp_frozen_str_names, str);
|
||||
if (stat != MP_IMPORT_STAT_NO_EXIST) {
|
||||
return stat;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_MODULE_FROZEN_MPY
|
||||
stat = mp_frozen_stat_helper(mp_frozen_mpy_names, str);
|
||||
if (stat != MP_IMPORT_STAT_NO_EXIST) {
|
||||
return stat;
|
||||
}
|
||||
#endif
|
||||
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
|
||||
int mp_find_frozen_module(const char *str, size_t len, void **data) {
|
||||
#if MICROPY_MODULE_FROZEN_STR
|
||||
mp_lexer_t *lex = mp_find_frozen_str(str, len);
|
||||
|
||||
@@ -31,3 +31,4 @@ enum {
|
||||
};
|
||||
|
||||
int mp_find_frozen_module(const char *str, size_t len, void **data);
|
||||
mp_import_stat_t mp_frozen_stat(const char *str);
|
||||
|
||||
14
py/gc.c
14
py/gc.c
@@ -693,11 +693,8 @@ void gc_dump_alloc_table(void) {
|
||||
}
|
||||
// print header for new line of blocks
|
||||
// (the cast to uint32_t is for 16-bit ports)
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
//mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff));
|
||||
mp_printf(&mp_plat_print, "\n%05x: ", (uint)((bl * BYTES_PER_BLOCK) & (uint32_t)0xfffff));
|
||||
#else
|
||||
mp_printf(&mp_plat_print, "\n%05x: ", (uint)(PTR_FROM_BLOCK(bl) & (uint32_t)0xfffff));
|
||||
#endif
|
||||
}
|
||||
int c = ' ';
|
||||
switch (ATB_GET_KIND(bl)) {
|
||||
@@ -734,6 +731,13 @@ void gc_dump_alloc_table(void) {
|
||||
if (*ptr == &mp_type_tuple) { c = 'T'; }
|
||||
else if (*ptr == &mp_type_list) { c = 'L'; }
|
||||
else if (*ptr == &mp_type_dict) { c = 'D'; }
|
||||
else if (*ptr == &mp_type_str || *ptr == &mp_type_bytes) { c = 'S'; }
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
else if (*ptr == &mp_type_bytearray) { c = 'A'; }
|
||||
#endif
|
||||
#if MICROPY_PY_ARRAY
|
||||
else if (*ptr == &mp_type_array) { c = 'A'; }
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
else if (*ptr == &mp_type_float) { c = 'F'; }
|
||||
#endif
|
||||
@@ -761,7 +765,7 @@ void gc_dump_alloc_table(void) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AT_TAIL: c = 't'; break;
|
||||
case AT_TAIL: c = '='; break;
|
||||
case AT_MARK: c = 'm'; break;
|
||||
}
|
||||
mp_printf(&mp_plat_print, "%c", c);
|
||||
|
||||
@@ -190,7 +190,7 @@ STATIC void indent_pop(mp_lexer_t *lex) {
|
||||
// c<op> = continue with <op>, if this opchar matches then continue matching
|
||||
// this means if the start of two ops are the same then they are equal til the last char
|
||||
|
||||
STATIC const char *tok_enc =
|
||||
STATIC const char *const tok_enc =
|
||||
"()[]{},:;@~" // singles
|
||||
"<e=c<e=" // < <= << <<=
|
||||
">e=c>e=" // > >= >> >>=
|
||||
@@ -227,7 +227,7 @@ STATIC const uint8_t tok_enc_kind[] = {
|
||||
};
|
||||
|
||||
// must have the same order as enum in lexer.h
|
||||
STATIC const char *tok_kw[] = {
|
||||
STATIC const char *const tok_kw[] = {
|
||||
"False",
|
||||
"None",
|
||||
"True",
|
||||
|
||||
@@ -116,7 +116,7 @@ def parse_input_headers(infiles):
|
||||
|
||||
def make_bytes(cfg_bytes_len, cfg_bytes_hash, qstr):
|
||||
qhash = compute_hash(qstr, cfg_bytes_hash)
|
||||
if all(32 <= ord(c) <= 126 and c != '\\' for c in qstr):
|
||||
if all(32 <= ord(c) <= 126 and c != '\\' and c != '"' for c in qstr):
|
||||
# qstr is all printable ASCII so render it as-is (for easier debugging)
|
||||
qlen = len(qstr)
|
||||
qdata = qstr
|
||||
|
||||
2
py/map.c
2
py/map.c
@@ -49,7 +49,7 @@ const mp_map_t mp_const_empty_map = {
|
||||
// The first set of sizes are chosen so the allocation fits exactly in a
|
||||
// 4-word GC block, and it's not so important for these small values to be
|
||||
// prime. The latter sizes are prime and increase at an increasing rate.
|
||||
STATIC uint16_t hash_allocation_sizes[] = {
|
||||
STATIC const uint16_t hash_allocation_sizes[] = {
|
||||
0, 2, 4, 6, 8, 10, 12, // +2
|
||||
17, 23, 29, 37, 47, 59, 73, // *1.25
|
||||
97, 127, 167, 223, 293, 389, 521, 691, 919, 1223, 1627, 2161, // *1.33
|
||||
|
||||
14
py/modio.c
14
py/modio.c
@@ -78,10 +78,13 @@ STATIC mp_uint_t bufwriter_write(mp_obj_t self_in, const void *buf, mp_uint_t si
|
||||
memcpy(self->buf + self->len, buf, rem);
|
||||
buf = (byte*)buf + rem;
|
||||
size -= rem;
|
||||
mp_uint_t out_sz = mp_stream_writeall(self->stream, self->buf, self->alloc, errcode);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->alloc, errcode);
|
||||
if (*errcode != 0) {
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
// TODO: try to recover from a case of non-blocking stream, e.g. move
|
||||
// remaining chunk to the beginning of buffer.
|
||||
assert(out_sz == self->alloc);
|
||||
self->len = 0;
|
||||
}
|
||||
|
||||
@@ -93,9 +96,12 @@ STATIC mp_obj_t bufwriter_flush(mp_obj_t self_in) {
|
||||
|
||||
if (self->len != 0) {
|
||||
int err;
|
||||
mp_uint_t out_sz = mp_stream_writeall(self->stream, self->buf, self->len, &err);
|
||||
mp_uint_t out_sz = mp_stream_write_exactly(self->stream, self->buf, self->len, &err);
|
||||
// TODO: try to recover from a case of non-blocking stream, e.g. move
|
||||
// remaining chunk to the beginning of buffer.
|
||||
assert(out_sz == self->len);
|
||||
self->len = 0;
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (err != 0) {
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(err)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
// M_PI is not part of the math.h standard and may not be defined
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265358979323846)
|
||||
#endif
|
||||
|
||||
/// \module math - mathematical functions
|
||||
///
|
||||
/// The `math` module provides some basic mathematical funtions for
|
||||
|
||||
@@ -103,29 +103,24 @@ STATIC mp_obj_t struct_calcsize(mp_obj_t fmt_in) {
|
||||
char fmt_type = get_fmt_type(&fmt);
|
||||
mp_uint_t size;
|
||||
for (size = 0; *fmt; fmt++) {
|
||||
mp_uint_t align = 1;
|
||||
mp_uint_t cnt = 1;
|
||||
if (unichar_isdigit(*fmt)) {
|
||||
cnt = get_fmt_num(&fmt);
|
||||
}
|
||||
|
||||
mp_uint_t sz = 0;
|
||||
if (*fmt == 's') {
|
||||
sz = cnt;
|
||||
cnt = 1;
|
||||
}
|
||||
|
||||
while (cnt--) {
|
||||
// If we already have size for 's' case, don't set it again
|
||||
size += cnt;
|
||||
} else {
|
||||
mp_uint_t align;
|
||||
size_t sz = mp_binary_get_size(fmt_type, *fmt, &align);
|
||||
if (sz == 0) {
|
||||
sz = (mp_uint_t)mp_binary_get_size(fmt_type, *fmt, &align);
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unsupported format"));
|
||||
}
|
||||
while (cnt--) {
|
||||
// Apply alignment
|
||||
size = (size + align - 1) & ~(align - 1);
|
||||
size += sz;
|
||||
}
|
||||
// TODO
|
||||
assert(sz != (mp_uint_t)-1);
|
||||
// Apply alignment
|
||||
size = (size + align - 1) & ~(align - 1);
|
||||
size += sz;
|
||||
sz = 0;
|
||||
}
|
||||
}
|
||||
return MP_OBJ_NEW_SMALL_INT(size);
|
||||
|
||||
105
py/moduerrno.c
Normal file
105
py/moduerrno.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
#if MICROPY_PY_UERRNO
|
||||
|
||||
// This list could be defined per port in mpconfigport.h to tailor it to a
|
||||
// specific port's needs. But for now we have a common list.
|
||||
#define ERRNO_LIST \
|
||||
X(EPERM) \
|
||||
X(ENOENT) \
|
||||
X(EIO) \
|
||||
X(EBADF) \
|
||||
X(EAGAIN) \
|
||||
X(ENOMEM) \
|
||||
X(EACCES) \
|
||||
X(EEXIST) \
|
||||
X(ENODEV) \
|
||||
X(EISDIR) \
|
||||
X(EINVAL) \
|
||||
X(EOPNOTSUPP) \
|
||||
X(EADDRINUSE) \
|
||||
X(ECONNABORTED) \
|
||||
X(ECONNRESET) \
|
||||
X(ENOBUFS) \
|
||||
X(ENOTCONN) \
|
||||
X(ETIMEDOUT) \
|
||||
X(ECONNREFUSED) \
|
||||
X(EHOSTUNREACH) \
|
||||
X(EALREADY) \
|
||||
X(EINPROGRESS) \
|
||||
|
||||
STATIC const mp_rom_map_elem_t errorcode_table[] = {
|
||||
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
|
||||
ERRNO_LIST
|
||||
#undef X
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t errorcode_dict = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 0, // keys are integers
|
||||
.is_fixed = 1,
|
||||
.is_ordered = 1,
|
||||
.used = MP_ARRAY_SIZE(errorcode_table),
|
||||
.alloc = MP_ARRAY_SIZE(errorcode_table),
|
||||
.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,
|
||||
},
|
||||
};
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
|
||||
|
||||
#define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },
|
||||
ERRNO_LIST
|
||||
#undef X
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_uerrno_globals, mp_module_uerrno_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_uerrno = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uerrno,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_uerrno_globals,
|
||||
};
|
||||
|
||||
qstr mp_errno_to_str(mp_obj_t errno_val) {
|
||||
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
|
||||
if (elem == NULL) {
|
||||
return MP_QSTR_NULL;
|
||||
} else {
|
||||
return MP_OBJ_QSTR_VALUE(elem->value);
|
||||
}
|
||||
}
|
||||
|
||||
#endif //MICROPY_PY_UERRNO
|
||||
@@ -555,6 +555,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (1)
|
||||
#endif
|
||||
|
||||
// Whether to use internally defined errno's (otherwise system provided ones)
|
||||
#ifndef MICROPY_USE_INTERNAL_ERRNO
|
||||
#define MICROPY_USE_INTERNAL_ERRNO (0)
|
||||
#endif
|
||||
|
||||
// Support for user-space VFS mount (selected ports)
|
||||
#ifndef MICROPY_FSUSERMOUNT
|
||||
#define MICROPY_FSUSERMOUNT (0)
|
||||
@@ -584,6 +589,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (0)
|
||||
#endif
|
||||
|
||||
// Whether str.center() method provided
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_CENTER
|
||||
#define MICROPY_PY_BUILTINS_STR_CENTER (0)
|
||||
#endif
|
||||
|
||||
// Whether str.splitlines() method provided
|
||||
#ifndef MICROPY_PY_BUILTINS_STR_SPLITLINES
|
||||
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (0)
|
||||
@@ -809,6 +819,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
|
||||
#endif
|
||||
|
||||
// Whether to provide "uerrno" module
|
||||
#ifndef MICROPY_PY_UERRNO
|
||||
#define MICROPY_PY_UERRNO (0)
|
||||
#endif
|
||||
|
||||
// Extended modules
|
||||
|
||||
#ifndef MICROPY_PY_UCTYPES
|
||||
@@ -852,6 +867,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_MACHINE (0)
|
||||
#endif
|
||||
|
||||
// Whether to include: time_pulse_us
|
||||
#ifndef MICROPY_PY_MACHINE_PULSE
|
||||
#define MICROPY_PY_MACHINE_PULSE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_MACHINE_I2C
|
||||
#define MICROPY_PY_MACHINE_I2C (0)
|
||||
#endif
|
||||
|
||||
143
py/mperrno.h
Normal file
143
py/mperrno.h
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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_PY_MPERRNO_H__
|
||||
#define __MICROPY_INCLUDED_PY_MPERRNO_H__
|
||||
|
||||
#if MICROPY_USE_INTERNAL_ERRNO
|
||||
|
||||
// MP_Exxx errno's are defined directly as numeric values
|
||||
// (Linux constants are used as a reference)
|
||||
|
||||
#define MP_EPERM (1) // Operation not permitted
|
||||
#define MP_ENOENT (2) // No such file or directory
|
||||
#define MP_ESRCH (3) // No such process
|
||||
#define MP_EINTR (4) // Interrupted system call
|
||||
#define MP_EIO (5) // I/O error
|
||||
#define MP_ENXIO (6) // No such device or address
|
||||
#define MP_E2BIG (7) // Argument list too long
|
||||
#define MP_ENOEXEC (8) // Exec format error
|
||||
#define MP_EBADF (9) // Bad file number
|
||||
#define MP_ECHILD (10) // No child processes
|
||||
#define MP_EAGAIN (11) // Try again
|
||||
#define MP_ENOMEM (12) // Out of memory
|
||||
#define MP_EACCES (13) // Permission denied
|
||||
#define MP_EFAULT (14) // Bad address
|
||||
#define MP_ENOTBLK (15) // Block device required
|
||||
#define MP_EBUSY (16) // Device or resource busy
|
||||
#define MP_EEXIST (17) // File exists
|
||||
#define MP_EXDEV (18) // Cross-device link
|
||||
#define MP_ENODEV (19) // No such device
|
||||
#define MP_ENOTDIR (20) // Not a directory
|
||||
#define MP_EISDIR (21) // Is a directory
|
||||
#define MP_EINVAL (22) // Invalid argument
|
||||
#define MP_ENFILE (23) // File table overflow
|
||||
#define MP_EMFILE (24) // Too many open files
|
||||
#define MP_ENOTTY (25) // Not a typewriter
|
||||
#define MP_ETXTBSY (26) // Text file busy
|
||||
#define MP_EFBIG (27) // File too large
|
||||
#define MP_ENOSPC (28) // No space left on device
|
||||
#define MP_ESPIPE (29) // Illegal seek
|
||||
#define MP_EROFS (30) // Read-only file system
|
||||
#define MP_EMLINK (31) // Too many links
|
||||
#define MP_EPIPE (32) // Broken pipe
|
||||
#define MP_EDOM (33) // Math argument out of domain of func
|
||||
#define MP_ERANGE (34) // Math result not representable
|
||||
#define MP_EWOULDBLOCK MP_EAGAIN // Operation would block
|
||||
#define MP_EOPNOTSUPP (95) // Operation not supported on transport endpoint
|
||||
#define MP_EAFNOSUPPORT (97) // Address family not supported by protocol
|
||||
#define MP_EADDRINUSE (98) // Address already in use
|
||||
#define MP_ECONNABORTED (103) // Software caused connection abort
|
||||
#define MP_ECONNRESET (104) // Connection reset by peer
|
||||
#define MP_ENOBUFS (105) // No buffer space available
|
||||
#define MP_ENOTCONN (107) // Transport endpoint is not connected
|
||||
#define MP_ETIMEDOUT (110) // Connection timed out
|
||||
#define MP_ECONNREFUSED (111) // Connection refused
|
||||
#define MP_EHOSTUNREACH (113) // No route to host
|
||||
#define MP_EALREADY (114) // Operation already in progress
|
||||
#define MP_EINPROGRESS (115) // Operation now in progress
|
||||
|
||||
#else
|
||||
|
||||
// MP_Exxx errno's are defined in terms of system supplied ones
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define MP_EPERM EPERM
|
||||
#define MP_ENOENT ENOENT
|
||||
#define MP_ESRCH ESRCH
|
||||
#define MP_EINTR EINTR
|
||||
#define MP_EIO EIO
|
||||
#define MP_ENXIO ENXIO
|
||||
#define MP_E2BIG E2BIG
|
||||
#define MP_ENOEXEC ENOEXEC
|
||||
#define MP_EBADF EBADF
|
||||
#define MP_ECHILD ECHILD
|
||||
#define MP_EAGAIN EAGAIN
|
||||
#define MP_ENOMEM ENOMEM
|
||||
#define MP_EACCES EACCES
|
||||
#define MP_EFAULT EFAULT
|
||||
#define MP_ENOTBLK ENOTBLK
|
||||
#define MP_EBUSY EBUSY
|
||||
#define MP_EEXIST EEXIST
|
||||
#define MP_EXDEV EXDEV
|
||||
#define MP_ENODEV ENODEV
|
||||
#define MP_ENOTDIR ENOTDIR
|
||||
#define MP_EISDIR EISDIR
|
||||
#define MP_EINVAL EINVAL
|
||||
#define MP_ENFILE ENFILE
|
||||
#define MP_EMFILE EMFILE
|
||||
#define MP_ENOTTY ENOTTY
|
||||
#define MP_ETXTBSY ETXTBSY
|
||||
#define MP_EFBIG EFBIG
|
||||
#define MP_ENOSPC ENOSPC
|
||||
#define MP_ESPIPE ESPIPE
|
||||
#define MP_EROFS EROFS
|
||||
#define MP_EMLINK EMLINK
|
||||
#define MP_EPIPE EPIPE
|
||||
#define MP_EDOM EDOM
|
||||
#define MP_ERANGE ERANGE
|
||||
#define MP_EWOULDBLOCK EAGAIN
|
||||
#define MP_EOPNOTSUPP EOPNOTSUPP
|
||||
#define MP_EAFNOSUPPORT EAFNOSUPPORT
|
||||
#define MP_EADDRINUSE EADDRINUSE
|
||||
#define MP_ECONNABORTED ECONNABORTED
|
||||
#define MP_ECONNRESET ECONNRESET
|
||||
#define MP_ENOBUFS ENOBUFS
|
||||
#define MP_ENOTCONN ENOTCONN
|
||||
#define MP_ETIMEDOUT ETIMEDOUT
|
||||
#define MP_ECONNREFUSED ECONNREFUSED
|
||||
#define MP_EHOSTUNREACH EHOSTUNREACH
|
||||
#define MP_EALREADY EALREADY
|
||||
#define MP_EINPROGRESS EINPROGRESS
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UERRNO
|
||||
qstr mp_errno_to_str(mp_obj_t errno_val);
|
||||
#endif
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_MPERRNO_H__
|
||||
17
py/mphal.h
17
py/mphal.h
@@ -54,8 +54,25 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len);
|
||||
void mp_hal_delay_ms(mp_uint_t ms);
|
||||
#endif
|
||||
|
||||
#ifndef mp_hal_delay_us
|
||||
void mp_hal_delay_us(mp_uint_t us);
|
||||
#endif
|
||||
|
||||
#ifndef mp_hal_ticks_ms
|
||||
mp_uint_t mp_hal_ticks_ms(void);
|
||||
#endif
|
||||
|
||||
#ifndef mp_hal_ticks_us
|
||||
mp_uint_t mp_hal_ticks_us(void);
|
||||
#endif
|
||||
|
||||
// If port HAL didn't define its own pin API, use generic
|
||||
// "virtual pin" API from the core.
|
||||
#ifndef mp_hal_pin_obj_t
|
||||
#define mp_hal_pin_obj_t mp_obj_t
|
||||
#define mp_hal_get_pin_obj(pin) (pin)
|
||||
#define mp_hal_pin_read(pin) mp_virtual_pin_read(pin)
|
||||
#define mp_hal_pin_write(pin, v) mp_virtual_pin_write(pin, v)
|
||||
#endif
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_MPHAL_H__
|
||||
|
||||
67
py/mpz.c
67
py/mpz.c
@@ -454,10 +454,8 @@ STATIC mp_uint_t mpn_mul(mpz_dig_t *idig, mpz_dig_t *jdig, mp_uint_t jlen, mpz_d
|
||||
assumes num_dig has enough memory to be extended by 1 digit
|
||||
assumes quo_dig has enough memory (as many digits as num)
|
||||
assumes quo_dig is filled with zeros
|
||||
modifies den_dig memory, but restors it to original state at end
|
||||
*/
|
||||
|
||||
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
|
||||
STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, const mpz_dig_t *den_dig, mp_uint_t den_len, mpz_dig_t *quo_dig, mp_uint_t *quo_len) {
|
||||
mpz_dig_t *orig_num_dig = num_dig;
|
||||
mpz_dig_t *orig_quo_dig = quo_dig;
|
||||
mpz_dig_t norm_shift = 0;
|
||||
@@ -478,6 +476,11 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
}
|
||||
}
|
||||
|
||||
// We need to normalise the denominator (leading bit of leading digit is 1)
|
||||
// so that the division routine works. Since the denominator memory is
|
||||
// read-only we do the normalisation on the fly, each time a digit of the
|
||||
// denominator is needed. We need to know is how many bits to shift by.
|
||||
|
||||
// count number of leading zeros in leading digit of denominator
|
||||
{
|
||||
mpz_dig_t d = den_dig[den_len - 1];
|
||||
@@ -487,13 +490,6 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
}
|
||||
}
|
||||
|
||||
// normalise denomenator (leading bit of leading digit is 1)
|
||||
for (mpz_dig_t *den = den_dig, carry = 0; den < den_dig + den_len; ++den) {
|
||||
mpz_dig_t d = *den;
|
||||
*den = ((d << norm_shift) | carry) & DIG_MASK;
|
||||
carry = d >> (DIG_SIZE - norm_shift);
|
||||
}
|
||||
|
||||
// now need to shift numerator by same amount as denominator
|
||||
// first, increase length of numerator in case we need more room to shift
|
||||
num_dig[*num_len] = 0;
|
||||
@@ -501,11 +497,14 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) {
|
||||
mpz_dig_t n = *num;
|
||||
*num = ((n << norm_shift) | carry) & DIG_MASK;
|
||||
carry = n >> (DIG_SIZE - norm_shift);
|
||||
carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift);
|
||||
}
|
||||
|
||||
// cache the leading digit of the denominator
|
||||
lead_den_digit = den_dig[den_len - 1];
|
||||
lead_den_digit = (mpz_dbl_dig_t)den_dig[den_len - 1] << norm_shift;
|
||||
if (den_len >= 2) {
|
||||
lead_den_digit |= (mpz_dbl_dig_t)den_dig[den_len - 2] >> (DIG_SIZE - norm_shift);
|
||||
}
|
||||
|
||||
// point num_dig to last digit in numerator
|
||||
num_dig += *num_len - 1;
|
||||
@@ -540,10 +539,13 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
// round up).
|
||||
|
||||
if (DIG_SIZE < 8 * sizeof(mpz_dbl_dig_t) / 2) {
|
||||
const mpz_dig_t *d = den_dig;
|
||||
mpz_dbl_dig_t d_norm = 0;
|
||||
mpz_dbl_dig_signed_t borrow = 0;
|
||||
|
||||
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
|
||||
borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (mpz_dbl_dig_t)*d; // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
|
||||
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
|
||||
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
|
||||
borrow += (mpz_dbl_dig_t)*n - (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK); // will overflow if DIG_SIZE >= 8*sizeof(mpz_dbl_dig_t)/2
|
||||
*n = borrow & DIG_MASK;
|
||||
borrow >>= DIG_SIZE;
|
||||
}
|
||||
@@ -553,9 +555,12 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
|
||||
// adjust quotient if it is too big
|
||||
for (; borrow != 0; --quo) {
|
||||
d = den_dig;
|
||||
d_norm = 0;
|
||||
mpz_dbl_dig_t carry = 0;
|
||||
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
|
||||
carry += (mpz_dbl_dig_t)*n + (mpz_dbl_dig_t)*d;
|
||||
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
|
||||
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
|
||||
carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
|
||||
*n = carry & DIG_MASK;
|
||||
carry >>= DIG_SIZE;
|
||||
}
|
||||
@@ -566,10 +571,13 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
borrow += carry;
|
||||
}
|
||||
} else { // DIG_SIZE == 8 * sizeof(mpz_dbl_dig_t) / 2
|
||||
const mpz_dig_t *d = den_dig;
|
||||
mpz_dbl_dig_t d_norm = 0;
|
||||
mpz_dbl_dig_t borrow = 0;
|
||||
|
||||
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
|
||||
mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (mpz_dbl_dig_t)(*d);
|
||||
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
|
||||
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
|
||||
mpz_dbl_dig_t x = (mpz_dbl_dig_t)quo * (d_norm & DIG_MASK);
|
||||
if (x >= *n || *n - x <= borrow) {
|
||||
borrow += (mpz_dbl_dig_t)x - (mpz_dbl_dig_t)*n;
|
||||
*n = (-borrow) & DIG_MASK;
|
||||
@@ -590,9 +598,12 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
|
||||
// adjust quotient if it is too big
|
||||
for (; borrow != 0; --quo) {
|
||||
d = den_dig;
|
||||
d_norm = 0;
|
||||
mpz_dbl_dig_t carry = 0;
|
||||
for (mpz_dig_t *n = num_dig - den_len, *d = den_dig; n < num_dig; ++n, ++d) {
|
||||
carry += (mpz_dbl_dig_t)*n + (mpz_dbl_dig_t)*d;
|
||||
for (mpz_dig_t *n = num_dig - den_len; n < num_dig; ++n, ++d) {
|
||||
d_norm = ((mpz_dbl_dig_t)*d << norm_shift) | (d_norm >> DIG_SIZE);
|
||||
carry += (mpz_dbl_dig_t)*n + (d_norm & DIG_MASK);
|
||||
*n = carry & DIG_MASK;
|
||||
carry >>= DIG_SIZE;
|
||||
}
|
||||
@@ -614,18 +625,11 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig,
|
||||
--(*num_len);
|
||||
}
|
||||
|
||||
// unnormalise denomenator
|
||||
for (mpz_dig_t *den = den_dig + den_len - 1, carry = 0; den >= den_dig; --den) {
|
||||
mpz_dig_t d = *den;
|
||||
*den = ((d >> norm_shift) | carry) & DIG_MASK;
|
||||
carry = d << (DIG_SIZE - norm_shift);
|
||||
}
|
||||
|
||||
// unnormalise numerator (remainder now)
|
||||
for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) {
|
||||
mpz_dig_t n = *num;
|
||||
*num = ((n >> norm_shift) | carry) & DIG_MASK;
|
||||
carry = n << (DIG_SIZE - norm_shift);
|
||||
carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift);
|
||||
}
|
||||
|
||||
// strip trailing zeros
|
||||
@@ -1506,11 +1510,16 @@ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const m
|
||||
dest_quo->len = 0;
|
||||
mpz_need_dig(dest_rem, lhs->len + 1); // +1 necessary?
|
||||
mpz_set(dest_rem, lhs);
|
||||
//rhs->dig[rhs->len] = 0;
|
||||
mpn_div(dest_rem->dig, &dest_rem->len, rhs->dig, rhs->len, dest_quo->dig, &dest_quo->len);
|
||||
|
||||
// check signs and do Python style modulo
|
||||
if (lhs->neg != rhs->neg) {
|
||||
dest_quo->neg = 1;
|
||||
if (!mpz_is_zero(dest_rem)) {
|
||||
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
|
||||
mpz_add_inpl(dest_quo, dest_quo, &mpzone);
|
||||
mpz_add_inpl(dest_rem, dest_rem, rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
py/obj.c
2
py/obj.c
@@ -317,6 +317,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// note: returned value in *items may point to the interior of a GC block
|
||||
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
|
||||
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
|
||||
mp_obj_tuple_get(o, len, items);
|
||||
@@ -333,6 +334,7 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
|
||||
}
|
||||
}
|
||||
|
||||
// note: returned value in *items may point to the interior of a GC block
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
|
||||
mp_uint_t seq_len;
|
||||
mp_obj_get_array(o, &seq_len, items);
|
||||
|
||||
4
py/obj.h
4
py/obj.h
@@ -651,8 +651,8 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in);
|
||||
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
|
||||
#endif
|
||||
//qstr mp_obj_get_qstr(mp_obj_t arg);
|
||||
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items);
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items);
|
||||
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items); // *items may point inside a GC block
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items); // *items may point inside a GC block
|
||||
mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
|
||||
mp_obj_t mp_obj_id(mp_obj_t o_in);
|
||||
mp_obj_t mp_obj_len(mp_obj_t o_in);
|
||||
|
||||
@@ -414,7 +414,7 @@ typedef enum _mp_dict_view_kind_t {
|
||||
MP_DICT_VIEW_VALUES,
|
||||
} mp_dict_view_kind_t;
|
||||
|
||||
STATIC char *mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
|
||||
STATIC const char *const mp_dict_view_names[] = {"dict_items", "dict_keys", "dict_values"};
|
||||
|
||||
typedef struct _mp_obj_dict_view_it_t {
|
||||
mp_obj_base_t base;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "py/objtype.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mperrno.h"
|
||||
|
||||
// Instance of MemoryError exception - needed by mp_malloc_fail
|
||||
const mp_obj_exception_t mp_const_MemoryError_obj = {{&mp_type_MemoryError}, 0, 0, NULL, (mp_obj_tuple_t*)&mp_const_empty_tuple_obj};
|
||||
@@ -107,6 +108,16 @@ STATIC void mp_obj_exception_print(const mp_print_t *print, mp_obj_t o_in, mp_pr
|
||||
mp_print_str(print, "");
|
||||
return;
|
||||
} else if (o->args->len == 1) {
|
||||
#if MICROPY_PY_UERRNO
|
||||
// try to provide a nice OSError error message
|
||||
if (o->base.type == &mp_type_OSError && MP_OBJ_IS_SMALL_INT(o->args->items[0])) {
|
||||
qstr qst = mp_errno_to_str(o->args->items[0]);
|
||||
if (qst != MP_QSTR_NULL) {
|
||||
mp_printf(print, "[Errno %d] %q", MP_OBJ_SMALL_INT_VALUE(o->args->items[0]), qst);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mp_obj_print_helper(print, o->args->items[0], PRINT_STR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,14 @@
|
||||
|
||||
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
|
||||
|
||||
// M_E and M_PI are not part of the math.h standard and may not be defined
|
||||
#ifndef M_E
|
||||
#define M_E (2.7182818284590452354)
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI (3.14159265358979323846)
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_float_t {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t value;
|
||||
|
||||
@@ -239,12 +239,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
}
|
||||
mpz_t rem; mpz_init_zero(&rem);
|
||||
mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs);
|
||||
if (zlhs->neg != zrhs->neg) {
|
||||
if (!mpz_is_zero(&rem)) {
|
||||
mpz_t mpzone; mpz_init_from_int(&mpzone, -1);
|
||||
mpz_add_inpl(&res->mpz, &res->mpz, &mpzone);
|
||||
}
|
||||
}
|
||||
mpz_deinit(&rem);
|
||||
break;
|
||||
}
|
||||
@@ -256,10 +250,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
mpz_t quo; mpz_init_zero(&quo);
|
||||
mpz_divmod_inpl(&quo, &res->mpz, zlhs, zrhs);
|
||||
mpz_deinit(&quo);
|
||||
// Check signs and do Python style modulo
|
||||
if (zlhs->neg != zrhs->neg) {
|
||||
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -303,10 +293,6 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
}
|
||||
mp_obj_int_t *quo = mp_obj_int_new_mpz();
|
||||
mpz_divmod_inpl(&quo->mpz, &res->mpz, zlhs, zrhs);
|
||||
// Check signs and do Python style modulo
|
||||
if (zlhs->neg != zrhs->neg) {
|
||||
mpz_add_inpl(&res->mpz, &res->mpz, zrhs);
|
||||
}
|
||||
mp_obj_t tuple[2] = {MP_OBJ_FROM_PTR(quo), MP_OBJ_FROM_PTR(res)};
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
|
||||
@@ -163,6 +163,9 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
|
||||
|
||||
// extmod modules
|
||||
|
||||
#if MICROPY_PY_UERRNO
|
||||
{ MP_ROM_QSTR(MP_QSTR_uerrno), MP_ROM_PTR(&mp_module_uerrno) },
|
||||
#endif
|
||||
#if MICROPY_PY_UCTYPES
|
||||
{ MP_ROM_QSTR(MP_QSTR_uctypes), MP_ROM_PTR(&mp_module_uctypes) },
|
||||
#endif
|
||||
|
||||
@@ -165,10 +165,7 @@ STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) {
|
||||
fields_in = mp_obj_str_split(1, &fields_in);
|
||||
}
|
||||
#endif
|
||||
if (!MP_OBJ_IS_TYPE(fields_in, &mp_type_list)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "list required"));
|
||||
}
|
||||
mp_obj_list_get(fields_in, &n_fields, &fields);
|
||||
mp_obj_get_array(fields_in, &n_fields, &fields);
|
||||
return mp_obj_new_namedtuple_type(name, n_fields, fields);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_namedtuple_obj, new_namedtuple_type);
|
||||
|
||||
83
py/objstr.c
83
py/objstr.c
@@ -464,9 +464,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
|
||||
return mp_obj_new_str_from_vstr(self_type, &vstr);
|
||||
}
|
||||
|
||||
enum {SPLIT = 0, KEEP = 1, SPLITLINES = 2};
|
||||
|
||||
STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args, int type) {
|
||||
mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(args[0]);
|
||||
mp_int_t splits = -1;
|
||||
mp_obj_t sep = mp_const_none;
|
||||
@@ -527,13 +525,7 @@ STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args
|
||||
}
|
||||
s++;
|
||||
}
|
||||
mp_uint_t sub_len = s - start;
|
||||
if (MP_LIKELY(!(sub_len == 0 && s == top && (type && SPLITLINES)))) {
|
||||
if (start + sub_len != top && (type & KEEP)) {
|
||||
sub_len++;
|
||||
}
|
||||
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len));
|
||||
}
|
||||
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, s - start));
|
||||
if (s >= top) {
|
||||
break;
|
||||
}
|
||||
@@ -547,25 +539,49 @@ STATIC inline mp_obj_t str_split_internal(mp_uint_t n_args, const mp_obj_t *args
|
||||
return res;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
|
||||
return str_split_internal(n_args, args, SPLIT);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_STR_SPLITLINES
|
||||
STATIC mp_obj_t str_splitlines(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_keepends };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_keepends, MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
|
||||
// parse args
|
||||
struct {
|
||||
mp_arg_val_t keepends;
|
||||
} args;
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, 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 - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
mp_obj_t new_args[2] = {pos_args[0], MP_OBJ_NEW_QSTR(MP_QSTR__0x0a_)};
|
||||
return str_split_internal(2, new_args, SPLITLINES | (args.keepends.u_bool ? KEEP : 0));
|
||||
const mp_obj_type_t *self_type = mp_obj_get_type(pos_args[0]);
|
||||
mp_obj_t res = mp_obj_new_list(0, NULL);
|
||||
|
||||
GET_STR_DATA_LEN(pos_args[0], s, len);
|
||||
const byte *top = s + len;
|
||||
|
||||
while (s < top) {
|
||||
const byte *start = s;
|
||||
size_t match = 0;
|
||||
while (s < top) {
|
||||
if (*s == '\n') {
|
||||
match = 1;
|
||||
break;
|
||||
} else if (*s == '\r') {
|
||||
if (s[1] == '\n') {
|
||||
match = 2;
|
||||
} else {
|
||||
match = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
size_t sub_len = s - start;
|
||||
if (args[ARG_keepends].u_bool) {
|
||||
sub_len += match;
|
||||
}
|
||||
mp_obj_list_append(res, mp_obj_new_str_of_type(self_type, start, sub_len));
|
||||
s += match;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -801,6 +817,23 @@ STATIC mp_obj_t str_rstrip(size_t n_args, const mp_obj_t *args) {
|
||||
return str_uni_strip(RSTRIP, n_args, args);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_STR_CENTER
|
||||
STATIC mp_obj_t str_center(mp_obj_t str_in, mp_obj_t width_in) {
|
||||
GET_STR_DATA_LEN(str_in, str, str_len);
|
||||
mp_uint_t width = mp_obj_get_int(width_in);
|
||||
if (str_len >= width) {
|
||||
return str_in;
|
||||
}
|
||||
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, width);
|
||||
memset(vstr.buf, ' ', width);
|
||||
int left = (width - str_len) / 2;
|
||||
memcpy(vstr.buf + left, str, str_len);
|
||||
return mp_obj_new_str_from_vstr(mp_obj_get_type(str_in), &vstr);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Takes an int arg, but only parses unsigned numbers, and only changes
|
||||
// *num if at least one digit was parsed.
|
||||
STATIC const char *str_to_int(const char *str, const char *top, int *num) {
|
||||
@@ -1806,7 +1839,7 @@ mp_int_t mp_obj_str_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_u
|
||||
GET_STR_DATA_LEN(self_in, str_data, str_len);
|
||||
bufinfo->buf = (void*)str_data;
|
||||
bufinfo->len = str_len;
|
||||
bufinfo->typecode = 'b';
|
||||
bufinfo->typecode = 'B'; // bytes should be unsigned, so should unicode byte-access
|
||||
return 0;
|
||||
} else {
|
||||
// can't write to a string
|
||||
@@ -1830,6 +1863,9 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, mp_obj_str_split);
|
||||
#if MICROPY_PY_BUILTINS_STR_SPLITLINES
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(str_splitlines_obj, 1, str_splitlines);
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_STR_CENTER
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(str_center_obj, str_center);
|
||||
#endif
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_rsplit_obj, 1, 3, str_rsplit);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_startswith_obj, 2, 3, str_startswith);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_endswith_obj, 2, 3, str_endswith);
|
||||
@@ -1881,6 +1917,9 @@ STATIC const mp_rom_map_elem_t str8_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&str_count_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_partition), MP_ROM_PTR(&str_partition_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rpartition), MP_ROM_PTR(&str_rpartition_obj) },
|
||||
#if MICROPY_PY_BUILTINS_STR_CENTER
|
||||
{ MP_ROM_QSTR(MP_QSTR_center), MP_ROM_PTR(&str_center_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_lower), MP_ROM_PTR(&str_lower_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_upper), MP_ROM_PTR(&str_upper_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_isspace), MP_ROM_PTR(&str_isspace_obj) },
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user