Compare commits
88 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff8d0e071c | ||
|
|
0e3722137f | ||
|
|
8e701604d5 | ||
|
|
bc0bc764fc | ||
|
|
183ac71dc8 | ||
|
|
1e3fde0a10 | ||
|
|
72165c01f0 | ||
|
|
ff319dffad | ||
|
|
0344fa1ddf | ||
|
|
2cd79fa924 | ||
|
|
bfd11a35db | ||
|
|
f6e825b42e | ||
|
|
6e6dfdc56b | ||
|
|
1060baa2c2 | ||
|
|
38bd762121 | ||
|
|
039887a0ac | ||
|
|
a58713a899 | ||
|
|
c7da7838ba | ||
|
|
109c1de015 | ||
|
|
4029f51842 | ||
|
|
1559a97810 | ||
|
|
fa73c9cb25 | ||
|
|
88d3054ac0 | ||
|
|
7c4445afe1 | ||
|
|
1a8573ed0e | ||
|
|
47f349e7de | ||
|
|
c92ef361c7 | ||
|
|
4ef67d30f1 | ||
|
|
9a41b32b3f | ||
|
|
efc49c5591 | ||
|
|
6a15ac80dc | ||
|
|
504636815e | ||
|
|
0e557facb9 | ||
|
|
e62a0fe367 | ||
|
|
31619cc589 | ||
|
|
11aa91615e | ||
|
|
8bb71f0b06 | ||
|
|
66d08eb4fe | ||
|
|
6d287a6a02 | ||
|
|
2559e13957 | ||
|
|
b1422de12f | ||
|
|
49c47da804 | ||
|
|
4e54c876a7 | ||
|
|
ccedf000ed | ||
|
|
429e3f077e | ||
|
|
8768f8ad4b | ||
|
|
e4e52f5370 | ||
|
|
e503512f83 | ||
|
|
bc1488a05f | ||
|
|
b2f19b8d34 | ||
|
|
480a7ce58f | ||
|
|
de3c806965 | ||
|
|
c76af32575 | ||
|
|
b0b0012fd8 | ||
|
|
91bd4e8a23 | ||
|
|
124df6f8d0 | ||
|
|
d7353fe6fe | ||
|
|
627852019b | ||
|
|
c9fc620723 | ||
|
|
e5a3759ff5 | ||
|
|
8becca7c82 | ||
|
|
8456cc017b | ||
|
|
1084b0f9c2 | ||
|
|
fcff4663dd | ||
|
|
8204db6831 | ||
|
|
21dfd207ca | ||
|
|
a64d5d67b5 | ||
|
|
0b13f3e026 | ||
|
|
564963a170 | ||
|
|
d00d8ac95c | ||
|
|
e294bee45b | ||
|
|
e5b1b7348a | ||
|
|
e2f8d98525 | ||
|
|
185cb0d943 | ||
|
|
e7bb0443cd | ||
|
|
dd4f4530ab | ||
|
|
3aa09f5784 | ||
|
|
37378f8a9d | ||
|
|
f5d69794a8 | ||
|
|
e72be1b999 | ||
|
|
5fc42a6c97 | ||
|
|
842210f53a | ||
|
|
e7a478204a | ||
|
|
efa04eafd3 | ||
|
|
d46a822262 | ||
|
|
3be6984b8f | ||
|
|
8d62bbd46a | ||
|
|
3e42570538 |
@@ -17,6 +17,7 @@ script:
|
||||
- make -C bare-arm
|
||||
- make -C qemu-arm
|
||||
- make -C stmhal
|
||||
- make -C stmhal -B MICROPY_PY_WIZNET5K=1 MICROPY_PY_CC3K=1
|
||||
- make -C stmhal BOARD=STM32F4DISC
|
||||
- make -C teensy
|
||||
- make -C windows CROSS_COMPILE=i586-mingw32msvc-
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#define MICROPY_HELPER_LEXER_UNIX (0)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (0)
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#define MICROPY_PY_BUILTINS_FROZENSET (0)
|
||||
#define MICROPY_PY_BUILTINS_SET (0)
|
||||
#define MICROPY_PY_BUILTINS_SLICE (0)
|
||||
|
||||
10
docs/conf.py
@@ -60,7 +60,7 @@ copyright = '2014, Damien P. George'
|
||||
# The short X.Y version.
|
||||
version = '1.3'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '1.3.1'
|
||||
release = '1.3.6'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
@@ -113,7 +113,7 @@ html_theme = 'default'
|
||||
#html_theme_options = {}
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = []
|
||||
html_theme_path = ['.']
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
@@ -124,7 +124,7 @@ html_theme = 'default'
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
#html_logo = None
|
||||
#html_logo = '../logo/trans-logo.png'
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
@@ -143,7 +143,7 @@ html_theme = 'default'
|
||||
|
||||
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||
# using the given strftime format.
|
||||
#html_last_updated_fmt = '%b %d, %Y'
|
||||
html_last_updated_fmt = '%d %b %Y'
|
||||
|
||||
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||
# typographically correct entities.
|
||||
@@ -154,7 +154,7 @@ html_theme = 'default'
|
||||
|
||||
# Additional templates that should be rendered to pages, maps page names to
|
||||
# template names.
|
||||
#html_additional_pages = {}
|
||||
html_additional_pages = {"index":"topindex.html"}
|
||||
|
||||
# If false, no module index is generated.
|
||||
#html_domain_indices = True
|
||||
|
||||
11
docs/contents.rst
Normal file
@@ -0,0 +1,11 @@
|
||||
Micro Python documentation contents
|
||||
===================================
|
||||
|
||||
.. toctree::
|
||||
|
||||
quickref.rst
|
||||
general.rst
|
||||
tutorial/index.rst
|
||||
library/index.rst
|
||||
hardware/index.rst
|
||||
license.rst
|
||||
20
docs/hardware/index.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
The pyboard hardware
|
||||
====================
|
||||
|
||||
* `PYBv1.0 schematics and layout <http://micropython.org/resources/PYBv10b.pdf>`_ (2.4MiB PDF)
|
||||
* `PYBv1.0 metric dimensions <http://micropython.org/resources/PYBv10b-metric-dimensions.pdf>`_ (360KiB PDF)
|
||||
* `PYBv1.0 imperial dimensions <http://micropython.org/resources/PYBv10b-imperial-dimensions.pdf>`_ (360KiB PDF)
|
||||
|
||||
Datasheets for the components on the pyboard
|
||||
============================================
|
||||
|
||||
* The microcontroller: `STM32F405RGT6 <http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144>`_ (link to manufacturer's site)
|
||||
* The accelerometer: `Freescale MMA7660 <http://micropython.org/resources/datasheets/MMA7660FC.pdf>`_ (800kiB PDF)
|
||||
* The LDO voltage regulator: `Microchip MCP1802 <http://micropython.org/resources/datasheets/MCP1802-22053C.pdf>`_ (400kiB PDF)
|
||||
|
||||
Datasheets for other components
|
||||
===============================
|
||||
|
||||
* The LCD display on the LCD touch-sensor skin: `Newhaven Display NHD-C12832A1Z-FSW-FBW-3V3 <http://micropython.org/resources/datasheets/NHD-C12832A1Z-FSW-FBW-3V3.pdf>`_ (460KiB PDF)
|
||||
* The touch sensor chip on the LCD touch-sensor skin: `Freescale MPR121 <http://micropython.org/resources/datasheets/MPR121.pdf>`_ (280KiB PDF)
|
||||
* The digital potentiometer on the audio skin: `Microchip MCP4541 <http://micropython.org/resources/datasheets/MCP4541-22107B.pdf>`_ (2.7MiB PDF)
|
||||
@@ -1,38 +1,15 @@
|
||||
.. Micro Python documentation master file
|
||||
|
||||
Micro Python documentation and references
|
||||
=========================================
|
||||
|
||||
Here you can find documentation for Micro Python and the pyboard.
|
||||
|
||||
Software
|
||||
--------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
quickref.rst
|
||||
general.rst
|
||||
tutorial/index.rst
|
||||
|
||||
..
|
||||
.. - Reference for the [pyb module](module/pyb/ "pyb module").
|
||||
.. - Reference for [all modules](module/ "all modules").
|
||||
.. - [Guide for setting up the pyboard on Windows](/static/doc/Micro-Python-Windows-setup.pdf), including DFU programming (PDF).
|
||||
|
||||
The pyboard hardware
|
||||
--------------------
|
||||
|
||||
.. - PYBv1.0 [schematics and layout](/static/doc/PYBv10b.pdf "PYBv1.0") (2.4MiB PDF).
|
||||
.. - PYBv1.0 [metric dimensions](/static/doc/PYBv10b-metric-dimensions.pdf "metric dimensions") (360KiB PDF).
|
||||
.. - PYBv1.0 [imperial dimensions](/static/doc/PYBv10b-imperial-dimensions.pdf "imperial dimensions") (360KiB PDF).
|
||||
|
||||
Datasheets for the components on the pyboard
|
||||
--------------------------------------------
|
||||
|
||||
.. - The microcontroller: [STM32F405RGT6](http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN1035/PF252144) (external link).
|
||||
.. - The accelerometer: [Freescale MMA7660](/static/doc/MMA7660FC.pdf) (800kiB PDF).
|
||||
.. - The LDO voltage regulator: [Microchip MCP1802](/static/doc/MCP1802-22053C.pdf) (400kiB PDF).
|
||||
|
||||
library/index.rst
|
||||
hardware/index.rst
|
||||
license.rst
|
||||
contents.rst
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
@@ -40,4 +17,3 @@ Indices and tables
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
||||
|
||||
|
||||
58
docs/library/cmath.rst
Normal file
@@ -0,0 +1,58 @@
|
||||
:mod:`cmath` -- mathematical functions for complex numbers
|
||||
==========================================================
|
||||
|
||||
.. module:: cmath
|
||||
:synopsis: mathematical functions for complex numbers
|
||||
|
||||
The ``cmath`` module provides some basic mathematical funtions for
|
||||
working with complex numbers.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: cos(z)
|
||||
|
||||
Return the cosine of ``z``.
|
||||
|
||||
.. function:: exp(z)
|
||||
|
||||
Return the exponential of ``z``.
|
||||
|
||||
.. function:: log(z)
|
||||
|
||||
Return the natural logarithm of ``z``. The branch cut is along the negative real axis.
|
||||
|
||||
.. function:: log10(z)
|
||||
|
||||
Return the base-10 logarithm of ``z``. The branch cut is along the negative real axis.
|
||||
|
||||
.. function:: phase(z)
|
||||
|
||||
Returns the phase of the number ``z``, in the range (-pi, +pi].
|
||||
|
||||
.. function:: polar(z)
|
||||
|
||||
Returns, as a tuple, the polar form of ``z``.
|
||||
|
||||
.. function:: rect(r, phi)
|
||||
|
||||
Returns the complex number with modulus ``r`` and phase ``phi``.
|
||||
|
||||
.. function:: sin(z)
|
||||
|
||||
Return the sine of ``z``.
|
||||
|
||||
.. function:: sqrt(z)
|
||||
|
||||
Return the square-root of ``z``.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: e
|
||||
|
||||
base of the natural logarithm
|
||||
|
||||
.. data:: pi
|
||||
|
||||
the ratio of a circle's circumference to its diameter
|
||||
29
docs/library/gc.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
:mod:`gc` -- control the garbage collector
|
||||
==========================================
|
||||
|
||||
.. module:: gc
|
||||
:synopsis: control the garbage collector
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: enable()
|
||||
|
||||
Enable automatic garbage collection.
|
||||
|
||||
.. function:: disable()
|
||||
|
||||
Disable automatic garbage collection. Heap memory can still be allocated,
|
||||
and garbage collection can still be initiated manually using :meth:`gc.collect`.
|
||||
|
||||
.. function:: collect()
|
||||
|
||||
Run a garbage collection.
|
||||
|
||||
.. function:: mem_alloc()
|
||||
|
||||
Return the number of bytes of heap RAM that are allocated.
|
||||
|
||||
.. function:: mem_free()
|
||||
|
||||
Return the number of bytes of available heap RAM.
|
||||
54
docs/library/index.rst
Normal file
@@ -0,0 +1,54 @@
|
||||
Micro Python libraries
|
||||
======================
|
||||
|
||||
Python standard libraries
|
||||
-------------------------
|
||||
|
||||
The following standard Python libraries are built in to Micro Python.
|
||||
|
||||
For additional libraries, please download them from the `micropython-lib repository
|
||||
<https://github.com/micropython/micropython-lib>`_.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmath.rst
|
||||
gc.rst
|
||||
math.rst
|
||||
os.rst
|
||||
select.rst
|
||||
struct.rst
|
||||
sys.rst
|
||||
time.rst
|
||||
|
||||
Python micro-libraries
|
||||
----------------------
|
||||
|
||||
The following standard Python libraries have been "micro-ified" to fit in with
|
||||
the philosophy of Micro Python. They provide the core functionality of that
|
||||
module and are intended to be a drop-in replacement for the standard Python
|
||||
library.
|
||||
|
||||
The modules are available by their u-name, and also by their non-u-name. The
|
||||
non-u-name can be overridden by a file of that name in your package path.
|
||||
For example, ``import json`` will first search for a file ``json.py`` or
|
||||
directory ``json`` and load that package if it is found. If nothing is found,
|
||||
it will fallback to loading the built-in ``ujson`` module.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usocket.rst
|
||||
uheapq.rst
|
||||
ujson.rst
|
||||
|
||||
Libraries specific to the pyboard
|
||||
---------------------------------
|
||||
|
||||
The following libraries are specific to the pyboard.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
pyb.rst
|
||||
network.rst
|
||||
177
docs/library/math.rst
Normal file
@@ -0,0 +1,177 @@
|
||||
:mod:`math` -- mathematical functions
|
||||
=====================================
|
||||
|
||||
.. module:: math
|
||||
:synopsis: mathematical functions
|
||||
|
||||
The ``math`` module provides some basic mathematical funtions for
|
||||
working with floating-point numbers.
|
||||
|
||||
*Note:* On the pyboard, floating-point numbers have 32-bit precision.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: acos(x)
|
||||
|
||||
Return the inverse cosine of ``x``.
|
||||
|
||||
.. function:: acosh(x)
|
||||
|
||||
Return the inverse hyperbolic cosine of ``x``.
|
||||
|
||||
.. function:: asin(x)
|
||||
|
||||
Return the inverse sine of ``x``.
|
||||
|
||||
.. function:: asinh(x)
|
||||
|
||||
Return the inverse hyperbolic sine of ``x``.
|
||||
|
||||
.. function:: atan(x)
|
||||
|
||||
Return the inverse tangent of ``x``.
|
||||
|
||||
.. function:: atan2(y, x)
|
||||
|
||||
Return the principal value of the inverse tangent of ``y/x``.
|
||||
|
||||
.. function:: atanh(x)
|
||||
|
||||
Return the inverse hyperbolic tangent of ``x``.
|
||||
|
||||
.. function:: ceil(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards positive infinity.
|
||||
|
||||
.. function:: copysign(x, y)
|
||||
|
||||
Return ``x`` with the sign of ``y``.
|
||||
|
||||
.. function:: cos(x)
|
||||
|
||||
Return the cosine of ``x``.
|
||||
|
||||
.. function:: cosh(x)
|
||||
|
||||
Return the hyperbolic cosine of ``x``.
|
||||
|
||||
.. function:: degrees(x)
|
||||
|
||||
Return radians ``x`` converted to degrees.
|
||||
|
||||
.. function:: erf(x)
|
||||
|
||||
Return the error function of ``x``.
|
||||
|
||||
.. function:: erfc(x)
|
||||
|
||||
Return the complementary error function of ``x``.
|
||||
|
||||
.. function:: exp(x)
|
||||
|
||||
Return the exponential of ``x``.
|
||||
|
||||
.. function:: expm1(x)
|
||||
|
||||
Return ``exp(x) - 1``.
|
||||
|
||||
.. function:: fabs(x)
|
||||
|
||||
Return the absolute value of ``x``.
|
||||
|
||||
.. function:: floor(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards negative infinity.
|
||||
|
||||
.. function:: fmod(x, y)
|
||||
|
||||
Return the remainder of ``x/y``.
|
||||
|
||||
.. function:: frexp(x)
|
||||
|
||||
Converts a floating-point number to fractional and integral components.
|
||||
|
||||
.. function:: gamma(x)
|
||||
|
||||
Return the gamma function of ``x``.
|
||||
|
||||
.. function:: isfinite(x)
|
||||
|
||||
Return ``True`` if ``x`` is finite.
|
||||
|
||||
.. function:: isinf(x)
|
||||
|
||||
Return ``True`` if ``x`` is infinite.
|
||||
|
||||
.. function:: isnan(x)
|
||||
|
||||
Return ``True`` if ``x`` is not-a-number
|
||||
|
||||
.. function:: ldexp(x, exp)
|
||||
|
||||
Return ``x * (2**exp)``.
|
||||
|
||||
.. function:: lgamma(x)
|
||||
|
||||
Return the natural logarithm of the gamma function of ``x``.
|
||||
|
||||
.. function:: log(x)
|
||||
|
||||
Return the natural logarithm of ``x``.
|
||||
|
||||
.. function:: log10(x)
|
||||
|
||||
Return the base-10 logarithm of ``x``.
|
||||
|
||||
.. function:: log2(x)
|
||||
|
||||
Return the base-2 logarithm of ``x``.
|
||||
|
||||
.. function:: modf(x)
|
||||
|
||||
Return a tuple of two floats, being the fractional and integral parts of
|
||||
``x``. Both return values have the same sign as ``x``.
|
||||
|
||||
.. function:: pow(x, y)
|
||||
|
||||
Returns ``x`` to the power of ``y``.
|
||||
|
||||
.. function:: radians(x)
|
||||
|
||||
Return degrees ``x`` converted to radians.
|
||||
|
||||
.. function:: sin(x)
|
||||
|
||||
Return the sine of ``x``.
|
||||
|
||||
.. function:: sinh(x)
|
||||
|
||||
Return the hyperbolic sine of ``x``.
|
||||
|
||||
.. function:: sqrt(x)
|
||||
|
||||
Return the square root of ``x``.
|
||||
|
||||
.. function:: tan(x)
|
||||
|
||||
Return the tangent of ``x``.
|
||||
|
||||
.. function:: tanh(x)
|
||||
|
||||
Return the hyperbolic tangent of ``x``.
|
||||
|
||||
.. function:: trunc(x)
|
||||
|
||||
Return an integer, being ``x`` rounded towards 0.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: e
|
||||
|
||||
base of the natural logarithm
|
||||
|
||||
.. data:: pi
|
||||
|
||||
the ratio of a circle's circumference to its diameter
|
||||
63
docs/library/network.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
****************************************
|
||||
:mod:`network` --- network configuration
|
||||
****************************************
|
||||
|
||||
.. module:: network
|
||||
:synopsis: network configuration
|
||||
|
||||
This module provides network drivers and routing configuration.
|
||||
|
||||
|
||||
class CC3k
|
||||
==========
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: CC3k(spi, pin_cs, pin_en, pin_irq)
|
||||
|
||||
Initialise the CC3000 using the given SPI bus and pins and return a CC3k object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: cc3k.connect(ssid, key=None, \*, security=WPA2, bssid=None)
|
||||
|
||||
|
||||
class WIZnet5k
|
||||
==============
|
||||
|
||||
This class allows you to control WIZnet5x00 Ethernet adaptors based on
|
||||
the W5200 and W5500 chipsets (only W5200 tested).
|
||||
|
||||
Example usage::
|
||||
|
||||
import wiznet5k
|
||||
w = wiznet5k.WIZnet5k()
|
||||
print(w.ipaddr())
|
||||
w.gethostbyname('micropython.org')
|
||||
s = w.socket()
|
||||
s.connect(('192.168.0.2', 8080))
|
||||
s.send('hello')
|
||||
print(s.recv(10))
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: WIZnet5k(spi, pin_cs, pin_rst)
|
||||
|
||||
Create and return a WIZnet5k object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: wiznet5k.ipaddr([(ip, subnet, gateway, dns)])
|
||||
|
||||
Get/set IP address, subnet mask, gateway and DNS.
|
||||
|
||||
.. method:: wiznet5k.regs()
|
||||
|
||||
Dump WIZnet5k registers.
|
||||
67
docs/library/os.rst
Normal file
@@ -0,0 +1,67 @@
|
||||
:mod:`os` -- basic "operating system" services
|
||||
==============================================
|
||||
|
||||
.. module:: os
|
||||
:synopsis: basic "operating system" services
|
||||
|
||||
The ``os`` module contains functions for filesystem access and ``urandom``.
|
||||
|
||||
Pyboard specifics
|
||||
-----------------
|
||||
|
||||
The filesystem on the pyboard has ``/`` as the root directory and the
|
||||
available physical drives are accessible from here. They are currently:
|
||||
|
||||
``/flash`` -- the internal flash filesystem
|
||||
|
||||
``/sd`` -- the SD card (if it exists)
|
||||
|
||||
On boot up, the current directory is ``/flash`` if no SD card is inserted,
|
||||
otherwise it is ``/sd``.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: chdir(path)
|
||||
|
||||
Change current directory.
|
||||
|
||||
.. function:: getcwd()
|
||||
|
||||
Get the current directory.
|
||||
|
||||
.. function:: listdir([dir])
|
||||
|
||||
With no argument, list the current directory. Otherwise list the given directory.
|
||||
|
||||
.. function:: mkdir(path)
|
||||
|
||||
Create a new directory.
|
||||
|
||||
.. function:: remove(path)
|
||||
|
||||
Remove a file.
|
||||
|
||||
.. function:: rmdir(path)
|
||||
|
||||
Remove a directory.
|
||||
|
||||
.. function:: stat(path)
|
||||
|
||||
Get the status of a file or directory.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
Sync all filesystems.
|
||||
|
||||
.. function:: urandom(n)
|
||||
|
||||
Return a bytes object with n random bytes, generated by the hardware
|
||||
random number generator.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: sep
|
||||
|
||||
separation character used in paths
|
||||
52
docs/library/pyb.ADC.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
.. _pyb.ADC:
|
||||
|
||||
class ADC -- analog to digital conversion: read analog values on a pin
|
||||
======================================================================
|
||||
|
||||
Usage::
|
||||
|
||||
import pyb
|
||||
|
||||
adc = pyb.ADC(pin) # create an analog object from a pin
|
||||
val = adc.read() # read an analog value
|
||||
|
||||
adc = pyb.ADCAll(resolution) # creale an ADCAll object
|
||||
val = adc.read_channel(channel) # read the given channel
|
||||
val = adc.read_core_temp() # read MCU temperature
|
||||
val = adc.read_core_vbat() # read MCU VBAT
|
||||
val = adc.read_core_vref() # read MCU VREF
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.ADC(pin)
|
||||
|
||||
Create an ADC object associated with the given pin.
|
||||
This allows you to then read analog values on that pin.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: adc.read()
|
||||
|
||||
Read the value on the analog pin and return it. The returned value
|
||||
will be between 0 and 4095.
|
||||
|
||||
.. method:: adc.read_timed(buf, freq)
|
||||
|
||||
Read analog values into the given buffer at the given frequency. Buffer
|
||||
can be bytearray or array.array for example. If a buffer with 8-bit elements
|
||||
is used, sample resolution will be reduced to 8 bits.
|
||||
|
||||
Example::
|
||||
|
||||
adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19
|
||||
buf = bytearray(100) # create a buffer of 100 bytes
|
||||
adc.read_timed(buf, 10) # read analog values into buf at 10Hz
|
||||
# this will take 10 seconds to finish
|
||||
for val in buf: # loop over all values
|
||||
print(val) # print the value out
|
||||
|
||||
This function does not allocate any memory.
|
||||
51
docs/library/pyb.Accel.rst
Normal file
@@ -0,0 +1,51 @@
|
||||
class Accel -- accelerometer control
|
||||
====================================
|
||||
|
||||
Accel is an object that controls the accelerometer. Example usage::
|
||||
|
||||
accel = pyb.Accel()
|
||||
for i in range(10):
|
||||
print(accel.x(), accel.y(), accel.z())
|
||||
|
||||
Raw values are between -32 and 31.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Accel()
|
||||
|
||||
Create and return an accelerometer object.
|
||||
|
||||
Note: if you read accelerometer values immediately after creating this object
|
||||
you will get 0. It takes around 20ms for the first sample to be ready, so,
|
||||
unless you have some other code between creating this object and reading its
|
||||
values, you should put a ``pyb.delay(20)`` after creating it. For example::
|
||||
|
||||
accel = pyb.Accel()
|
||||
pyb.delay(20)
|
||||
print(accel.x())
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: accel.filtered_xyz()
|
||||
|
||||
Get a 3-tuple of filtered x, y and z values.
|
||||
|
||||
.. method:: accel.tilt()
|
||||
|
||||
Get the tilt register.
|
||||
|
||||
.. method:: accel.x()
|
||||
|
||||
Get the x-axis value.
|
||||
|
||||
.. method:: accel.y()
|
||||
|
||||
Get the y-axis value.
|
||||
|
||||
.. method:: accel.z()
|
||||
|
||||
Get the z-axis value.
|
||||
87
docs/library/pyb.CAN.rst
Normal file
@@ -0,0 +1,87 @@
|
||||
class CAN -- controller area network communication bus
|
||||
======================================================
|
||||
|
||||
CAN implements the standard CAN communications protocol. At
|
||||
the physical level it consists of 2 lines: RX and TX. Note that
|
||||
to connect the pyboard to a CAN bus you must use a CAN transceiver
|
||||
to convert the CAN logic signals from the pyboard to the correct
|
||||
voltage levels on the bus.
|
||||
|
||||
Note that this driver does not yet support filter configuration
|
||||
(it defaults to a single filter that lets through all messages),
|
||||
or bus timing configuration (except for setting the prescaler).
|
||||
|
||||
Example usage (works without anything connected)::
|
||||
|
||||
from pyb import CAN
|
||||
can = pyb.CAN(1, pyb.CAN.LOOPBACK)
|
||||
can.send('message!', 123) # send message to id 123
|
||||
can.recv(0) # receive message on FIFO 0
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.CAN(bus, ...)
|
||||
|
||||
Construct a CAN object on the given bus. ``bus`` can be 1-2, or 'YA' or 'YB'.
|
||||
With no additional parameters, the CAN object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the CAN busses are:
|
||||
|
||||
- ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)``
|
||||
- ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)``
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: can.init(mode, extframe=False, prescaler=100, \*, sjw=1, bs1=6, bs2=8)
|
||||
|
||||
Initialise the CAN bus with the given parameters:
|
||||
|
||||
- ``mode`` is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK
|
||||
|
||||
If ``extframe`` is True then the bus uses extended identifiers in the frames (29 bits).
|
||||
Otherwise it uses standard 11 bit identifiers.
|
||||
|
||||
.. method:: can.deinit()
|
||||
|
||||
Turn off the CAN bus.
|
||||
|
||||
.. method:: can.any(fifo)
|
||||
|
||||
Return ``True`` if any message waiting on the FIFO, else ``False``.
|
||||
|
||||
.. method:: can.recv(fifo, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``fifo`` is an integer, which is the FIFO to receive on
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: buffer of data bytes.
|
||||
|
||||
.. method:: can.send(send, addr, \*, timeout=5000)
|
||||
|
||||
Send a message on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``addr`` is the address to send to
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: CAN.NORMAL
|
||||
.. data:: CAN.LOOPBACK
|
||||
.. data:: CAN.SILENT
|
||||
.. data:: CAN.SILENT_LOOPBACK
|
||||
|
||||
the mode of the CAN bus
|
||||
69
docs/library/pyb.DAC.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
.. _pyb.DAC:
|
||||
|
||||
class DAC -- digital to analog conversion
|
||||
=========================================
|
||||
|
||||
The DAC is used to output analog values (a specific voltage) on pin X5 or pin X6.
|
||||
The voltage will be between 0 and 3.3V.
|
||||
|
||||
*This module will undergo changes to the API.*
|
||||
|
||||
Example usage::
|
||||
|
||||
from pyb import DAC
|
||||
|
||||
dac = DAC(1) # create DAC 1 on pin X5
|
||||
dac.write(128) # write a value to the DAC (makes X5 1.65V)
|
||||
|
||||
To output a continuous sine-wave::
|
||||
|
||||
import math
|
||||
from pyb import DAC
|
||||
|
||||
# create a buffer containing a sine-wave
|
||||
buf = bytearray(100)
|
||||
for i in range(len(buf)):
|
||||
buf[i] = 128 + int(127 \* math.sin(2 \* math.pi \* i / len(buf)))
|
||||
|
||||
# output the sine-wave at 400Hz
|
||||
dac = DAC(1)
|
||||
dac.write_timed(buf, 400 \* len(buf), mode=DAC.CIRCULAR)
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.DAC(port)
|
||||
|
||||
Construct a new DAC object.
|
||||
|
||||
``port`` can be a pin object, or an integer (1 or 2).
|
||||
DAC(1) is on pin X5 and DAC(2) is on pin X6.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: dac.noise(freq)
|
||||
|
||||
Generate a pseudo-random noise signal. A new random sample is written
|
||||
to the DAC output at the given frequency.
|
||||
|
||||
.. method:: dac.triangle(freq)
|
||||
|
||||
Generate a triangle wave. The value on the DAC output changes at
|
||||
the given frequency, and the frequence of the repeating triangle wave
|
||||
itself is 256 (or 1024, need to check) times smaller.
|
||||
|
||||
.. method:: dac.write(value)
|
||||
|
||||
Direct access to the DAC output (8 bit only at the moment).
|
||||
|
||||
.. method:: dac.write_timed(data, freq, \*, mode=DAC.NORMAL)
|
||||
|
||||
Initiates a burst of RAM to DAC using a DMA transfer.
|
||||
The input data is treated as an array of bytes (8 bit data).
|
||||
|
||||
``mode`` can be ``DAC.NORMAL`` or ``DAC.CIRCULAR``.
|
||||
|
||||
TIM6 is used to control the frequency of the transfer.
|
||||
113
docs/library/pyb.ExtInt.rst
Normal file
@@ -0,0 +1,113 @@
|
||||
.. _pyb.ExtInt:
|
||||
|
||||
class ExtInt -- configure I/O pins to interrupt on external events
|
||||
==================================================================
|
||||
|
||||
There are a total of 22 interrupt lines. 16 of these can come from GPIO pins
|
||||
and the remaining 6 are from internal sources.
|
||||
|
||||
For lines 0 thru 15, a given line can map to the corresponding line from an
|
||||
arbitrary port. So line 0 can map to Px0 where x is A, B, C, ... and
|
||||
line 1 can map to Px1 where x is A, B, C, ... ::
|
||||
|
||||
def callback(line):
|
||||
print("line =", line)
|
||||
|
||||
Note: ExtInt will automatically configure the gpio line as an input. ::
|
||||
|
||||
extint = pyb.ExtInt(pin, pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, callback)
|
||||
|
||||
Now every time a falling edge is seen on the X1 pin, the callback will be
|
||||
called. Caution: mechanical pushbuttons have "bounce" and pushing or
|
||||
releasing a switch will often generate multiple edges.
|
||||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
|
||||
explanation, along with various techniques for debouncing.
|
||||
|
||||
Trying to register 2 callbacks onto the same pin will throw an exception.
|
||||
|
||||
If pin is passed as an integer, then it is assumed to map to one of the
|
||||
internal interrupt sources, and must be in the range 16 thru 22.
|
||||
|
||||
All other pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins. ::
|
||||
|
||||
extint = pyb.ExtInt(pin, mode, pull, callback)
|
||||
|
||||
Valid modes are pyb.ExtInt.IRQ_RISING, pyb.ExtInt.IRQ_FALLING,
|
||||
pyb.ExtInt.IRQ_RISING_FALLING, pyb.ExtInt.EVT_RISING,
|
||||
pyb.ExtInt.EVT_FALLING, and pyb.ExtInt.EVT_RISING_FALLING.
|
||||
|
||||
Only the IRQ_xxx modes have been tested. The EVT_xxx modes have
|
||||
something to do with sleep mode and the WFE instruction.
|
||||
|
||||
Valid pull values are pyb.Pin.PULL_UP, pyb.Pin.PULL_DOWN, pyb.Pin.PULL_NONE.
|
||||
|
||||
There is also a C API, so that drivers which require EXTI interrupt lines
|
||||
can also use this code. See extint.h for the available functions and
|
||||
usrsw.h for an example of using this.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.ExtInt(pin, mode, pull, callback)
|
||||
|
||||
Create an ExtInt object:
|
||||
|
||||
- ``pin`` is the pin on which to enable the interrupt (can be a pin object or any valid pin name).
|
||||
- ``mode`` can be one of:
|
||||
- ``ExtInt.IRQ_RISING`` - trigger on a rising edge;
|
||||
- ``ExtInt.IRQ_FALLING`` - trigger on a falling edge;
|
||||
- ``ExtInt.IRQ_RISING_FALLING`` - trigger on a rising or falling edge.
|
||||
- ``pull`` can be one of:
|
||||
- ``pyb.Pin.PULL_NONE`` - no pull up or down resistors;
|
||||
- ``pyb.Pin.PULL_UP`` - enable the pull-up resistor;
|
||||
- ``pyb.Pin.PULL_DOWN`` - enable the pull-down resistor.
|
||||
- ``callback`` is the function to call when the interrupt triggers. The
|
||||
callback function must accept exactly 1 argument, which is the line that
|
||||
triggered the interrupt.
|
||||
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
|
||||
.. method:: ExtInt.regs()
|
||||
|
||||
Dump the values of the EXTI registers.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: extint.disable()
|
||||
|
||||
Disable the interrupt associated with the ExtInt object.
|
||||
This could be useful for debouncing.
|
||||
|
||||
.. method:: extint.enable()
|
||||
|
||||
Enable a disabled interrupt.
|
||||
|
||||
.. method:: extint.line()
|
||||
|
||||
Return the line number that the pin is mapped to.
|
||||
|
||||
.. method:: extint.swint()
|
||||
|
||||
Trigger the callback from software.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: ExtInt.IRQ_FALLING
|
||||
|
||||
interrupt on a falling edge
|
||||
|
||||
.. data:: ExtInt.IRQ_RISING
|
||||
|
||||
interrupt on a rising edge
|
||||
|
||||
.. data:: ExtInt.IRQ_RISING_FALLING
|
||||
|
||||
interrupt on a rising or falling edge
|
||||
153
docs/library/pyb.I2C.rst
Normal file
@@ -0,0 +1,153 @@
|
||||
.. _pyb.I2C:
|
||||
|
||||
class I2C -- a two-wire serial protocol
|
||||
=======================================
|
||||
|
||||
I2C is a two-wire protocol for communicating between devices. At the physical
|
||||
level it consists of 2 wires: SCL and SDA, the clock and data lines respectively.
|
||||
|
||||
I2C objects are created attached to a specific bus. They can be initialised
|
||||
when created, or initialised later on::
|
||||
|
||||
from pyb import I2C
|
||||
|
||||
i2c = I2C(1) # create on bus 1
|
||||
i2c = I2C(1, I2C.MASTER) # create and init as a master
|
||||
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
|
||||
i2c.init(I2C.SLAVE, addr=0x42) # init as a slave with given address
|
||||
i2c.deinit() # turn off the peripheral
|
||||
|
||||
Printing the i2c object gives you information about its configuration.
|
||||
|
||||
Basic methods for slave are send and recv::
|
||||
|
||||
i2c.send('abc') # send 3 bytes
|
||||
i2c.send(0x42) # send a single byte, given by the number
|
||||
data = i2c.recv(3) # receive 3 bytes
|
||||
|
||||
To receive inplace, first create a bytearray::
|
||||
|
||||
data = bytearray(3) # create a buffer
|
||||
i2c.recv(data) # receive 3 bytes, writing them into data
|
||||
|
||||
You can specify a timeout (in ms)::
|
||||
|
||||
i2c.send(b'123', timeout=2000) # timout after 2 seconds
|
||||
|
||||
A master must specify the recipient's address::
|
||||
|
||||
i2c.init(I2C.MASTER)
|
||||
i2c.send('123', 0x42) # send 3 bytes to slave with address 0x42
|
||||
i2c.send(b'456', addr=0x42) # keyword for address
|
||||
|
||||
Master also has other methods::
|
||||
|
||||
i2c.is_ready(0x42) # check if slave 0x42 is ready
|
||||
i2c.scan() # scan for slaves on the bus, returning
|
||||
# a list of valid addresses
|
||||
i2c.mem_read(3, 0x42, 2) # read 3 bytes from memory of slave 0x42,
|
||||
# starting at address 2 in the slave
|
||||
i2c.mem_write('abc', 0x42, 2, timeout=1000)
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.I2C(bus, ...)
|
||||
|
||||
Construct an I2C object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the I2C object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the I2C busses are:
|
||||
|
||||
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
|
||||
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)``
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: i2c.deinit()
|
||||
|
||||
Turn off the I2C bus.
|
||||
|
||||
.. method:: i2c.init(mode, \*, addr=0x12, baudrate=400000, gencall=False)
|
||||
|
||||
Initialise the I2C bus with the given parameters:
|
||||
|
||||
- ``mode`` must be either ``I2C.MASTER`` or ``I2C.SLAVE``
|
||||
- ``addr`` is the 7-bit address (only sensible for a slave)
|
||||
- ``baudrate`` is the SCL clock rate (only sensible for a master)
|
||||
- ``gencall`` is whether to support general call mode
|
||||
|
||||
.. method:: i2c.is_ready(addr)
|
||||
|
||||
Check if an I2C device responds to the given address. Only valid when in master mode.
|
||||
|
||||
.. method:: i2c.mem_read(data, addr, memaddr, timeout=5000, addr_size=8)
|
||||
|
||||
Read from the memory of an I2C device:
|
||||
|
||||
- ``data`` can be an integer or a buffer to read into
|
||||
- ``addr`` is the I2C device address
|
||||
- ``memaddr`` is the memory location within the I2C device
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the read
|
||||
- ``addr_size`` selects width of memaddr: 8 or 16 bits
|
||||
|
||||
Returns the read data.
|
||||
This is only valid in master mode.
|
||||
|
||||
.. method:: i2c.mem_write(data, addr, memaddr, timeout=5000, addr_size=8)
|
||||
|
||||
Write to the memory of an I2C device:
|
||||
|
||||
- ``data`` can be an integer or a buffer to write from
|
||||
- ``addr`` is the I2C device address
|
||||
- ``memaddr`` is the memory location within the I2C device
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the write
|
||||
- ``addr_size`` selects width of memaddr: 8 or 16 bits
|
||||
|
||||
Returns ``None``.
|
||||
This is only valid in master mode.
|
||||
|
||||
.. method:: i2c.recv(recv, addr=0x00, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``recv`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes
|
||||
- ``addr`` is the address to receive from (only required in master mode)
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive
|
||||
|
||||
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the same buffer that was passed in to ``recv``.
|
||||
|
||||
.. method:: i2c.scan()
|
||||
|
||||
Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond.
|
||||
Only valid when in master mode.
|
||||
|
||||
.. method:: i2c.send(send, addr=0x00, timeout=5000)
|
||||
|
||||
Send data on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object)
|
||||
- ``addr`` is the address to send to (only required in master mode)
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: I2C.MASTER
|
||||
|
||||
for initialising the bus to master mode
|
||||
|
||||
.. data:: I2C.SLAVE
|
||||
|
||||
for initialising the bus to slave mode
|
||||
94
docs/library/pyb.LCD.rst
Normal file
@@ -0,0 +1,94 @@
|
||||
class LCD -- LCD control for the LCD touch-sensor pyskin
|
||||
========================================================
|
||||
|
||||
The LCD class is used to control the LCD on the LCD touch-sensor pyskin,
|
||||
LCD32MKv1.0. The LCD is a 128x32 pixel monochrome screen, part NHD-C12832A1Z.
|
||||
|
||||
The pyskin must be connected in either the X or Y positions, and then
|
||||
an LCD object is made using::
|
||||
|
||||
lcd = pyb.LCD('X') # if pyskin is in the X position
|
||||
lcd = pyb.LCD('Y') # if pyskin is in the Y position
|
||||
|
||||
Then you can use::
|
||||
|
||||
lcd.light(True) # turn the backlight on
|
||||
lcd.write('Hello world!\n') # print text to the screen
|
||||
|
||||
This driver implements a double buffer for setting/getting pixels.
|
||||
For example, to make a bouncing dot, try::
|
||||
|
||||
x = y = 0
|
||||
dx = dy = 1
|
||||
while True:
|
||||
# update the dot's position
|
||||
x += dx
|
||||
y += dy
|
||||
|
||||
# make the dot bounce of the edges of the screen
|
||||
if x <= 0 or x >= 127: dx = -dx
|
||||
if y <= 0 or y >= 31: dy = -dy
|
||||
|
||||
lcd.fill(0) # clear the buffer
|
||||
lcd.pixel(x, y, 1) # draw the dot
|
||||
lcd.show() # show the buffer
|
||||
pyb.delay(50) # pause for 50ms
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.LCD(skin_position)
|
||||
|
||||
Construct an LCD object in the given skin position. ``skin_position`` can be 'X' or 'Y', and
|
||||
should match the position where the LCD pyskin is plugged in.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: lcd.command(instr_data, buf)
|
||||
|
||||
Send an arbitrary command to the LCD. Pass 0 for ``instr_data`` to send an
|
||||
instruction, otherwise pass 1 to send data. ``buf`` is a buffer with the
|
||||
instructions/data to send.
|
||||
|
||||
.. method:: lcd.contrast(value)
|
||||
|
||||
Set the contrast of the LCD. Valid values are between 0 and 47.
|
||||
|
||||
.. method:: lcd.fill(colour)
|
||||
|
||||
Fill the screen with the given colour (0 or 1 for white or black).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.get(x, y)
|
||||
|
||||
Get the pixel at the position ``(x, y)``. Returns 0 or 1.
|
||||
|
||||
This method reads from the visible buffer.
|
||||
|
||||
.. method:: lcd.light(value)
|
||||
|
||||
Turn the backlight on/off. True or 1 turns it on, False or 0 turns it off.
|
||||
|
||||
.. method:: lcd.pixel(x, y, colour)
|
||||
|
||||
Set the pixel at ``(x, y)`` to the given colour (0 or 1).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.show()
|
||||
|
||||
Show the hidden buffer on the screen.
|
||||
|
||||
.. method:: lcd.text(str, x, y, colour)
|
||||
|
||||
Draw the given text to the position ``(x, y)`` using the given colour (0 or 1).
|
||||
|
||||
This method writes to the hidden buffer. Use ``show()`` to show the buffer.
|
||||
|
||||
.. method:: lcd.write(str)
|
||||
|
||||
Write the string ``str`` to the screen. It will appear immediately.
|
||||
38
docs/library/pyb.LED.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
.. _pyb.LED:
|
||||
|
||||
class LED -- LED object
|
||||
=======================
|
||||
|
||||
The LED object controls an individual LED (Light Emitting Diode).
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.LED(id)
|
||||
|
||||
Create an LED object associated with the given LED:
|
||||
|
||||
- ``id`` is the LED number, 1-4.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: led.intensity([value])
|
||||
|
||||
Get or set the LED intensity. Intensity ranges between 0 (off) and 255 (full on).
|
||||
If no argument is given, return the LED intensity.
|
||||
If an argument is given, set the LED intensity and return ``None``.
|
||||
|
||||
.. method:: led.off()
|
||||
|
||||
Turn the LED off.
|
||||
|
||||
.. method:: led.on()
|
||||
|
||||
Turn the LED on.
|
||||
|
||||
.. method:: led.toggle()
|
||||
|
||||
Toggle the LED between on and off.
|
||||
266
docs/library/pyb.Pin.rst
Normal file
@@ -0,0 +1,266 @@
|
||||
.. _pyb.Pin:
|
||||
|
||||
class Pin -- control I/O pins
|
||||
=============================
|
||||
|
||||
A pin is the basic object to control I/O pins. It has methods to set
|
||||
the mode of the pin (input, output, etc) and methods to get and set the
|
||||
digital logic level. For analog control of a pin, see the ADC class.
|
||||
|
||||
Usage Model:
|
||||
|
||||
All Board Pins are predefined as pyb.Pin.board.Name ::
|
||||
|
||||
x1_pin = pyb.Pin.board.X1
|
||||
|
||||
g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN)
|
||||
|
||||
CPU pins which correspond to the board pins are available
|
||||
as ``pyb.cpu.Name``. For the CPU pins, the names are the port letter
|
||||
followed by the pin number. On the PYBv1.0, ``pyb.Pin.board.X1`` and
|
||||
``pyb.Pin.cpu.B6`` are the same pin.
|
||||
|
||||
You can also use strings::
|
||||
|
||||
g = pyb.Pin('X1', pyb.Pin.OUT_PP)
|
||||
|
||||
Users can add their own names::
|
||||
|
||||
MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 }
|
||||
pyb.Pin.dict(MyMapperDict)
|
||||
g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD)
|
||||
|
||||
and can query mappings ::
|
||||
|
||||
pin = pyb.Pin("LeftMotorDir")
|
||||
|
||||
Users can also add their own mapping function::
|
||||
|
||||
def MyMapper(pin_name):
|
||||
if pin_name == "LeftMotorDir":
|
||||
return pyb.Pin.cpu.A0
|
||||
|
||||
pyb.Pin.mapper(MyMapper)
|
||||
|
||||
So, if you were to call: ``pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)``
|
||||
then ``"LeftMotorDir"`` is passed directly to the mapper function.
|
||||
|
||||
To summarise, the following order determines how things get mapped into
|
||||
an ordinal pin number:
|
||||
|
||||
1. Directly specify a pin object
|
||||
2. User supplied mapping function
|
||||
3. User supplied mapping (object must be usable as a dictionary key)
|
||||
4. Supply a string which matches a board pin
|
||||
5. Supply a string which matches a CPU port/pin
|
||||
|
||||
You can set ``pyb.Pin.debug(True)`` to get some debug information about
|
||||
how a particular object gets mapped to a pin.
|
||||
|
||||
When a pin has the ``Pin.PULL_UP`` or ``Pin.PULL_DOWN`` pull-mode enabled,
|
||||
that pin has an effective 40k Ohm resistor pulling it to 3V3 or GND
|
||||
respectively (except pin Y5 which has 11k Ohm resistors).
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Pin(id, ...)
|
||||
|
||||
Create a new Pin object associated with the id. If additional arguments are given,
|
||||
they are used to initialise the pin. See :meth:`pin.init`.
|
||||
|
||||
|
||||
Class methods
|
||||
-------------
|
||||
|
||||
.. method:: Pin.af_list()
|
||||
|
||||
Returns an array of alternate functions available for this pin.
|
||||
|
||||
.. method:: Pin.debug([state])
|
||||
|
||||
Get or set the debugging state (``True`` or ``False`` for on or off).
|
||||
|
||||
.. method:: Pin.dict([dict])
|
||||
|
||||
Get or set the pin mapper dictionary.
|
||||
|
||||
.. method:: Pin.mapper([fun])
|
||||
|
||||
Get or set the pin mapper function.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: pin.init(mode, pull=Pin.PULL_NONE, af=-1)
|
||||
|
||||
Initialise the pin:
|
||||
|
||||
- ``mode`` can be one of:
|
||||
- ``Pin.IN`` - configure the pin for input;
|
||||
- ``Pin.OUT_PP`` - configure the pin for output, with push-pull control;
|
||||
- ``Pin.OUT_OD`` - configure the pin for output, with open-drain control;
|
||||
- ``Pin.AF_PP`` - configure the pin for alternate function, pull-pull;
|
||||
- ``Pin.AF_OD`` - configure the pin for alternate function, open-drain;
|
||||
- ``Pin.ANALOG`` - configure the pin for analog.
|
||||
- ``pull`` can be one of:
|
||||
- ``Pin.PULL_NONE`` - no pull up or down resistors;
|
||||
- ``Pin.PULL_UP`` - enable the pull-up resistor;
|
||||
- ``Pin.PULL_DOWN`` - enable the pull-down resistor.
|
||||
- when mode is Pin.AF_PP or Pin.AF_OD, then af can be the index or name
|
||||
of one of the alternate functions associated with a pin.
|
||||
|
||||
Returns: ``None``.
|
||||
|
||||
.. method:: pin.high()
|
||||
|
||||
Set the pin to a high logic level.
|
||||
|
||||
.. method:: pin.low()
|
||||
|
||||
Set the pin to a low logic level.
|
||||
|
||||
.. method:: pin.value([value])
|
||||
|
||||
Get or set the digital logic level of the pin:
|
||||
|
||||
- With no argument, return 0 or 1 depending on the logic level of the pin.
|
||||
- With ``value`` given, set the logic level of the pin. ``value`` can be
|
||||
anything that converts to a boolean. If it converts to ``True``, the pin
|
||||
is set high, otherwise it is set low.
|
||||
|
||||
.. method:: pin.__str__()
|
||||
|
||||
Return a string describing the pin object.
|
||||
|
||||
.. method:: pin.af()
|
||||
|
||||
Returns the currently configured alternate-function of the pin. The
|
||||
integer returned will match one of the allowed constants for the af
|
||||
argument to the init function.
|
||||
|
||||
.. method:: pin.gpio()
|
||||
|
||||
Returns the base address of the GPIO block associated with this pin.
|
||||
|
||||
.. method:: pin.mode()
|
||||
|
||||
Returns the currently configured mode of the pin. The integer returned
|
||||
will match one of the allowed constants for the mode argument to the init
|
||||
function.
|
||||
|
||||
.. method:: pin.name()
|
||||
|
||||
Get the pin name.
|
||||
|
||||
.. method:: pin.names()
|
||||
|
||||
Returns the cpu and board names for this pin.
|
||||
|
||||
.. method:: pin.pin()
|
||||
|
||||
Get the pin number.
|
||||
|
||||
.. method:: pin.port()
|
||||
|
||||
Get the pin port.
|
||||
|
||||
.. method:: pin.pull()
|
||||
|
||||
Returns the currently configured pull of the pin. The integer returned
|
||||
will match one of the allowed constants for the pull argument to the init
|
||||
function.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: Pin.AF_OD
|
||||
|
||||
initialise the pin to alternate-function mode with an open-drain drive
|
||||
|
||||
.. data:: Pin.AF_PP
|
||||
|
||||
initialise the pin to alternate-function mode with a push-pull drive
|
||||
|
||||
.. data:: Pin.ANALOG
|
||||
|
||||
initialise the pin to analog mode
|
||||
|
||||
.. data:: Pin.IN
|
||||
|
||||
initialise the pin to input mode
|
||||
|
||||
.. data:: Pin.OUT_OD
|
||||
|
||||
initialise the pin to output mode with an open-drain drive
|
||||
|
||||
.. data:: Pin.OUT_PP
|
||||
|
||||
initialise the pin to output mode with a push-pull drive
|
||||
|
||||
.. data:: Pin.PULL_DOWN
|
||||
|
||||
enable the pull-down resistor on the pin
|
||||
|
||||
.. data:: Pin.PULL_NONE
|
||||
|
||||
don't enable any pull up or down resistors on the pin
|
||||
|
||||
.. data:: Pin.PULL_UP
|
||||
|
||||
enable the pull-up resistor on the pin
|
||||
|
||||
|
||||
class PinAF -- Pin Alternate Functions
|
||||
======================================
|
||||
|
||||
A Pin represents a physical pin on the microcprocessor. Each pin
|
||||
can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF
|
||||
object represents a particular function for a pin.
|
||||
|
||||
Usage Model::
|
||||
|
||||
x3 = pyb.Pin.board.X3
|
||||
x3_af = x3.af_list()
|
||||
|
||||
x3_af will now contain an array of PinAF objects which are availble on
|
||||
pin X3.
|
||||
|
||||
For the pyboard, x3_af would contain:
|
||||
[Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
|
||||
|
||||
Normally, each peripheral would configure the af automatically, but sometimes
|
||||
the same function is available on multiple pins, and having more control
|
||||
is desired.
|
||||
|
||||
To configure X3 to expose TIM2_CH3, you could use::
|
||||
|
||||
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
|
||||
|
||||
or::
|
||||
|
||||
pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1)
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: pinaf.__str__()
|
||||
|
||||
Return a string describing the alternate function.
|
||||
|
||||
.. method:: pinaf.index()
|
||||
|
||||
Return the alternate function index.
|
||||
|
||||
.. method:: pinaf.name()
|
||||
|
||||
Return the name of the alternate function.
|
||||
|
||||
.. method:: pinaf.reg()
|
||||
|
||||
Return the base register associated with the peripheral assigned to this
|
||||
alternate function. For example, if the alternate function were TIM2_CH3
|
||||
this would return stm.TIM2
|
||||
48
docs/library/pyb.RTC.rst
Normal file
@@ -0,0 +1,48 @@
|
||||
class RTC -- real time clock
|
||||
============================
|
||||
|
||||
The RTC is and independent clock that keeps track of the date
|
||||
and time.
|
||||
|
||||
Example usage::
|
||||
|
||||
rtc = pyb.RTC()
|
||||
rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
|
||||
print(rtc.datetime())
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.RTC()
|
||||
|
||||
Create an RTC object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: rtc.datetime([datetimetuple])
|
||||
|
||||
Get or set the date and time of the RTC.
|
||||
|
||||
With no arguments, this method returns an 8-tuple with the current
|
||||
date and time. With 1 argument (being an 8-tuple) it sets the date
|
||||
and time.
|
||||
|
||||
The 8-tuple has the following format:
|
||||
|
||||
(year, month, day, weekday, hours, minutes, seconds, subseconds)
|
||||
|
||||
``weekday`` is 1-7 for Monday through Sunday.
|
||||
|
||||
``subseconds`` counts down from 255 to 0
|
||||
|
||||
.. method:: rtc.info()
|
||||
|
||||
Get information about the startup time and reset source.
|
||||
|
||||
- The lower 0xffff are the number of milliseconds the RTC took to
|
||||
start up.
|
||||
- Bit 0x10000 is set if a power-on reset occurred.
|
||||
- Bit 0x20000 is set if an external reset occurred
|
||||
106
docs/library/pyb.SPI.rst
Normal file
@@ -0,0 +1,106 @@
|
||||
.. _pyb.SPI:
|
||||
|
||||
class SPI -- a master-driven serial protocol
|
||||
============================================
|
||||
|
||||
SPI is a serial protocol that is driven by a master. At the physical level
|
||||
there are 3 lines: SCK, MOSI, MISO.
|
||||
|
||||
See usage model of I2C; SPI is very similar. Main difference is
|
||||
parameters to init the SPI bus::
|
||||
|
||||
from pyb import SPI
|
||||
spi = SPI(1, SPI.MASTER, baudrate=600000, polarity=1, phase=0, crc=0x7)
|
||||
|
||||
Only required parameter is mode, SPI.MASTER or SPI.SLAVE. Polarity can be
|
||||
0 or 1, and is the level the idle clock line sits at. Phase can be 0 or 1
|
||||
to sample data on the first or second clock edge respectively. Crc can be
|
||||
None for no CRC, or a polynomial specifier.
|
||||
|
||||
Additional method for SPI::
|
||||
|
||||
data = spi.send_recv(b'1234') # send 4 bytes and receive 4 bytes
|
||||
buf = bytearray(4)
|
||||
spi.send_recv(b'1234', buf) # send 4 bytes and receive 4 into buf
|
||||
spi.send_recv(buf, buf) # send/recv 4 bytes from/to buf
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.SPI(bus, ...)
|
||||
|
||||
Construct an SPI object on the given bus. ``bus`` can be 1 or 2.
|
||||
With no additional parameters, the SPI object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the SPI busses are:
|
||||
|
||||
- ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)``
|
||||
- ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)``
|
||||
|
||||
At the moment, the NSS pin is not used by the SPI driver and is free
|
||||
for other use.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: spi.deinit()
|
||||
|
||||
Turn off the SPI bus.
|
||||
|
||||
.. method:: spi.init(mode, baudrate=328125, \*, polarity=1, phase=0, bits=8, firstbit=SPI.MSB, ti=False, crc=None)
|
||||
|
||||
Initialise the SPI bus with the given parameters:
|
||||
|
||||
- ``mode`` must be either ``SPI.MASTER`` or ``SPI.SLAVE``.
|
||||
- ``baudrate`` is the SCK clock rate (only sensible for a master).
|
||||
|
||||
.. method:: spi.recv(recv, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``recv`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: if ``recv`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the same buffer that was passed in to ``recv``.
|
||||
|
||||
.. method:: spi.send(send, \*, timeout=5000)
|
||||
|
||||
Send data on the bus:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: ``None``.
|
||||
|
||||
.. method:: spi.send_recv(send, recv=None, \*, timeout=5000)
|
||||
|
||||
Send and receive data on the bus at the same time:
|
||||
|
||||
- ``send`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``recv`` is a mutable buffer which will be filled with received bytes.
|
||||
It can be the same as ``send``, or omitted. If omitted, a new buffer will
|
||||
be created.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: the buffer with the received bytes.
|
||||
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: SPI.MASTER
|
||||
.. data:: SPI.SLAVE
|
||||
|
||||
for initialising the SPI bus to master or slave mode
|
||||
|
||||
.. data:: SPI.LSB
|
||||
.. data:: SPI.MSB
|
||||
|
||||
set the first bit to be the least or most significant bit
|
||||
38
docs/library/pyb.Servo.rst
Normal file
@@ -0,0 +1,38 @@
|
||||
class Servo -- 3-wire hobby servo driver
|
||||
========================================
|
||||
|
||||
Servo controls standard hobby servos with 3-wires (ground, power, signal).
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Servo(id)
|
||||
|
||||
Create a servo object. ``id`` is 1-4.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: servo.angle([angle, time=0])
|
||||
|
||||
Get or set the angle of the servo.
|
||||
|
||||
- ``angle`` is the angle to move to in degrees.
|
||||
- ``time`` is the number of milliseconds to take to get to the specified angle.
|
||||
|
||||
.. method:: servo.calibration([pulse_min, pulse_max, pulse_centre, [pulse_angle_90, pulse_speed_100]])
|
||||
|
||||
Get or set the calibration of the servo timing.
|
||||
|
||||
.. method:: servo.pulse_width([value])
|
||||
|
||||
Get or set the pulse width in milliseconds.
|
||||
|
||||
.. method:: servo.speed([speed, time=0])
|
||||
|
||||
Get or set the speed of a continuous rotation servo.
|
||||
|
||||
- ``speed`` is the speed to move to change to, between -100 and 100.
|
||||
- ``time`` is the number of milliseconds to take to get to the specified speed.
|
||||
37
docs/library/pyb.Switch.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
class Switch -- switch object
|
||||
=============================
|
||||
|
||||
A Switch object is used to control a push-button switch.
|
||||
|
||||
Usage::
|
||||
|
||||
sw = pyb.Switch() # create a switch object
|
||||
sw() # get state (True if pressed, False otherwise)
|
||||
sw.callback(f) # register a callback to be called when the
|
||||
# switch is pressed down
|
||||
sw.callback(None) # remove the callback
|
||||
|
||||
Example::
|
||||
|
||||
pyb.Switch().callback(lambda: pyb.LED(1).toggle())
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Switch()
|
||||
|
||||
Create and return a switch object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: switch()
|
||||
|
||||
Return the switch state: ``True`` if pressed down, ``False`` otherwise.
|
||||
|
||||
.. method:: switch.callback(fun)
|
||||
|
||||
Register the given function to be called when the switch is pressed down.
|
||||
If ``fun`` is ``None``, then it disables the callback.
|
||||
234
docs/library/pyb.Timer.rst
Normal file
@@ -0,0 +1,234 @@
|
||||
.. _pyb.Timer:
|
||||
|
||||
class Timer -- control internal timers
|
||||
======================================
|
||||
|
||||
Timers can be used for a great variety of tasks. At the moment, only
|
||||
the simplest case is implemented: that of calling a function periodically.
|
||||
|
||||
Each timer consists of a counter that counts up at a certain rate. The rate
|
||||
at which it counts is the peripheral clock frequency (in Hz) divided by the
|
||||
timer prescaler. When the counter reaches the timer period it triggers an
|
||||
event, and the counter resets back to zero. By using the callback method,
|
||||
the timer event can call a Python function.
|
||||
|
||||
Example usage to toggle an LED at a fixed frequency::
|
||||
|
||||
tim = pyb.Timer(4) # create a timer object using timer 4
|
||||
tim.init(freq=2) # trigger at 2Hz
|
||||
tim.callback(lambda t:pyb.LED(1).toggle())
|
||||
|
||||
Further examples::
|
||||
|
||||
tim = pyb.Timer(4, freq=100) # freq in Hz
|
||||
tim = pyb.Timer(4, prescaler=0, period=99)
|
||||
tim.counter() # get counter (can also set)
|
||||
tim.prescaler(2) # set prescaler (can also get)
|
||||
tim.period(199) # set period (can also get)
|
||||
tim.callback(lambda t: ...) # set callback for update interrupt (t=tim instance)
|
||||
tim.callback(None) # clear callback
|
||||
|
||||
*Note:* Timer 3 is reserved for internal use. Timer 5 controls
|
||||
the servo driver, and Timer 6 is used for timed ADC/DAC reading/writing.
|
||||
It is recommended to use the other timers in your programs.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.Timer(id, ...)
|
||||
|
||||
Construct a new timer object of the given id. If additional
|
||||
arguments are given, then the timer is initialised by ``init(...)``.
|
||||
``id`` can be 1 to 14, excluding 3.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: timer.callback(fun)
|
||||
|
||||
Set the function to be called when the timer triggers.
|
||||
``fun`` is passed 1 argument, the timer object.
|
||||
If ``fun`` is ``None`` then the callback will be disabled.
|
||||
|
||||
.. method:: timer.channel(channel, mode, ...)
|
||||
|
||||
If only a channel number is passed, then a previously initialized channel
|
||||
object is returned (or ``None`` if there is no previous channel).
|
||||
|
||||
Othwerwise, a TimerChannel object is initialized and returned.
|
||||
|
||||
Each channel can be configured to perform pwm, output compare, or
|
||||
input capture. All channels share the same underlying timer, which means
|
||||
that they share the same timer clock.
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
- ``mode`` can be one of:
|
||||
|
||||
- ``Timer.PWM`` --- configure the timer in PWM mode (active high).
|
||||
- ``Timer.PWM_INVERTED`` --- configure the timer in PWM mode (active low).
|
||||
- ``Timer.OC_TIMING`` --- indicates that no pin is driven.
|
||||
- ``Timer.OC_ACTIVE`` --- the pin will be made active when a compare match occurs (active is determined by polarity)
|
||||
- ``Timer.OC_INACTIVE`` --- the pin will be made inactive when a compare match occurs.
|
||||
- ``Timer.OC_TOGGLE`` --- the pin will be toggled when an compare match occurs.
|
||||
- ``Timer.OC_FORCED_ACTIVE`` --- the pin is forced active (compare match is ignored).
|
||||
- ``Timer.OC_FORCED_INACTIVE`` --- the pin is forced inactive (compare match is ignored).
|
||||
- ``Timer.IC`` --- configure the timer in Input Capture mode.
|
||||
|
||||
- ``callback`` - as per TimerChannel.callback()
|
||||
|
||||
- ``pin`` None (the default) or a Pin object. If specified (and not None)
|
||||
this will cause the alternate function of the the indicated pin
|
||||
to be configured for this timer channel. An error will be raised if
|
||||
the pin doesn't support any alternate functions for this timer channel.
|
||||
|
||||
Keyword arguments for Timer.PWM modes:
|
||||
|
||||
- ``pulse_width`` - determines the initial pulse width value to use.
|
||||
- ``pulse_width_percent`` - determines the initial pulse width percentage to use.
|
||||
|
||||
Keyword arguments for Timer.OC modes:
|
||||
|
||||
- ``compare`` - determines the initial value of the compare register.
|
||||
|
||||
- ``polarity`` can be one of:
|
||||
- ``Timer.HIGH`` - output is active high
|
||||
- ``Timer.LOW`` - output is acive low
|
||||
|
||||
Optional keyword arguments for Timer.IC modes:
|
||||
|
||||
- ``polarity`` can be one of:
|
||||
- ``Timer.RISING`` - captures on rising edge.
|
||||
- ``Timer.FALLING`` - captures on falling edge.
|
||||
- ``Timer.BOTH`` - captures on both edges.
|
||||
|
||||
Note that capture only works on the primary channel, and not on the
|
||||
complimentary channels.
|
||||
|
||||
PWM Example::
|
||||
|
||||
timer = pyb.Timer(2, freq=1000)
|
||||
ch2 = timer.channel(2, pyb.Timer.PWM, pin=pyb.Pin.board.X2, pulse_width=210000)
|
||||
ch3 = timer.channel(3, pyb.Timer.PWM, pin=pyb.Pin.board.X3, pulse_width=420000)
|
||||
|
||||
.. method:: timer.counter([value])
|
||||
|
||||
Get or set the timer counter.
|
||||
|
||||
.. method:: timer.deinit()
|
||||
|
||||
Deinitialises the timer.
|
||||
|
||||
Disables the callback (and the associated irq).
|
||||
Disables any channel callbacks (and the associated irq).
|
||||
Stops the timer, and disables the timer peripheral.
|
||||
|
||||
.. method:: timer.freq([value])
|
||||
|
||||
Get or set the frequency for the timer (changes prescaler and period if set).
|
||||
|
||||
.. method:: timer.init(\*, freq, prescaler, period)
|
||||
|
||||
Initialise the timer. Initialisation must be either by frequency (in Hz)
|
||||
or by prescaler and period::
|
||||
|
||||
tim.init(freq=100) # set the timer to trigger at 100Hz
|
||||
tim.init(prescaler=83, period=999) # set the prescaler and period directly
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
- ``freq`` --- specifies the periodic frequency of the timer. You migh also
|
||||
view this as the frequency with which the timer goes through one complete cycle.
|
||||
|
||||
- ``prescaler`` [0-0xffff] - specifies the value to be loaded into the
|
||||
timer's Prescaler Register (PSC). The timer clock source is divided by
|
||||
(``prescaler + 1``) to arrive at the timer clock. Timers 2-7 and 12-14
|
||||
have a clock source of 84 MHz (pyb.freq()[2] \* 2), and Timers 1, and 8-11
|
||||
have a clock source of 168 MHz (pyb.freq()[3] \* 2).
|
||||
|
||||
- ``period`` [0-0xffff] for timers 1, 3, 4, and 6-15. [0-0x3fffffff] for timers 2 & 5.
|
||||
Specifies the value to be loaded into the timer's AutoReload
|
||||
Register (ARR). This determines the period of the timer (i.e. when the
|
||||
counter cycles). The timer counter will roll-over after ``period + 1``
|
||||
timer clock cycles.
|
||||
|
||||
- ``mode`` can be one of:
|
||||
|
||||
- ``Timer.UP`` - configures the timer to count from 0 to ARR (default)
|
||||
- ``Timer.DOWN`` - configures the timer to count from ARR down to 0.
|
||||
- ``Timer.CENTER`` - confgures the timer to count from 0 to ARR and
|
||||
then back down to 0.
|
||||
|
||||
- ``div`` can be one of 1, 2, or 4. Divides the timer clock to determine
|
||||
the sampling clock used by the digital filters.
|
||||
|
||||
- ``callback`` - as per Timer.callback()
|
||||
|
||||
- ``deadtime`` - specifies the amount of "dead" or inactive time between
|
||||
transitions on complimentary channels (both channels will be inactive)
|
||||
for this time). ``deadtime`` may be an integer between 0 and 1008, with
|
||||
the following restrictions: 0-128 in steps of 1. 128-256 in steps of
|
||||
2, 256-512 in steps of 8, and 512-1008 in steps of 16. ``deadime``
|
||||
measures ticks of ``source_freq`` divided by ``div`` clock ticks.
|
||||
``deadtime`` is only available on timers 1 and 8.
|
||||
|
||||
You must either specify freq or both of period and prescaler.
|
||||
|
||||
.. method:: timer.period([value])
|
||||
|
||||
Get or set the period of the timer.
|
||||
|
||||
.. method:: timer.prescaler([value])
|
||||
|
||||
Get or set the prescaler for the timer.
|
||||
|
||||
.. method:: timer.source_freq()
|
||||
|
||||
Get the frequency of the source of the timer.
|
||||
|
||||
class TimerChannel --- setup a channel for a timer
|
||||
==================================================
|
||||
|
||||
Timer channels are used to generate/capture a signal using a timer.
|
||||
|
||||
TimerChannel objects are created using the Timer.channel() method.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: timerchannel.callback(fun)
|
||||
|
||||
Set the function to be called when the timer channel triggers.
|
||||
``fun`` is passed 1 argument, the timer object.
|
||||
If ``fun`` is ``None`` then the callback will be disabled.
|
||||
|
||||
.. method:: timerchannel.capture([value])
|
||||
|
||||
Get or set the capture value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
capture is the logical name to use when the channel is in input capture mode.
|
||||
|
||||
.. method:: timerchannel.compare([value])
|
||||
|
||||
Get or set the compare value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
compare is the logical name to use when the channel is in output compare mode.
|
||||
|
||||
.. method:: timerchannel.pulse_width([value])
|
||||
|
||||
Get or set the pulse width value associated with a channel.
|
||||
capture, compare, and pulse_width are all aliases for the same function.
|
||||
pulse_width is the logical name to use when the channel is in PWM mode.
|
||||
|
||||
In edge aligned mode, a pulse_width of ``period + 1`` corresponds to a duty cycle of 100%
|
||||
In center aligned mode, a pulse width of ``period`` corresponds to a duty cycle of 100%
|
||||
|
||||
.. method:: timerchannel.pulse_width_percent([value])
|
||||
|
||||
Get or set the pulse width percentage associated with a channel. The value
|
||||
is a number between 0 and 100 and sets the percentage of the timer period
|
||||
for which the pulse is active. The value can be an integer or
|
||||
floating-point number for more accuracy. For example, a value of 25 gives
|
||||
a duty cycle of 25%.
|
||||
136
docs/library/pyb.UART.rst
Normal file
@@ -0,0 +1,136 @@
|
||||
.. _pyb.UART:
|
||||
|
||||
class UART -- duplex serial communication bus
|
||||
=============================================
|
||||
|
||||
UART implements the standard UART/USART duplex serial communications protocol. At
|
||||
the physical level it consists of 2 lines: RX and TX. The unit of communication
|
||||
is a character (not to be confused with a string character) which can be 8 or 9
|
||||
bits wide.
|
||||
|
||||
UART objects can be created and initialised using::
|
||||
|
||||
from pyb import UART
|
||||
|
||||
uart = UART(1, 9600) # init with given baudrate
|
||||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
|
||||
|
||||
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
|
||||
|
||||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||
only 7 and 8 bits are supported.
|
||||
|
||||
A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
|
||||
uart.read(10) # read 10 characters, returns a bytes object
|
||||
uart.readall() # read all available characters
|
||||
uart.readline() # read a line
|
||||
uart.readinto(buf) # read and store into the given buffer
|
||||
uart.write('abc') # write the 3 characters
|
||||
|
||||
Individual characters can be read/written using::
|
||||
|
||||
uart.readchar() # read 1 character and returns it as an integer
|
||||
uart.writechar(42) # write 1 character
|
||||
|
||||
To check if there is anything to be read, use::
|
||||
|
||||
uart.any() # returns True if any characters waiting
|
||||
|
||||
*Note:* The stream functions ``read``, ``write`` etc Are new in Micro Python since v1.3.4.
|
||||
Earlier versions use ``uart.send`` and ``uart.recv``.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.UART(bus, ...)
|
||||
|
||||
Construct a UART object on the given bus. ``bus`` can be 1-6, or 'XA', 'XB', 'YA', or 'YB'.
|
||||
With no additional parameters, the UART object is created but not
|
||||
initialised (it has the settings from the last initialisation of
|
||||
the bus, if any). If extra arguments are given, the bus is initialised.
|
||||
See ``init`` for parameters of initialisation.
|
||||
|
||||
The physical pins of the UART busses are:
|
||||
|
||||
- ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)``
|
||||
- ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)``
|
||||
- ``UART(6)`` is on ``YA``: ``(TX, RX) = (Y1, Y2) = (PC6, PC7)``
|
||||
- ``UART(3)`` is on ``YB``: ``(TX, RX) = (Y9, Y10) = (PB10, PB11)``
|
||||
- ``UART(2)`` is on: ``(TX, RX) = (X3, X4) = (PA2, PA3)``
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: uart.init(baudrate, bits=8, parity=None, stop=1, \*, timeout=1000, timeout_char=0, read_buf_len=64)
|
||||
|
||||
Initialise the UART bus with the given parameters:
|
||||
|
||||
- ``baudrate`` is the clock rate.
|
||||
- ``bits`` is the number of bits per character, 7, 8 or 9.
|
||||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the first character.
|
||||
- ``timeout_char`` is the timeout in milliseconds to wait between characters.
|
||||
- ``read_buf_len`` is the character length of the read buffer (0 to disable).
|
||||
|
||||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||
only 7 and 8 bits are supported.
|
||||
|
||||
.. method:: uart.deinit()
|
||||
|
||||
Turn off the UART bus.
|
||||
|
||||
.. method:: uart.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
|
||||
.. method:: uart.read([nbytes])
|
||||
|
||||
Read characters. If ``nbytes`` is specified then read at most that many bytes.
|
||||
|
||||
*Note:* for 9 bit characters each character takes two bytes, ``nbytes`` must
|
||||
be even, and the number of characters is ``nbytes/2``.
|
||||
|
||||
Return value: a bytes object containing the bytes read in. Returns ``b''``
|
||||
on timeout.
|
||||
|
||||
.. method:: uart.readall()
|
||||
|
||||
Read as much data as possible.
|
||||
|
||||
Return value: a bytes object.
|
||||
|
||||
.. method:: uart.readchar()
|
||||
|
||||
Receive a single character on the bus.
|
||||
|
||||
Return value: The character read, as an integer. Returns -1 on timeout.
|
||||
|
||||
.. method:: uart.readinto(buf[, nbytes])
|
||||
|
||||
Read bytes into the ``buf``. If ``nbytes`` is specified then read at most
|
||||
that many bytes. Otherwise, read at most ``len(buf)`` bytes.
|
||||
|
||||
Return value: number of bytes read and stored into ``buf``.
|
||||
|
||||
.. method:: uart.readline()
|
||||
|
||||
Read a line, ending in a newline character.
|
||||
|
||||
Return value: the line read.
|
||||
|
||||
.. method:: uart.write(buf)
|
||||
|
||||
Write the buffer of bytes to the bus. If characters are 7 or 8 bits wide
|
||||
then each byte is one character. If characters are 9 bits wide then two
|
||||
bytes are used for each character (little endian), and ``buf`` must contain
|
||||
an even number of bytes.
|
||||
|
||||
Return value: number of bytes written.
|
||||
|
||||
.. method:: uart.writechar(char)
|
||||
|
||||
Write a single character on the bus. ``char`` is an integer to write.
|
||||
Return value: ``None``.
|
||||
57
docs/library/pyb.USB_VCP.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
class USB_VCP -- USB virtual comm port
|
||||
======================================
|
||||
|
||||
The USB_VCP class allows creation of an object representing the USB
|
||||
virtual comm port. It can be used to read and write data over USB to
|
||||
the connected host.
|
||||
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. class:: pyb.USB_VCP()
|
||||
|
||||
Create a new USB_VCP object.
|
||||
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: usb_vcp.any()
|
||||
|
||||
Return ``True`` if any characters waiting, else ``False``.
|
||||
|
||||
.. method:: usb_vcp.close()
|
||||
|
||||
|
||||
.. method:: usb_vcp.read([nbytes])
|
||||
|
||||
|
||||
.. method:: usb_vcp.readall()
|
||||
|
||||
|
||||
.. method:: usb_vcp.readline()
|
||||
|
||||
|
||||
.. method:: usb_vcp.recv(data, \*, timeout=5000)
|
||||
|
||||
Receive data on the bus:
|
||||
|
||||
- ``data`` can be an integer, which is the number of bytes to receive,
|
||||
or a mutable buffer, which will be filled with received bytes.
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the receive.
|
||||
|
||||
Return value: if ``data`` is an integer then a new buffer of the bytes received,
|
||||
otherwise the number of bytes read into ``data`` is returned.
|
||||
|
||||
.. method:: usb_vcp.send(data, \*, timeout=5000)
|
||||
|
||||
Send data over the USB VCP:
|
||||
|
||||
- ``data`` is the data to send (an integer to send, or a buffer object).
|
||||
- ``timeout`` is the timeout in milliseconds to wait for the send.
|
||||
|
||||
Return value: number of bytes sent.
|
||||
|
||||
.. method:: usb_vcp.write(buf)
|
||||
|
||||
182
docs/library/pyb.rst
Normal file
@@ -0,0 +1,182 @@
|
||||
:mod:`pyb` --- functions related to the pyboard
|
||||
===============================================
|
||||
|
||||
.. module:: pyb
|
||||
:synopsis: functions related to the pyboard
|
||||
|
||||
The ``pyb`` module contains specific functions related to the pyboard.
|
||||
|
||||
Time related functions
|
||||
----------------------
|
||||
|
||||
.. function:: delay(ms)
|
||||
|
||||
Delay for the given number of milliseconds.
|
||||
|
||||
.. function:: udelay(us)
|
||||
|
||||
Delay for the given number of microseconds.
|
||||
|
||||
.. function:: millis()
|
||||
|
||||
Returns the number of milliseconds since the board was last reset.
|
||||
|
||||
The result is always a micropython smallint (31-bit signed number), so
|
||||
after 2^30 milliseconds (about 12.4 days) this will start to return
|
||||
negative numbers.
|
||||
|
||||
.. function:: micros()
|
||||
|
||||
Returns the number of microseconds since the board was last reset.
|
||||
|
||||
The result is always a micropython smallint (31-bit signed number), so
|
||||
after 2^30 microseconds (about 17.8 minutes) this will start to return
|
||||
negative numbers.
|
||||
|
||||
.. function:: elapsed_millis(start)
|
||||
|
||||
Returns the number of milliseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 12.4 days.
|
||||
|
||||
Example::
|
||||
|
||||
start = pyb.millis()
|
||||
while pyb.elapsed_millis(start) < 1000:
|
||||
# Perform some operation
|
||||
|
||||
.. function:: elapsed_micros(start)
|
||||
|
||||
Returns the number of microseconds which have elapsed since ``start``.
|
||||
|
||||
This function takes care of counter wrap, and always returns a positive
|
||||
number. This means it can be used to measure periods upto about 17.8 minutes.
|
||||
|
||||
Example::
|
||||
|
||||
start = pyb.micros()
|
||||
while pyb.elapsed_micros(start) < 1000:
|
||||
# Perform some operation
|
||||
pass
|
||||
|
||||
Reset related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: hard_reset()
|
||||
|
||||
Resets the pyboard in a manner similar to pushing the external RESET
|
||||
button.
|
||||
|
||||
.. function:: bootloader()
|
||||
|
||||
Activate the bootloader without BOOT\* pins.
|
||||
|
||||
Interrupt related functions
|
||||
---------------------------
|
||||
|
||||
.. 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.
|
||||
|
||||
.. function:: enable_irq(state=True)
|
||||
|
||||
Enable interrupt requests.
|
||||
If ``state`` is ``True`` (the default value) then IRQs are enabled.
|
||||
If ``state`` is ``False`` then IRQs are disabled. The most common use of
|
||||
this function is to pass it the value returned by ``disable_irq`` to
|
||||
exit a critical section.
|
||||
|
||||
Power related functions
|
||||
-----------------------
|
||||
|
||||
.. function:: freq([sys_freq])
|
||||
|
||||
If given no arguments, returns a tuple of clock frequencies:
|
||||
(SYSCLK, HCLK, PCLK1, PCLK2).
|
||||
|
||||
If given an argument, sets the system frequency to that value in Hz.
|
||||
Eg freq(120000000) gives 120MHz. Note that not all values are
|
||||
supported and the largest supported frequency not greater than
|
||||
the given sys_freq will be selected.
|
||||
|
||||
Supported frequencies are (in MHz): 8, 16, 24, 30, 32, 36, 40, 42, 48,
|
||||
54, 56, 60, 64, 72, 84, 96, 108, 120, 144, 168.
|
||||
|
||||
8MHz uses the HSE (external crystal) directly and 16MHz uses the HSI
|
||||
(internal oscillator) directly. The higher frequencies use the HSE to
|
||||
drive the PLL (phase locked loop), and then use the output of the PLL.
|
||||
|
||||
Note that if you change the frequency while the USB is enabled then
|
||||
the USB may become unreliable. It is best to change the frequency
|
||||
in boot.py, before the USB peripheral is started. Also note that
|
||||
frequencies below 36MHz do not allow the USB to function correctly.
|
||||
|
||||
.. function:: wfi()
|
||||
|
||||
Wait for an interrupt.
|
||||
This executies a ``wfi`` instruction which reduces power consumption
|
||||
of the MCU until an interrupt occurs, at which point execution continues.
|
||||
|
||||
.. function:: standby()
|
||||
|
||||
|
||||
.. function:: stop()
|
||||
|
||||
Miscellaneous functions
|
||||
-----------------------
|
||||
|
||||
.. function:: have_cdc()
|
||||
|
||||
Return True if USB is connected as a serial device, False otherwise.
|
||||
|
||||
.. function:: hid((buttons, x, y, z))
|
||||
|
||||
Takes a 4-tuple (or list) and sends it to the USB host (the PC) to
|
||||
signal a HID mouse-motion event.
|
||||
|
||||
.. function:: info([dump_alloc_table])
|
||||
|
||||
Print out lots of information about the board.
|
||||
|
||||
.. function:: repl_uart(uart)
|
||||
|
||||
Get or set the UART object that the REPL is repeated on.
|
||||
|
||||
.. function:: rng()
|
||||
|
||||
Return a 30-bit hardware generated random number.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
Sync all file systems.
|
||||
|
||||
.. function:: unique_id()
|
||||
|
||||
Returns a string of 12 bytes (96 bits), which is the unique ID for the MCU.
|
||||
|
||||
Classes
|
||||
-------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
pyb.Accel.rst
|
||||
pyb.ADC.rst
|
||||
pyb.CAN.rst
|
||||
pyb.DAC.rst
|
||||
pyb.ExtInt.rst
|
||||
pyb.I2C.rst
|
||||
pyb.LCD.rst
|
||||
pyb.LED.rst
|
||||
pyb.Pin.rst
|
||||
pyb.RTC.rst
|
||||
pyb.Servo.rst
|
||||
pyb.SPI.rst
|
||||
pyb.Switch.rst
|
||||
pyb.Timer.rst
|
||||
pyb.UART.rst
|
||||
pyb.USB_VCP.rst
|
||||
52
docs/library/select.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
:mod:`select` -- Provides select function to wait for events on a stream
|
||||
========================================================================
|
||||
|
||||
.. module:: select
|
||||
:synopsis: Provides select function to wait for events on a stream
|
||||
|
||||
This module provides the select function.
|
||||
|
||||
Pyboard specifics
|
||||
-----------------
|
||||
|
||||
Polling is an efficient way of waiting for read/write activity on multiple
|
||||
objects. Current objects that support polling are: :class:`pyb.UART`,
|
||||
:class:`pyb.USB_VCP`.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: poll()
|
||||
|
||||
Create an instance of the Poll class.
|
||||
|
||||
.. function:: select(rlist, wlist, xlist[, timeout])
|
||||
|
||||
Wait for activity on a set of objects.
|
||||
|
||||
.. _class: Poll
|
||||
|
||||
class ``Poll``
|
||||
--------------
|
||||
|
||||
Methods
|
||||
~~~~~~~
|
||||
|
||||
.. method:: poll.register(obj[, eventmask])
|
||||
|
||||
Register ``obj`` for polling. ``eventmask`` is 1 for read, 2 for
|
||||
write, 3 for read-write.
|
||||
|
||||
.. method:: poll.unregister(obj)
|
||||
|
||||
Unregister ``obj`` from polling.
|
||||
|
||||
.. method:: poll.modify(obj, eventmask)
|
||||
|
||||
Modify the ``eventmask`` for ``obj``.
|
||||
|
||||
.. method:: poll.poll([timeout])
|
||||
|
||||
Wait for one of the registered objects to become ready.
|
||||
|
||||
Timeout is in milliseconds.
|
||||
25
docs/library/struct.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
:mod:`struct` -- pack and unpack primitive data types
|
||||
=====================================================
|
||||
|
||||
.. module:: struct
|
||||
:synopsis: pack and unpack primitive data types
|
||||
|
||||
See `Python struct <https://docs.python.org/3/library/struct.html>`_ for more
|
||||
information.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: calcsize(fmt)
|
||||
|
||||
Return the number of bytes needed to store the given ``fmt``.
|
||||
|
||||
.. function:: pack(fmt, v1, v2, ...)
|
||||
|
||||
Pack the values ``v1``, ``v2``, ... according to the format string ``fmt``.
|
||||
The return value is a bytes object encoding the values.
|
||||
|
||||
.. function:: unpack(fmt, data)
|
||||
|
||||
Unpack from the ``data`` according to the format string ``fmt``.
|
||||
The return value is a tuple of the unpacked values.
|
||||
52
docs/library/sys.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
:mod:`sys` -- system specific functions
|
||||
=======================================
|
||||
|
||||
.. module:: sys
|
||||
:synopsis: system specific functions
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: exit([retval])
|
||||
|
||||
Raise a ``SystemExit`` exception. If an argument is given, it is the
|
||||
value given to ``SystemExit``.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: argv
|
||||
|
||||
a mutable list of arguments this program started with
|
||||
|
||||
.. data:: byteorder
|
||||
|
||||
the byte order of the system ("little" or "big")
|
||||
|
||||
.. data:: path
|
||||
|
||||
a mutable list of directories to search for imported modules
|
||||
|
||||
.. data:: platform
|
||||
|
||||
the platform that Micro Python is running on
|
||||
|
||||
.. data:: stderr
|
||||
|
||||
standard error (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: stdin
|
||||
|
||||
standard input (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: stdout
|
||||
|
||||
standard output (connected to USB VCP, and optional UART object)
|
||||
|
||||
.. data:: version
|
||||
|
||||
Python language version that this implementation conforms to, as a string
|
||||
|
||||
.. data:: version_info
|
||||
|
||||
Python language version that this implementation conforms to, as a tuple of ints
|
||||
41
docs/library/time.rst
Normal file
@@ -0,0 +1,41 @@
|
||||
:mod:`time` -- time related functions
|
||||
=====================================
|
||||
|
||||
.. module:: time
|
||||
:synopsis: time related functions
|
||||
|
||||
The ``time`` module provides functions for getting the current time and date,
|
||||
and for sleeping.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: localtime([secs])
|
||||
|
||||
Convert a time expressed in seconds since Jan 1, 2000 into an 8-tuple which
|
||||
contains: (year, month, mday, hour, minute, second, weekday, yearday)
|
||||
If secs is not provided or None, then the current time from the RTC is used.
|
||||
year includes the century (for example 2014).
|
||||
|
||||
* month is 1-12
|
||||
* mday is 1-31
|
||||
* hour is 0-23
|
||||
* minute is 0-59
|
||||
* second is 0-59
|
||||
* weekday is 0-6 for Mon-Sun
|
||||
* yearday is 1-366
|
||||
|
||||
.. function:: mktime()
|
||||
|
||||
This is inverse function of localtime. It's argument is a full 8-tuple
|
||||
which expresses a time as per localtime. It returns an integer which is
|
||||
the number of seconds since Jan 1, 2000.
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds. Seconds can be a floating-point number to
|
||||
sleep for a fractional number of seconds.
|
||||
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since 1/1/2000.
|
||||
25
docs/library/uheapq.rst
Normal file
@@ -0,0 +1,25 @@
|
||||
:mod:`uheapq` -- heap queue algorithm
|
||||
=====================================
|
||||
|
||||
.. module:: uheapq
|
||||
:synopsis: heap queue algorithm
|
||||
|
||||
This module implements the heap queue algorithm.
|
||||
|
||||
A heap queue is simply a list that has its elements stored in a certain way.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: heappush(heap, item)
|
||||
|
||||
Push the ``item`` onto the ``heap``.
|
||||
|
||||
.. function:: heappop(heap)
|
||||
|
||||
Pop the first item froh the ``heap``, and return it. Raises IndexError if
|
||||
heap is empty.
|
||||
|
||||
.. function:: heapify(x)
|
||||
|
||||
Convert the list ``x`` into a heap. This is an in-place operation.
|
||||
20
docs/library/ujson.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
:mod:`ujson` -- JSON encoding and decoding
|
||||
==========================================
|
||||
|
||||
.. module:: ujson
|
||||
:synopsis: JSON encoding and decoding
|
||||
|
||||
This modules allows to convert between Python objects and the JSON
|
||||
data format.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: dumps(obj)
|
||||
|
||||
Return ``obj`` represented as a JSON string.
|
||||
|
||||
.. function:: loads(str)
|
||||
|
||||
Parse the JSON ``str`` and return an object. Raises ValueError if the
|
||||
string is not correctly formed.
|
||||
17
docs/library/usocket.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
:mod:`usocket` -- socket module
|
||||
===============================
|
||||
|
||||
.. module:: usocket
|
||||
:synopsis: socket module
|
||||
|
||||
Socket functionality.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: getaddrinfo(host, port)
|
||||
|
||||
|
||||
.. function:: socket(family=AF_INET, type=SOCK_STREAM, fileno=-1)
|
||||
|
||||
Create a socket.
|
||||
24
docs/license.rst
Normal file
@@ -0,0 +1,24 @@
|
||||
Micro Python license information
|
||||
================================
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013, 2014 Damien P. George, and others
|
||||
|
||||
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.
|
||||
140
docs/quickref.rst
Normal file
@@ -0,0 +1,140 @@
|
||||
.. _quickref:
|
||||
|
||||
Quick reference for the pyboard
|
||||
===============================
|
||||
|
||||
.. image:: http://micropython.org/resources/pybv10-pinout.jpg
|
||||
:alt: PYBv1.0 pinout
|
||||
:width: 700px
|
||||
|
||||
General board control
|
||||
---------------------
|
||||
|
||||
See :mod:`pyb`. ::
|
||||
|
||||
import pyb
|
||||
|
||||
pyb.delay(50) # wait 50 milliseconds
|
||||
pyb.millis() # number of milliseconds since bootup
|
||||
pyb.repl_uart(pyb.UART(1, 9600)) # duplicate REPL on UART(1)
|
||||
pyb.wfi() # pause CPU, waiting for interrupt
|
||||
pyb.freq() # get CPU and bus frequencies
|
||||
pyb.freq(60000000) # set CPU freq to 60MHz
|
||||
pyb.stop() # stop CPU, waiting for external interrupt
|
||||
|
||||
LEDs
|
||||
----
|
||||
|
||||
See :ref:`pyb.LED <pyb.LED>`. ::
|
||||
|
||||
from pyb import LED
|
||||
|
||||
led = LED(1) # red led
|
||||
led.toggle()
|
||||
led.on()
|
||||
led.off()
|
||||
|
||||
Pins and GPIO
|
||||
-------------
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>`. ::
|
||||
|
||||
from pyb import Pin
|
||||
|
||||
p_out = Pin('X1', Pin.OUT_PP)
|
||||
p_out.high()
|
||||
p_out.low()
|
||||
|
||||
p_in = Pin('X2', Pin.IN, Pin.PULL_UP)
|
||||
p_in.value() # get value, 0 or 1
|
||||
|
||||
External interrupts
|
||||
-------------------
|
||||
|
||||
See :ref:`pyb.ExtInt <pyb.ExtInt>`. ::
|
||||
|
||||
from pyb import Pin, ExtInt
|
||||
|
||||
callback = lambda e: print("intr")
|
||||
ext = ExtInt(Pin('Y1'), ExtInt.IRQ_RISING, Pin.PULL_NONE, callback)
|
||||
|
||||
Timers
|
||||
------
|
||||
|
||||
See :ref:`pyb.Timer <pyb.Timer>`. ::
|
||||
|
||||
from pyb import Timer
|
||||
|
||||
tim = Timer(1, freq=1000)
|
||||
tim.counter() # get counter value
|
||||
tim.freq(0.5) # 0.5 Hz
|
||||
tim.callback(lambda t: pyb.LED(1).toggle())
|
||||
|
||||
PWM (pulse width modulation)
|
||||
----------------------------
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.Timer <pyb.Timer>`. ::
|
||||
|
||||
from pyb import Pin, Timer
|
||||
|
||||
p = Pin('X1') # X1 has TIM2, CH1
|
||||
tim = Timer(2, freq=1000)
|
||||
ch = tim.channel(1, Timer.PWM, pin=p)
|
||||
ch.pulse_width_percent(50)
|
||||
|
||||
ADC (analog to digital conversion)
|
||||
----------------------------------
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.ADC <pyb.ADC>`. ::
|
||||
|
||||
from pyb import Pin, ADC
|
||||
|
||||
adc = ADC(Pin('X19'))
|
||||
adc.read() # read value, 0-4095
|
||||
|
||||
DAC (digital to analog conversion)
|
||||
----------------------------------
|
||||
|
||||
See :ref:`pyb.Pin <pyb.Pin>` and :ref:`pyb.DAC <pyb.DAC>`. ::
|
||||
|
||||
from pyb import Pin, DAC
|
||||
|
||||
dac = DAC(Pin('X5'))
|
||||
dac.write(120) # output between 0 and 255
|
||||
|
||||
UART (serial bus)
|
||||
-----------------
|
||||
|
||||
See :ref:`pyb.UART <pyb.UART>`. ::
|
||||
|
||||
from pyb import UART
|
||||
|
||||
uart = UART(1, 9600)
|
||||
uart.write('hello')
|
||||
uart.read(5) # read up to 5 bytes
|
||||
|
||||
SPI bus
|
||||
-------
|
||||
|
||||
See :ref:`pyb.SPI <pyb.SPI>`. ::
|
||||
|
||||
from pyb import SPI
|
||||
|
||||
spi = SPI(1, SPI.MASTER, baudrate=200000, polarity=1, phase=0)
|
||||
spi.send('hello')
|
||||
spi.recv(5) # receive 5 bytes on the bus
|
||||
spi.send_recv('hello') # send a receive 5 bytes
|
||||
|
||||
I2C bus
|
||||
-------
|
||||
|
||||
See :ref:`pyb.I2C <pyb.I2C>`. ::
|
||||
|
||||
from pyb import I2C
|
||||
|
||||
i2c = I2C(1, I2C.MASTER, baudrate=100000)
|
||||
i2c.scan() # returns list of slave addresses
|
||||
i2c.send('hello', 0x42) # send 5 bytes to slave with address 0x42
|
||||
i2c.recv(5, 0x42) # receive 5 bytes from slave
|
||||
i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10
|
||||
i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10
|
||||
93
docs/topindex.html
Normal file
@@ -0,0 +1,93 @@
|
||||
{% extends "defindex.html" %}
|
||||
{% block body %}
|
||||
|
||||
<h1>Micro Python documentation</h1>
|
||||
|
||||
<p>
|
||||
{{ _('Welcome! This is the documentation for Micro Python') }}
|
||||
v{{ release|e }}{% if last_updated %}, {{ _('last updated') }} {{ last_updated|e }}{% endif %}.
|
||||
</p>
|
||||
|
||||
<p><strong>Documentation for Micro Python and the pyboard:</strong></p>
|
||||
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("quickref") }}">Quick reference for the pyboard</a><br/>
|
||||
<span class="linkdescr">pinout for the pyboard and snippets of useful code</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("general") }}">General information about the pyboard</a><br/>
|
||||
<span class="linkdescr">read this first for a quick overview</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("tutorial/index") }}">Tutorials and code examples</a><br/>
|
||||
<span class="linkdescr">start here</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("library/index") }}">Library Reference</a><br/>
|
||||
<span class="linkdescr">Micro Python libraries, including the <a href="{{ pathto("library/pyb") }}">pyb module</a></span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("hardware/index") }}">The pyboard hardware</a><br/>
|
||||
<span class="linkdescr">schematics, dimensions and component datasheets</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://micropython.org/resources/Micro-Python-Windows-setup.pdf">Guide for pyboard on Windows (PDF)</a><br/>
|
||||
<span class="linkdescr">including DFU programming</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("license") }}">License</a><br/>
|
||||
<span class="linkdescr">Micro Python license information</span>
|
||||
</p>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
<p><strong>Indices and tables:</strong></p>
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("py-modindex") }}">Module index</a><br/>
|
||||
<span class="linkdescr">quick access to all modules</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("genindex") }}">Full index</a><br/>
|
||||
<span class="linkdescr">all functions, classes, constants</span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("contents") }}">Table of contents</a><br/>
|
||||
<span class="linkdescr">a list of all sections and subsections</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
|
||||
<span class="linkdescr">search this documentation</span>
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
||||
<p><strong>External links:</strong></p>
|
||||
|
||||
<table class="contentstable"><tr>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://micropython.org">Micro Python homepage</a><br/>
|
||||
<span class="linkdescr">the official Micro Python site</span>
|
||||
</p>
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="http://forum.micropython.org">Micro Python forum</a><br/>
|
||||
<span class="linkdescr">community discussion for all things related to Micro Python</span>
|
||||
</p>
|
||||
</td>
|
||||
<td width="40%" style="padding-left:2em;">
|
||||
<p class="biglink">
|
||||
<a class="biglink" href="https://github.com/micropython">Micro Python on GitHub</a><br/>
|
||||
<span class="linkdescr">contribute to the source code on GitHub</span>
|
||||
</p>
|
||||
</td>
|
||||
</tr></table>
|
||||
|
||||
{% endblock %}
|
||||
@@ -3,11 +3,11 @@ The AMP audio skin
|
||||
|
||||
Soldering and using the AMP audio skin.
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-amp-1.jpg
|
||||
.. image:: img/skin_amp_1.jpg
|
||||
:alt: AMP skin
|
||||
:width: 250px
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-amp-3.jpg
|
||||
.. image:: img/skin_amp_2.jpg
|
||||
:alt: AMP skin
|
||||
:width: 250px
|
||||
|
||||
@@ -26,6 +26,7 @@ potentiometer, which is an I2C device with address 46 on the ``IC2(1)`` bus.
|
||||
|
||||
To set the volume, define the following function::
|
||||
|
||||
import pyb
|
||||
def volume(val):
|
||||
pyb.I2C(1, pyb.I2C.MASTER).mem_write(val, 46, 0)
|
||||
|
||||
@@ -50,11 +51,11 @@ For example::
|
||||
dac.write_timed(buf, 400 * len(buf), mode=DAC.CIRCULAR)
|
||||
|
||||
You can also play WAV files using the Python ``wave`` module. You can get
|
||||
the wave module [here](/static/doc/examples/wave.py) and you will also need
|
||||
the chunk module available [here](/static/doc/examples/chunk.py). Put these
|
||||
the wave module `here <http://micropython.org/resources/examples/wave.py>`_ and you will also need
|
||||
the chunk module available `here <http://micropython.org/resources/examples/chunk.py>`_. Put these
|
||||
on your pyboard (either on the flash or the SD card in the top-level
|
||||
directory). You will need an 8-bit WAV file to play, such as
|
||||
[this one](/static/doc/examples/test.wav). Then you can do::
|
||||
`this one <http://micropython.org/resources/examples/test.wav>`_. Then you can do::
|
||||
|
||||
>>> import wave
|
||||
>>> from pyb import DAC
|
||||
|
||||
37
docs/tutorial/debounce.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
Debouncing a pin input
|
||||
======================
|
||||
|
||||
A pin used as input from a switch or other mechanical device can have a lot
|
||||
of noise on it, rapidly changing from low to high when the switch is first
|
||||
pressed or released. This noise can be eliminated using a capacitor (a
|
||||
debouncing circuit). It can also be eliminated using a simple function that
|
||||
makes sure the value on the pin is stable.
|
||||
|
||||
The following function does just this. It gets the current value of the given
|
||||
pin, and then waits for the value to change. The new pin value must be stable
|
||||
for a continuous 20ms for it to register the change. You can adjust this time
|
||||
(to say 50ms) if you still have noise. ::
|
||||
|
||||
import pyb
|
||||
|
||||
def wait_pin_change(pin):
|
||||
# wait for pin to change value
|
||||
# it needs to be stable for a continuous 20ms
|
||||
cur_value = pin.value()
|
||||
active = 0
|
||||
while active < 20:
|
||||
if pin.value() != cur_value:
|
||||
active += 1
|
||||
else:
|
||||
active = 0
|
||||
pyb.delay(1)
|
||||
|
||||
|
||||
Use it something like this::
|
||||
|
||||
import pyb
|
||||
|
||||
pin_x1 = pyb.Pin('X1', pyb.Pin.IN, pyb.Pin.PULL_DOWN)
|
||||
while True:
|
||||
wait_pin_change(pin_x1)
|
||||
pyb.LED(4).toggle()
|
||||
89
docs/tutorial/fading_led.rst
Normal file
@@ -0,0 +1,89 @@
|
||||
Fading LEDs
|
||||
===========
|
||||
|
||||
In addition to turning LEDs on and off, it is also possible to control the brightness of an LED using `Pulse-Width Modulation (PWM) <http://en.wikipedia.org/wiki/Pulse-width_modulation>`_, a common technique for obtaining variable output from a digital pin. This allows us to fade an LED:
|
||||
|
||||
.. image:: http://upload.wikimedia.org/wikipedia/commons/a/a9/Fade.gif
|
||||
|
||||
Components
|
||||
----------
|
||||
|
||||
You will need:
|
||||
|
||||
- Standard 5 or 3 mm LED
|
||||
- 100 Ohm resistor
|
||||
- Wires
|
||||
- `Breadboard <http://en.wikipedia.org/wiki/Breadboard>`_ (optional, but makes things easier)
|
||||
|
||||
Connecting Things Up
|
||||
--------------------
|
||||
|
||||
For this tutorial, we will use the ``X1`` pin. Connect one end of the resistor to ``X1``, and the other end to the **anode** of the LED, which is the longer leg. Connect the **cathode** of the LED to ground.
|
||||
|
||||
.. image:: img/fading_leds_breadboard_fritzing.png
|
||||
|
||||
Code
|
||||
----
|
||||
By examining the :ref:`quickref`, we see that ``X1`` is connected to channel 1 of timer 5 (``TIM5 CH1``). Therefore we will first create a ``Timer`` object for timer 5, then create a ``TimerChannel`` object for channel 1::
|
||||
|
||||
from pyb import Timer
|
||||
from time import sleep
|
||||
|
||||
# timer 5 will be created with a frequency of 100 Hz
|
||||
tim = pyb.Timer(5, freq=100)
|
||||
tchannel = tim.channel(1, Timer.PWM, pin=pyb.Pin.board.X1, pulse_width=0)
|
||||
|
||||
Brightness of the LED in PWM is controlled by controlling the pulse-width, that is the amount of time the LED is on every cycle. With a timer frequency of 100 Hz, each cycle takes 0.01 second, or 10 ms.
|
||||
|
||||
To achieve the fading effect shown at the beginning of this tutorial, we want to set the pulse-width to a small value, then slowly increase the pulse-width to brighten the LED, and start over when we reach some maximum brightness::
|
||||
|
||||
# maximum and minimum pulse-width, which corresponds to maximum
|
||||
# and minimum brightness
|
||||
max_width = 200000
|
||||
min_width = 20000
|
||||
|
||||
# how much to change the pulse-width by each step
|
||||
wstep = 1500
|
||||
cur_width = min_width
|
||||
|
||||
while True:
|
||||
tchannel.pulse_width(cur_width)
|
||||
|
||||
# this determines how often we change the pulse-width. It is
|
||||
# analogous to frames-per-second
|
||||
sleep(0.01)
|
||||
|
||||
cur_width += wstep
|
||||
|
||||
if cur_width > max_width:
|
||||
cur_width = min_width
|
||||
|
||||
Breathing Effect
|
||||
----------------
|
||||
|
||||
If we want to have a breathing effect, where the LED fades from dim to bright then bright to dim, then we simply need to reverse the sign of ``wstep`` when we reach maximum brightness, and reverse it again at minimum brightness. To do this we modify the ``while`` loop to be::
|
||||
|
||||
while True:
|
||||
tchannel.pulse_width(cur_width)
|
||||
|
||||
sleep(0.01)
|
||||
|
||||
cur_width += wstep
|
||||
|
||||
if cur_width > max_width:
|
||||
cur_width = max_width
|
||||
wstep *= -1
|
||||
elif cur_width < min_width:
|
||||
cur_width = min_width
|
||||
wstep *= -1
|
||||
|
||||
Advanced Exercise
|
||||
-----------------
|
||||
|
||||
You may have noticed that the LED brightness seems to fade slowly, but increases quickly. This is because our eyes interprets brightness logarithmically (`Weber's Law <http://www.telescope-optics.net/eye_intensity_response.htm>`_
|
||||
), while the LED's brightness changes linearly, that is by the same amount each time. How do you solve this problem? (Hint: what is the opposite of the logarithmic function?)
|
||||
|
||||
Addendum
|
||||
--------
|
||||
|
||||
We could have also used the digital-to-analog converter (DAC) to achieve the same effect. The PWM method has the advantage that it drives the LED with the same current each time, but for different lengths of time. This allows better control over the brightness, because LEDs do not necessarily exhibit a linear relationship between the driving current and brightness.
|
||||
BIN
docs/tutorial/img/fading_leds_breadboard_fritzing.png
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
docs/tutorial/img/pyboard_servo.jpg
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
docs/tutorial/img/pyboard_usb_micro.jpg
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
docs/tutorial/img/skin_amp_1.jpg
Normal file
|
After Width: | Height: | Size: 82 KiB |
BIN
docs/tutorial/img/skin_amp_2.jpg
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
docs/tutorial/img/skin_lcd_1.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
docs/tutorial/img/skin_lcd_2.jpg
Normal file
|
After Width: | Height: | Size: 68 KiB |
@@ -22,6 +22,7 @@ the tutorial through in the order below.
|
||||
usb_mouse.rst
|
||||
timer.rst
|
||||
assembler.rst
|
||||
power_ctrl.rst
|
||||
|
||||
Tutorials requiring extra components
|
||||
------------------------------------
|
||||
@@ -31,5 +32,16 @@ Tutorials requiring extra components
|
||||
:numbered:
|
||||
|
||||
servo.rst
|
||||
fading_led.rst
|
||||
lcd_skin.rst
|
||||
amp_skin.rst
|
||||
|
||||
Tips, tricks and useful things to know
|
||||
--------------------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:numbered:
|
||||
|
||||
debounce.rst
|
||||
pass_through.rst
|
||||
|
||||
@@ -3,11 +3,11 @@ The LCD and touch-sensor skin
|
||||
|
||||
Soldering and using the LCD and touch-sensor skin.
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-lcd-3.jpg
|
||||
.. image:: img/skin_lcd_1.jpg
|
||||
:alt: pyboard with LCD skin
|
||||
:width: 250px
|
||||
|
||||
.. image:: http://micropython.org/static/doc/skin-lcd-1.jpg
|
||||
.. image:: img/skin_lcd_2.jpg
|
||||
:alt: pyboard with LCD skin
|
||||
:width: 250px
|
||||
|
||||
@@ -24,12 +24,14 @@ Using the LCD
|
||||
To get started using the LCD, try the following at the Micro Python prompt.
|
||||
Make sure the LCD skin is attached to the pyboard as pictured at the top of this page. ::
|
||||
|
||||
>>> import pyb
|
||||
>>> lcd = pyb.LCD('X')
|
||||
>>> lcd.light(True)
|
||||
>>> lcd.write('Hello uPy!\n')
|
||||
|
||||
You can make a simple animation using the code::
|
||||
|
||||
import pyb
|
||||
lcd = pyb.LCD('X')
|
||||
lcd.light(True)
|
||||
for x in range(-80, 128):
|
||||
@@ -46,6 +48,7 @@ MPR121 capacitive touch sensor has address 90.
|
||||
|
||||
To get started, try::
|
||||
|
||||
>>> import pyb
|
||||
>>> i2c = pyb.I2C(1, pyb.I2C.MASTER)
|
||||
>>> i2c.mem_write(4, 90, 0x5e)
|
||||
>>> touch = i2c.mem_read(1, 90, 0)[0]
|
||||
@@ -55,7 +58,7 @@ enables the 4 touch sensors. The third line reads the touch
|
||||
status and the ``touch`` variable holds the state of the 4 touch
|
||||
buttons (A, B, X, Y).
|
||||
|
||||
There is a simple driver [here](/static/doc/examples/mpr121.py)
|
||||
There is a simple driver `here <http://micropython.org/resources/examples/mpr121.py>`_
|
||||
which allows you to set the threshold and debounce parameters, and
|
||||
easily read the touch status and electrode voltage levels. Copy
|
||||
this script to your pyboard (either flash or SD card, in the top
|
||||
@@ -78,4 +81,4 @@ initialise the I2C bus using::
|
||||
>>> m = mpr121.MPR121(pyb.I2C(2, pyb.I2C.MASTER))
|
||||
|
||||
There is also a demo which uses the LCD and the touch sensors together,
|
||||
and can be found [here](/static/doc/examples/lcddemo.py).
|
||||
and can be found `here <http://micropython.org/resources/examples/lcddemo.py>`_.
|
||||
|
||||
17
docs/tutorial/pass_through.rst
Normal file
@@ -0,0 +1,17 @@
|
||||
Making a UART - USB pass through
|
||||
================================
|
||||
|
||||
It's as simple as::
|
||||
|
||||
import pyb
|
||||
import select
|
||||
|
||||
def pass_through(usb, uart):
|
||||
while True:
|
||||
select.select([usb, uart], [], [])
|
||||
if usb.any():
|
||||
uart.write(usb.read(256))
|
||||
if uart.any():
|
||||
usb.write(uart.read(256))
|
||||
|
||||
pass_through(pyb.USB_VCP(), pyb.UART(1, 9600))
|
||||
13
docs/tutorial/power_ctrl.rst
Normal file
@@ -0,0 +1,13 @@
|
||||
Power control
|
||||
=============
|
||||
|
||||
:meth:`pyb.wfi` is used to reduce power consumption while waiting for an
|
||||
event such as an interrupt. You would use it in the following situation::
|
||||
|
||||
while True:
|
||||
do_some_processing()
|
||||
pyb.wfi()
|
||||
|
||||
Control the frequency using :meth:`pyb.freq`::
|
||||
|
||||
pyb.freq(30000000) # set CPU frequency to 30MHz
|
||||
@@ -26,7 +26,7 @@ and see which COM port it is (eg COM4).
|
||||
|
||||
You now need to run your terminal program. You can use HyperTerminal if you
|
||||
have it installed, or download the free program PuTTY:
|
||||
[`putty.exe`](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html).
|
||||
`putty.exe <http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html>`_.
|
||||
Using your serial program you must connect to the COM port that you found in the
|
||||
previous step. With PuTTY, click on "Session" in the left-hand panel, then click
|
||||
the "Serial" radio button on the right, then enter you COM port (eg COM4) in the
|
||||
@@ -39,7 +39,7 @@ Open a terminal and run::
|
||||
|
||||
screen /dev/tty.usbmodem*
|
||||
|
||||
When you are finishend and want to exit screen, type CTRL-A CTRL-\\.
|
||||
When you are finished and want to exit screen, type CTRL-A CTRL-\\.
|
||||
|
||||
Linux
|
||||
-----
|
||||
|
||||
@@ -10,7 +10,7 @@ Connecting your pyboard
|
||||
Connect your pyboard to your PC (Windows, Mac or Linux) with a micro USB cable.
|
||||
There is only one way that the cable will connect, so you can't get it wrong.
|
||||
|
||||
<img src="/static/doc/pyboard-usb-micro.jpg" alt="pyboard with USB micro cable" style="width:200px; border:1px solid black; display:inline-block;"/>
|
||||
.. image:: img/pyboard_usb_micro.jpg
|
||||
|
||||
When the pyboard is connected to your PC it will power on and enter the start up
|
||||
process (the boot process). The green LED should light up for half a second or
|
||||
@@ -46,16 +46,16 @@ a window (or command line) should be showing the files on the pyboard drive.
|
||||
The drive you are looking at is known as ``/flash`` by the pyboard, and should contain
|
||||
the following 4 files:
|
||||
|
||||
- [``boot.py``](/static/doc/fresh-pyboard/boot.py) -- this script is executed when the pyboard boots up. It sets
|
||||
* `boot.py <http://micropython.org/resources/fresh-pyboard/boot.py>`_ -- this script is executed when the pyboard boots up. It sets
|
||||
up various configuration options for the pyboard.
|
||||
|
||||
- [``main.py``](/static/doc/fresh-pyboard/main.py) -- this is the main script that will contain your Python program.
|
||||
* `main.py <http://micropython.org/resources/fresh-pyboard/main.py>`_ -- this is the main script that will contain your Python program.
|
||||
It is executed after ``boot.py``.
|
||||
|
||||
- [``README.txt``](/static/doc/fresh-pyboard/README.txt) -- this contains some very basic information about getting
|
||||
* `README.txt <http://micropython.org/resources/fresh-pyboard/README.txt>`_ -- this contains some very basic information about getting
|
||||
started with the pyboard.
|
||||
|
||||
- [``pybcdc.inf``](/static/doc/fresh-pyboard/pybcdc.inf) -- this is a Windows driver file to configure the serial USB
|
||||
* `pybcdc.inf <http://micropython.org/resources/fresh-pyboard/pybcdc.inf>`_ -- this is a Windows driver file to configure the serial USB
|
||||
device. More about this in the next tutorial.
|
||||
|
||||
Editing ``main.py``
|
||||
|
||||
@@ -8,7 +8,7 @@ These motors have 3 wires: ground, power and signal. On the pyboard you
|
||||
can connect them in the bottom right corner, with the signal pin on the
|
||||
far right. Pins X1, X2, X3 and X4 are the 4 dedicated servo signal pins.
|
||||
|
||||
<img src="/static/doc/pyboard-servo.jpg" alt="pyboard with servo motors" style="width:250px; border:1px solid black; display:inline-block;"/>
|
||||
.. image:: img/pyboard_servo.jpg
|
||||
|
||||
In this picture there are male-male double adaptors to connect the servos
|
||||
to the header pins on the pyboard.
|
||||
|
||||
@@ -19,7 +19,7 @@ while True:
|
||||
if switch():
|
||||
pyb.delay(200) # delay avoids detection of multiple presses
|
||||
blue.on() # blue LED indicates file open
|
||||
log = open('1:/log.csv', 'w') # open file on SD (SD: '1:/', flash: '0/)
|
||||
log = open('/sd/log.csv', 'w') # open file on SD (SD: '/sd/', flash: '/flash/)
|
||||
|
||||
# until switch is pressed again
|
||||
while not switch():
|
||||
|
||||
@@ -101,11 +101,16 @@ enum {
|
||||
|
||||
// Here we need to set sign bit right
|
||||
#define TYPE2SMALLINT(x, nbits) ((((int)x) << (32 - nbits)) >> 1)
|
||||
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1));
|
||||
#define GET_TYPE(x, nbits) (((x) >> (31 - nbits)) & ((1 << nbits) - 1))
|
||||
// Bit 0 is "is_signed"
|
||||
#define GET_SCALAR_SIZE(val_type) (1 << ((val_type) >> 1))
|
||||
#define VALUE_MASK(type_nbits) ~((int)0x80000000 >> type_nbits)
|
||||
|
||||
#define IS_SCALAR_ARRAY(tuple_desc) ((tuple_desc)->len == 2)
|
||||
// We cannot apply the below to INT8, as their range [-128, 127]
|
||||
#define IS_SCALAR_ARRAY_OF_BYTES(tuple_desc) (GET_TYPE(MP_OBJ_SMALL_INT_VALUE((tuple_desc)->items[1]), VAL_TYPE_BITS) == UINT8)
|
||||
|
||||
// "struct" in uctypes context means "structural", i.e. aggregate, type.
|
||||
STATIC const mp_obj_type_t uctypes_struct_type;
|
||||
|
||||
typedef struct _mp_obj_uctypes_struct_t {
|
||||
@@ -153,6 +158,10 @@ STATIC void uctypes_struct_print(void (*print)(void *env, const char *fmt, ...),
|
||||
print(env, "<struct %s %p>", typen, self->addr);
|
||||
}
|
||||
|
||||
// Get size of any type descriptor
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size);
|
||||
|
||||
// Get size of scalar type descriptor
|
||||
static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
|
||||
if (val_type == FLOAT32) {
|
||||
return 4;
|
||||
@@ -161,11 +170,60 @@ static inline mp_uint_t uctypes_struct_scalar_size(int val_type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Get size of aggregate type descriptor
|
||||
STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, mp_uint_t *max_field_size) {
|
||||
mp_uint_t total_size = 0;
|
||||
|
||||
mp_int_t offset_ = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset_, AGG_TYPE_BITS);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT:
|
||||
return uctypes_struct_size(t->items[1], max_field_size);
|
||||
case PTR:
|
||||
if (sizeof(void*) > *max_field_size) {
|
||||
*max_field_size = sizeof(void*);
|
||||
}
|
||||
return sizeof(void*);
|
||||
case ARRAY: {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t item_s;
|
||||
if (t->len == 2) {
|
||||
// Elements of array are scalar
|
||||
item_s = GET_SCALAR_SIZE(val_type);
|
||||
if (item_s > *max_field_size) {
|
||||
*max_field_size = item_s;
|
||||
}
|
||||
} else {
|
||||
// Elements of array are aggregates
|
||||
item_s = uctypes_struct_size(t->items[2], max_field_size);
|
||||
}
|
||||
|
||||
return item_s * arr_sz;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size) {
|
||||
mp_obj_dict_t *d = desc_in;
|
||||
mp_uint_t total_size = 0;
|
||||
|
||||
if (!MP_OBJ_IS_TYPE(desc_in, &mp_type_dict)) {
|
||||
if (MP_OBJ_IS_TYPE(desc_in, &mp_type_tuple)) {
|
||||
return uctypes_struct_agg_size((mp_obj_tuple_t*)desc_in, max_field_size);
|
||||
} else if (MP_OBJ_IS_SMALL_INT(desc_in)) {
|
||||
// We allow sizeof on both type definitions and structures/structure fields,
|
||||
// but scalar structure field is lowered into native Python int, so all
|
||||
// type info is lost. So, we cannot say if it's scalar type description,
|
||||
// or such lowered scalar.
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "Cannot unambiguously get sizeof scalar"));
|
||||
}
|
||||
syntax_error();
|
||||
}
|
||||
|
||||
@@ -189,48 +247,10 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
|
||||
}
|
||||
mp_obj_tuple_t *t = (mp_obj_tuple_t*)v;
|
||||
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(t->items[0]);
|
||||
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
|
||||
offset &= VALUE_MASK(AGG_TYPE_BITS);
|
||||
|
||||
switch (agg_type) {
|
||||
case STRUCT: {
|
||||
mp_uint_t s = uctypes_struct_size(t->items[1], max_field_size);
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PTR: {
|
||||
if (offset + sizeof(void*) > total_size) {
|
||||
total_size = offset + sizeof(void*);
|
||||
}
|
||||
if (sizeof(void*) > *max_field_size) {
|
||||
*max_field_size = sizeof(void*);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARRAY: {
|
||||
mp_int_t arr_sz = MP_OBJ_SMALL_INT_VALUE(t->items[1]);
|
||||
uint val_type = GET_TYPE(arr_sz, VAL_TYPE_BITS);
|
||||
arr_sz &= VALUE_MASK(VAL_TYPE_BITS);
|
||||
mp_uint_t item_s;
|
||||
if (t->len == 2) {
|
||||
item_s = GET_SCALAR_SIZE(val_type);
|
||||
if (item_s > *max_field_size) {
|
||||
*max_field_size = item_s;
|
||||
}
|
||||
} else {
|
||||
item_s = uctypes_struct_size(t->items[2], max_field_size);
|
||||
}
|
||||
|
||||
mp_uint_t byte_sz = item_s * arr_sz;
|
||||
if (offset + byte_sz > total_size) {
|
||||
total_size = offset + byte_sz;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
mp_uint_t s = uctypes_struct_agg_size(t, max_field_size);
|
||||
if (offset + s > total_size) {
|
||||
total_size = offset + s;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -243,7 +263,13 @@ STATIC mp_uint_t uctypes_struct_size(mp_obj_t desc_in, mp_uint_t *max_field_size
|
||||
|
||||
STATIC mp_obj_t uctypes_struct_sizeof(mp_obj_t obj_in) {
|
||||
mp_uint_t max_field_size = 0;
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &mp_type_bytearray)) {
|
||||
return mp_obj_len(obj_in);
|
||||
}
|
||||
// We can apply sizeof either to structure definition (a dict)
|
||||
// or to instantiated structure
|
||||
if (MP_OBJ_IS_TYPE(obj_in, &uctypes_struct_type)) {
|
||||
// Extract structure definition
|
||||
mp_obj_uctypes_struct_t *obj = obj_in;
|
||||
obj_in = obj->desc;
|
||||
}
|
||||
@@ -435,7 +461,14 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
|
||||
o->flags = self->flags;
|
||||
return o;
|
||||
}
|
||||
case PTR: case ARRAY: {
|
||||
case ARRAY: {
|
||||
mp_uint_t dummy;
|
||||
if (IS_SCALAR_ARRAY(sub) && IS_SCALAR_ARRAY_OF_BYTES(sub)) {
|
||||
return mp_obj_new_bytearray_by_ref(uctypes_struct_agg_size(sub, &dummy), self->addr + offset);
|
||||
}
|
||||
// Fall thru to return uctypes struct object
|
||||
}
|
||||
case PTR: {
|
||||
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t);
|
||||
o->base.type = &uctypes_struct_type;
|
||||
o->desc = sub;
|
||||
|
||||
138
extmod/moduheapq.c
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 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 <unistd.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "nlr.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objlist.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
|
||||
// the algorithm here is modelled on CPython's heapq.py
|
||||
|
||||
STATIC mp_obj_list_t *get_heap(mp_obj_t heap_in) {
|
||||
if (!MP_OBJ_IS_TYPE(heap_in, &mp_type_list)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "heap must be a list"));
|
||||
}
|
||||
return heap_in;
|
||||
}
|
||||
|
||||
STATIC void heap_siftdown(mp_obj_list_t *heap, mp_uint_t start_pos, mp_uint_t pos) {
|
||||
mp_obj_t item = heap->items[pos];
|
||||
while (pos > start_pos) {
|
||||
mp_uint_t parent_pos = (pos - 1) >> 1;
|
||||
mp_obj_t parent = heap->items[parent_pos];
|
||||
if (mp_binary_op(MP_BINARY_OP_LESS, item, parent) == mp_const_true) {
|
||||
heap->items[pos] = parent;
|
||||
pos = parent_pos;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
}
|
||||
|
||||
STATIC void heap_siftup(mp_obj_list_t *heap, mp_uint_t pos) {
|
||||
mp_uint_t start_pos = pos;
|
||||
mp_uint_t end_pos = heap->len;
|
||||
mp_obj_t item = heap->items[pos];
|
||||
for (mp_uint_t child_pos = 2 * pos + 1; child_pos < end_pos; child_pos = 2 * pos + 1) {
|
||||
// choose right child if it's <= left child
|
||||
if (child_pos + 1 < end_pos && mp_binary_op(MP_BINARY_OP_LESS, heap->items[child_pos], heap->items[child_pos + 1]) == mp_const_false) {
|
||||
child_pos += 1;
|
||||
}
|
||||
// bubble up the smaller child
|
||||
heap->items[pos] = heap->items[child_pos];
|
||||
pos = child_pos;
|
||||
}
|
||||
heap->items[pos] = item;
|
||||
heap_siftdown(heap, start_pos, pos);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappush(mp_obj_t heap_in, mp_obj_t item) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
mp_obj_list_append(heap, item);
|
||||
heap_siftdown(heap, 0, heap->len - 1);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_uheapq_heappush_obj, mod_uheapq_heappush);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heappop(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
|
||||
}
|
||||
mp_obj_t item = heap->items[0];
|
||||
heap->len -= 1;
|
||||
heap->items[0] = heap->items[heap->len];
|
||||
heap->items[heap->len] = MP_OBJ_NULL; // so we don't retain a pointer
|
||||
if (heap->len) {
|
||||
heap_siftup(heap, 0);
|
||||
}
|
||||
return item;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heappop_obj, mod_uheapq_heappop);
|
||||
|
||||
STATIC mp_obj_t mod_uheapq_heapify(mp_obj_t heap_in) {
|
||||
mp_obj_list_t *heap = get_heap(heap_in);
|
||||
for (mp_uint_t i = heap->len / 2; i > 0;) {
|
||||
heap_siftup(heap, --i);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_uheapq_heapify_obj, mod_uheapq_heapify);
|
||||
|
||||
STATIC const mp_map_elem_t mp_module_uheapq_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uheapq) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heappush), (mp_obj_t)&mod_uheapq_heappush_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heappop), (mp_obj_t)&mod_uheapq_heappop_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_heapify), (mp_obj_t)&mod_uheapq_heapify_obj },
|
||||
};
|
||||
|
||||
STATIC const mp_obj_dict_t mp_module_uheapq_globals = {
|
||||
.base = {&mp_type_dict},
|
||||
.map = {
|
||||
.all_keys_are_qstrs = 1,
|
||||
.table_is_fixed_array = 1,
|
||||
.used = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.alloc = MP_ARRAY_SIZE(mp_module_uheapq_globals_table),
|
||||
.table = (mp_map_elem_t*)mp_module_uheapq_globals_table,
|
||||
},
|
||||
};
|
||||
|
||||
const mp_obj_module_t mp_module_uheapq = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_uheapq,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_uheapq_globals,
|
||||
};
|
||||
|
||||
#endif //MICROPY_PY_UHEAPQ
|
||||
33
lib/libm/roundf.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
// roundf from musl-0.9.15
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
float roundf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {x};
|
||||
int e = u.i >> 23 & 0xff;
|
||||
float_t y;
|
||||
|
||||
if (e >= 0x7f+23)
|
||||
return x;
|
||||
if (u.i >> 31)
|
||||
x = -x;
|
||||
if (e < 0x7f-1) {
|
||||
FORCE_EVAL(x + 0x1p23f);
|
||||
return 0*u.f;
|
||||
}
|
||||
y = (float)(x + 0x1p23f) - 0x1p23f - x;
|
||||
if (y > 0.5f)
|
||||
y = y + x - 1;
|
||||
else if (y <= -0.5f)
|
||||
y = y + x + 1;
|
||||
else
|
||||
y = y + x;
|
||||
if (u.i >> 31)
|
||||
y = -y;
|
||||
return y;
|
||||
}
|
||||
20
py/bc.c
@@ -93,7 +93,6 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
|
||||
// usage for the common case of positional only args.
|
||||
mp_obj_fun_bc_t *self = self_in;
|
||||
mp_uint_t n_state = code_state->n_state;
|
||||
const byte *ip = code_state->ip;
|
||||
|
||||
code_state->code_info = self->bytecode;
|
||||
code_state->sp = &code_state->state[0] - 1;
|
||||
@@ -153,13 +152,21 @@ void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t
|
||||
*var_pos_kw_args = dict;
|
||||
}
|
||||
|
||||
// get pointer to arg_names array at start of bytecode prelude
|
||||
const mp_obj_t *arg_names;
|
||||
{
|
||||
const byte *code_info = code_state->code_info;
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
arg_names = (const mp_obj_t*)(code_state->code_info + code_info_size);
|
||||
}
|
||||
|
||||
for (mp_uint_t i = 0; i < n_kw; i++) {
|
||||
qstr arg_name = MP_OBJ_QSTR_VALUE(kwargs[2 * i]);
|
||||
mp_obj_t wanted_arg_name = kwargs[2 * i];
|
||||
for (mp_uint_t j = 0; j < self->n_pos_args + self->n_kwonly_args; j++) {
|
||||
if (arg_name == self->args[j]) {
|
||||
if (wanted_arg_name == arg_names[j]) {
|
||||
if (code_state->state[n_state - 1 - j] != MP_OBJ_NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"function got multiple values for argument '%s'", qstr_str(arg_name)));
|
||||
"function got multiple values for argument '%s'", qstr_str(MP_OBJ_QSTR_VALUE(wanted_arg_name))));
|
||||
}
|
||||
code_state->state[n_state - 1 - j] = kwargs[2 * i + 1];
|
||||
goto continue2;
|
||||
@@ -202,13 +209,13 @@ continue2:;
|
||||
if (code_state->state[n_state - 1 - self->n_pos_args - i] == MP_OBJ_NULL) {
|
||||
mp_map_elem_t *elem = NULL;
|
||||
if (self->has_def_kw_args) {
|
||||
elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, MP_OBJ_NEW_QSTR(self->args[self->n_pos_args + i]), MP_MAP_LOOKUP);
|
||||
elem = mp_map_lookup(&((mp_obj_dict_t*)self->extra_args[self->n_def_args])->map, arg_names[self->n_pos_args + i], MP_MAP_LOOKUP);
|
||||
}
|
||||
if (elem != NULL) {
|
||||
code_state->state[n_state - 1 - self->n_pos_args - i] = elem->value;
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"function missing required keyword argument '%s'", qstr_str(self->args[self->n_pos_args + i])));
|
||||
"function missing required keyword argument '%s'", qstr_str(MP_OBJ_QSTR_VALUE(arg_names[self->n_pos_args + i]))));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -225,6 +232,7 @@ continue2:;
|
||||
}
|
||||
|
||||
// bytecode prelude: initialise closed over variables
|
||||
const byte *ip = code_state->ip;
|
||||
for (mp_uint_t n_local = *ip++; n_local > 0; n_local--) {
|
||||
mp_uint_t local_num = *ip++;
|
||||
code_state->state[n_state - 1 - local_num] = mp_obj_new_cell(code_state->state[n_state - 1 - local_num]);
|
||||
|
||||
2
py/bc.h
@@ -53,7 +53,7 @@ mp_uint_t mp_decode_uint(const byte **ptr);
|
||||
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state *code_state, volatile mp_obj_t inject_exc);
|
||||
void mp_setup_code_state(mp_code_state *code_state, mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len);
|
||||
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *code, mp_uint_t len);
|
||||
void mp_bytecode_print2(const byte *code, mp_uint_t len);
|
||||
|
||||
// Helper macros to access pointer with least significant bit holding a flag
|
||||
|
||||
152
py/bc0.h
@@ -31,92 +31,90 @@
|
||||
#define MP_BC_LOAD_CONST_NONE (0x11)
|
||||
#define MP_BC_LOAD_CONST_TRUE (0x12)
|
||||
#define MP_BC_LOAD_CONST_ELLIPSIS (0x13)
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // 24-bit, in excess
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT (0x14) // signed var-int
|
||||
#define MP_BC_LOAD_CONST_INT (0x15) // qstr
|
||||
#define MP_BC_LOAD_CONST_DEC (0x16) // qstr
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x18) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x19) // qstr
|
||||
#define MP_BC_LOAD_NULL (0x1a)
|
||||
#define MP_BC_LOAD_CONST_BYTES (0x17) // qstr
|
||||
#define MP_BC_LOAD_CONST_STRING (0x18) // qstr
|
||||
#define MP_BC_LOAD_NULL (0x19)
|
||||
|
||||
#define MP_BC_LOAD_FAST_0 (0x20)
|
||||
#define MP_BC_LOAD_FAST_1 (0x21)
|
||||
#define MP_BC_LOAD_FAST_2 (0x22)
|
||||
#define MP_BC_LOAD_FAST_N (0x23) // uint
|
||||
#define MP_BC_LOAD_DEREF (0x25) // uint
|
||||
#define MP_BC_LOAD_NAME (0x26) // qstr
|
||||
#define MP_BC_LOAD_GLOBAL (0x27) // qstr
|
||||
#define MP_BC_LOAD_ATTR (0x28) // qstr
|
||||
#define MP_BC_LOAD_METHOD (0x29) // qstr
|
||||
#define MP_BC_LOAD_BUILD_CLASS (0x2a)
|
||||
#define MP_BC_LOAD_SUBSCR (0x2b)
|
||||
#define MP_BC_LOAD_FAST_N (0x1a) // uint
|
||||
#define MP_BC_LOAD_DEREF (0x1b) // uint
|
||||
#define MP_BC_LOAD_NAME (0x1c) // qstr
|
||||
#define MP_BC_LOAD_GLOBAL (0x1d) // qstr
|
||||
#define MP_BC_LOAD_ATTR (0x1e) // qstr
|
||||
#define MP_BC_LOAD_METHOD (0x1f) // qstr
|
||||
#define MP_BC_LOAD_BUILD_CLASS (0x20)
|
||||
#define MP_BC_LOAD_SUBSCR (0x21)
|
||||
|
||||
#define MP_BC_STORE_FAST_0 (0x30)
|
||||
#define MP_BC_STORE_FAST_1 (0x31)
|
||||
#define MP_BC_STORE_FAST_2 (0x32)
|
||||
#define MP_BC_STORE_FAST_N (0x33) // uint
|
||||
#define MP_BC_STORE_DEREF (0x34) // uint
|
||||
#define MP_BC_STORE_NAME (0x35) // qstr
|
||||
#define MP_BC_STORE_GLOBAL (0x36) // qstr
|
||||
#define MP_BC_STORE_ATTR (0x37) // qstr
|
||||
#define MP_BC_STORE_SUBSCR (0x38)
|
||||
#define MP_BC_STORE_FAST_N (0x22) // uint
|
||||
#define MP_BC_STORE_DEREF (0x23) // uint
|
||||
#define MP_BC_STORE_NAME (0x24) // qstr
|
||||
#define MP_BC_STORE_GLOBAL (0x25) // qstr
|
||||
#define MP_BC_STORE_ATTR (0x26) // qstr
|
||||
#define MP_BC_STORE_SUBSCR (0x27)
|
||||
|
||||
#define MP_BC_DELETE_FAST (0x39) // uint
|
||||
#define MP_BC_DELETE_DEREF (0x3a) // uint
|
||||
#define MP_BC_DELETE_NAME (0x3b) // qstr
|
||||
#define MP_BC_DELETE_GLOBAL (0x3c) // qstr
|
||||
#define MP_BC_DELETE_FAST (0x28) // uint
|
||||
#define MP_BC_DELETE_DEREF (0x29) // uint
|
||||
#define MP_BC_DELETE_NAME (0x2a) // qstr
|
||||
#define MP_BC_DELETE_GLOBAL (0x2b) // qstr
|
||||
|
||||
#define MP_BC_DUP_TOP (0x40)
|
||||
#define MP_BC_DUP_TOP_TWO (0x41)
|
||||
#define MP_BC_POP_TOP (0x42)
|
||||
#define MP_BC_ROT_TWO (0x43)
|
||||
#define MP_BC_ROT_THREE (0x44)
|
||||
#define MP_BC_DUP_TOP (0x30)
|
||||
#define MP_BC_DUP_TOP_TWO (0x31)
|
||||
#define MP_BC_POP_TOP (0x32)
|
||||
#define MP_BC_ROT_TWO (0x33)
|
||||
#define MP_BC_ROT_THREE (0x34)
|
||||
|
||||
#define MP_BC_JUMP (0x45) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_TRUE (0x46) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_FALSE (0x47) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x48) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x49) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_SETUP_WITH (0x4d) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_WITH_CLEANUP (0x4e)
|
||||
#define MP_BC_SETUP_EXCEPT (0x4f) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_SETUP_FINALLY (0x50) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_END_FINALLY (0x51)
|
||||
#define MP_BC_GET_ITER (0x52)
|
||||
#define MP_BC_FOR_ITER (0x53) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_POP_BLOCK (0x54)
|
||||
#define MP_BC_POP_EXCEPT (0x55)
|
||||
#define MP_BC_UNWIND_JUMP (0x56) // rel byte code offset, 16-bit signed, in excess; then a byte
|
||||
#define MP_BC_JUMP (0x35) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_TRUE (0x36) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_POP_JUMP_IF_FALSE (0x37) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_TRUE_OR_POP (0x38) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_JUMP_IF_FALSE_OR_POP (0x39) // rel byte code offset, 16-bit signed, in excess
|
||||
#define MP_BC_SETUP_WITH (0x3d) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_WITH_CLEANUP (0x3e)
|
||||
#define MP_BC_SETUP_EXCEPT (0x3f) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_SETUP_FINALLY (0x40) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_END_FINALLY (0x41)
|
||||
#define MP_BC_GET_ITER (0x42)
|
||||
#define MP_BC_FOR_ITER (0x43) // rel byte code offset, 16-bit unsigned
|
||||
#define MP_BC_POP_BLOCK (0x44)
|
||||
#define MP_BC_POP_EXCEPT (0x45)
|
||||
#define MP_BC_UNWIND_JUMP (0x46) // rel byte code offset, 16-bit signed, in excess; then a byte
|
||||
|
||||
#define MP_BC_NOT (0x60)
|
||||
#define MP_BC_UNARY_OP (0x61) // byte
|
||||
#define MP_BC_BINARY_OP (0x62) // byte
|
||||
#define MP_BC_NOT (0x47)
|
||||
|
||||
#define MP_BC_BUILD_TUPLE (0x70) // uint
|
||||
#define MP_BC_BUILD_LIST (0x71) // uint
|
||||
#define MP_BC_LIST_APPEND (0x72) // uint
|
||||
#define MP_BC_BUILD_MAP (0x73) // uint
|
||||
#define MP_BC_STORE_MAP (0x74)
|
||||
#define MP_BC_MAP_ADD (0x75) // uint
|
||||
#define MP_BC_BUILD_SET (0x76) // uint
|
||||
#define MP_BC_SET_ADD (0x77) // uint
|
||||
#define MP_BC_BUILD_SLICE (0x78) // uint
|
||||
#define MP_BC_UNPACK_SEQUENCE (0x79) // uint
|
||||
#define MP_BC_UNPACK_EX (0x7a) // uint
|
||||
#define MP_BC_BUILD_TUPLE (0x50) // uint
|
||||
#define MP_BC_BUILD_LIST (0x51) // uint
|
||||
#define MP_BC_LIST_APPEND (0x52) // uint
|
||||
#define MP_BC_BUILD_MAP (0x53) // uint
|
||||
#define MP_BC_STORE_MAP (0x54)
|
||||
#define MP_BC_MAP_ADD (0x55) // uint
|
||||
#define MP_BC_BUILD_SET (0x56) // uint
|
||||
#define MP_BC_SET_ADD (0x57) // uint
|
||||
#define MP_BC_BUILD_SLICE (0x58) // uint
|
||||
#define MP_BC_UNPACK_SEQUENCE (0x59) // uint
|
||||
#define MP_BC_UNPACK_EX (0x5a) // uint
|
||||
|
||||
#define MP_BC_RETURN_VALUE (0x80)
|
||||
#define MP_BC_RAISE_VARARGS (0x81) // byte
|
||||
#define MP_BC_YIELD_VALUE (0x82)
|
||||
#define MP_BC_YIELD_FROM (0x83)
|
||||
#define MP_BC_RETURN_VALUE (0x5b)
|
||||
#define MP_BC_RAISE_VARARGS (0x5c) // byte
|
||||
#define MP_BC_YIELD_VALUE (0x5d)
|
||||
#define MP_BC_YIELD_FROM (0x5e)
|
||||
|
||||
#define MP_BC_MAKE_FUNCTION (0x90) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x91) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x92) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x93) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x94) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x95) // uint
|
||||
#define MP_BC_CALL_METHOD (0x96) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x97) // uint
|
||||
#define MP_BC_MAKE_FUNCTION (0x60) // uint
|
||||
#define MP_BC_MAKE_FUNCTION_DEFARGS (0x61) // uint
|
||||
#define MP_BC_MAKE_CLOSURE (0x62) // uint
|
||||
#define MP_BC_MAKE_CLOSURE_DEFARGS (0x63) // uint
|
||||
#define MP_BC_CALL_FUNCTION (0x64) // uint
|
||||
#define MP_BC_CALL_FUNCTION_VAR_KW (0x65) // uint
|
||||
#define MP_BC_CALL_METHOD (0x66) // uint
|
||||
#define MP_BC_CALL_METHOD_VAR_KW (0x67) // uint
|
||||
|
||||
#define MP_BC_IMPORT_NAME (0xe0) // qstr
|
||||
#define MP_BC_IMPORT_FROM (0xe1) // qstr
|
||||
#define MP_BC_IMPORT_STAR (0xe2)
|
||||
#define MP_BC_IMPORT_NAME (0x68) // qstr
|
||||
#define MP_BC_IMPORT_FROM (0x69) // qstr
|
||||
#define MP_BC_IMPORT_STAR (0x6a)
|
||||
|
||||
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)
|
||||
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
|
||||
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
|
||||
#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(5)
|
||||
#define MP_BC_BINARY_OP_MULTI (0xd5) // + op(35)
|
||||
|
||||
28
py/builtin.c
@@ -33,6 +33,7 @@
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objstr.h"
|
||||
#include "smallint.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
@@ -253,8 +254,8 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
|
||||
}
|
||||
mp_obj_t args[2];
|
||||
args[0] = MP_OBJ_NEW_SMALL_INT(i1 / i2);
|
||||
args[1] = MP_OBJ_NEW_SMALL_INT(i1 % i2);
|
||||
args[0] = MP_OBJ_NEW_SMALL_INT(mp_small_int_floor_divide(i1, i2));
|
||||
args[1] = MP_OBJ_NEW_SMALL_INT(mp_small_int_modulo(i1, i2));
|
||||
return mp_obj_new_tuple(2, args);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
} else if (MP_OBJ_IS_TYPE(o1_in, &mp_type_float) || MP_OBJ_IS_TYPE(o2_in, &mp_type_float)) {
|
||||
@@ -447,9 +448,30 @@ STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) {
|
||||
vstr_free(vstr);
|
||||
return s;
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_repr_obj, mp_builtin_repr);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_round(mp_obj_t o_in) {
|
||||
// TODO support second arg
|
||||
if (MP_OBJ_IS_INT(o_in)) {
|
||||
return o_in;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_float_t val = mp_obj_get_float(o_in);
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
|
||||
mp_int_t r = rounded;
|
||||
// make rounded value even if it was halfway between ints
|
||||
if (val - rounded == 0.5) {
|
||||
r = (r + 1) & (~1);
|
||||
} else if (val - rounded == -0.5) {
|
||||
r &= ~1;
|
||||
}
|
||||
#else
|
||||
mp_int_t r = mp_obj_get_int(o_in);
|
||||
#endif
|
||||
return mp_obj_new_int(r);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_round_obj, mp_builtin_round);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_sum(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
assert(1 <= n_args && n_args <= 2);
|
||||
mp_obj_t value;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args);
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_builtin_open(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
|
||||
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin___build_class___obj);
|
||||
@@ -35,6 +35,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bin_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_compile_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_divmod_obj);
|
||||
@@ -60,6 +61,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_repr_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_round_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sorted_obj);
|
||||
MP_DECLARE_CONST_FUN_OBJ(mp_builtin_sum_obj);
|
||||
|
||||
@@ -91,3 +93,4 @@ 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;
|
||||
extern const mp_obj_module_t mp_module_ure;
|
||||
extern const mp_obj_module_t mp_module_uheapq;
|
||||
|
||||
@@ -34,19 +34,87 @@
|
||||
#include "lexerunix.h"
|
||||
#include "parse.h"
|
||||
#include "obj.h"
|
||||
#include "objfun.h"
|
||||
#include "parsehelper.h"
|
||||
#include "compile.h"
|
||||
#include "runtime0.h"
|
||||
#include "runtime.h"
|
||||
#include "builtin.h"
|
||||
|
||||
STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
|
||||
typedef struct _mp_obj_code_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t module_fun;
|
||||
} mp_obj_code_t;
|
||||
|
||||
STATIC const mp_obj_type_t mp_type_code = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_code,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t code_execute(mp_obj_code_t *self, mp_obj_t globals, mp_obj_t locals) {
|
||||
// save context and set new context
|
||||
mp_obj_dict_t *old_globals = mp_globals_get();
|
||||
mp_obj_dict_t *old_locals = mp_locals_get();
|
||||
mp_globals_set(globals);
|
||||
mp_locals_set(locals);
|
||||
|
||||
// a bit of a hack: fun_bc will re-set globals, so need to make sure it's
|
||||
// the correct one
|
||||
if (MP_OBJ_IS_TYPE(self->module_fun, &mp_type_fun_bc)) {
|
||||
mp_obj_fun_bc_t *fun_bc = self->module_fun;
|
||||
fun_bc->globals = globals;
|
||||
}
|
||||
|
||||
// execute code
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
mp_obj_t ret = mp_call_function_0(self->module_fun);
|
||||
nlr_pop();
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
return ret;
|
||||
} else {
|
||||
// exception; restore context and re-raise same exception
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
nlr_raise(nlr.ret_val);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t mp_builtin_compile(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
// get the source
|
||||
mp_uint_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
// get the filename
|
||||
qstr filename = mp_obj_str_get_qstr(args[1]);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(filename, str, str_len, 0);
|
||||
|
||||
// get the compile mode
|
||||
qstr mode = mp_obj_str_get_qstr(args[2]);
|
||||
mp_parse_input_kind_t parse_input_kind;
|
||||
switch (mode) {
|
||||
case MP_QSTR_single: parse_input_kind = MP_PARSE_SINGLE_INPUT; break;
|
||||
case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break;
|
||||
case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad compile mode"));
|
||||
}
|
||||
|
||||
mp_obj_code_t *code = m_new_obj(mp_obj_code_t);
|
||||
code->base.type = &mp_type_code;
|
||||
code->module_fun = mp_parse_compile_execute(lex, parse_input_kind, NULL, NULL);
|
||||
return code;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_compile_obj, 3, 6, mp_builtin_compile);
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_COMPILE
|
||||
|
||||
STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_parse_input_kind_t parse_input_kind) {
|
||||
// work out the context
|
||||
mp_obj_dict_t *globals = mp_globals_get();
|
||||
mp_obj_dict_t *locals = mp_locals_get();
|
||||
@@ -59,6 +127,18 @@ STATIC mp_obj_t eval_exec_helper(mp_uint_t n_args, const mp_obj_t *args, mp_pars
|
||||
}
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_code)) {
|
||||
return code_execute(args[0], globals, locals);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_uint_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_string_gt_, str, str_len, 0);
|
||||
|
||||
return mp_parse_compile_execute(lex, parse_input_kind, globals, locals);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,12 @@
|
||||
|
||||
#define PATH_SEP_CHAR '/'
|
||||
|
||||
bool mp_obj_is_package(mp_obj_t module) {
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method_maybe(module, MP_QSTR___path__, dest);
|
||||
return dest[0] != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
|
||||
//printf("stat %s\n", vstr_str(path));
|
||||
mp_import_stat_t stat = mp_import_stat(vstr_str(path));
|
||||
@@ -122,7 +128,7 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
|
||||
mp_parse_compile_execute(lex, MP_PARSE_FILE_INPUT, mod_globals, mod_globals);
|
||||
}
|
||||
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) {
|
||||
mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
#if DEBUG_PRINT
|
||||
DEBUG_printf("__import__:\n");
|
||||
for (mp_uint_t i = 0; i < n_args; i++) {
|
||||
@@ -280,6 +286,14 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, mp_obj_t *args) {
|
||||
|
||||
module_obj = mp_obj_new_module(mod_name);
|
||||
|
||||
// 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).
|
||||
if (i == mod_len && fromtuple == mp_const_false) {
|
||||
mp_obj_module_t *o = module_obj;
|
||||
mp_obj_dict_store(o->globals, MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
|
||||
}
|
||||
|
||||
if (stat == MP_IMPORT_STAT_DIR) {
|
||||
DEBUG_printf("%s is dir\n", vstr_str(&path));
|
||||
// https://docs.python.org/3/reference/import.html
|
||||
|
||||
@@ -61,6 +61,9 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_int), (mp_obj_t)&mp_type_int },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_list), (mp_obj_t)&mp_type_list },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_map), (mp_obj_t)&mp_type_map },
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_memoryview), (mp_obj_t)&mp_type_memoryview },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_object), (mp_obj_t)&mp_type_object },
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_property), (mp_obj_t)&mp_type_property },
|
||||
@@ -88,6 +91,9 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj },
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_compile), (mp_obj_t)&mp_builtin_compile_obj },
|
||||
#endif
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_divmod), (mp_obj_t)&mp_builtin_divmod_obj },
|
||||
@@ -112,6 +118,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_repr), (mp_obj_t)&mp_builtin_repr_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_round), (mp_obj_t)&mp_builtin_round_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sorted), (mp_obj_t)&mp_builtin_sorted_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sum), (mp_obj_t)&mp_builtin_sum_obj },
|
||||
|
||||
@@ -136,7 +143,6 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RuntimeError), (mp_obj_t)&mp_type_RuntimeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_StopIteration), (mp_obj_t)&mp_type_StopIteration },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SyntaxError), (mp_obj_t)&mp_type_SyntaxError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemError), (mp_obj_t)&mp_type_SystemError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SystemExit), (mp_obj_t)&mp_type_SystemExit },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TypeError), (mp_obj_t)&mp_type_TypeError },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ValueError), (mp_obj_t)&mp_type_ValueError },
|
||||
@@ -212,6 +218,9 @@ STATIC const mp_map_elem_t mp_builtin_module_table[] = {
|
||||
#if MICROPY_PY_URE
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ure), (mp_obj_t)&mp_module_ure },
|
||||
#endif
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uheapq), (mp_obj_t)&mp_module_uheapq },
|
||||
#endif
|
||||
|
||||
// extra builtin modules as defined by a port
|
||||
MICROPY_PORT_BUILTIN_MODULES
|
||||
|
||||
@@ -233,6 +233,11 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
|
||||
}
|
||||
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
|
||||
// int >> int
|
||||
if (arg1 >= BITS_PER_WORD) {
|
||||
// Shifting to big amounts is underfined behavior
|
||||
// in C and is CPU-dependent; propagate sign bit.
|
||||
arg1 = BITS_PER_WORD - 1;
|
||||
}
|
||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
|
||||
} else {
|
||||
// shouldn't happen
|
||||
|
||||
54
py/emitbc.c
@@ -218,6 +218,13 @@ STATIC void emit_write_bytecode_byte_uint(emit_t* emit, byte b, mp_uint_t val) {
|
||||
emit_write_uint(emit, emit_get_cur_to_write_bytecode, val);
|
||||
}
|
||||
|
||||
STATIC void emit_write_bytecode_prealigned_ptr(emit_t* emit, void *ptr) {
|
||||
mp_uint_t *c = (mp_uint_t*)emit_get_cur_to_write_bytecode(emit, sizeof(mp_uint_t));
|
||||
// Verify thar c is already uint-aligned
|
||||
assert(c == MP_ALIGN(c, sizeof(mp_uint_t)));
|
||||
*c = (mp_uint_t)ptr;
|
||||
}
|
||||
|
||||
// aligns the pointer so it is friendly to GC
|
||||
STATIC void emit_write_bytecode_byte_ptr(emit_t* emit, byte b, void *ptr) {
|
||||
emit_write_bytecode_byte(emit, b);
|
||||
@@ -294,7 +301,16 @@ STATIC void emit_bc_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scope) {
|
||||
emit_write_code_info_qstr(emit, scope->simple_name);
|
||||
emit_write_code_info_qstr(emit, scope->source_file);
|
||||
|
||||
// bytecode prelude: local state size and exception stack size; 16 bit uints for now
|
||||
// bytecode prelude: argument names (needed to resolve positional args passed as keywords)
|
||||
// we store them as full word-sized objects for efficient access in mp_setup_code_state
|
||||
// this is the start of the prelude and is guaranteed to be aligned on a word boundary
|
||||
{
|
||||
for (int i = 0; i < scope->num_pos_args + scope->num_kwonly_args; i++) {
|
||||
emit_write_bytecode_prealigned_ptr(emit, MP_OBJ_NEW_QSTR(scope->id_info[i].qst));
|
||||
}
|
||||
}
|
||||
|
||||
// bytecode prelude: local state size and exception stack size
|
||||
{
|
||||
mp_uint_t n_state = scope->num_locals + scope->stack_size;
|
||||
if (n_state == 0) {
|
||||
@@ -358,13 +374,9 @@ STATIC void emit_bc_end_pass(emit_t *emit) {
|
||||
emit->code_base = m_new0(byte, emit->code_info_size + emit->bytecode_size);
|
||||
|
||||
} else if (emit->pass == MP_PASS_EMIT) {
|
||||
qstr *arg_names = m_new(qstr, emit->scope->num_pos_args + emit->scope->num_kwonly_args);
|
||||
for (int i = 0; i < emit->scope->num_pos_args + emit->scope->num_kwonly_args; i++) {
|
||||
arg_names[i] = emit->scope->id_info[i].qst;
|
||||
}
|
||||
mp_emit_glue_assign_bytecode(emit->scope->raw_code, emit->code_base,
|
||||
emit->code_info_size + emit->bytecode_size,
|
||||
emit->scope->num_pos_args, emit->scope->num_kwonly_args, arg_names,
|
||||
emit->scope->num_pos_args, emit->scope->num_kwonly_args,
|
||||
emit->scope->scope_flags);
|
||||
}
|
||||
}
|
||||
@@ -457,7 +469,11 @@ STATIC void emit_bc_load_const_tok(emit_t *emit, mp_token_kind_t tok) {
|
||||
|
||||
STATIC void emit_bc_load_const_small_int(emit_t *emit, mp_int_t arg) {
|
||||
emit_bc_pre(emit, 1);
|
||||
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
|
||||
if (-16 <= arg && arg <= 47) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_LOAD_CONST_SMALL_INT_MULTI + 16 + arg);
|
||||
} else {
|
||||
emit_write_bytecode_byte_int(emit, MP_BC_LOAD_CONST_SMALL_INT, arg);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void emit_bc_load_const_int(emit_t *emit, qstr qst) {
|
||||
@@ -487,11 +503,10 @@ STATIC void emit_bc_load_null(emit_t *emit) {
|
||||
STATIC void emit_bc_load_fast(emit_t *emit, qstr qst, mp_uint_t id_flags, mp_uint_t local_num) {
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, 1);
|
||||
switch (local_num) {
|
||||
case 0: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_0); break;
|
||||
case 1: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_1); break;
|
||||
case 2: emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_2); break;
|
||||
default: emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num); break;
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_LOAD_FAST_MULTI + local_num);
|
||||
} else {
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_LOAD_FAST_N, local_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -533,11 +548,10 @@ STATIC void emit_bc_load_subscr(emit_t *emit) {
|
||||
STATIC void emit_bc_store_fast(emit_t *emit, qstr qst, mp_uint_t local_num) {
|
||||
assert(local_num >= 0);
|
||||
emit_bc_pre(emit, -1);
|
||||
switch (local_num) {
|
||||
case 0: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_0); break;
|
||||
case 1: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_1); break;
|
||||
case 2: emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_2); break;
|
||||
default: emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num); break;
|
||||
if (local_num <= 15) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_STORE_FAST_MULTI + local_num);
|
||||
} else {
|
||||
emit_write_bytecode_byte_uint(emit, MP_BC_STORE_FAST_N, local_num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,12 +726,12 @@ STATIC void emit_bc_pop_except(emit_t *emit) {
|
||||
STATIC void emit_bc_unary_op(emit_t *emit, mp_unary_op_t op) {
|
||||
if (op == MP_UNARY_OP_NOT) {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_UNARY_OP, MP_UNARY_OP_BOOL);
|
||||
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_BOOL);
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_NOT);
|
||||
} else {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_UNARY_OP, op);
|
||||
emit_write_bytecode_byte(emit, MP_BC_UNARY_OP_MULTI + op);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -731,7 +745,7 @@ STATIC void emit_bc_binary_op(emit_t *emit, mp_binary_op_t op) {
|
||||
op = MP_BINARY_OP_IS;
|
||||
}
|
||||
emit_bc_pre(emit, -1);
|
||||
emit_write_bytecode_byte_byte(emit, MP_BC_BINARY_OP, op);
|
||||
emit_write_bytecode_byte(emit, MP_BC_BINARY_OP_MULTI + op);
|
||||
if (invert) {
|
||||
emit_bc_pre(emit, 0);
|
||||
emit_write_bytecode_byte(emit, MP_BC_NOT);
|
||||
|
||||
@@ -55,33 +55,20 @@ mp_raw_code_t *mp_emit_glue_new_raw_code(void) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, qstr *arg_names, mp_uint_t scope_flags) {
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags) {
|
||||
rc->kind = MP_CODE_BYTECODE;
|
||||
rc->scope_flags = scope_flags;
|
||||
rc->n_pos_args = n_pos_args;
|
||||
rc->n_kwonly_args = n_kwonly_args;
|
||||
rc->arg_names = arg_names;
|
||||
rc->u_byte.code = code;
|
||||
rc->u_byte.len = len;
|
||||
|
||||
#ifdef DEBUG_PRINT
|
||||
DEBUG_printf("assign byte code: code=%p len=" UINT_FMT " n_pos_args=" UINT_FMT " n_kwonly_args=" UINT_FMT " flags=%x\n", code, len, n_pos_args, n_kwonly_args, (uint)scope_flags);
|
||||
DEBUG_printf(" arg names:");
|
||||
for (int i = 0; i < n_pos_args + n_kwonly_args; i++) {
|
||||
DEBUG_printf(" %s", qstr_str(arg_names[i]));
|
||||
}
|
||||
DEBUG_printf("\n");
|
||||
#endif
|
||||
#if MICROPY_DEBUG_PRINTERS
|
||||
if (mp_verbose_flag > 0) {
|
||||
for (mp_uint_t i = 0; i < len; i++) {
|
||||
if (i > 0 && i % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" %02x", code[i]);
|
||||
}
|
||||
printf("\n");
|
||||
mp_bytecode_print(rc, code, len);
|
||||
if (mp_verbose_flag >= 2) {
|
||||
mp_bytecode_print(rc, n_pos_args + n_kwonly_args, code, len);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -128,7 +115,7 @@ mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp
|
||||
mp_obj_t fun;
|
||||
switch (rc->kind) {
|
||||
case MP_CODE_BYTECODE:
|
||||
fun = mp_obj_new_fun_bc(rc->scope_flags, rc->arg_names, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->u_byte.code);
|
||||
fun = mp_obj_new_fun_bc(rc->scope_flags, rc->n_pos_args, rc->n_kwonly_args, def_args, def_kw_args, rc->u_byte.code);
|
||||
break;
|
||||
#if MICROPY_EMIT_NATIVE
|
||||
case MP_CODE_NATIVE_PY:
|
||||
|
||||
@@ -35,12 +35,11 @@ typedef enum {
|
||||
MP_CODE_NATIVE_ASM,
|
||||
} mp_raw_code_kind_t;
|
||||
|
||||
typedef struct _mp_code_t {
|
||||
typedef struct _mp_raw_code_t {
|
||||
mp_raw_code_kind_t kind : 3;
|
||||
mp_uint_t scope_flags : 7;
|
||||
mp_uint_t n_pos_args : 11;
|
||||
mp_uint_t n_kwonly_args : 11;
|
||||
qstr *arg_names;
|
||||
union {
|
||||
struct {
|
||||
byte *code;
|
||||
@@ -55,7 +54,7 @@ typedef struct _mp_code_t {
|
||||
|
||||
mp_raw_code_t *mp_emit_glue_new_raw_code(void);
|
||||
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, qstr *arg_names, mp_uint_t scope_flags);
|
||||
void mp_emit_glue_assign_bytecode(mp_raw_code_t *rc, byte *code, mp_uint_t len, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_uint_t scope_flags);
|
||||
void mp_emit_glue_assign_native(mp_raw_code_t *rc, mp_raw_code_kind_t kind, void *fun_data, mp_uint_t fun_len, mp_uint_t n_args, mp_uint_t type_sig);
|
||||
|
||||
mp_obj_t mp_make_function_from_raw_code(mp_raw_code_t *rc, mp_obj_t def_args, mp_obj_t def_kw_args);
|
||||
|
||||
54
py/gc.c
@@ -28,6 +28,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
@@ -68,7 +69,8 @@ STATIC mp_uint_t *gc_pool_end;
|
||||
STATIC int gc_stack_overflow;
|
||||
STATIC mp_uint_t gc_stack[STACK_SIZE];
|
||||
STATIC mp_uint_t *gc_sp;
|
||||
STATIC mp_uint_t gc_lock_depth;
|
||||
STATIC uint16_t gc_lock_depth;
|
||||
uint16_t gc_auto_collect_enabled;
|
||||
STATIC mp_uint_t gc_last_free_atb_index;
|
||||
|
||||
// ATB = allocation table byte
|
||||
@@ -163,6 +165,9 @@ void gc_init(void *start, void *end) {
|
||||
// unlock the GC
|
||||
gc_lock_depth = 0;
|
||||
|
||||
// allow auto collection
|
||||
gc_auto_collect_enabled = 1;
|
||||
|
||||
DEBUG_printf("GC layout:\n");
|
||||
DEBUG_printf(" alloc table at %p, length " UINT_FMT " bytes, " UINT_FMT " blocks\n", gc_alloc_table_start, gc_alloc_table_byte_len, gc_alloc_table_byte_len * BLOCKS_PER_ATB);
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
@@ -375,7 +380,7 @@ void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser) {
|
||||
mp_uint_t end_block;
|
||||
mp_uint_t start_block;
|
||||
mp_uint_t n_free = 0;
|
||||
int collected = 0;
|
||||
int collected = !gc_auto_collect_enabled;
|
||||
for (;;) {
|
||||
|
||||
// look for a run of n_blocks available blocks
|
||||
@@ -484,11 +489,15 @@ void gc_free(void *ptr_in) {
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
gc_dump_alloc_table();
|
||||
#endif
|
||||
} else {
|
||||
assert(!"bad free");
|
||||
}
|
||||
} else if (ptr_in != NULL) {
|
||||
assert(!"bad free");
|
||||
}
|
||||
}
|
||||
|
||||
mp_uint_t gc_nbytes(void *ptr_in) {
|
||||
mp_uint_t gc_nbytes(const void *ptr_in) {
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
if (VERIFY_PTR(ptr)) {
|
||||
@@ -546,6 +555,12 @@ void *gc_realloc(void *ptr_in, mp_uint_t n_bytes) {
|
||||
return gc_alloc(n_bytes, false);
|
||||
}
|
||||
|
||||
// check for pure free
|
||||
if (n_bytes == 0) {
|
||||
gc_free(ptr_in);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mp_uint_t ptr = (mp_uint_t)ptr_in;
|
||||
|
||||
// sanity check the ptr
|
||||
@@ -671,31 +686,32 @@ void gc_dump_alloc_table(void) {
|
||||
for (mp_uint_t bl = 0; bl < gc_alloc_table_byte_len * BLOCKS_PER_ATB; bl++) {
|
||||
if (bl % DUMP_BYTES_PER_LINE == 0) {
|
||||
// a new line of blocks
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
{
|
||||
// check if this line contains only free blocks
|
||||
bool only_free_blocks = true;
|
||||
for (mp_uint_t bl2 = bl; bl2 < gc_alloc_table_byte_len * BLOCKS_PER_ATB && bl2 < bl + DUMP_BYTES_PER_LINE; bl2++) {
|
||||
if (ATB_GET_KIND(bl2) != AT_FREE) {
|
||||
|
||||
only_free_blocks = false;
|
||||
mp_uint_t bl2 = bl;
|
||||
while (bl2 < gc_alloc_table_byte_len * BLOCKS_PER_ATB && ATB_GET_KIND(bl2) == AT_FREE) {
|
||||
bl2++;
|
||||
}
|
||||
if (bl2 - bl >= 2 * DUMP_BYTES_PER_LINE) {
|
||||
// there are at least 2 lines containing only free blocks, so abbreviate their printing
|
||||
printf("\n (" UINT_FMT " lines all free)", (bl2 - bl) / DUMP_BYTES_PER_LINE);
|
||||
bl = bl2 & (~(DUMP_BYTES_PER_LINE - 1));
|
||||
if (bl >= gc_alloc_table_byte_len * BLOCKS_PER_ATB) {
|
||||
// got to end of heap
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (only_free_blocks) {
|
||||
// line contains only free blocks, so skip printing it
|
||||
bl += DUMP_BYTES_PER_LINE - 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// print header for new line of blocks
|
||||
printf("\n%04x: ", (uint)bl);
|
||||
#if EXTENSIVE_HEAP_PROFILING
|
||||
printf("\n%05x: ", (uint)(bl * BYTES_PER_BLOCK) & 0xfffff);
|
||||
#else
|
||||
printf("\n%05x: ", (uint)PTR_FROM_BLOCK(bl) & 0xfffff);
|
||||
#endif
|
||||
}
|
||||
int c = ' ';
|
||||
switch (ATB_GET_KIND(bl)) {
|
||||
case AT_FREE: c = '.'; break;
|
||||
case AT_HEAD: c = 'h'; break;
|
||||
/* this prints out if the object is reachable from BSS or STACK (for unix only)
|
||||
case AT_HEAD: {
|
||||
extern char __bss_start, _end;
|
||||
@@ -724,7 +740,7 @@ void gc_dump_alloc_table(void) {
|
||||
break;
|
||||
}
|
||||
*/
|
||||
/* this prints the uPy object type of the head block
|
||||
/* this prints the uPy object type of the head block */
|
||||
case AT_HEAD: {
|
||||
mp_uint_t *ptr = gc_pool_start + bl * WORDS_PER_BLOCK;
|
||||
if (*ptr == (mp_uint_t)&mp_type_tuple) { c = 'T'; }
|
||||
@@ -732,10 +748,10 @@ void gc_dump_alloc_table(void) {
|
||||
else if (*ptr == (mp_uint_t)&mp_type_dict) { c = 'D'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_float) { c = 'F'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_fun_bc) { c = 'B'; }
|
||||
else if (*ptr == (mp_uint_t)&mp_type_module) { c = 'M'; }
|
||||
else { c = 'h'; }
|
||||
break;
|
||||
}
|
||||
*/
|
||||
case AT_TAIL: c = 't'; break;
|
||||
case AT_MARK: c = 'm'; break;
|
||||
}
|
||||
|
||||
7
py/gc.h
@@ -32,6 +32,11 @@ void gc_lock(void);
|
||||
void gc_unlock(void);
|
||||
bool gc_is_locked(void);
|
||||
|
||||
// This variable controls auto garbage collection. If set to 0 then the
|
||||
// GC won't automatically run when gc_alloc can't find enough blocks. But
|
||||
// you can still allocate/free memory and also explicitly call gc_collect.
|
||||
extern uint16_t gc_auto_collect_enabled;
|
||||
|
||||
// A given port must implement gc_collect by using the other collect functions.
|
||||
void gc_collect(void);
|
||||
void gc_collect_start(void);
|
||||
@@ -40,7 +45,7 @@ void gc_collect_end(void);
|
||||
|
||||
void *gc_alloc(mp_uint_t n_bytes, bool has_finaliser);
|
||||
void gc_free(void *ptr);
|
||||
mp_uint_t gc_nbytes(void *ptr);
|
||||
mp_uint_t gc_nbytes(const void *ptr);
|
||||
void *gc_realloc(void *ptr, mp_uint_t n_bytes);
|
||||
|
||||
typedef struct _gc_info_t {
|
||||
|
||||
43
py/malloc.c
@@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
@@ -63,11 +64,8 @@ STATIC size_t peak_bytes_allocated = 0;
|
||||
#endif // MICROPY_ENABLE_GC
|
||||
|
||||
void *m_malloc(size_t num_bytes) {
|
||||
if (num_bytes == 0) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr = malloc(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -81,9 +79,6 @@ void *m_malloc(size_t num_bytes) {
|
||||
|
||||
void *m_malloc_maybe(size_t num_bytes) {
|
||||
void *ptr = malloc(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
total_bytes_allocated += num_bytes;
|
||||
current_bytes_allocated += num_bytes;
|
||||
@@ -95,11 +90,8 @@ void *m_malloc_maybe(size_t num_bytes) {
|
||||
|
||||
#if MICROPY_ENABLE_FINALISER
|
||||
void *m_malloc_with_finaliser(size_t num_bytes) {
|
||||
if (num_bytes == 0) {
|
||||
return NULL;
|
||||
}
|
||||
void *ptr = malloc_with_finaliser(num_bytes);
|
||||
if (ptr == NULL) {
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -114,19 +106,16 @@ void *m_malloc_with_finaliser(size_t num_bytes) {
|
||||
|
||||
void *m_malloc0(size_t num_bytes) {
|
||||
void *ptr = m_malloc(num_bytes);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, num_bytes);
|
||||
if (ptr == NULL && num_bytes != 0) {
|
||||
return m_malloc_fail(num_bytes);
|
||||
}
|
||||
memset(ptr, 0, num_bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
if (new_num_bytes == 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
void *new_ptr = realloc(ptr, new_num_bytes);
|
||||
if (new_ptr == NULL) {
|
||||
if (new_ptr == NULL && new_num_bytes != 0) {
|
||||
return m_malloc_fail(new_num_bytes);
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
@@ -146,28 +135,26 @@ void *m_realloc(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
|
||||
void *m_realloc_maybe(void *ptr, size_t old_num_bytes, size_t new_num_bytes) {
|
||||
void *new_ptr = realloc(ptr, new_num_bytes);
|
||||
if (new_ptr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
#if MICROPY_MEM_STATS
|
||||
// At first thought, "Total bytes allocated" should only grow,
|
||||
// after all, it's *total*. But consider for example 2K block
|
||||
// shrunk to 1K and then grown to 2K again. It's still 2K
|
||||
// allocated total. If we process only positive increments,
|
||||
// we'll count 3K.
|
||||
size_t diff = new_num_bytes - old_num_bytes;
|
||||
total_bytes_allocated += diff;
|
||||
current_bytes_allocated += diff;
|
||||
UPDATE_PEAK();
|
||||
// Also, don't count failed reallocs.
|
||||
if (!(new_ptr == NULL && new_num_bytes != 0)) {
|
||||
size_t diff = new_num_bytes - old_num_bytes;
|
||||
total_bytes_allocated += diff;
|
||||
current_bytes_allocated += diff;
|
||||
UPDATE_PEAK();
|
||||
}
|
||||
#endif
|
||||
DEBUG_printf("realloc %p, %d, %d : %p\n", ptr, old_num_bytes, new_num_bytes, new_ptr);
|
||||
return new_ptr;
|
||||
}
|
||||
|
||||
void m_free(void *ptr, size_t num_bytes) {
|
||||
if (ptr != NULL) {
|
||||
free(ptr);
|
||||
}
|
||||
free(ptr);
|
||||
#if MICROPY_MEM_STATS
|
||||
current_bytes_allocated -= num_bytes;
|
||||
#endif
|
||||
|
||||
16
py/modgc.c
@@ -24,15 +24,13 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "builtin.h"
|
||||
#include "runtime.h"
|
||||
#include "objlist.h"
|
||||
#include "objtuple.h"
|
||||
#include "objstr.h"
|
||||
#include "gc.h"
|
||||
|
||||
#if MICROPY_PY_GC && MICROPY_ENABLE_GC
|
||||
@@ -56,7 +54,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(gc_collect_obj, py_gc_collect);
|
||||
/// \function disable()
|
||||
/// Disable the garbage collector.
|
||||
STATIC mp_obj_t gc_disable(void) {
|
||||
gc_lock();
|
||||
gc_auto_collect_enabled = 0;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
|
||||
@@ -64,11 +62,16 @@ MP_DEFINE_CONST_FUN_OBJ_0(gc_disable_obj, gc_disable);
|
||||
/// \function enable()
|
||||
/// Enable the garbage collector.
|
||||
STATIC mp_obj_t gc_enable(void) {
|
||||
gc_unlock();
|
||||
gc_auto_collect_enabled = 1;
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_enable_obj, gc_enable);
|
||||
|
||||
STATIC mp_obj_t gc_isenabled(void) {
|
||||
return MP_BOOL(gc_auto_collect_enabled);
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(gc_isenabled_obj, gc_isenabled);
|
||||
|
||||
/// \function mem_free()
|
||||
/// Return the number of bytes of available heap RAM.
|
||||
STATIC mp_obj_t gc_mem_free(void) {
|
||||
@@ -92,6 +95,7 @@ STATIC const mp_map_elem_t mp_module_gc_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_collect), (mp_obj_t)&gc_collect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&gc_disable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&gc_enable_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_isenabled), (mp_obj_t)&gc_isenabled_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_free), (mp_obj_t)&gc_mem_free_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_mem_alloc), (mp_obj_t)&gc_mem_alloc_obj },
|
||||
};
|
||||
|
||||
@@ -25,10 +25,23 @@
|
||||
*/
|
||||
|
||||
// This file contains default configuration settings for MicroPython.
|
||||
// You can override any of these options using mpconfigport.h file located
|
||||
// in a directory of your port.
|
||||
// You can override any of the options below using mpconfigport.h file
|
||||
// located in a directory of your port.
|
||||
|
||||
// mpconfigport.h is a file containing configuration settings for a
|
||||
// particular port. mpconfigport.h is actually a default name for
|
||||
// such config, and it can be overriden using MP_CONFIGFILE preprocessor
|
||||
// define (you can do that by passing CFLAGS_EXTRA='-DMP_CONFIGFILE="<file.h>"'
|
||||
// argument to make when using standard MicroPython makefiles).
|
||||
// This is useful to have more than one config per port, for example,
|
||||
// release vs debug configs, etc. Note that if you switch from one config
|
||||
// to another, you must rebuild from scratch using "-B" switch to make.
|
||||
|
||||
#ifdef MP_CONFIGFILE
|
||||
#include MP_CONFIGFILE
|
||||
#else
|
||||
#include <mpconfigport.h>
|
||||
#endif
|
||||
|
||||
// Any options not explicitly set in mpconfigport.h will get default
|
||||
// values below.
|
||||
@@ -287,6 +300,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
|
||||
#endif
|
||||
|
||||
// Whether to support memoryview object
|
||||
#ifndef MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
|
||||
#endif
|
||||
|
||||
// Whether to support set object
|
||||
#ifndef MICROPY_PY_BUILTINS_SET
|
||||
#define MICROPY_PY_BUILTINS_SET (1)
|
||||
@@ -307,6 +325,11 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
||||
#endif
|
||||
|
||||
// Whether to support compile function
|
||||
#ifndef MICROPY_PY_BUILTINS_COMPILE
|
||||
#define MICROPY_PY_BUILTINS_COMPILE (0)
|
||||
#endif
|
||||
|
||||
// Whether to set __file__ for imported modules
|
||||
#ifndef MICROPY_PY___FILE__
|
||||
#define MICROPY_PY___FILE__ (1)
|
||||
@@ -403,6 +426,10 @@ typedef double mp_float_t;
|
||||
#define MICROPY_PY_URE (0)
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_PY_UHEAPQ
|
||||
#define MICROPY_PY_UHEAPQ (0)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Hooks for a port to add builtins */
|
||||
|
||||
|
||||
6
py/mpz.c
@@ -37,9 +37,9 @@
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
|
||||
|
||||
#define DIG_SIZE (MPZ_DIG_SIZE)
|
||||
#define DIG_MASK ((1L << DIG_SIZE) - 1)
|
||||
#define DIG_MSB (1L << (DIG_SIZE - 1))
|
||||
#define DIG_BASE (1L << DIG_SIZE)
|
||||
#define DIG_MASK ((MPZ_LONG_1 << DIG_SIZE) - 1)
|
||||
#define DIG_MSB (MPZ_LONG_1 << (DIG_SIZE - 1))
|
||||
#define DIG_BASE (MPZ_LONG_1 << DIG_SIZE)
|
||||
|
||||
/*
|
||||
mpz is an arbitrary precision integer type with a public API.
|
||||
|
||||
8
py/mpz.h
@@ -36,7 +36,7 @@
|
||||
// depending on the machine, but it (and MPZ_DIG_SIZE) can be freely changed so
|
||||
// long as the constraints mentioned above are met.
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#if defined(__x86_64__) || defined(_WIN64)
|
||||
// 64-bit machine, using 32-bit storage for digits
|
||||
typedef uint32_t mpz_dig_t;
|
||||
typedef uint64_t mpz_dbl_dig_t;
|
||||
@@ -50,6 +50,12 @@ typedef int32_t mpz_dbl_dig_signed_t;
|
||||
#define MPZ_DIG_SIZE (16)
|
||||
#endif
|
||||
|
||||
#ifdef _WIN64
|
||||
#define MPZ_LONG_1 1i64
|
||||
#else
|
||||
#define MPZ_LONG_1 1L
|
||||
#endif
|
||||
|
||||
#define MPZ_NUM_DIG_FOR_INT (sizeof(mp_int_t) * 8 / MPZ_DIG_SIZE + 1)
|
||||
#define MPZ_NUM_DIG_FOR_LL (sizeof(long long) * 8 / MPZ_DIG_SIZE + 1)
|
||||
|
||||
|
||||
7
py/obj.c
@@ -34,6 +34,7 @@
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "obj.h"
|
||||
#include "objtype.h"
|
||||
#include "mpz.h"
|
||||
#include "objint.h"
|
||||
#include "runtime0.h"
|
||||
@@ -145,7 +146,11 @@ bool mp_obj_is_true(mp_obj_t arg) {
|
||||
}
|
||||
|
||||
bool mp_obj_is_callable(mp_obj_t o_in) {
|
||||
return mp_obj_get_type(o_in)->call != NULL;
|
||||
mp_call_fun_t call = mp_obj_get_type(o_in)->call;
|
||||
if (call != mp_obj_instance_call) {
|
||||
return call != NULL;
|
||||
}
|
||||
return mp_obj_instance_is_callable(o_in);
|
||||
}
|
||||
|
||||
mp_int_t mp_obj_hash(mp_obj_t o_in) {
|
||||
|
||||
8
py/obj.h
@@ -292,6 +292,7 @@ extern const mp_obj_type_t mp_type_int;
|
||||
extern const mp_obj_type_t mp_type_str;
|
||||
extern const mp_obj_type_t mp_type_bytes;
|
||||
extern const mp_obj_type_t mp_type_bytearray;
|
||||
extern const mp_obj_type_t mp_type_memoryview;
|
||||
extern const mp_obj_type_t mp_type_float;
|
||||
extern const mp_obj_type_t mp_type_complex;
|
||||
extern const mp_obj_type_t mp_type_tuple;
|
||||
@@ -329,6 +330,7 @@ extern const mp_obj_type_t mp_type_GeneratorExit;
|
||||
extern const mp_obj_type_t mp_type_ImportError;
|
||||
extern const mp_obj_type_t mp_type_IndentationError;
|
||||
extern const mp_obj_type_t mp_type_IndexError;
|
||||
extern const mp_obj_type_t mp_type_KeyboardInterrupt;
|
||||
extern const mp_obj_type_t mp_type_KeyError;
|
||||
extern const mp_obj_type_t mp_type_LookupError;
|
||||
extern const mp_obj_type_t mp_type_MemoryError;
|
||||
@@ -339,7 +341,6 @@ extern const mp_obj_type_t mp_type_OverflowError;
|
||||
extern const mp_obj_type_t mp_type_RuntimeError;
|
||||
extern const mp_obj_type_t mp_type_StopIteration;
|
||||
extern const mp_obj_type_t mp_type_SyntaxError;
|
||||
extern const mp_obj_type_t mp_type_SystemError;
|
||||
extern const mp_obj_type_t mp_type_SystemExit;
|
||||
extern const mp_obj_type_t mp_type_TypeError;
|
||||
extern const mp_obj_type_t mp_type_ValueError;
|
||||
@@ -383,7 +384,7 @@ mp_obj_t mp_obj_new_exception_arg1(const mp_obj_type_t *exc_type, mp_obj_t arg);
|
||||
mp_obj_t mp_obj_new_exception_args(const mp_obj_type_t *exc_type, mp_uint_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_obj_new_exception_msg(const mp_obj_type_t *exc_type, const char *msg);
|
||||
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...); // counts args by number of % symbols in fmt, excluding %%; can only handle void* sizes (ie no float/double!)
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args, mp_obj_t def_kw_args, const byte *code);
|
||||
mp_obj_t mp_obj_new_fun_native(mp_uint_t n_args, void *fun_data);
|
||||
mp_obj_t mp_obj_new_fun_viper(mp_uint_t n_args, void *fun_data, mp_uint_t type_sig);
|
||||
mp_obj_t mp_obj_new_fun_asm(mp_uint_t n_args, void *fun_data);
|
||||
@@ -529,7 +530,6 @@ void mp_obj_set_store(mp_obj_t self_in, mp_obj_t item);
|
||||
void mp_obj_slice_get(mp_obj_t self_in, mp_obj_t *start, mp_obj_t *stop, mp_obj_t *step);
|
||||
|
||||
// array
|
||||
mp_uint_t mp_obj_array_len(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items);
|
||||
|
||||
// functions
|
||||
@@ -556,6 +556,8 @@ typedef struct _mp_obj_module_t {
|
||||
mp_obj_dict_t *globals;
|
||||
} mp_obj_module_t;
|
||||
mp_obj_dict_t *mp_obj_module_get_globals(mp_obj_t self_in);
|
||||
// check if given module object is a package
|
||||
bool mp_obj_is_package(mp_obj_t module);
|
||||
|
||||
// staticmethod and classmethod types; defined here so we can make const versions
|
||||
// this structure is used for instances of both staticmethod and classmethod
|
||||
|
||||
183
py/objarray.c
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
@@ -37,7 +38,28 @@
|
||||
#include "runtime.h"
|
||||
#include "binary.h"
|
||||
|
||||
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
#if MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
|
||||
// About memoryview object: We want to reuse as much code as possible from
|
||||
// array, and keep the memoryview object 4 words in size so it fits in 1 GC
|
||||
// block. Also, memoryview must keep a pointer to the base of the buffer so
|
||||
// that the buffer is not GC'd if the original parent object is no longer
|
||||
// around (we are assuming that all memoryview'able objects return a pointer
|
||||
// which points to the start of a GC chunk). Given the above constraints we
|
||||
// do the following:
|
||||
// - typecode high bit is set if the buffer is read-write (else read-only)
|
||||
// - free is the offset in elements to the first item in the memoryview
|
||||
// - len is the length in elements
|
||||
// - items points to the start of the original buffer
|
||||
// Note that we don't handle the case where the original buffer might change
|
||||
// size due to a resize of the original parent object.
|
||||
|
||||
// make (& TYPECODE_MASK) a null operation if memorview not enabled
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
#define TYPECODE_MASK (0x7f)
|
||||
#else
|
||||
#define TYPECODE_MASK (~(mp_uint_t)1)
|
||||
#endif
|
||||
|
||||
typedef struct _mp_obj_array_t {
|
||||
mp_obj_base_t base;
|
||||
@@ -50,13 +72,13 @@ typedef struct _mp_obj_array_t {
|
||||
} mp_obj_array_t;
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in);
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n);
|
||||
STATIC mp_obj_t array_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags);
|
||||
|
||||
/******************************************************************************/
|
||||
/* array */
|
||||
// array
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t o_in, mp_print_kind_t kind) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
if (o->typecode == BYTEARRAY_TYPECODE) {
|
||||
@@ -77,7 +99,31 @@ STATIC void array_print(void (*print)(void *env, const char *fmt, ...), void *en
|
||||
}
|
||||
print(env, ")");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
|
||||
int typecode_size = mp_binary_get_size('@', typecode, NULL);
|
||||
if (typecode_size <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
|
||||
}
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY
|
||||
o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
|
||||
#elif MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
o->base.type = &mp_type_bytearray;
|
||||
#else
|
||||
o->base.type = &mp_type_array;
|
||||
#endif
|
||||
o->typecode = typecode;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = m_malloc(typecode_size * o->len);
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
uint len;
|
||||
// Try to create array of exact len if initializer len is known
|
||||
@@ -103,7 +149,9 @@ STATIC mp_obj_t array_construct(char typecode, mp_obj_t initializer) {
|
||||
|
||||
return array;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
|
||||
@@ -119,7 +167,9 @@ STATIC mp_obj_t array_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
|
||||
return array_construct(*typecode, args[1]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
|
||||
@@ -137,6 +187,33 @@ STATIC mp_obj_t bytearray_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
|
||||
return array_construct(BYTEARRAY_TYPECODE, args[0]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
STATIC mp_obj_t memoryview_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
// TODO possibly allow memoryview constructor to take start/stop so that one
|
||||
// can do memoryview(b, 4, 8) instead of memoryview(b)[4:8] (uses less RAM)
|
||||
|
||||
mp_arg_check_num(n_args, n_kw, 1, 1, false);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
mp_obj_array_t *self = m_new_obj(mp_obj_array_t);
|
||||
self->base.type = type_in;
|
||||
self->typecode = bufinfo.typecode;
|
||||
self->free = 0;
|
||||
self->len = bufinfo.len / mp_binary_get_size('@', bufinfo.typecode, NULL); // element len
|
||||
self->items = bufinfo.buf;
|
||||
|
||||
// test if the object can be written to
|
||||
if (mp_get_buffer(args[0], &bufinfo, MP_BUFFER_RW)) {
|
||||
self->typecode |= 0x80; // used to indicate writable buffer
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t array_unary_op(mp_uint_t op, mp_obj_t o_in) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
@@ -154,7 +231,7 @@ STATIC mp_obj_t array_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
|
||||
mp_buffer_info_t rhs_bufinfo;
|
||||
array_get_buffer(lhs_in, &lhs_bufinfo, MP_BUFFER_READ);
|
||||
if (!mp_get_buffer(rhs_in, &rhs_bufinfo, MP_BUFFER_READ)) {
|
||||
return mp_const_false;
|
||||
return mp_const_false;
|
||||
}
|
||||
return MP_BOOL(mp_seq_cmp_bytes(op, lhs_bufinfo.buf, lhs_bufinfo.len, rhs_bufinfo.buf, rhs_bufinfo.len));
|
||||
}
|
||||
@@ -202,21 +279,41 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
|
||||
"only slices with step=1 (aka None) are supported"));
|
||||
}
|
||||
mp_obj_array_t *res = array_new(o->typecode, slice.stop - slice.start);
|
||||
int sz = mp_binary_get_size('@', o->typecode, NULL);
|
||||
mp_obj_array_t *res;
|
||||
int sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
|
||||
assert(sz > 0);
|
||||
byte *p = o->items;
|
||||
memcpy(res->items, p + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
if (0) {
|
||||
// dummy
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
} else if (o->base.type == &mp_type_memoryview) {
|
||||
res = m_new_obj(mp_obj_array_t);
|
||||
*res = *o;
|
||||
res->free += slice.start;
|
||||
res->len = slice.stop - slice.start;
|
||||
#endif
|
||||
} else {
|
||||
res = array_new(o->typecode, slice.stop - slice.start);
|
||||
memcpy(res->items, (uint8_t*)o->items + slice.start * sz, (slice.stop - slice.start) * sz);
|
||||
}
|
||||
return res;
|
||||
#endif
|
||||
} else {
|
||||
mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (o->base.type == &mp_type_memoryview) {
|
||||
index += o->free;
|
||||
if (value != MP_OBJ_SENTINEL && (o->typecode & 0x80) == 0) {
|
||||
// store to read-only memoryview
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
return mp_binary_get_val_array(o->typecode, o->items, index);
|
||||
return mp_binary_get_val_array(o->typecode & TYPECODE_MASK, o->items, index);
|
||||
} else {
|
||||
// store
|
||||
mp_binary_set_val_array(o->typecode, o->items, index, value);
|
||||
mp_binary_set_val_array(o->typecode & TYPECODE_MASK, o->items, index, value);
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
@@ -225,18 +322,31 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
|
||||
STATIC mp_int_t array_get_buffer(mp_obj_t o_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
mp_obj_array_t *o = o_in;
|
||||
int sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
|
||||
bufinfo->buf = o->items;
|
||||
bufinfo->len = o->len * mp_binary_get_size('@', o->typecode, NULL);
|
||||
bufinfo->typecode = o->typecode;
|
||||
bufinfo->len = o->len * sz;
|
||||
bufinfo->typecode = o->typecode & TYPECODE_MASK;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (o->base.type == &mp_type_memoryview) {
|
||||
if ((o->typecode & 0x80) == 0 && (flags & MP_BUFFER_WRITE)) {
|
||||
// read-only memoryview
|
||||
return 1;
|
||||
}
|
||||
bufinfo->buf = (uint8_t*)bufinfo->buf + (mp_uint_t)o->free * sz;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_ARRAY
|
||||
STATIC const mp_map_elem_t array_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_append), (mp_obj_t)&array_append_obj },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(array_locals_dict, array_locals_dict_table);
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_ARRAY
|
||||
const mp_obj_type_t mp_type_array = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_array,
|
||||
@@ -249,7 +359,9 @@ const mp_obj_type_t mp_type_array = {
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&array_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
const mp_obj_type_t mp_type_bytearray = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_bytearray,
|
||||
@@ -262,25 +374,28 @@ const mp_obj_type_t mp_type_bytearray = {
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
.locals_dict = (mp_obj_t)&array_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) {
|
||||
int typecode_size = mp_binary_get_size('@', typecode, NULL);
|
||||
if (typecode_size <= 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode"));
|
||||
}
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
o->base.type = (typecode == BYTEARRAY_TYPECODE) ? &mp_type_bytearray : &mp_type_array;
|
||||
o->typecode = typecode;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = m_malloc(typecode_size * o->len);
|
||||
return o;
|
||||
}
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
const mp_obj_type_t mp_type_memoryview = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_memoryview,
|
||||
.make_new = memoryview_make_new,
|
||||
.getiter = array_iterator_new,
|
||||
.unary_op = array_unary_op,
|
||||
.binary_op = array_binary_op,
|
||||
.subscr = array_subscr,
|
||||
.buffer_p = { .get_buffer = array_get_buffer },
|
||||
};
|
||||
#endif
|
||||
|
||||
/* unused
|
||||
mp_uint_t mp_obj_array_len(mp_obj_t self_in) {
|
||||
return ((mp_obj_array_t *)self_in)->len;
|
||||
}
|
||||
*/
|
||||
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
|
||||
mp_obj_array_t *o = array_new(BYTEARRAY_TYPECODE, n);
|
||||
memcpy(o->items, items, n);
|
||||
@@ -290,27 +405,29 @@ mp_obj_t mp_obj_new_bytearray(mp_uint_t n, void *items) {
|
||||
// Create bytearray which references specified memory area
|
||||
mp_obj_t mp_obj_new_bytearray_by_ref(mp_uint_t n, void *items) {
|
||||
mp_obj_array_t *o = m_new_obj(mp_obj_array_t);
|
||||
o->base.type = &mp_type_array;
|
||||
o->base.type = &mp_type_bytearray;
|
||||
o->typecode = BYTEARRAY_TYPECODE;
|
||||
o->free = 0;
|
||||
o->len = n;
|
||||
o->items = items;
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/* array iterator */
|
||||
// array iterator
|
||||
|
||||
typedef struct _mp_obj_array_it_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_array_t *array;
|
||||
mp_uint_t offset;
|
||||
mp_uint_t cur;
|
||||
} mp_obj_array_it_t;
|
||||
|
||||
STATIC mp_obj_t array_it_iternext(mp_obj_t self_in) {
|
||||
mp_obj_array_it_t *self = self_in;
|
||||
if (self->cur < self->array->len) {
|
||||
return mp_binary_get_val_array(self->array->typecode, self->array->items, self->cur++);
|
||||
return mp_binary_get_val_array(self->array->typecode & TYPECODE_MASK, self->array->items, self->offset + self->cur++);
|
||||
} else {
|
||||
return MP_OBJ_STOP_ITERATION;
|
||||
}
|
||||
@@ -325,11 +442,15 @@ STATIC const mp_obj_type_t array_it_type = {
|
||||
|
||||
STATIC mp_obj_t array_iterator_new(mp_obj_t array_in) {
|
||||
mp_obj_array_t *array = array_in;
|
||||
mp_obj_array_it_t *o = m_new_obj(mp_obj_array_it_t);
|
||||
mp_obj_array_it_t *o = m_new0(mp_obj_array_it_t, 1);
|
||||
o->base.type = &array_it_type;
|
||||
o->array = array;
|
||||
o->cur = 0;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (array->base.type == &mp_type_memoryview) {
|
||||
o->offset = array->free;
|
||||
}
|
||||
#endif
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
#endif // MICROPY_PY_ARRAY || MICROPY_PY_BUILTINS_BYTEARRAY || MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "nlr.h"
|
||||
@@ -211,7 +212,7 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
|
||||
// http://docs.python.org/3/library/exceptions.html
|
||||
MP_DEFINE_EXCEPTION_BASE(BaseException)
|
||||
MP_DEFINE_EXCEPTION(SystemExit, BaseException)
|
||||
//MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
|
||||
MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
|
||||
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
|
||||
MP_DEFINE_EXCEPTION(Exception, BaseException)
|
||||
MP_DEFINE_EXCEPTION_BASE(Exception)
|
||||
@@ -268,7 +269,7 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
|
||||
MP_DEFINE_EXCEPTION_BASE(IndentationError)
|
||||
MP_DEFINE_EXCEPTION(TabError, IndentationError)
|
||||
*/
|
||||
MP_DEFINE_EXCEPTION(SystemError, Exception)
|
||||
//MP_DEFINE_EXCEPTION(SystemError, Exception)
|
||||
MP_DEFINE_EXCEPTION(TypeError, Exception)
|
||||
MP_DEFINE_EXCEPTION(ValueError, Exception)
|
||||
//TODO: Implement UnicodeErrors which take arguments
|
||||
|
||||
@@ -173,7 +173,10 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
const byte *ip = self->bytecode + code_info_size;
|
||||
|
||||
// bytecode prelude: state size and exception stack size; 16 bit uints
|
||||
// bytecode prelude: skip arg names
|
||||
ip += (self->n_pos_args + self->n_kwonly_args) * sizeof(mp_obj_t);
|
||||
|
||||
// bytecode prelude: state size and exception stack size
|
||||
mp_uint_t n_state = mp_decode_uint(&ip);
|
||||
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
|
||||
|
||||
@@ -268,7 +271,7 @@ const mp_obj_type_t mp_type_fun_bc = {
|
||||
.binary_op = mp_obj_fun_binary_op,
|
||||
};
|
||||
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) {
|
||||
mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, mp_uint_t n_pos_args, mp_uint_t n_kwonly_args, mp_obj_t def_args_in, mp_obj_t def_kw_args, const byte *code) {
|
||||
mp_uint_t n_def_args = 0;
|
||||
mp_uint_t n_extra_args = 0;
|
||||
mp_obj_tuple_t *def_args = def_args_in;
|
||||
@@ -283,7 +286,6 @@ mp_obj_t mp_obj_new_fun_bc(mp_uint_t scope_flags, qstr *args, mp_uint_t n_pos_ar
|
||||
mp_obj_fun_bc_t *o = m_new_obj_var(mp_obj_fun_bc_t, mp_obj_t, n_extra_args);
|
||||
o->base.type = &mp_type_fun_bc;
|
||||
o->globals = mp_globals_get();
|
||||
o->args = args;
|
||||
o->n_pos_args = n_pos_args;
|
||||
o->n_kwonly_args = n_kwonly_args;
|
||||
o->n_def_args = n_def_args;
|
||||
|
||||
@@ -27,14 +27,13 @@
|
||||
typedef struct _mp_obj_fun_bc_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_dict_t *globals; // the context within which this function was defined
|
||||
mp_uint_t n_pos_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_kwonly_args : 16; // number of arguments this function takes
|
||||
mp_uint_t n_def_args : 16; // number of default arguments
|
||||
mp_uint_t n_pos_args : 8; // number of arguments this function takes
|
||||
mp_uint_t n_kwonly_args : 8; // number of keyword-only arguments this function takes
|
||||
mp_uint_t n_def_args : 8; // number of default arguments
|
||||
mp_uint_t has_def_kw_args : 1; // set if this function has default keyword args
|
||||
mp_uint_t takes_var_args : 1; // set if this function takes variable args
|
||||
mp_uint_t takes_kw_args : 1; // set if this function takes keyword args
|
||||
const byte *bytecode; // bytecode for the function
|
||||
qstr *args; // argument names (needed to resolve positional args passed as keywords)
|
||||
// the following extra_args array is allocated space to take (in order):
|
||||
// - values of positional default args (if any)
|
||||
// - a single slot for default kw args dict (if it has them)
|
||||
|
||||
@@ -62,6 +62,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
|
||||
mp_uint_t code_info_size = mp_decode_uint(&code_info);
|
||||
const byte *ip = self_fun->bytecode + code_info_size;
|
||||
|
||||
// bytecode prelude: skip arg names
|
||||
ip += (self_fun->n_pos_args + self_fun->n_kwonly_args) * sizeof(mp_obj_t);
|
||||
|
||||
// bytecode prelude: get state size and exception stack size
|
||||
mp_uint_t n_state = mp_decode_uint(&ip);
|
||||
mp_uint_t n_exc_stack = mp_decode_uint(&ip);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
#if MICROPY_PY_SYS_MAXSIZE
|
||||
// Export value for sys.maxsize
|
||||
#define DIG_MASK ((1L << MPZ_DIG_SIZE) - 1)
|
||||
#define DIG_MASK ((MPZ_LONG_1 << MPZ_DIG_SIZE) - 1)
|
||||
STATIC const mpz_dig_t maxsize_dig[MPZ_NUM_DIG_FOR_INT] = {
|
||||
(MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) & DIG_MASK,
|
||||
#if (MP_SSIZE_MAX >> MPZ_DIG_SIZE * 0) > DIG_MASK
|
||||
|
||||
23
py/objstr.c
@@ -160,15 +160,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
case 3:
|
||||
{
|
||||
// TODO: validate 2nd/3rd args
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
|
||||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -215,7 +218,7 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
|
||||
mp_int_t len;
|
||||
byte *data;
|
||||
vstr_t *vstr = NULL;
|
||||
mp_obj_t o = NULL;
|
||||
mp_obj_t o = MP_OBJ_NULL;
|
||||
// Try to create array of exact len if initializer len is known
|
||||
mp_obj_t len_in = mp_obj_len_maybe(args[0]);
|
||||
if (len_in == MP_OBJ_NULL) {
|
||||
@@ -1895,7 +1898,7 @@ qstr mp_obj_str_get_qstr(mp_obj_t self_in) {
|
||||
// only use this function if you need the str data to be zero terminated
|
||||
// at the moment all strings are zero terminated to help with C ASCIIZ compatibility
|
||||
const char *mp_obj_str_get_str(mp_obj_t self_in) {
|
||||
if (MP_OBJ_IS_STR(self_in)) {
|
||||
if (MP_OBJ_IS_STR_OR_BYTES(self_in)) {
|
||||
GET_STR_DATA_LEN(self_in, s, l);
|
||||
(void)l; // len unused
|
||||
return (const char*)s;
|
||||
|
||||
@@ -142,15 +142,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
|
||||
case 3:
|
||||
{
|
||||
// TODO: validate 2nd/3rd args
|
||||
if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
|
||||
if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
} else {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
|
||||
return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
|
||||
}
|
||||
GET_STR_DATA_LEN(args[0], str_data, str_len);
|
||||
GET_STR_HASH(args[0], str_hash);
|
||||
mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
|
||||
o->data = str_data;
|
||||
o->hash = str_hash;
|
||||
return o;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
30
py/objtype.c
@@ -204,6 +204,7 @@ STATIC void instance_print(void (*print)(void *env, const char *fmt, ...), void
|
||||
.attr = meth,
|
||||
.meth_offset = offsetof(mp_obj_type_t, print),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL && kind == PRINT_STR) {
|
||||
@@ -261,6 +262,7 @@ mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, c
|
||||
.attr = MP_QSTR___new__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, make_new),
|
||||
.dest = init_fn,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self);
|
||||
|
||||
@@ -292,7 +294,7 @@ mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, c
|
||||
o = new_ret;
|
||||
|
||||
// now call Python class __init__ function with all args
|
||||
init_fn[0] = init_fn[1] = NULL;
|
||||
init_fn[0] = init_fn[1] = MP_OBJ_NULL;
|
||||
lookup.obj = o;
|
||||
lookup.attr = MP_QSTR___init__;
|
||||
lookup.meth_offset = 0;
|
||||
@@ -341,6 +343,7 @@ STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
|
||||
.attr = op_name,
|
||||
.meth_offset = offsetof(mp_obj_type_t, unary_op),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_SENTINEL) {
|
||||
@@ -437,6 +440,7 @@ STATIC mp_obj_t instance_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
|
||||
.attr = op_name,
|
||||
.meth_offset = offsetof(mp_obj_type_t, binary_op),
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, lhs->base.type);
|
||||
if (dest[0] == MP_OBJ_SENTINEL) {
|
||||
@@ -467,6 +471,7 @@ STATIC void instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
mp_obj_t member = dest[0];
|
||||
@@ -514,6 +519,7 @@ STATIC bool instance_store_attr(mp_obj_t self_in, qstr attr, mp_obj_t value) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] != MP_OBJ_NULL && MP_OBJ_IS_TYPE(member[0], &mp_type_property)) {
|
||||
@@ -549,6 +555,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
.obj = self,
|
||||
.meth_offset = offsetof(mp_obj_type_t, subscr),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
uint meth_args;
|
||||
if (value == MP_OBJ_NULL) {
|
||||
@@ -583,7 +590,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
bool mp_obj_instance_is_callable(mp_obj_t self_in) {
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_obj_t member[2] = {MP_OBJ_NULL};
|
||||
struct class_lookup_data lookup = {
|
||||
@@ -591,6 +598,21 @@ STATIC mp_obj_t instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
|
||||
.attr = MP_QSTR___call__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, call),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
return member[0] != MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_obj_instance_t *self = self_in;
|
||||
mp_obj_t member[2] = {MP_OBJ_NULL, MP_OBJ_NULL};
|
||||
struct class_lookup_data lookup = {
|
||||
.obj = self,
|
||||
.attr = MP_QSTR___call__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, call),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL) {
|
||||
@@ -611,6 +633,7 @@ STATIC mp_obj_t instance_getiter(mp_obj_t self_in) {
|
||||
.attr = MP_QSTR___iter__,
|
||||
.meth_offset = offsetof(mp_obj_type_t, getiter),
|
||||
.dest = member,
|
||||
.is_type = false,
|
||||
};
|
||||
mp_obj_class_lookup(&lookup, self->base.type);
|
||||
if (member[0] == MP_OBJ_NULL) {
|
||||
@@ -777,7 +800,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
|
||||
o->load_attr = instance_load_attr;
|
||||
o->store_attr = instance_store_attr;
|
||||
o->subscr = instance_subscr;
|
||||
o->call = instance_call;
|
||||
o->call = mp_obj_instance_call;
|
||||
o->getiter = instance_getiter;
|
||||
o->bases_tuple = bases_tuple;
|
||||
o->locals_dict = locals_dict;
|
||||
@@ -850,6 +873,7 @@ STATIC void super_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
.attr = attr,
|
||||
.meth_offset = 0,
|
||||
.dest = dest,
|
||||
.is_type = false,
|
||||
};
|
||||
for (uint i = 0; i < len; i++) {
|
||||
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
|
||||
|
||||
@@ -32,3 +32,7 @@ typedef struct _mp_obj_instance_t {
|
||||
mp_obj_t subobj[];
|
||||
// TODO maybe cache __getattr__ and __setattr__ for efficient lookup of them
|
||||
} mp_obj_instance_t;
|
||||
|
||||
// these need to be exposed so mp_obj_is_callable can work correctly
|
||||
bool mp_obj_instance_is_callable(mp_obj_t self_in);
|
||||
mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args);
|
||||
|
||||
22
py/parse.c
@@ -180,17 +180,17 @@ void mp_parse_node_free(mp_parse_node_t pn) {
|
||||
mp_uint_t rule_id = MP_PARSE_NODE_STRUCT_KIND(pns);
|
||||
if (rule_id == RULE_string) {
|
||||
m_del(char, (char*)pns->nodes[0], (mp_uint_t)pns->nodes[1]);
|
||||
return;
|
||||
}
|
||||
bool adjust = ADD_BLANK_NODE(rule_id);
|
||||
if (adjust) {
|
||||
n--;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_free(pns->nodes[i]);
|
||||
}
|
||||
if (adjust) {
|
||||
n++;
|
||||
} else {
|
||||
bool adjust = ADD_BLANK_NODE(rule_id);
|
||||
if (adjust) {
|
||||
n--;
|
||||
}
|
||||
for (mp_uint_t i = 0; i < n; i++) {
|
||||
mp_parse_node_free(pns->nodes[i]);
|
||||
}
|
||||
if (adjust) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
m_del_var(mp_parse_node_struct_t, mp_parse_node_t, n, pns);
|
||||
}
|
||||
|
||||
1
py/py.mk
@@ -114,6 +114,7 @@ PY_O_BASENAME = \
|
||||
../extmod/modujson.o \
|
||||
../extmod/modure.o \
|
||||
../extmod/moduzlib.o \
|
||||
../extmod/moduheapq.o \
|
||||
|
||||
# prepend the build destination prefix to the py object files
|
||||
PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME))
|
||||
|
||||
10
py/qstr.c
@@ -26,10 +26,12 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mpconfig.h"
|
||||
#include "misc.h"
|
||||
#include "qstr.h"
|
||||
#include "gc.h"
|
||||
|
||||
// NOTE: we are using linear arrays to store and search for qstr's (unique strings, interned strings)
|
||||
// ultimately we will replace this with a static hash table of some kind
|
||||
@@ -220,9 +222,17 @@ void qstr_pool_info(mp_uint_t *n_pool, mp_uint_t *n_qstr, mp_uint_t *n_str_data_
|
||||
*n_pool += 1;
|
||||
*n_qstr += pool->len;
|
||||
for (const byte **q = pool->qstrs, **q_top = pool->qstrs + pool->len; q < q_top; q++) {
|
||||
#if MICROPY_ENABLE_GC
|
||||
*n_str_data_bytes += gc_nbytes(*q); // this counts actual bytes used in heap
|
||||
#else
|
||||
*n_str_data_bytes += Q_GET_ALLOC(*q);
|
||||
#endif
|
||||
}
|
||||
#if MICROPY_ENABLE_GC
|
||||
*n_total_bytes += gc_nbytes(pool); // this counts actual bytes used in heap
|
||||
#else
|
||||
*n_total_bytes += sizeof(qstr_pool_t) + sizeof(qstr) * pool->alloc;
|
||||
#endif
|
||||
}
|
||||
*n_total_bytes += *n_str_data_bytes;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ Q(GeneratorExit)
|
||||
Q(ImportError)
|
||||
Q(IndentationError)
|
||||
Q(IndexError)
|
||||
Q(KeyboardInterrupt)
|
||||
Q(KeyError)
|
||||
Q(LookupError)
|
||||
Q(MemoryError)
|
||||
@@ -117,7 +118,6 @@ Q(OSError)
|
||||
Q(OverflowError)
|
||||
Q(RuntimeError)
|
||||
Q(SyntaxError)
|
||||
Q(SystemError)
|
||||
Q(SystemExit)
|
||||
Q(TypeError)
|
||||
Q(UnboundLocalError)
|
||||
@@ -135,11 +135,18 @@ Q(abs)
|
||||
Q(all)
|
||||
Q(any)
|
||||
Q(args)
|
||||
#if MICROPY_PY_ARRAY
|
||||
Q(array)
|
||||
#endif
|
||||
Q(bin)
|
||||
Q({:#b})
|
||||
Q(bool)
|
||||
#if MICROPY_PY_BUILTINS_BYTEARRAY
|
||||
Q(bytearray)
|
||||
#endif
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
Q(memoryview)
|
||||
#endif
|
||||
Q(bytes)
|
||||
Q(callable)
|
||||
#if MICROPY_PY_STRUCT
|
||||
@@ -194,6 +201,7 @@ Q(range)
|
||||
Q(read)
|
||||
Q(repr)
|
||||
Q(reversed)
|
||||
Q(round)
|
||||
Q(sorted)
|
||||
Q(staticmethod)
|
||||
Q(sum)
|
||||
@@ -207,6 +215,12 @@ Q(value)
|
||||
Q(write)
|
||||
Q(zip)
|
||||
|
||||
#if MICROPY_PY_BUILTINS_COMPILE
|
||||
Q(compile)
|
||||
Q(code)
|
||||
Q(single)
|
||||
#endif
|
||||
|
||||
Q(sep)
|
||||
Q(end)
|
||||
|
||||
@@ -456,6 +470,7 @@ Q(gc)
|
||||
Q(collect)
|
||||
Q(disable)
|
||||
Q(enable)
|
||||
Q(isenabled)
|
||||
Q(mem_free)
|
||||
Q(mem_alloc)
|
||||
#endif
|
||||
@@ -486,3 +501,10 @@ Q(search)
|
||||
Q(group)
|
||||
Q(DEBUG)
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_UHEAPQ
|
||||
Q(uheapq)
|
||||
Q(heappush)
|
||||
Q(heappop)
|
||||
Q(heapify)
|
||||
#endif
|
||||
|
||||
23
py/runtime.c
@@ -62,6 +62,9 @@
|
||||
#define DEBUG_OP_printf(...) (void)0
|
||||
#endif
|
||||
|
||||
// pending exception object (MP_OBJ_NULL if not pending)
|
||||
mp_obj_t mp_pending_exception;
|
||||
|
||||
// locals and globals need to be pointers because they can be the same in outer module scope
|
||||
STATIC mp_obj_dict_t *dict_locals;
|
||||
STATIC mp_obj_dict_t *dict_globals;
|
||||
@@ -79,6 +82,9 @@ void mp_init(void) {
|
||||
qstr_init();
|
||||
mp_stack_ctrl_init();
|
||||
|
||||
// no pending exceptions to start with
|
||||
mp_pending_exception = MP_OBJ_NULL;
|
||||
|
||||
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
|
||||
mp_init_emergency_exception_buf();
|
||||
#endif
|
||||
@@ -331,6 +337,11 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
|
||||
} else {
|
||||
// standard precision is enough for right-shift
|
||||
if (rhs_val >= BITS_PER_WORD) {
|
||||
// Shifting to big amounts is underfined behavior
|
||||
// in C and is CPU-dependent; propagate sign bit.
|
||||
rhs_val = BITS_PER_WORD - 1;
|
||||
}
|
||||
lhs_val >>= rhs_val;
|
||||
}
|
||||
break;
|
||||
@@ -475,8 +486,8 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
|
||||
}
|
||||
if (type->getiter != NULL) {
|
||||
/* second attempt, walk the iterator */
|
||||
mp_obj_t next = NULL;
|
||||
mp_obj_t iter = mp_getiter(rhs);
|
||||
mp_obj_t next;
|
||||
while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
|
||||
if (mp_obj_equal(next, lhs)) {
|
||||
return mp_const_true;
|
||||
@@ -1098,8 +1109,7 @@ import_error:
|
||||
}
|
||||
|
||||
// See if it's a package, then can try FS import
|
||||
mp_load_method_maybe(module, MP_QSTR___path__, dest);
|
||||
if (dest[0] == MP_OBJ_NULL) {
|
||||
if (!mp_obj_is_package(module)) {
|
||||
goto import_error;
|
||||
}
|
||||
|
||||
@@ -1190,6 +1200,13 @@ mp_obj_t mp_parse_compile_execute(mp_lexer_t *lex, mp_parse_input_kind_t parse_i
|
||||
nlr_raise(module_fun);
|
||||
}
|
||||
|
||||
// for compile only
|
||||
if (MICROPY_PY_BUILTINS_COMPILE && globals == NULL) {
|
||||
mp_globals_set(old_globals);
|
||||
mp_locals_set(old_locals);
|
||||
return module_fun;
|
||||
}
|
||||
|
||||
// complied successfully, execute it
|
||||
nlr_buf_t nlr;
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
|
||||
@@ -116,6 +116,7 @@ mp_obj_t mp_convert_native_to_obj(mp_uint_t val, mp_uint_t type);
|
||||
mp_obj_t mp_native_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args_kw, const mp_obj_t *args);
|
||||
NORETURN void mp_native_raise(mp_obj_t o);
|
||||
|
||||
extern mp_obj_t mp_pending_exception;
|
||||
extern struct _mp_obj_list_t mp_sys_path_obj;
|
||||
extern struct _mp_obj_list_t mp_sys_argv_obj;
|
||||
#define mp_sys_path ((mp_obj_t)&mp_sys_path_obj)
|
||||
|
||||
78
py/showbc.c
@@ -57,7 +57,7 @@
|
||||
ip += sizeof(mp_uint_t); \
|
||||
} while (0)
|
||||
|
||||
void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
void mp_bytecode_print(const void *descr, mp_uint_t n_total_args, const byte *ip, mp_uint_t len) {
|
||||
const byte *ip_start = ip;
|
||||
|
||||
// get code info size
|
||||
@@ -70,6 +70,24 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
printf("File %s, code block '%s' (descriptor: %p, bytecode @%p " UINT_FMT " bytes)\n",
|
||||
qstr_str(source_file), qstr_str(block_name), descr, code_info, len);
|
||||
|
||||
// raw bytecode dump
|
||||
printf("Raw bytecode (code_info_size=" UINT_FMT ", bytecode_size=" UINT_FMT "):\n", code_info_size, len - code_info_size);
|
||||
for (mp_uint_t i = 0; i < len; i++) {
|
||||
if (i > 0 && i % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
printf(" %02x", ip_start[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// bytecode prelude: arg names (as qstr objects)
|
||||
printf("arg names:");
|
||||
for (int i = 0; i < n_total_args; i++) {
|
||||
printf(" %s", qstr_str(MP_OBJ_QSTR_VALUE(*(mp_obj_t*)ip)));
|
||||
ip += sizeof(mp_obj_t);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// bytecode prelude: state size and exception stack size; 16 bit uints
|
||||
{
|
||||
uint n_state = mp_decode_uint(&ip);
|
||||
@@ -87,15 +105,14 @@ void mp_bytecode_print(const void *descr, const byte *ip, mp_uint_t len) {
|
||||
printf("(INIT_CELL %u)\n", local_num);
|
||||
}
|
||||
len -= ip - ip_start;
|
||||
ip_start = ip;
|
||||
}
|
||||
|
||||
// print out line number info
|
||||
{
|
||||
mp_int_t bc = (code_info + code_info_size) - ip;
|
||||
mp_int_t bc = (ip_start + code_info_size) - ip; // start counting from the prelude
|
||||
mp_uint_t source_line = 1;
|
||||
printf(" bc=" INT_FMT " line=" UINT_FMT "\n", bc, source_line);
|
||||
for (const byte* ci = code_info + 12; *ci;) {
|
||||
for (const byte* ci = code_info; *ci;) {
|
||||
if ((ci[0] & 0x80) == 0) {
|
||||
// 0b0LLBBBBB encoding
|
||||
bc += ci[0] & 0x1f;
|
||||
@@ -173,18 +190,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("LOAD_NULL");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_0:
|
||||
printf("LOAD_FAST_0");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_1:
|
||||
printf("LOAD_FAST_1");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_2:
|
||||
printf("LOAD_FAST_2");
|
||||
break;
|
||||
|
||||
case MP_BC_LOAD_FAST_N:
|
||||
DECODE_UINT;
|
||||
printf("LOAD_FAST_N " UINT_FMT, unum);
|
||||
@@ -223,18 +228,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("LOAD_SUBSCR");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_0:
|
||||
printf("STORE_FAST_0");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_1:
|
||||
printf("STORE_FAST_1");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_2:
|
||||
printf("STORE_FAST_2");
|
||||
break;
|
||||
|
||||
case MP_BC_STORE_FAST_N:
|
||||
DECODE_UINT;
|
||||
printf("STORE_FAST_N " UINT_FMT, unum);
|
||||
@@ -380,16 +373,6 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
printf("NOT");
|
||||
break;
|
||||
|
||||
case MP_BC_UNARY_OP:
|
||||
unum = *ip++;
|
||||
printf("UNARY_OP " UINT_FMT, unum);
|
||||
break;
|
||||
|
||||
case MP_BC_BINARY_OP:
|
||||
unum = *ip++;
|
||||
printf("BINARY_OP " UINT_FMT, unum);
|
||||
break;
|
||||
|
||||
case MP_BC_BUILD_TUPLE:
|
||||
DECODE_UINT;
|
||||
printf("BUILD_TUPLE " UINT_FMT, unum);
|
||||
@@ -517,9 +500,22 @@ void mp_bytecode_print2(const byte *ip, mp_uint_t len) {
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("code %p, byte code 0x%02x not implemented\n", ip, ip[-1]);
|
||||
assert(0);
|
||||
return;
|
||||
if (ip[-1] < MP_BC_LOAD_CONST_SMALL_INT_MULTI + 64) {
|
||||
printf("LOAD_CONST_SMALL_INT " INT_FMT, (mp_int_t)ip[-1] - MP_BC_LOAD_CONST_SMALL_INT_MULTI - 16);
|
||||
} else if (ip[-1] < MP_BC_LOAD_FAST_MULTI + 16) {
|
||||
printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
|
||||
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
|
||||
printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
|
||||
} else if (ip[-1] < MP_BC_UNARY_OP_MULTI + 5) {
|
||||
printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
|
||||
} else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 35) {
|
||||
printf("BINARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_BINARY_OP_MULTI);
|
||||
} else {
|
||||
printf("code %p, byte code 0x%02x not implemented\n", ip, ip[-1]);
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@@ -57,23 +57,23 @@ bool mp_small_int_mul_overflow(mp_int_t x, mp_int_t y) {
|
||||
}
|
||||
|
||||
mp_int_t mp_small_int_modulo(mp_int_t dividend, mp_int_t divisor) {
|
||||
mp_int_t lsign = (dividend >= 0) ? 1 :-1;
|
||||
mp_int_t rsign = (divisor >= 0) ? 1 :-1;
|
||||
// Python specs require that mod has same sign as second operand
|
||||
dividend %= divisor;
|
||||
if (lsign != rsign) {
|
||||
if ((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0)) {
|
||||
dividend += divisor;
|
||||
}
|
||||
return dividend;
|
||||
}
|
||||
|
||||
mp_int_t mp_small_int_floor_divide(mp_int_t num, mp_int_t denom) {
|
||||
mp_int_t lsign = num > 0 ? 1 : -1;
|
||||
mp_int_t rsign = denom > 0 ? 1 : -1;
|
||||
if (lsign == -1) {num *= -1;}
|
||||
if (rsign == -1) {denom *= -1;}
|
||||
if (lsign != rsign){
|
||||
return - ( num + denom - 1) / denom;
|
||||
if (num >= 0) {
|
||||
if (denom < 0) {
|
||||
num += -denom - 1;
|
||||
}
|
||||
} else {
|
||||
return num / denom;
|
||||
if (denom >= 0) {
|
||||
num += -denom + 1;
|
||||
}
|
||||
}
|
||||
return num / denom;
|
||||
}
|
||||
|
||||
33
py/stream.c
@@ -60,7 +60,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in);
|
||||
|
||||
#define STREAM_CONTENT_TYPE(stream) (((stream)->is_text) ? &mp_type_str : &mp_type_bytes)
|
||||
|
||||
STATIC mp_obj_t stream_read(uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t stream_read(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
@@ -215,17 +215,28 @@ STATIC mp_obj_t stream_write_method(mp_obj_t self_in, mp_obj_t arg) {
|
||||
return mp_stream_write(self_in, bufinfo.buf, bufinfo.len);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t stream_readinto(mp_obj_t self_in, mp_obj_t arg) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in;
|
||||
STATIC mp_obj_t stream_readinto(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_WRITE);
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE);
|
||||
|
||||
// CPython extension: if 2nd arg is provided, that's max len to read,
|
||||
// instead of full buffer. Similar to
|
||||
// https://docs.python.org/3/library/socket.html#socket.socket.recv_into
|
||||
mp_uint_t len = bufinfo.len;
|
||||
if (n_args > 2) {
|
||||
len = mp_obj_int_get(args[2]);
|
||||
if (len > bufinfo.len) {
|
||||
len = bufinfo.len;
|
||||
}
|
||||
}
|
||||
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, bufinfo.buf, bufinfo.len, &error);
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, bufinfo.buf, len, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
return mp_const_none;
|
||||
@@ -243,12 +254,12 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported"));
|
||||
}
|
||||
|
||||
int total_size = 0;
|
||||
mp_uint_t total_size = 0;
|
||||
vstr_t *vstr = vstr_new_size(DEFAULT_BUFFER_SIZE);
|
||||
char *p = vstr_str(vstr);
|
||||
int error;
|
||||
int current_read = DEFAULT_BUFFER_SIZE;
|
||||
mp_uint_t current_read = DEFAULT_BUFFER_SIZE;
|
||||
while (true) {
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
@@ -285,7 +296,7 @@ STATIC mp_obj_t stream_readall(mp_obj_t self_in) {
|
||||
}
|
||||
|
||||
// Unbuffered, inefficient implementation of readline() for raw I/O files.
|
||||
STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
STATIC mp_obj_t stream_unbuffered_readline(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0];
|
||||
if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) {
|
||||
// CPython: io.UnsupportedOperation, OSError subclass
|
||||
@@ -304,13 +315,13 @@ STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) {
|
||||
vstr = vstr_new();
|
||||
}
|
||||
|
||||
int error;
|
||||
while (max_size == -1 || max_size-- != 0) {
|
||||
char *p = vstr_add_len(vstr, 1);
|
||||
if (p == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory"));
|
||||
}
|
||||
|
||||
int error;
|
||||
mp_uint_t out_sz = o->type->stream_p->read(o, p, 1, &error);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
if (is_nonblocking_error(error)) {
|
||||
@@ -370,7 +381,7 @@ mp_obj_t mp_stream_unbuffered_iter(mp_obj_t self) {
|
||||
}
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_read_obj, 1, 2, stream_read);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_readinto_obj, stream_readinto);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_readinto_obj, 2, 3, stream_readinto);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_stream_readall_obj, stream_readall);
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_stream_unbuffered_readline_obj, 1, 2, stream_unbuffered_readline);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(mp_stream_write_obj, stream_write_method);
|
||||
|
||||